mirror of
https://github.com/Motion-Project/motion.git
synced 2026-05-17 12:40:38 +00:00
Merge branch '5.0'
This commit is contained in:
@@ -5,4 +5,8 @@ contact_links:
|
||||
about: Please ask and answer questions here.
|
||||
- name: Motion Enhancements
|
||||
url: https://github.com/Motion-Project/motion/discussions
|
||||
about: Please use the discussions page and tag as an enhancement request.
|
||||
<<<<<<< HEAD
|
||||
about: Please use the discussions page and tag as an enhancement request.
|
||||
=======
|
||||
about: Please use the discussions page and tag as an enhancement request.
|
||||
>>>>>>> 5.0
|
||||
|
||||
@@ -30,9 +30,15 @@ body:
|
||||
- 4.5.x
|
||||
- 4.6.x
|
||||
- 4.7.x
|
||||
<<<<<<< HEAD
|
||||
- 4.8.x
|
||||
- 4.9.x
|
||||
- 4.10.x
|
||||
=======
|
||||
- 5.0.x
|
||||
- 5.1.x
|
||||
- 5.2.x
|
||||
>>>>>>> 5.0
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
@@ -53,7 +59,11 @@ body:
|
||||
options:
|
||||
- ARM-32bit
|
||||
- ARM-64bit
|
||||
<<<<<<< HEAD
|
||||
- x86
|
||||
=======
|
||||
- x86/x64
|
||||
>>>>>>> 5.0
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
@@ -80,6 +90,7 @@ body:
|
||||
- type: dropdown
|
||||
id: camtype
|
||||
attributes:
|
||||
<<<<<<< HEAD
|
||||
label: Camera type(s) being used?
|
||||
multiple: true
|
||||
options:
|
||||
@@ -89,6 +100,18 @@ body:
|
||||
- PI cam via MMAL
|
||||
- Network camera with RTSP
|
||||
- Network camera with HTTP
|
||||
=======
|
||||
label: Camera/Sound type(s) being used?
|
||||
multiple: true
|
||||
options:
|
||||
- v4l2 camera
|
||||
- PI cam via libcamerify
|
||||
- PI camera via libcam
|
||||
- Network camera with RTSP
|
||||
- Network camera with HTTP
|
||||
- Sound via ALSA
|
||||
- Sound via PulseAudio
|
||||
>>>>>>> 5.0
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
@@ -103,8 +126,13 @@ body:
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
<<<<<<< HEAD
|
||||
label: Motion log output at log_level 8
|
||||
description: Provide the entire log output from Motion start up to when the issue occurs so we can see the parameters. This will be automatically formatted into code, so no need for backticks.
|
||||
=======
|
||||
label: Full Motion log output (at log_level 8)
|
||||
description: Please copy and paste the full log output. This will be automatically formatted into code, so no need for backticks.
|
||||
>>>>>>> 5.0
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- .github/ISSUE_TEMPLATE/**
|
||||
- doc/**
|
||||
- man/**
|
||||
- '**/LICENCE'
|
||||
- '**/.gitignore'
|
||||
- '**.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- .github/ISSUE_TEMPLATE/**
|
||||
- doc/**
|
||||
- man/**
|
||||
- '**/LICENCE'
|
||||
- '**/.gitignore'
|
||||
- '**.md'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
cxx: [g++, clang++]
|
||||
libc: [glibc, musl]
|
||||
include:
|
||||
- cxx: g++
|
||||
cc: gcc
|
||||
- cxx: clang++
|
||||
cc: clang
|
||||
- libc: glibc
|
||||
shell: bash
|
||||
- libc: musl
|
||||
shell: alpine.sh {0}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: ${{ matrix.shell }}
|
||||
|
||||
steps:
|
||||
- name: Set up Ubuntu
|
||||
if: matrix.libc == 'glibc'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y autopoint pkgconf gettext libcamera-dev libopencv-dev libavcodec-dev libavdevice-dev libavformat-dev libavutil-dev libswscale-dev libwebp-dev libmicrohttpd-dev libmariadb-dev libasound2-dev libpulse-dev libfftw3-dev
|
||||
|
||||
- name: Set up Alpine
|
||||
if: matrix.libc == 'musl'
|
||||
uses: jirutka/setup-alpine@master
|
||||
with:
|
||||
branch: edge
|
||||
packages: >
|
||||
build-base
|
||||
clang
|
||||
file
|
||||
autoconf
|
||||
automake
|
||||
gettext-dev
|
||||
libtool
|
||||
libzip-dev
|
||||
jpeg-dev
|
||||
v4l-utils-libs
|
||||
libcamera-dev
|
||||
opencv-dev
|
||||
ffmpeg-dev
|
||||
libmicrohttpd-dev
|
||||
sqlite-dev
|
||||
mariadb-dev
|
||||
alsa-lib-dev
|
||||
pulseaudio-dev
|
||||
fftw-dev
|
||||
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@main
|
||||
|
||||
- name: Configure build
|
||||
run: |
|
||||
autoreconf -fiv
|
||||
./configure CC=${{ matrix.cc }} CXX=${{ matrix.cxx }}
|
||||
|
||||
- name: Build target
|
||||
run: |
|
||||
${{ matrix.CXX }} --version
|
||||
make -j $(($(nproc)+1))
|
||||
|
||||
- name: Run artifact
|
||||
run: |
|
||||
file ./src/motion
|
||||
./src/motion -h || true
|
||||
+17
@@ -3,9 +3,15 @@ Makefile.in
|
||||
ABOUT-NLS
|
||||
compile
|
||||
config.guess
|
||||
<<<<<<< HEAD
|
||||
config.h
|
||||
config.h.in
|
||||
config.h.in~
|
||||
=======
|
||||
config.hpp
|
||||
config.hpp.in
|
||||
config.hpp.in~
|
||||
>>>>>>> 5.0
|
||||
config.log
|
||||
config.rpath
|
||||
config.status
|
||||
@@ -20,12 +26,20 @@ missing
|
||||
stamp-h1
|
||||
|
||||
#data
|
||||
<<<<<<< HEAD
|
||||
data/motion.service
|
||||
=======
|
||||
data/motion-dist.service
|
||||
>>>>>>> 5.0
|
||||
data/motion-dist.conf
|
||||
data/camera1-dist.conf
|
||||
data/camera2-dist.conf
|
||||
data/camera3-dist.conf
|
||||
<<<<<<< HEAD
|
||||
data/camera4-dist.conf
|
||||
=======
|
||||
data/sound1-dist.conf
|
||||
>>>>>>> 5.0
|
||||
|
||||
#src
|
||||
src/*.o
|
||||
@@ -35,9 +49,12 @@ src/Makefile.in
|
||||
src/.deps/
|
||||
src/Makefile
|
||||
src/Makefile.in
|
||||
<<<<<<< HEAD
|
||||
src/raspicam/*.o
|
||||
src/raspicam/.dirstamp
|
||||
src/raspicam/.deps/
|
||||
=======
|
||||
>>>>>>> 5.0
|
||||
*.log
|
||||
.depend
|
||||
|
||||
|
||||
+6
-50
@@ -1,58 +1,14 @@
|
||||
# How to contribute
|
||||
|
||||
Issues on the github site are intended to discuss code problems, crashes and application enhancements. If you are having an issue with the setup,
|
||||
configuration or use of Motion, we have the following additional resources which are better suited to meet these needs.
|
||||
Issues on the github site are intended to discuss code problems, crashes and application enhancements. The discussions is intended for questions after you have read the guide.
|
||||
|
||||
<<<<<<< HEAD
|
||||
* User guide: [Motion User Guide](https://motion-project.github.io/motion_guide.html)
|
||||
* User Group List: Please sign-up and send your issue to the list [Motion User](https://lists.sourceforge.net/lists/listinfo/motion-user)
|
||||
* IRC: [#motion](ircs://irc.libera.chat:6697/motion) on Libera Chat
|
||||
=======
|
||||
## Questions submitted as issues
|
||||
>>>>>>> 5.0
|
||||
|
||||
It is very important to use these resources for non-code issues since it engages a much wider audience who may have experience resolving
|
||||
the particular issue you are trying to resolve.
|
||||
Questions that are submitted as a github issue will be transferred to the discussions section.
|
||||
|
||||
## Submitting Problems
|
||||
|
||||
Before submitting a issue, please make sure that you are using either the latest release as posted
|
||||
[here](https://github.com/Motion-Project/motion/releases) or that you have built the latest source code
|
||||
from the github master branch.
|
||||
|
||||
If the issue still remains with the current version, please validate that the issue has not already been reported
|
||||
by searching through the issue log.
|
||||
|
||||
Next, we must be provided the following in order to replicate and ultimately resolve the issue:
|
||||
|
||||
* A complete Motion log for a single run from startup to shutdown at the INF/7 log level.
|
||||
* The expected versus actual result
|
||||
|
||||
The preferred method of providing the log file is by posting it on [gist](https://gist.github.com/). Only provide
|
||||
the link to the gist file within the issue. The full configuration will be printed out to the log at the INF/7 level
|
||||
with the most common, sensitive information (URLs, usernames/passwords, etc) masked. It is recommended that you
|
||||
double check before posting the log file.
|
||||
For more information please read [privacy wiki article](https://github.com/Motion-Project/motion/wiki/Privacy)
|
||||
|
||||
Note that the developers do not use any front-end application to use Motion and we need the actual logs from the Motion
|
||||
application rather than logs from the front-end application.
|
||||
|
||||
|
||||
## Submitting an Enhancement Request
|
||||
|
||||
Motion has a extremely large number of configuration options. With so many options, it is important to include a description
|
||||
of how/why the enhancement will be used. It is possible that the existing options can be configured to address the need.
|
||||
(Which could then lead to a different enhancement than originally contemplated of making those options easier to use or documented
|
||||
better.)
|
||||
|
||||
|
||||
## Submitting changes
|
||||
|
||||
Generally, it is best to first submit a issue on the particular enhancement prior to a pull request. This allows the particular
|
||||
item to be discussed and determine how it would fit into the application.
|
||||
|
||||
As pull requests are prepared, in addition to the actual code, please also consider:
|
||||
|
||||
* Changes needed to the Motion_Guide.html which is our user guide.
|
||||
* Changes to the motion.1 file which is the manual
|
||||
* Changes to the configuration templates of motion.conf, camera1.conf, etc.
|
||||
|
||||
|
||||
Thanks,
|
||||
Motion-Project Team.
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
<<<<<<< HEAD
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
=======
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
>>>>>>> 5.0
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
<<<<<<< HEAD
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
@@ -16,11 +23,24 @@ General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
=======
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
>>>>>>> 5.0
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
<<<<<<< HEAD
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
@@ -52,10 +72,55 @@ patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
=======
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
>>>>>>> 5.0
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
<<<<<<< HEAD
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
@@ -276,6 +341,557 @@ TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
=======
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
>>>>>>> 5.0
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
@@ -287,15 +903,25 @@ free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
<<<<<<< HEAD
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
=======
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
>>>>>>> 5.0
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
<<<<<<< HEAD
|
||||
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
|
||||
=======
|
||||
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 3 of the License, or
|
||||
>>>>>>> 5.0
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
@@ -303,6 +929,7 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
<<<<<<< HEAD
|
||||
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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
@@ -314,10 +941,23 @@ when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
=======
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
>>>>>>> 5.0
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
<<<<<<< HEAD
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
@@ -337,3 +977,19 @@ proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
=======
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
>>>>>>> 5.0
|
||||
|
||||
+96
@@ -1,18 +1,51 @@
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
#/*
|
||||
# * This file is part of Motion.
|
||||
# *
|
||||
# * Motion 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 3 of the License, or
|
||||
# * (at your option) any later version.
|
||||
# *
|
||||
# * Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
# *
|
||||
# */
|
||||
|
||||
|
||||
>>>>>>> 5.0
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
SUBDIRS = src po
|
||||
|
||||
pkgsysconfdir = $(sysconfdir)/@PACKAGE@
|
||||
<<<<<<< HEAD
|
||||
dist_pkgsysconf_DATA = \
|
||||
=======
|
||||
libstatedir = @localstatedir@/lib/@PACKAGE@
|
||||
|
||||
dist_libstate_DATA = \
|
||||
>>>>>>> 5.0
|
||||
data/motion-dist.conf \
|
||||
data/camera1-dist.conf \
|
||||
data/camera2-dist.conf \
|
||||
data/camera3-dist.conf \
|
||||
<<<<<<< HEAD
|
||||
data/camera4-dist.conf
|
||||
=======
|
||||
data/sound1-dist.conf
|
||||
>>>>>>> 5.0
|
||||
|
||||
dist_man_MANS = man/motion.1
|
||||
|
||||
dist_doc_DATA = \
|
||||
<<<<<<< HEAD
|
||||
doc/mask1.png \
|
||||
doc/normal.jpg \
|
||||
doc/outputmotion1.jpg \
|
||||
@@ -20,20 +53,39 @@ dist_doc_DATA = \
|
||||
doc/motion_guide.html \
|
||||
doc/motion_stylesheet.css \
|
||||
doc/CREDITS \
|
||||
=======
|
||||
doc/motion_guide.html \
|
||||
doc/motion_stylesheet.css \
|
||||
>>>>>>> 5.0
|
||||
doc/motion_build.html \
|
||||
doc/motion_config.html
|
||||
|
||||
###################################################################
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
## Clean tilde crumbs and add prefix in config file.
|
||||
###################################################################
|
||||
all-local:
|
||||
@rm -f po/*.po\~
|
||||
@sed -e 's|$${prefix}|$(prefix)|' data/motion-dist.conf > data/motion-dist.conf.tmp && mv -f data/motion-dist.conf.tmp data/motion-dist.conf
|
||||
|
||||
###################################################################
|
||||
>>>>>>> 5.0
|
||||
## Create pristine directories to match exactly distributed files
|
||||
###################################################################
|
||||
cleanall: distclean
|
||||
@rm -rf autom4te.cache m4
|
||||
<<<<<<< HEAD
|
||||
@rm -f config.h.in config.h.in~ aclocal.m4 config.sub ABOUT-NLS missing
|
||||
=======
|
||||
@rm -f config.hpp.in config.hpp.in~ aclocal.m4 config.sub ABOUT-NLS missing
|
||||
>>>>>>> 5.0
|
||||
@rm -f compile config.guess config.rpath configure depcomp install-sh
|
||||
@rm -f po/en@boldquot.header po/en@quot.header po/insert-header.sin
|
||||
@rm -f po/Makevars.template po/quot.sed po/remove-potcdate.sin
|
||||
@rm -f po/Rules-quot po/stamp-po po/*.gmo po/motion.pot po/boldquot.sed
|
||||
@rm -f Makefile.in src/Makefile.in po/Makefile.in.in man/Makefile.in
|
||||
<<<<<<< HEAD
|
||||
@rm -f data/motion.service data/motion-dist.conf
|
||||
@rm -f data/camera1-dist.conf data/camera2-dist.conf
|
||||
@rm -f data/camera3-dist.conf data/camera4-dist.conf
|
||||
@@ -58,9 +110,53 @@ maintainer-check:
|
||||
--without-mysql \
|
||||
--without-mariadb \
|
||||
&& $(MAKE) clean && $(MAKE)
|
||||
=======
|
||||
@rm -f data/motion-dist.service data/motion-dist.conf
|
||||
@rm -f data/camera1-dist.conf data/camera2-dist.conf
|
||||
@rm -f data/camera3-dist.conf data/sound1-dist.conf
|
||||
|
||||
###################################################################
|
||||
## Testing options for maintainer
|
||||
###################################################################
|
||||
maintainer-clang:
|
||||
./configure --with-clang-flags CC=clang CXX=clang++ LD=clang++ && $(MAKE) clean && $(MAKE)
|
||||
|
||||
maintainer-check:
|
||||
./configure --with-developer-flags && $(MAKE) clean && $(MAKE) -j6
|
||||
./configure --with-developer-flags --without-libcam && $(MAKE) clean && $(MAKE) -j6
|
||||
./configure --with-developer-flags --without-opencv && $(MAKE) clean && $(MAKE) -j6
|
||||
./configure --with-developer-flags --without-mariadb && $(MAKE) clean && $(MAKE) -j6
|
||||
./configure --with-developer-flags --without-mysql && $(MAKE) clean && $(MAKE) -j6
|
||||
./configure --with-developer-flags --without-mariadb && $(MAKE) clean && $(MAKE) -j6
|
||||
./configure --with-developer-flags --without-sqlite3 && $(MAKE) clean && $(MAKE) -j6
|
||||
./configure --with-developer-flags --without-pgsql && $(MAKE) clean && $(MAKE) -j6
|
||||
./configure --with-developer-flags --without-v4l2 && $(MAKE) clean && $(MAKE) -j6
|
||||
./configure --with-developer-flags --without-webp && $(MAKE) clean && $(MAKE) -j6
|
||||
./configure --with-developer-flags --without-alsa && $(MAKE) clean && $(MAKE) -j6
|
||||
./configure --with-developer-flags --without-pulse && $(MAKE) clean && $(MAKE) -j6
|
||||
./configure --with-developer-flags --without-fftw3 && $(MAKE) clean && $(MAKE) -j6
|
||||
./configure --with-developer-flags \
|
||||
--without-mysql \
|
||||
--without-mariadb \
|
||||
&& $(MAKE) clean && $(MAKE) -j6
|
||||
>>>>>>> 5.0
|
||||
./configure --with-developer-flags \
|
||||
--without-mysql \
|
||||
--without-mariadb \
|
||||
--without-sqlite3 \
|
||||
--without-pgsql \
|
||||
<<<<<<< HEAD
|
||||
&& $(MAKE) clean && $(MAKE)
|
||||
=======
|
||||
&& $(MAKE) clean && $(MAKE) -j6
|
||||
./configure --with-developer-flags \
|
||||
--without-alsa \
|
||||
--without-pulse \
|
||||
&& $(MAKE) clean && $(MAKE) -j6
|
||||
./configure --with-developer-flags \
|
||||
--without-alsa \
|
||||
--without-pulse \
|
||||
--without-fftw3 \
|
||||
&& $(MAKE) clean && $(MAKE) -j6
|
||||
|
||||
>>>>>>> 5.0
|
||||
|
||||
@@ -3,37 +3,36 @@ Motion
|
||||
|
||||
## Description
|
||||
|
||||
Motion is a program that monitors the video signal from one or more cameras and
|
||||
is able to detect if a significant part of the picture has changed. Or in other
|
||||
words, it can detect motion.
|
||||
Motion is a program that monitors the signal from video cameras
|
||||
and detects changes in the images. Version 5.0 and later versions
|
||||
remove some of the outdated processes, cleans up the code base and
|
||||
introduces new functionality.
|
||||
|
||||
## Documentation
|
||||
|
||||
The documentation for Motion is contained within the file motion_guide.html.
|
||||
|
||||
The offline version of this file is available in the **doc/motion** directory. The
|
||||
online version of the motion_guide.html file can be viewed [here](https://motion-project.github.io/motion_guide.html)
|
||||
|
||||
In addition to the detailed building instructions included within the guide, the
|
||||
INSTALL file contains abbreviated building instructions.
|
||||
|
||||
## Resources
|
||||
|
||||
Please join the mailing list [here](https://lists.sourceforge.net/lists/listinfo/motion-user)
|
||||
|
||||
We prefer support through the mailing list because more people will have the benefit from the answers.
|
||||
A archive of mailing list discussions can be viewed [here](https://sourceforge.net/p/motion/mailman/motion-user/)
|
||||
The following are some of the things that are different from earlier
|
||||
version of Motion (versions 4.7 and lower).
|
||||
- Secondary detection method via OpenCV
|
||||
- HOG (Histogram of Oriented Gradients)
|
||||
- Haar cascade classifiers
|
||||
- Deep neural networks(Caffe, TensorFlow, etc.)
|
||||
- Direct Pi camera support and ability to change camera parameters
|
||||
- Sound frequency detection
|
||||
- Additional primary detection parameters
|
||||
- Sound recording from network camera sources
|
||||
- ROI pictures for output or secondary detection
|
||||
- Enhanced web contorl
|
||||
- Single port for all camera video streams and controls
|
||||
- Consolidated stream(a single image) showing all cameras
|
||||
- List/download movies
|
||||
- Add/delete cameras
|
||||
- Live view of the Motion log output
|
||||
- Video streams via MPEGTS format
|
||||
- Change/update configuration parameters
|
||||
- Permits a user created web page
|
||||
- JSON status/configuration pages
|
||||
- POST web control processing
|
||||
|
||||
## License
|
||||
|
||||
Motion is mainly distributed under the GNU GENERAL PUBLIC LICENSE (GPL) version 2 or later.
|
||||
See the copyright file for a list of all the licensing terms of the various components of Motion.
|
||||
Motion version 5.0 and later is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) version 3 or later.
|
||||
|
||||
The file CREDITS lists the many people who have contributed to Motion over the years.
|
||||
|
||||
## Contributing
|
||||
|
||||
Issues and Patches should be submitted via github and include detail descriptions
|
||||
of the issue being addressed as well as any documentation updates that would be
|
||||
needed with the change.
|
||||
|
||||
|
||||
+559
-5
@@ -1,9 +1,15 @@
|
||||
AC_INIT(motion, esyscmd(['./scripts/version.sh']))
|
||||
AM_INIT_AUTOMAKE([subdir-objects foreign])
|
||||
<<<<<<< HEAD
|
||||
AM_MAINTAINER_MODE([enable])
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_GNU_SOURCE
|
||||
=======
|
||||
CXXFLAGS="$CXXFLAGS -std=c++17"
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
>>>>>>> 5.0
|
||||
AC_CONFIG_HEADERS([config.hpp])
|
||||
AC_CONFIG_SRCDIR([src/motion.cpp])
|
||||
AC_CANONICAL_HOST
|
||||
@@ -25,11 +31,19 @@ AC_CHECK_HEADERS(stdio.h stdlib.h sys/time.h sys/wait.h \
|
||||
)
|
||||
|
||||
##############################################################################
|
||||
<<<<<<< HEAD
|
||||
### Check pkg-config - Required. Needed to get lib paths/info
|
||||
##############################################################################
|
||||
AC_CHECK_PROG([PKGCONFIG],[pkg-config],[yes],[no])
|
||||
AS_IF([test "${PKGCONFIG}" = "no" ],[
|
||||
AC_MSG_ERROR([Required package 'pkg-config' not found, please check motion_guide.html and install necessary dependencies.])
|
||||
=======
|
||||
### Check pkgconf - Required. Needed to get lib paths/info
|
||||
##############################################################################
|
||||
AC_CHECK_PROG([PKGCONFIG],[pkgconf],[yes],[no])
|
||||
AS_IF([test "${PKGCONFIG}" = "no" ],[
|
||||
AC_MSG_ERROR([Required package 'pkgconf' not found, please check motion_guide.html and install necessary dependencies.])
|
||||
>>>>>>> 5.0
|
||||
]
|
||||
)
|
||||
|
||||
@@ -37,21 +51,36 @@ AS_IF([test "${PKGCONFIG}" = "no" ],[
|
||||
### Check pthread
|
||||
##############################################################################
|
||||
AC_CHECK_HEADERS(pthread.h,,AC_MSG_ERROR([pthread is required.]))
|
||||
<<<<<<< HEAD
|
||||
TEMP_CFLAGS="-x c -D_THREAD_SAFE"
|
||||
=======
|
||||
CPPFLAGS="${CPPFLAGS} -D_THREAD_SAFE "
|
||||
>>>>>>> 5.0
|
||||
LIBS="$LIBS -pthread "
|
||||
|
||||
##############################################################################
|
||||
### Check JPG - Required. Needed for image processing
|
||||
##############################################################################
|
||||
<<<<<<< HEAD
|
||||
AS_IF([pkg-config libjpeg ], [
|
||||
TEMP_CFLAGS="$TEMP_CFLAGS "`pkg-config --cflags libjpeg`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkg-config --libs libjpeg`
|
||||
=======
|
||||
AS_IF([pkgconf libjpeg ], [
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS "`pkgconf --cflags libjpeg`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkgconf --libs libjpeg`
|
||||
>>>>>>> 5.0
|
||||
],[
|
||||
TEMP_LIBS="$TEMP_LIBS -ljpeg"
|
||||
]
|
||||
)
|
||||
<<<<<<< HEAD
|
||||
HOLD_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $TEMP_CFLAGS"
|
||||
=======
|
||||
HOLD_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $TEMP_CPPFLAGS"
|
||||
>>>>>>> 5.0
|
||||
AC_CHECK_HEADERS(setjmp.h jerror.h jpeglib.h,[JPGS="yes"],[JPGS="no"])
|
||||
AC_MSG_CHECKING(jpg libraries)
|
||||
AC_MSG_RESULT($JPGS)
|
||||
@@ -59,20 +88,35 @@ AS_IF([test "${JPGS}" != "yes" ], [
|
||||
AC_MSG_ERROR([Required jpeg headers not found, please check motion_guide.html and install necessary dependencies])
|
||||
]
|
||||
)
|
||||
<<<<<<< HEAD
|
||||
CFLAGS="$HOLD_CFLAGS"
|
||||
=======
|
||||
CPPFLAGS="$HOLD_CPPFLAGS"
|
||||
>>>>>>> 5.0
|
||||
|
||||
##############################################################################
|
||||
### Check libmicrohttpd - Required. Needed for stream/webcontrol
|
||||
##############################################################################
|
||||
<<<<<<< HEAD
|
||||
AS_IF([pkg-config libmicrohttpd ], [
|
||||
TEMP_CFLAGS="$TEMP_CFLAGS "`pkg-config --cflags libmicrohttpd`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkg-config --libs libmicrohttpd`
|
||||
=======
|
||||
AS_IF([pkgconf libmicrohttpd ], [
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS "`pkgconf --cflags libmicrohttpd`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkgconf --libs libmicrohttpd`
|
||||
>>>>>>> 5.0
|
||||
],[
|
||||
AC_MSG_ERROR([Required package libmicrohttpd-dev not found, please check motion_guide.html and install necessary dependencies])
|
||||
]
|
||||
)
|
||||
<<<<<<< HEAD
|
||||
HOLD_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $TEMP_CFLAGS"
|
||||
=======
|
||||
HOLD_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $TEMP_CPPFLAGS"
|
||||
>>>>>>> 5.0
|
||||
AC_CHECK_HEADERS(microhttpd.h,[MHTTP="yes"],[MHTTP="no"])
|
||||
AC_MSG_CHECKING(libmicrohttpd libraries)
|
||||
AC_MSG_RESULT($MHTTP)
|
||||
@@ -80,7 +124,32 @@ AS_IF([test "${MHTTP}" != "yes" ], [
|
||||
AC_MSG_ERROR([Required package libmicrohttpd-dev not found, please check motion_guide.html and install necessary dependencies])
|
||||
]
|
||||
)
|
||||
<<<<<<< HEAD
|
||||
CFLAGS="$HOLD_CFLAGS"
|
||||
=======
|
||||
CPPFLAGS="$HOLD_CPPFLAGS"
|
||||
|
||||
##############################################################################
|
||||
### Check zlib - Required. Needed for stream/webcontrol
|
||||
##############################################################################
|
||||
AS_IF([pkgconf zlib ], [
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS "`pkgconf --cflags zlib`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkgconf --libs zlib`
|
||||
],[
|
||||
AC_MSG_ERROR([Required package zlib not found, please check motion_guide.html and install necessary dependencies])
|
||||
]
|
||||
)
|
||||
HOLD_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $TEMP_CPPFLAGS"
|
||||
AC_CHECK_HEADERS(zlib.h,[ZLIB="yes"],[ZLIB="no"])
|
||||
AC_MSG_CHECKING(zlib libraries)
|
||||
AC_MSG_RESULT($ZLIB)
|
||||
AS_IF([test "${ZLIB}" != "yes" ], [
|
||||
AC_MSG_ERROR([Required package zlib not found, please check motion_guide.html and install necessary dependencies])
|
||||
]
|
||||
)
|
||||
CPPFLAGS="$HOLD_CPPFLAGS"
|
||||
>>>>>>> 5.0
|
||||
|
||||
##############################################################################
|
||||
### Check setting/getting thread names
|
||||
@@ -114,20 +183,28 @@ AC_LINK_IFELSE(
|
||||
)
|
||||
|
||||
##############################################################################
|
||||
<<<<<<< HEAD
|
||||
### Check XSI strerror_r. Check for Linux/*BSD/Apple/MUSL variations
|
||||
=======
|
||||
### Check XSI strerror_r.
|
||||
>>>>>>> 5.0
|
||||
##############################################################################
|
||||
AC_MSG_CHECKING([for XSI strerror_r])
|
||||
HOLD_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Werror"
|
||||
HOLD_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS -Werror"
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_SOURCE[
|
||||
[AC_LANG_SOURCE([[
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
int main(int argc, char** argv) {
|
||||
char buf[1024];
|
||||
int ret = strerror_r(ENOMEM, buf, sizeof(buf));
|
||||
return ret;
|
||||
<<<<<<< HEAD
|
||||
}]
|
||||
=======
|
||||
}]])
|
||||
>>>>>>> 5.0
|
||||
],[
|
||||
AC_DEFINE([XSI_STRERROR_R], [1], [Define if you have XSI strerror_r function.])
|
||||
XSI_STRERROR="yes"
|
||||
@@ -137,6 +214,7 @@ AC_LINK_IFELSE(
|
||||
AC_MSG_RESULT([no])
|
||||
]
|
||||
)
|
||||
<<<<<<< HEAD
|
||||
CFLAGS="$HOLD_CFLAGS"
|
||||
|
||||
###############################################################################
|
||||
@@ -177,6 +255,27 @@ AS_IF([test "${V4L2}" = "yes" ], [
|
||||
]
|
||||
)
|
||||
|
||||
=======
|
||||
CPPFLAGS="$HOLD_CPPFLAGS"
|
||||
|
||||
###############################################################################
|
||||
### V4L2 Video System - Optional
|
||||
###############################################################################
|
||||
AC_ARG_WITH(v4l2,
|
||||
AS_HELP_STRING([--without-v4l2],[Disable V4L2 devices]),
|
||||
[V4L2="$withval"],
|
||||
[V4L2="yes"]
|
||||
)
|
||||
AS_IF([test "${V4L2}" = "yes" ], [
|
||||
AC_CHECK_HEADERS(linux/videodev2.h sys/videoio.h,[V4L2="yes";break],[V4L2="no"])
|
||||
AS_IF([test "${V4L2}" = "yes" ], [
|
||||
AC_DEFINE([HAVE_V4L2], [1], [Define to 1 if V4L2 is around])
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
>>>>>>> 5.0
|
||||
##############################################################################
|
||||
### Webp Image Format - Optional.
|
||||
##############################################################################
|
||||
@@ -184,6 +283,7 @@ AC_ARG_WITH([webp],
|
||||
AS_HELP_STRING([--with-webp],[Compile with Webp image support]),
|
||||
[WEBP="$withval"],
|
||||
[WEBP="yes]"
|
||||
<<<<<<< HEAD
|
||||
)
|
||||
|
||||
AS_IF([test "${WEBP}" = "yes" ], [
|
||||
@@ -197,11 +297,73 @@ AS_IF([test "${WEBP}" = "yes" ], [
|
||||
AC_MSG_RESULT(no)
|
||||
]
|
||||
)
|
||||
=======
|
||||
)
|
||||
WEBP_VER=""
|
||||
AS_IF([test "${WEBP}" = "yes" ], [
|
||||
AC_MSG_CHECKING(for webp)
|
||||
AS_IF([pkgconf libwebpmux ], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([HAVE_WEBP], [1], [Define to 1 if WEBP is around])
|
||||
WEBP_VER="("`pkgconf --modversion libwebp`")"
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS "`pkgconf --cflags libwebpmux libwebp`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkgconf --libs libwebpmux libwebp`
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
##############################################################################
|
||||
### libcamera - Optional.
|
||||
##############################################################################
|
||||
AC_ARG_WITH([libcam],
|
||||
AS_HELP_STRING([--with-libcam[=DIR]],[Compile with libcamera support]),
|
||||
[LIBCAM="$withval"],
|
||||
[LIBCAM="yes"]
|
||||
)
|
||||
LIBCAM_VER=""
|
||||
AS_IF([test "${LIBCAM}" = "no"], [
|
||||
AC_MSG_CHECKING(for LIBCAM)
|
||||
AC_MSG_RESULT(skipped)
|
||||
],[
|
||||
AC_MSG_CHECKING(LIBCAM pkgconf path)
|
||||
TEMP_PATH=$PKG_CONFIG_PATH
|
||||
AS_IF([test "${LIBCAM}" != "yes"], [
|
||||
PKG_CONFIG_PATH=${LIBCAM}/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
LIBCAM="yes"
|
||||
],[
|
||||
PKG_CONFIG_PATH=.:/usr/lib/pkgconfig
|
||||
]
|
||||
)
|
||||
export PKG_CONFIG_PATH
|
||||
AC_MSG_RESULT($PKG_CONFIG_PATH)
|
||||
|
||||
AC_MSG_CHECKING(for LIBCAM)
|
||||
AS_IF([pkgconf libcamera], [
|
||||
LIBCAM_VER="("`pkgconf --modversion libcamera`")"
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS "`pkgconf --cflags libcamera`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkgconf --libs libcamera`
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE([HAVE_LIBCAM], [1], [Define to 1 if LIBCAM is around])
|
||||
],[
|
||||
AC_MSG_RESULT([no])
|
||||
LIBCAM="no"
|
||||
]
|
||||
)
|
||||
PKG_CONFIG_PATH=$TEMP_PATH
|
||||
export PKG_CONFIG_PATH
|
||||
>>>>>>> 5.0
|
||||
]
|
||||
)
|
||||
|
||||
##############################################################################
|
||||
<<<<<<< HEAD
|
||||
### Check for ffmpeg - Optional.
|
||||
=======
|
||||
### Check for ffmpeg
|
||||
>>>>>>> 5.0
|
||||
##############################################################################
|
||||
FFMPEG_VER="--"
|
||||
AC_ARG_WITH([ffmpeg],
|
||||
@@ -209,6 +371,7 @@ AC_ARG_WITH([ffmpeg],
|
||||
[FFMPEG=$withval],
|
||||
[FFMPEG="yes"]
|
||||
)
|
||||
<<<<<<< HEAD
|
||||
|
||||
AS_IF([test "${FFMPEG}" = "no"], [
|
||||
AC_MSG_CHECKING(for FFmpeg)
|
||||
@@ -219,11 +382,64 @@ AS_IF([test "${FFMPEG}" = "no"], [
|
||||
AS_IF([test "${FFMPEG}" != "yes"], [
|
||||
PKG_CONFIG_PATH=${FFMPEG}/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
FFMPEG="yes"
|
||||
=======
|
||||
FFMPEG_VER=""
|
||||
AS_IF([test "${FFMPEG}" = "no"], [
|
||||
AC_MSG_CHECKING(for FFmpeg)
|
||||
AC_MSG_ERROR([Package ffmpeg is required.])
|
||||
],[
|
||||
AC_MSG_CHECKING(FFmpeg pkgconf path)
|
||||
TEMP_PATH=$PKG_CONFIG_PATH
|
||||
AS_IF([test "${FFMPEG}" != "yes"], [
|
||||
PKG_CONFIG_PATH=${FFMPEG}/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
FFMPEG="yes"
|
||||
]
|
||||
)
|
||||
export PKG_CONFIG_PATH
|
||||
AC_MSG_RESULT($PKG_CONFIG_PATH)
|
||||
|
||||
FFMPEG_DEPS="libavutil libavformat libavcodec libswscale libavdevice"
|
||||
AC_MSG_CHECKING(for FFmpeg)
|
||||
AS_IF([pkgconf $FFMPEG_DEPS], [
|
||||
FFMPEG_VER="("`pkgconf --modversion libavformat`")"
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS "`pkgconf --cflags $FFMPEG_DEPS`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkgconf --libs $FFMPEG_DEPS`
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([Required ffmpeg packages 'libavutil-dev libavformat-dev libavcodec-dev libswscale-dev libavdevice-dev' were not found. Please check motion_guide.html and install necessary dependencies])
|
||||
]
|
||||
)
|
||||
PKG_CONFIG_PATH=$TEMP_PATH
|
||||
export PKG_CONFIG_PATH
|
||||
]
|
||||
)
|
||||
##############################################################################
|
||||
### OpenCV support
|
||||
##############################################################################
|
||||
OPENCV_VER="--"
|
||||
AC_ARG_WITH([opencv],
|
||||
AS_HELP_STRING([--with-opencv[=DIR]],[Build with OpenCV support]),
|
||||
[OPENCV=$withval],
|
||||
[OPENCV="yes"]
|
||||
)
|
||||
OPENCV_VER=""
|
||||
AS_IF([test "${OPENCV}" = "no"], [
|
||||
AC_MSG_CHECKING(for OpenCV support)
|
||||
AC_MSG_RESULT(skipped)
|
||||
],[
|
||||
TEMP_PATH=$PKG_CONFIG_PATH
|
||||
AC_MSG_CHECKING(OpenCV pkgconf path)
|
||||
AS_IF([test "${OPENCV}" != "yes"], [
|
||||
PKG_CONFIG_PATH=${OPENCV}/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
OPENCV="yes"
|
||||
>>>>>>> 5.0
|
||||
]
|
||||
)
|
||||
export PKG_CONFIG_PATH
|
||||
AC_MSG_RESULT($PKG_CONFIG_PATH)
|
||||
|
||||
<<<<<<< HEAD
|
||||
FFMPEG_DEPS="libavutil libavformat libavcodec libswscale libavdevice"
|
||||
AC_MSG_CHECKING(for FFmpeg)
|
||||
AS_IF([pkg-config $FFMPEG_DEPS], [
|
||||
@@ -237,6 +453,28 @@ AS_IF([test "${FFMPEG}" = "no"], [
|
||||
AC_MSG_ERROR([Required ffmpeg packages 'libavutil-dev libavformat-dev libavcodec-dev libswscale-dev libavdevice-dev' were not found. Please check motion_guide.html and install necessary dependencies or use the '--without-ffmpeg' configuration option.])
|
||||
]
|
||||
)
|
||||
=======
|
||||
AC_MSG_CHECKING(for OpenCV)
|
||||
AS_IF([pkgconf opencv], [
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS "`pkgconf --cflags opencv`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkgconf --libs opencv`
|
||||
OPENCV_VER="("`pkgconf --modversion opencv`")"
|
||||
AC_DEFINE([HAVE_OPENCV], [1], [Define to 1 if OpenCV is around])
|
||||
],[
|
||||
AS_IF([pkgconf opencv4], [
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS "`pkgconf --cflags opencv4`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkgconf --libs opencv4`
|
||||
OPENCV_VER="("`pkgconf --modversion opencv4`")"
|
||||
AC_DEFINE([HAVE_OPENCV], [1], [Define to 1 if OpenCV is around])
|
||||
],[
|
||||
OPENCV="no"
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
AC_MSG_RESULT([$OPENCV])
|
||||
>>>>>>> 5.0
|
||||
PKG_CONFIG_PATH=$TEMP_PATH
|
||||
export PKG_CONFIG_PATH
|
||||
]
|
||||
@@ -250,13 +488,21 @@ AC_ARG_WITH(mariadb,
|
||||
[MARIADB="$withval"],
|
||||
[MARIADB="yes"]
|
||||
)
|
||||
<<<<<<< HEAD
|
||||
|
||||
=======
|
||||
MARIADB_VER=""
|
||||
>>>>>>> 5.0
|
||||
AS_IF([test "${MARIADB}" = "no"], [
|
||||
AC_MSG_CHECKING(for MariaDB)
|
||||
AC_MSG_RESULT(skipped)
|
||||
],[
|
||||
TEMP_PATH=$PKG_CONFIG_PATH
|
||||
<<<<<<< HEAD
|
||||
AC_MSG_CHECKING(MariaDB pkg-config path)
|
||||
=======
|
||||
AC_MSG_CHECKING(MariaDB pkgconf path)
|
||||
>>>>>>> 5.0
|
||||
AS_IF([test "${MARIADB}" != "yes"], [
|
||||
PKG_CONFIG_PATH=${MARIADB}/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
MARIADB="yes"
|
||||
@@ -266,9 +512,16 @@ AS_IF([test "${MARIADB}" = "no"], [
|
||||
AC_MSG_RESULT($PKG_CONFIG_PATH)
|
||||
|
||||
AC_MSG_CHECKING(for MariaDB)
|
||||
<<<<<<< HEAD
|
||||
AS_IF([pkg-config libmariadb], [
|
||||
TEMP_CFLAGS="$TEMP_CFLAGS "`pkg-config --cflags libmariadb`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkg-config --libs libmariadb`
|
||||
=======
|
||||
AS_IF([pkgconf libmariadb], [
|
||||
MARIADB_VER="("`pkgconf --modversion libmariadb`")"
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS "`pkgconf --cflags libmariadb`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkgconf --libs libmariadb`
|
||||
>>>>>>> 5.0
|
||||
AC_DEFINE([HAVE_MARIADB], [1], [Define to 1 if you have MariaDB support])
|
||||
],[
|
||||
MARIADB="no"
|
||||
@@ -276,9 +529,15 @@ AS_IF([test "${MARIADB}" = "no"], [
|
||||
)
|
||||
# Check for the old pkg name for MariaDB
|
||||
AS_IF([test "${MARIADB}" = "no"], [
|
||||
<<<<<<< HEAD
|
||||
AS_IF([pkg-config mariadb], [
|
||||
TEMP_CFLAGS="$TEMP_CFLAGS "`pkg-config --cflags mariadb`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkg-config --libs mariadb`
|
||||
=======
|
||||
AS_IF([pkgconf mariadb], [
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS "`pkgconf --cflags mariadb`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkgconf --libs mariadb`
|
||||
>>>>>>> 5.0
|
||||
MARIADB="yes"
|
||||
AC_DEFINE([HAVE_MARIADB], [1], [Define to 1 if you have MariaDB support])
|
||||
])
|
||||
@@ -292,6 +551,7 @@ AS_IF([test "${MARIADB}" = "no"], [
|
||||
|
||||
##############################################################################
|
||||
### Check for MySQL - Optional
|
||||
<<<<<<< HEAD
|
||||
##############################################################################
|
||||
AC_ARG_WITH(mysql,
|
||||
AS_HELP_STRING([--with-mysql[=DIR]],[Build with MySQL support]),
|
||||
@@ -386,12 +646,89 @@ AS_IF([test "${SQLITE3}" = "no"], [
|
||||
SQLITE3="no"
|
||||
]
|
||||
)
|
||||
=======
|
||||
##############################################################################
|
||||
AC_ARG_WITH(mysql,
|
||||
AS_HELP_STRING([--with-mysql[=DIR]],[Build with MySQL support]),
|
||||
[MYSQLDB="$withval"],
|
||||
[MYSQLDB="yes"]
|
||||
)
|
||||
MYSQLDB_VER=""
|
||||
AS_IF([test "${MYSQLDB}" = "no"], [
|
||||
AC_MSG_CHECKING(for MySQL)
|
||||
AC_MSG_RESULT(skipped)
|
||||
],[
|
||||
TEMP_PATH=$PKG_CONFIG_PATH
|
||||
AC_MSG_CHECKING(MySQL pkgconf path)
|
||||
AS_IF([test "${MYSQLDB}" != "yes"], [
|
||||
PKG_CONFIG_PATH=${MYSQLDB}/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
MYSQLDB="yes"
|
||||
]
|
||||
)
|
||||
export PKG_CONFIG_PATH
|
||||
AC_MSG_RESULT($PKG_CONFIG_PATH)
|
||||
|
||||
AC_MSG_CHECKING(for MySQL)
|
||||
AS_IF([pkgconf mysqlclient], [
|
||||
MYSQLDB_VER="("`pkgconf --modversion mysqlclient`")"
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS "`pkgconf --cflags mysqlclient`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkgconf --libs mysqlclient`
|
||||
AC_DEFINE([HAVE_MARIADB], [1], [Define to 1 if you have MySQLDB/MariaDB support])
|
||||
MYSQLDB="yes"
|
||||
],[
|
||||
MYSQLDB="no"
|
||||
]
|
||||
)
|
||||
AC_MSG_RESULT([$MYSQLDB])
|
||||
PKG_CONFIG_PATH=$TEMP_PATH
|
||||
export PKG_CONFIG_PATH
|
||||
]
|
||||
)
|
||||
|
||||
##############################################################################
|
||||
### Optimize compiler
|
||||
### Check for PostgreSQL - Optional
|
||||
##############################################################################
|
||||
AC_ARG_WITH(pgsql,
|
||||
AS_HELP_STRING([--with-pgsql[=DIR]],[Build with PostgreSQL support]),
|
||||
[PGSQLDB="$withval"],
|
||||
[PGSQLDB="yes"]
|
||||
)
|
||||
PGSQLDB_VER=""
|
||||
AS_IF([test "${PGSQLDB}" = "no"], [
|
||||
AC_MSG_CHECKING(for PostgreSQL)
|
||||
AC_MSG_RESULT(skipped)
|
||||
],[
|
||||
TEMP_PATH=$PKG_CONFIG_PATH
|
||||
AC_MSG_CHECKING(PostgreSQL pkgconf path)
|
||||
AS_IF([test "${PGSQLDB}" != "yes"], [
|
||||
PKG_CONFIG_PATH=${PGSQLDB}/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
PGSQLDB="yes"
|
||||
]
|
||||
)
|
||||
export PKG_CONFIG_PATH
|
||||
AC_MSG_RESULT($PKG_CONFIG_PATH)
|
||||
|
||||
AC_MSG_CHECKING(for PostgreSQL)
|
||||
AS_IF([pkgconf libpq], [
|
||||
PGSQLDB_VER="("`pkgconf --modversion libpq`")"
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS "`pkgconf --cflags libpq`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkgconf --libs libpq`
|
||||
AC_DEFINE([HAVE_PGSQLDB], [1], [Define to 1 if you have PostgreSQL support])
|
||||
],[
|
||||
PGSQLDB="no"
|
||||
]
|
||||
)
|
||||
AC_MSG_RESULT([$PGSQLDB])
|
||||
PKG_CONFIG_PATH=$TEMP_PATH
|
||||
export PKG_CONFIG_PATH
|
||||
>>>>>>> 5.0
|
||||
]
|
||||
)
|
||||
|
||||
##############################################################################
|
||||
### Check for SQLITE3DB
|
||||
##############################################################################
|
||||
<<<<<<< HEAD
|
||||
AC_ARG_WITH([optimizecpu],
|
||||
AS_HELP_STRING([--without-optimizecpu],
|
||||
[Exclude autodetecting platform and cpu type. This will disable the compilation of gcc optimizing code by platform and cpu.]),
|
||||
@@ -409,6 +746,166 @@ AS_IF([test "${OPTIMIZECPU}" = "yes"], [
|
||||
)
|
||||
]
|
||||
)
|
||||
=======
|
||||
AC_ARG_WITH([sqlite3],
|
||||
AS_HELP_STRING([--with-sqlite3[=DIR]],[Build with sqlite3 support]),
|
||||
[SQLITE3DB=$withval],
|
||||
[SQLITE3DB="yes"]
|
||||
)
|
||||
SQLITE3DB_VER=""
|
||||
AS_IF([test "${SQLITE3DB}" = "no"], [
|
||||
AC_MSG_CHECKING(for SQLite3)
|
||||
AC_MSG_RESULT(skipped)
|
||||
],[
|
||||
AC_MSG_CHECKING(SQLite3 pkgconf path)
|
||||
TEMP_PATH=$PKG_CONFIG_PATH
|
||||
AS_IF([test "${SQLITE3DB}" != "yes"], [
|
||||
PKG_CONFIG_PATH=${SQLITE3DB}/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
SQLITE3DB="yes"
|
||||
]
|
||||
)
|
||||
export PKG_CONFIG_PATH
|
||||
AC_MSG_RESULT($PKG_CONFIG_PATH done)
|
||||
|
||||
AC_MSG_CHECKING(for SQLite3)
|
||||
AS_IF([pkgconf sqlite3], [
|
||||
SQLITE3DB_VER="("`pkgconf --modversion sqlite3`")"
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS "`pkgconf --cflags sqlite3`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkgconf --libs sqlite3`
|
||||
AC_DEFINE([HAVE_SQLITE3DB], [1], [Define to 1 if you have SQLITE3 support])
|
||||
SQLITE3DB="yes"
|
||||
],[
|
||||
SQLITE3DB="no"
|
||||
]
|
||||
)
|
||||
|
||||
AC_MSG_RESULT([$SQLITE3DB])
|
||||
PKG_CONFIG_PATH=$TEMP_PATH
|
||||
export PKG_CONFIG_PATH
|
||||
]
|
||||
)
|
||||
|
||||
##############################################################################
|
||||
### Check for Pulse
|
||||
##############################################################################
|
||||
AC_ARG_WITH([pulse],
|
||||
AS_HELP_STRING([--with-pulse[=DIR]],[Build with PulseAudio support]),
|
||||
[PULSE=$withval],
|
||||
[PULSE="yes"]
|
||||
)
|
||||
PULSE_VER=""
|
||||
AS_IF([test "${PULSE}" = "no"], [
|
||||
AC_MSG_CHECKING(for PulseAudio)
|
||||
AC_MSG_RESULT(skipped)
|
||||
],[
|
||||
AC_MSG_CHECKING(PULSE pkgconf path)
|
||||
TEMP_PATH=$PKG_CONFIG_PATH
|
||||
AS_IF([test "${PULSE}" != "yes"], [
|
||||
PKG_CONFIG_PATH=${PULSE}/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
PULSE="yes"
|
||||
]
|
||||
)
|
||||
export PKG_CONFIG_PATH
|
||||
AC_MSG_RESULT($PKG_CONFIG_PATH done)
|
||||
|
||||
AC_MSG_CHECKING(for PulseAudio)
|
||||
AS_IF([pkgconf libpulse], [
|
||||
PULSE_VER="("`pkgconf --modversion libpulse`")"
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS "`pkgconf --cflags libpulse`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkgconf --libs libpulse`" -lpulse-simple "
|
||||
AC_DEFINE([HAVE_PULSE], [1], [Define to 1 if you have PulseAudio support])
|
||||
PULSE="yes"
|
||||
],[
|
||||
PULSE="no"
|
||||
]
|
||||
)
|
||||
|
||||
AC_MSG_RESULT([$PULSE])
|
||||
PKG_CONFIG_PATH=$TEMP_PATH
|
||||
export PKG_CONFIG_PATH
|
||||
]
|
||||
)
|
||||
|
||||
##############################################################################
|
||||
### Check for ALSA
|
||||
##############################################################################
|
||||
AC_ARG_WITH([alsa],
|
||||
AS_HELP_STRING([--with-alsa[=DIR]],[Build with ALSA support]),
|
||||
[ALSA=$withval],
|
||||
[ALSA="yes"]
|
||||
)
|
||||
ALSA_VER=""
|
||||
AS_IF([test "${ALSA}" = "no"], [
|
||||
AC_MSG_CHECKING(for ALSA)
|
||||
AC_MSG_RESULT(skipped)
|
||||
],[
|
||||
AC_MSG_CHECKING(ALSA pkgconf path)
|
||||
TEMP_PATH=$PKG_CONFIG_PATH
|
||||
AS_IF([test "${ALSA}" != "yes"], [
|
||||
PKG_CONFIG_PATH=${ALSA}/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
ALSA="yes"
|
||||
]
|
||||
)
|
||||
export PKG_CONFIG_PATH
|
||||
AC_MSG_RESULT($PKG_CONFIG_PATH done)
|
||||
|
||||
AC_MSG_CHECKING(for ALSA)
|
||||
AS_IF([pkgconf alsa], [
|
||||
ALSA_VER="("`pkgconf --modversion alsa`")"
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS "`pkgconf --cflags alsa`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkgconf --libs alsa`
|
||||
AC_DEFINE([HAVE_ALSA], [1], [Define to 1 if you have ALSA support])
|
||||
ALSA="yes"
|
||||
],[
|
||||
ALSA="no"
|
||||
]
|
||||
)
|
||||
|
||||
AC_MSG_RESULT([$ALSA])
|
||||
PKG_CONFIG_PATH=$TEMP_PATH
|
||||
export PKG_CONFIG_PATH
|
||||
]
|
||||
)
|
||||
|
||||
##############################################################################
|
||||
### Check for FFTW3
|
||||
##############################################################################
|
||||
AC_ARG_WITH([fftw3],
|
||||
AS_HELP_STRING([--with-fftw3[=DIR]],[Build with FFTW3 support]),
|
||||
[FFTW3=$withval],
|
||||
[FFTW3="yes"]
|
||||
)
|
||||
FFTW3_VER=""
|
||||
AS_IF([test "${FFTW3}" = "no"], [
|
||||
AC_MSG_CHECKING(for FFTW3)
|
||||
AC_MSG_RESULT(skipped)
|
||||
],[
|
||||
AC_MSG_CHECKING(FFTW3 pkgconf path)
|
||||
TEMP_PATH=$PKG_CONFIG_PATH
|
||||
AS_IF([test "${FFTW3}" != "yes"], [
|
||||
PKG_CONFIG_PATH=${FFTW3}/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
FFTW3="yes"
|
||||
]
|
||||
)
|
||||
export PKG_CONFIG_PATH
|
||||
AC_MSG_RESULT($PKG_CONFIG_PATH done)
|
||||
|
||||
AC_MSG_CHECKING(for FFTW3)
|
||||
AS_IF([pkgconf fftw3], [
|
||||
FFTW3_VER="("`pkgconf --modversion fftw3`")"
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS "`pkgconf --cflags fftw3`
|
||||
TEMP_LIBS="$TEMP_LIBS "`pkgconf --libs fftw3`
|
||||
AC_DEFINE([HAVE_FFTW3], [1], [Define to 1 if you have FFTW3 support])
|
||||
FFTW3="yes"
|
||||
],[
|
||||
FFTW3="no"
|
||||
]
|
||||
)
|
||||
|
||||
AC_MSG_RESULT([$FFTW3])
|
||||
PKG_CONFIG_PATH=$TEMP_PATH
|
||||
export PKG_CONFIG_PATH
|
||||
>>>>>>> 5.0
|
||||
]
|
||||
)
|
||||
|
||||
@@ -421,6 +918,7 @@ AC_ARG_WITH([developer-flags],
|
||||
[DEVELOPER_FLAGS=$withval],
|
||||
[DEVELOPER_FLAGS=no])
|
||||
|
||||
<<<<<<< HEAD
|
||||
AS_IF([test "${DEVELOPER_FLAGS}" = "yes"], [
|
||||
TEMP_CFLAGS="$TEMP_CFLAGS -W -Werror -Wall -Wextra -Wformat -Wshadow -Wpointer-arith -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -Wredundant-decls -Wno-long-long -ggdb -g3"
|
||||
]
|
||||
@@ -444,6 +942,27 @@ CPPFLAGS="$CPPFLAGS $TEMP_CFLAGS"
|
||||
AC_SUBST(AM_CFLAGS, "$TEMP_CFLAGS")
|
||||
LIBS="$LIBS $TEMP_LIBS"
|
||||
AC_SUBST(AM_LDFLAGS, "$TEMP_LDFLAGS")
|
||||
=======
|
||||
AC_ARG_WITH([clang-flags],
|
||||
AS_HELP_STRING([--with-clang-flags],
|
||||
[clang warning flags]),
|
||||
[CLANG_FLAGS=$withval],
|
||||
[CLANG_FLAGS=no])
|
||||
|
||||
AS_IF([test "${DEVELOPER_FLAGS}" = "yes"], [
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS -W -pedantic -Werror -Wall -Wextra -Wconversion -Wformat -Wshadow -Wpointer-arith -Wwrite-strings -Wredundant-decls -Wno-sign-conversion -Wno-sign-compare -ggdb -g3"
|
||||
],[
|
||||
AS_IF([test "${CLANG_FLAGS}" = "yes"], [
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS -W -pedantic -Werror -Wall -Wextra -Wconversion -Wformat -Wshadow -Wpointer-arith -Wwrite-strings -Wredundant-decls -Wno-c11-extensions -Wno-sign-conversion -Wno-sign-compare -ggdb -g3 "
|
||||
],[
|
||||
TEMP_CPPFLAGS="$TEMP_CPPFLAGS -W -O3 -Wall -Wextra -Wconversion -Wformat -Wshadow -Wpointer-arith -Wwrite-strings -Wredundant-decls -Wno-sign-conversion -Wno-sign-compare -ggdb -g3 "
|
||||
])
|
||||
])
|
||||
|
||||
CPPFLAGS="$CPPFLAGS $TEMP_CPPFLAGS"
|
||||
LIBS="$LIBS $TEMP_LIBS"
|
||||
LDFLAGS="$TEMP_LDFLAGS"
|
||||
>>>>>>> 5.0
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
@@ -452,6 +971,7 @@ AC_CONFIG_FILES([
|
||||
data/camera1-dist.conf
|
||||
data/camera2-dist.conf
|
||||
data/camera3-dist.conf
|
||||
<<<<<<< HEAD
|
||||
data/camera4-dist.conf
|
||||
data/motion-dist.conf
|
||||
data/motion.service
|
||||
@@ -459,6 +979,13 @@ AC_CONFIG_FILES([
|
||||
|
||||
AC_ARG_VAR([KILL],[the 'kill' program to use to send signals to motion])
|
||||
AC_PATH_PROG([KILL],[kill],['/bin/kill'])
|
||||
=======
|
||||
data/sound1-dist.conf
|
||||
data/motion-dist.conf
|
||||
data/motion-dist.service
|
||||
])
|
||||
|
||||
>>>>>>> 5.0
|
||||
AC_OUTPUT
|
||||
|
||||
##############################################################################
|
||||
@@ -470,6 +997,7 @@ echo " Configure status "
|
||||
echo " ${PACKAGE_NAME} ${PACKAGE_VERSION}"
|
||||
echo " **************************"
|
||||
echo
|
||||
<<<<<<< HEAD
|
||||
echo "CFLAGS: $TEMP_CFLAGS $CFLAGS"
|
||||
echo
|
||||
echo "LIBS: $LIBS"
|
||||
@@ -491,6 +1019,32 @@ echo "SQLite3 support : $SQLITE3"
|
||||
echo "MYSQL support : $MYSQL"
|
||||
echo "PostgreSQL support : $PGSQL"
|
||||
echo "MariaDB support : $MARIADB"
|
||||
=======
|
||||
echo "CPPFLAGS: $CPPFLAGS"
|
||||
echo
|
||||
echo "Install prefix: $prefix"
|
||||
echo "LIBS: $LIBS"
|
||||
echo
|
||||
echo "LDFLAGS: $LDFLAGS"
|
||||
>>>>>>> 5.0
|
||||
echo
|
||||
echo
|
||||
echo "OS : $host_os"
|
||||
echo "pthread_np : $PTHREAD_NP"
|
||||
echo "pthread_setname_np : $PTHREAD_SETNAME_NP"
|
||||
echo "pthread_getname_np : $PTHREAD_GETNAME_NP"
|
||||
echo "XSI error : $XSI_STRERROR"
|
||||
echo "V4L2 : $V4L2"
|
||||
echo "webp : $WEBP$WEBP_VER"
|
||||
echo "libcamera : $LIBCAM$LIBCAM_VER"
|
||||
echo "FFmpeg : $FFMPEG$FFMPEG_VER"
|
||||
echo "OpenCV : $OPENCV$OPENCV_VER"
|
||||
echo "SQLite3 : $SQLITE3DB$SQLITE3DB_VER"
|
||||
echo "MYSQL : $MYSQLDB$MYSQLDB_VER"
|
||||
echo "PostgreSQL : $PGSQLDB$PGSQLDB_VER"
|
||||
echo "MariaDB : $MARIADB$MARIADB_VER"
|
||||
echo "ALSA : $ALSA$ALSA_VER"
|
||||
echo "PulseAudio : $PULSE$PULSE_VER"
|
||||
echo "FFTW : $FFTW3$FFTW3_VER"
|
||||
echo
|
||||
echo "Install prefix : $prefix"
|
||||
echo
|
||||
|
||||
+23
-16
@@ -1,29 +1,36 @@
|
||||
# @prefix@/etc/motion/camera1.conf
|
||||
#
|
||||
# This config file was generated by @PACKAGE_NAME@ @PACKAGE_VERSION@
|
||||
; @prefix@/etc/motion/camera1.conf
|
||||
;
|
||||
; This config file was generated by @PACKAGE_NAME@ @PACKAGE_VERSION@
|
||||
|
||||
###########################################################
|
||||
# Configuration options specific to camera 1
|
||||
############################################################
|
||||
# User defined name for the camera.
|
||||
camera_name MyCam1
|
||||
;*************************************************
|
||||
; Configuration options specific to camera 1
|
||||
;*************************************************
|
||||
|
||||
# Numeric identifier for the camera.
|
||||
camera_id 101
|
||||
;*************************************************
|
||||
;***** Camera
|
||||
;*************************************************
|
||||
device_name MyCam1
|
||||
device_id 101
|
||||
|
||||
# The full URL of the network camera stream.
|
||||
;*************************************************
|
||||
;***** Source
|
||||
;*************************************************
|
||||
netcam_url rtsp://yourcamera1ip:port/camera/specific/url
|
||||
|
||||
# Image width in pixels.
|
||||
;*************************************************
|
||||
;***** Image
|
||||
;*************************************************
|
||||
width 1280
|
||||
|
||||
# Image height in pixels.
|
||||
height 720
|
||||
|
||||
# Text to be overlayed in the lower left corner of images
|
||||
;*************************************************
|
||||
;***** Overlays
|
||||
;*************************************************
|
||||
text_left CAMERA 1
|
||||
|
||||
# File name(without extension) for movies relative to target directory
|
||||
;*************************************************
|
||||
;***** Movie
|
||||
;*************************************************
|
||||
movie_filename CAM01_%t-%v-%Y%m%d%H%M%S
|
||||
|
||||
|
||||
|
||||
+23
-18
@@ -1,31 +1,36 @@
|
||||
# @prefix@/etc/motion/camera2.conf
|
||||
#
|
||||
# This config file was generated by @PACKAGE_NAME@ @PACKAGE_VERSION@
|
||||
; @prefix@/etc/motion/camera2.conf
|
||||
;
|
||||
; This config file was generated by @PACKAGE_NAME@ @PACKAGE_VERSION@
|
||||
|
||||
###########################################################
|
||||
# Configuration options specific to camera 2
|
||||
############################################################
|
||||
# User defined name for the camera.
|
||||
camera_name Patio
|
||||
;*************************************************
|
||||
; Configuration options specific to camera 2
|
||||
;*************************************************
|
||||
|
||||
# Numeric identifier for the camera.
|
||||
camera_id 102
|
||||
;*************************************************
|
||||
;***** Camera
|
||||
;*************************************************
|
||||
device_name Patio
|
||||
device_id 102
|
||||
|
||||
# The full URL of the network camera stream.
|
||||
;*************************************************
|
||||
;***** Source
|
||||
;*************************************************
|
||||
netcam_url http://yourcamera2ip:port/camera/specific/url
|
||||
|
||||
# Image width in pixels.
|
||||
;*************************************************
|
||||
;***** Image
|
||||
;*************************************************
|
||||
width 352
|
||||
|
||||
# Image height in pixels.
|
||||
height 288
|
||||
|
||||
# Text to be overlayed in the lower left corner of images
|
||||
;*************************************************
|
||||
;***** Overlays
|
||||
;*************************************************
|
||||
text_left Camera2
|
||||
|
||||
# Text to be overlayed in the lower right corner of images.
|
||||
text_right Patio\n%Y-%m-%d\n%T-%q
|
||||
|
||||
# File name(without extension) for movies relative to target directory
|
||||
;*************************************************
|
||||
;***** Movie
|
||||
;*************************************************
|
||||
movie_filename CAM02_%t-%v-%Y%m%d%H%M%S
|
||||
|
||||
|
||||
+23
-20
@@ -1,35 +1,38 @@
|
||||
# @prefix@/etc/motion/camera3.conf
|
||||
#
|
||||
# This config file was generated by @PACKAGE_NAME@ @PACKAGE_VERSION@
|
||||
; @prefix@/etc/motion/camera3.conf
|
||||
;
|
||||
; This config file was generated by @PACKAGE_NAME@ @PACKAGE_VERSION@
|
||||
|
||||
###########################################################
|
||||
# Configuration options specific to camera 3
|
||||
############################################################
|
||||
# User defined name for the camera.
|
||||
camera_name Front Door
|
||||
;*************************************************
|
||||
; Configuration options specific to camera 3
|
||||
;*************************************************
|
||||
|
||||
# Numeric identifier for the camera.
|
||||
camera_id 103
|
||||
;*************************************************
|
||||
;***** Camera
|
||||
;*************************************************
|
||||
device_name Front Door
|
||||
device_id 103
|
||||
|
||||
# The full URL of the network camera stream.
|
||||
;*************************************************
|
||||
;***** Source
|
||||
;*************************************************
|
||||
netcam_url rtmp://yourcamera3ip:port/camera/specific/url
|
||||
|
||||
netcam_userpass myusername:mypassword
|
||||
|
||||
# Image width in pixels.
|
||||
;*************************************************
|
||||
;***** Image
|
||||
;*************************************************
|
||||
width 2048
|
||||
|
||||
# Image height in pixels.
|
||||
height 1536
|
||||
|
||||
# Text to be overlayed in the lower left corner of images
|
||||
;*************************************************
|
||||
;***** Overlays
|
||||
;*************************************************
|
||||
text_left Camera3
|
||||
|
||||
# Text to be overlayed in the lower right corner of images.
|
||||
text_right FrontDoor\n%Y-%m-%d\n%T-%q
|
||||
|
||||
text_scale 4
|
||||
|
||||
# File name(without extension) for movies relative to target directory
|
||||
;*************************************************
|
||||
;***** Movie
|
||||
;*************************************************
|
||||
movie_filename CAM03_%t-%v-%Y%m%d%H%M%S
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
# @prefix@/etc/motion/camera4.conf
|
||||
#
|
||||
# This config file was generated by @PACKAGE_NAME@ @PACKAGE_VERSION@
|
||||
|
||||
###########################################################
|
||||
# Configuration options specific to camera 4
|
||||
############################################################
|
||||
# User defined name for the camera.
|
||||
camera_name Server room
|
||||
|
||||
# Numeric identifier for the camera.
|
||||
camera_id 104
|
||||
|
||||
# Video device (e.g. /dev/video0) to be used for capturing.
|
||||
video_device /dev/video0
|
||||
|
||||
# Image width in pixels.
|
||||
width 640
|
||||
|
||||
# Image height in pixels.
|
||||
height 480
|
||||
|
||||
# Text to be overlayed in the lower left corner of images
|
||||
text_left
|
||||
|
||||
# Text to be overlayed in the lower right corner of images.
|
||||
text_right Camera4\n%Y-%m-%d\n%T-%q
|
||||
|
||||
# File name(without extension) for movies relative to target directory
|
||||
movie_filename CAM04_%t-%v-%Y%m%d%H%M%S
|
||||
@@ -1,165 +0,0 @@
|
||||
# Rename this distribution example file to motion.conf
|
||||
#
|
||||
# This config file was generated by @PACKAGE_NAME@ @PACKAGE_VERSION@
|
||||
# Documentation: @prefix@/share/doc/motion/motion_guide.html
|
||||
#
|
||||
# This file contains only the basic configuration options to get a
|
||||
# system working. There are many more options available. Please
|
||||
# consult the documentation for the complete list of all options.
|
||||
#
|
||||
|
||||
############################################################
|
||||
# System control configuration parameters
|
||||
############################################################
|
||||
|
||||
# Start in daemon (background) mode and release terminal.
|
||||
daemon off
|
||||
|
||||
# Start in Setup-Mode, daemon disabled.
|
||||
setup_mode off
|
||||
|
||||
# File to store the process ID.
|
||||
; pid_file value
|
||||
|
||||
# File to write logs messages into. If not defined stderr and syslog is used.
|
||||
; log_file value
|
||||
|
||||
# Level of log messages [1..9] (EMG, ALR, CRT, ERR, WRN, NTC, INF, DBG, ALL).
|
||||
log_level 6
|
||||
|
||||
# Target directory for pictures, snapshots and movies
|
||||
; target_dir value
|
||||
|
||||
# Video device (e.g. /dev/video0) to be used for capturing.
|
||||
video_device /dev/video0
|
||||
|
||||
# Parameters to control video device. See motion_guide.html
|
||||
; video_params value
|
||||
|
||||
# The full URL of the network camera stream.
|
||||
; netcam_url value
|
||||
|
||||
############################################################
|
||||
# Image Processing configuration parameters
|
||||
############################################################
|
||||
|
||||
# Image width in pixels.
|
||||
width 640
|
||||
|
||||
# Image height in pixels.
|
||||
height 480
|
||||
|
||||
# Maximum number of frames to be captured per second.
|
||||
framerate 15
|
||||
|
||||
# Text to be overlayed in the lower left corner of images
|
||||
text_left CAMERA1
|
||||
|
||||
# Text to be overlayed in the lower right corner of images.
|
||||
text_right %Y-%m-%d\n%T-%q
|
||||
|
||||
############################################################
|
||||
# Motion detection configuration parameters
|
||||
############################################################
|
||||
|
||||
# Always save pictures and movies even if there was no motion.
|
||||
emulate_motion off
|
||||
|
||||
# Threshold for number of changed pixels that triggers motion.
|
||||
threshold 1500
|
||||
|
||||
# Noise threshold for the motion detection.
|
||||
; noise_level 32
|
||||
|
||||
# Despeckle the image using (E/e)rode or (D/d)ilate or (l)abel.
|
||||
despeckle_filter EedDl
|
||||
|
||||
# Number of images that must contain motion to trigger an event.
|
||||
minimum_motion_frames 1
|
||||
|
||||
# Gap in seconds of no motion detected that triggers the end of an event.
|
||||
event_gap 60
|
||||
|
||||
# The number of pre-captured (buffered) pictures from before motion.
|
||||
pre_capture 3
|
||||
|
||||
# Number of frames to capture after motion is no longer detected.
|
||||
post_capture 0
|
||||
|
||||
############################################################
|
||||
# Script execution configuration parameters
|
||||
############################################################
|
||||
|
||||
# Command to be executed when an event starts.
|
||||
; on_event_start value
|
||||
|
||||
# Command to be executed when an event ends.
|
||||
; on_event_end value
|
||||
|
||||
# Command to be executed when a movie file is closed.
|
||||
; on_movie_end value
|
||||
|
||||
############################################################
|
||||
# Picture output configuration parameters
|
||||
############################################################
|
||||
|
||||
# Output pictures when motion is detected
|
||||
picture_output off
|
||||
|
||||
# File name(without extension) for pictures relative to target directory
|
||||
picture_filename %Y%m%d%H%M%S-%q
|
||||
|
||||
############################################################
|
||||
# Movie output configuration parameters
|
||||
############################################################
|
||||
|
||||
# Create movies of motion events.
|
||||
movie_output on
|
||||
|
||||
# Maximum length of movie in seconds.
|
||||
movie_max_time 60
|
||||
|
||||
# The encoding quality of the movie. (0=use bitrate. 1=worst quality, 100=best)
|
||||
movie_quality 45
|
||||
|
||||
# Container/Codec to used for the movie. See motion_guide.html
|
||||
movie_codec mkv
|
||||
|
||||
# File name(without extension) for movies relative to target directory
|
||||
movie_filename %t-%v-%Y%m%d%H%M%S
|
||||
|
||||
############################################################
|
||||
# Webcontrol configuration parameters
|
||||
############################################################
|
||||
|
||||
# Port number used for the webcontrol.
|
||||
webcontrol_port 8080
|
||||
|
||||
# Restrict webcontrol connections to the localhost.
|
||||
webcontrol_localhost on
|
||||
|
||||
# Type of configuration options to allow via the webcontrol.
|
||||
webcontrol_parms 0
|
||||
|
||||
############################################################
|
||||
# Live stream configuration parameters
|
||||
############################################################
|
||||
|
||||
# The port number for the live stream.
|
||||
stream_port 8081
|
||||
|
||||
# Restrict stream connections to the localhost.
|
||||
stream_localhost on
|
||||
|
||||
##############################################################
|
||||
# Camera config files - One for each camera.
|
||||
##############################################################
|
||||
; camera @prefix@/etc/motion/camera1.conf
|
||||
; camera @prefix@/etc/motion/camera2.conf
|
||||
; camera @prefix@/etc/motion/camera3.conf
|
||||
; camera @prefix@/etc/motion/camera4.conf
|
||||
|
||||
##############################################################
|
||||
# Directory to read '.conf' files for cameras.
|
||||
##############################################################
|
||||
; camera_dir @prefix@/etc/motion/conf.d
|
||||
@@ -0,0 +1,70 @@
|
||||
#
|
||||
# This file is part of Motion.
|
||||
#
|
||||
# MotionPLus 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 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
#
|
||||
|
||||
[Unit]
|
||||
Description=Motion - Enhanced security camera monitoring software.
|
||||
Documentation=man:motion(1)
|
||||
After=local-fs.target network.target
|
||||
|
||||
[Service]
|
||||
User=motion
|
||||
UMask=002
|
||||
ExecStart=@BIN_PATH@/motion
|
||||
|
||||
Type=simple
|
||||
# Set StandardError=journal to use journald to log messages from motion.
|
||||
# See also the "log_file" config file option in motion(1) and systemd.service(5).
|
||||
StandardError=null
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
ExecStartPre=!/bin/mkdir -p /var/log/motion
|
||||
ExecStartPre=!/bin/chown motion:adm /var/log/motion
|
||||
|
||||
# Don't restart if unconfigured / misconfigured e.g. daemon disabled
|
||||
# in defaults file. See also /usr/include/sysexits.h or sysexits(3)
|
||||
RestartPreventExitStatus=78
|
||||
|
||||
# To tune restart behaviour, see systemd.unit(5) and use
|
||||
# "systemctl edit motion" to change the following settings:
|
||||
#StartLimitBurst=
|
||||
#StartLimitIntervalSec=
|
||||
#StartLimitAction=
|
||||
#FailureAction=
|
||||
|
||||
# The following can be used to increase the security of the
|
||||
# installation, by mitigating risk from attacks on motion and the
|
||||
# binaries, libraries and scripts which it relies on. They are disabled
|
||||
# by default in case they break existing installations, e.g. those which
|
||||
# call site-local scripts which would inherit the same restrictions.
|
||||
#
|
||||
# See systemd.exec(5) and
|
||||
# http://0pointer.net/public/systemd-nluug-2014.pdf for more details
|
||||
# of these and other related options.
|
||||
#
|
||||
# Use "systemctl edit motion" to change these settings.
|
||||
#PrivateTmp=true
|
||||
#NoNewPrivileges=yes
|
||||
#PrivateNetwork=yes
|
||||
#ProtectHome=yes
|
||||
#DeviceAllow=/dev/video0
|
||||
#MountFlags=slave
|
||||
#SystemCallFilter=
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,69 @@
|
||||
#
|
||||
# This systemd unit file is part of the motion project:
|
||||
#
|
||||
# https://motion-project.github.io/
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of version 2 of the GNU General Public License as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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 Lesser General Public
|
||||
# License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
|
||||
#
|
||||
|
||||
[Unit]
|
||||
Description=Motion - monitor live video, trigger responses, record video/stills.
|
||||
Documentation=man:motion(1)
|
||||
After=local-fs.target network.target
|
||||
|
||||
[Service]
|
||||
User=motion
|
||||
EnvironmentFile=-/etc/default/motion
|
||||
# The the sleep on the following line is needed with systemd version
|
||||
# 232, otherwise the error message that we echo doesn't hit 'systemctl
|
||||
# status'.
|
||||
ExecStart=/bin/sh -c '([ -r "/etc/default/motion" ] && [ "x$start_motion_daemon" != "xyes" ]) && echo "Not starting motion because start_motion_daemon=$start_motion_daemon - check /etc/default/motion" && sleep 1 && exit 78 ; exec @BIN_PATH@/motion -n'
|
||||
Type=simple
|
||||
# Set StandardError=journal to use journald to log messages from motion.
|
||||
# See also the "log_file" config file option in motion(1) and
|
||||
# systemd.service(5).
|
||||
StandardError=null
|
||||
ExecReload=/usr/bin/kill -HUP $MAINPID
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
# Don't restart if unconfigured / misconfigured e.g. daemon disabled
|
||||
# in defaults file. See also /usr/include/sysexits.h or sysexits(3)
|
||||
RestartPreventExitStatus=78
|
||||
# To tune restart behaviour, see systemd.unit(5) and use
|
||||
# "systemctl edit motion" to change the following settings:
|
||||
#StartLimitBurst=
|
||||
#StartLimitIntervalSec=
|
||||
#StartLimitAction=
|
||||
#FailureAction=
|
||||
# The following can be used to increase the security of the
|
||||
# installation, by mitigating risk from attacks on motion and the
|
||||
# binaries, libraries and scripts which it relies on. They are disabled
|
||||
# by default in case they break existing installations, e.g. those which
|
||||
# call site-local scripts which would inherit the same restrictions.
|
||||
#
|
||||
# See systemd.exec(5) and
|
||||
# http://0pointer.net/public/systemd-nluug-2014.pdf for more details
|
||||
# of these and other related options.
|
||||
#
|
||||
# Use "systemctl edit motion" to change these settings.
|
||||
#PrivateTmp=true
|
||||
#NoNewPrivileges=yes
|
||||
#PrivateNetwork=yes
|
||||
#ProtectHome=yes
|
||||
#DeviceAllow=/dev/video0
|
||||
#MountFlags=slave
|
||||
#SystemCallFilter=
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,24 @@
|
||||
; @prefix@/etc/motion/sound1.conf
|
||||
;
|
||||
; This config file was generated by @PACKAGE_NAME@ @PACKAGE_VERSION@
|
||||
|
||||
;*************************************************
|
||||
; Configuration options specific to sound device 1
|
||||
;*************************************************
|
||||
|
||||
device_id 5
|
||||
|
||||
;*************************************************
|
||||
;***** Sound
|
||||
;*************************************************
|
||||
snd_device hw:1,0
|
||||
snd_params
|
||||
|
||||
snd_alerts alert_id=01,volume_level=01,volume_count=10,freq_low=3398,freq_high=3399,alert_nm=water_alert
|
||||
snd_alerts alert_id=02,volume_level=01,volume_count=10,freq_low=3187,freq_high=3188,alert_nm=smoke_alarm1
|
||||
snd_alerts alert_id=03,volume_level=01,volume_count=10,freq_low=3375,freq_high=3376,alert_nm=smoke_alarm2
|
||||
snd_alerts alert_id=04,volume_level=01,volume_count=200,freq_low=679.6875,freq_high=679.6875,trigger_threshold=100,alert_nm=doorbell
|
||||
|
||||
snd_window hamming
|
||||
|
||||
snd_show off
|
||||
-1482
File diff suppressed because it is too large
Load Diff
+6
-8
@@ -1,17 +1,15 @@
|
||||
The following is a brief overview of the building and installing instructions for debian / ubuntu.
|
||||
The following is a brief overview of the building and installing instructions for Debian / Ubuntu.
|
||||
|
||||
For full instructions on how to build and install Motion, see the motion_guide.html that is
|
||||
distributed with this source code. The guide also includes instructions for building Motion
|
||||
on distributions other than debian/ubuntu such as BSD, Mac and Centos.
|
||||
For full instructions on how to build and install Motion, see the motion_build.html that is
|
||||
distributed with this source code.
|
||||
|
||||
The packages and library names change frequently and vary across base operating systems.
|
||||
Adjust the following lines as required by the base operating system.
|
||||
|
||||
Install basic build packages:
|
||||
sudo apt-get install autoconf automake autopoint pkgconf libtool libjpeg8-dev build-essential libzip-dev gettext libmicrohttpd-dev
|
||||
|
||||
Install FFMPEG packages
|
||||
sudo apt-get install libavformat-dev libavcodec-dev libavutil-dev libswscale-dev libavdevice-dev
|
||||
sudo apt install autoconf automake autopoint build-essential pkgconf libtool libzip-dev
|
||||
libjpeg-dev git libavformat-dev libavcodec-dev libavutil-dev libswscale-dev libavdevice-dev
|
||||
libwebp-dev gettext libmicrohttpd-dev libmariadb-dev libasound2-dev libfftw3-dev
|
||||
|
||||
Once required packages are installed, execute:
|
||||
autoreconf -fiv
|
||||
|
||||
@@ -2769,3 +2769,4 @@ van Heusden (http://www.vanheusden.com/).
|
||||
Renamed image1 and image2 to image_ref and image_new
|
||||
|
||||
0.1 Initial release
|
||||
|
||||
|
||||
+17
-218
@@ -1,76 +1,15 @@
|
||||
Formatting rules for Motion code.
|
||||
|
||||
Note: To understand them you must view this document with spaces and tabs
|
||||
visible.
|
||||
Formatting for Motion.
|
||||
|
||||
--------------------
|
||||
RULE 1
|
||||
Code is generally indented using 4 spaces
|
||||
|
||||
Example
|
||||
/* allocate some memory and check if that succeeded or not. If it failed
|
||||
* do some error logging and bail out
|
||||
*/
|
||||
void * mymalloc(size_t nbytes)
|
||||
{
|
||||
void *dummy = malloc(nbytes);
|
||||
if (!dummy) {
|
||||
printf("Could not allocate %llu bytes of memory!\n", (unsigned long long) nbytes);
|
||||
syslog(EMERG, TYPE_ALL, "%s: Could not allocate %llu bytes of memory!",
|
||||
__FUNCTION__, (unsigned long long) nbytes);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return dummy;
|
||||
}
|
||||
|
||||
RULE 1A
|
||||
Preprocessor statements such as #IF, #DEFINE, etc are to be indented
|
||||
similar to normal code. These statements shall not be forced to start in column 1.
|
||||
|
||||
RULE 1B
|
||||
When entire functions are enclosed in a #IF block, the functions should continue to
|
||||
start in column 1.
|
||||
|
||||
|
||||
--------------------
|
||||
RULE 2
|
||||
If a line or statement is broken into two lines you will normally want the text
|
||||
in the 2nd line to align with text in the first line if it enhances the readability
|
||||
of the statement. The alignment is done using spaces making the code on the
|
||||
following lines appear in a natural way below the corresponding code above.
|
||||
Use common sense to enhance readability.
|
||||
|
||||
Example
|
||||
/* allocate some memory and check if that succeeded or not. If it failed
|
||||
* do some error logging and bail out
|
||||
*/
|
||||
void * mymalloc(size_t nbytes)
|
||||
{
|
||||
void *dummy = malloc(nbytes);
|
||||
if (!dummy) {
|
||||
printf("Could not allocate %llu bytes of memory!\n",
|
||||
(unsigned long long) nbytes);
|
||||
syslog(EMERG, TYPE_ALL,"Could not allocate %llu bytes of memory!",
|
||||
__FUNCTION__, (unsigned long long) nbytes);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return dummy;
|
||||
}
|
||||
|
||||
Example
|
||||
cnt->sql_mask = cnt->conf.sql_log_image * (FTYPE_IMAGE + FTYPE_IMAGE_MOTION) +
|
||||
cnt->conf.sql_log_snapshot * FTYPE_IMAGE_SNAPSHOT +
|
||||
cnt->conf.sql_log_mpeg * (FTYPE_MPEG + FTYPE_MPEG_MOTION) +
|
||||
cnt->conf.sql_log_timelapse * FTYPE_MPEG_TIMELAPSE;
|
||||
|
||||
|
||||
|
||||
Example
|
||||
char msg[] = "This is a very long message which we would like to break"
|
||||
"into two lines or more because otherwise the line gets"
|
||||
"too long to read. We align them below each other for readability"
|
||||
in the 2nd line to align with text in the first line. The alignment is done
|
||||
using spaces making the code on the following lines appear in a natural way below
|
||||
the corresponding code above. Use common sense to enhance readability.
|
||||
|
||||
--------------------
|
||||
RULE 3
|
||||
@@ -79,177 +18,37 @@ and 8 in another. A space is always a space.
|
||||
|
||||
--------------------
|
||||
RULE 4
|
||||
Functions should be written with this syntax.
|
||||
|
||||
GOOD EXAMPLE
|
||||
/* Comment block
|
||||
* A comment block should be at least one line saying what the function does.
|
||||
* It is better to make several lines explaining what it does, what it takes
|
||||
* for arguments and what it returns. It is a bad idea to try to use tabs to
|
||||
* align text in the comment block
|
||||
*/
|
||||
type function_name(parameters)
|
||||
{
|
||||
declarations
|
||||
declarations
|
||||
|
||||
statements
|
||||
statements
|
||||
}
|
||||
|
||||
For function declarations that span more than one line, a triple indent is
|
||||
generally used for the second and subsequent lines to avoid excessive lines.
|
||||
|
||||
Do not stuff everything on a single line. Keep the line length to less than
|
||||
100 characters. All variable names should be seen without having to scroll.
|
||||
|
||||
Do not put the '{' after the function declaration. Put it on an empty line
|
||||
right after. Note that this rule is only for functions.
|
||||
If blocks always use braces and follow K&R. Braces are free and do not cost money,
|
||||
use them to clarify what you are doing.
|
||||
|
||||
--------------------
|
||||
RULE 5
|
||||
Blocks follow K&R.
|
||||
|
||||
GOOD EXAMPLE
|
||||
|
||||
if ((picture=fopen(cnt->conf.mask_file, "r"))) {
|
||||
cnt->imgs.mask=get_pgm(cnt, picture, cnt->imgs.width, cnt->imgs.height);
|
||||
} else {
|
||||
printf("Hello world\n");
|
||||
}
|
||||
|
||||
|
||||
BAD EXAMPLE
|
||||
|
||||
if ((picture=fopen(cnt->conf.mask_file, "r")))
|
||||
{
|
||||
cnt->imgs.mask=get_pgm(cnt, picture, cnt->imgs.width, cnt->imgs.height);
|
||||
fclose(picture);
|
||||
}
|
||||
else
|
||||
{
|
||||
put_fixed_mask(cnt, cnt->conf.mask_file);
|
||||
printf("Hello world\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
GOOD EXAMPLE
|
||||
|
||||
switch (expr) {
|
||||
case ABC:
|
||||
case DEF:
|
||||
statement;
|
||||
break;
|
||||
case UVW:
|
||||
statement;
|
||||
break;
|
||||
default:
|
||||
/* default case */
|
||||
statement;
|
||||
}
|
||||
|
||||
BAD EXAMPLE
|
||||
|
||||
switch (expr) {
|
||||
case ABC:
|
||||
case DEF:
|
||||
statement;
|
||||
break;
|
||||
case UVW:
|
||||
statement;
|
||||
break;
|
||||
default:
|
||||
/* default case */
|
||||
statement;
|
||||
}
|
||||
|
||||
RULE 5A
|
||||
if, while and for statements shall always use braces.
|
||||
|
||||
|
||||
--------------------
|
||||
RULE 6
|
||||
Whitespace.
|
||||
To ensure that Motion code looks homogeneous and to enhance readability:
|
||||
1. Do not use a space before a comma
|
||||
Use whitespace, commas, braces and indentation to enhance readability:
|
||||
1. No spaces before a comma
|
||||
2. Always leave at least one space after a comma
|
||||
3. Use one space between a block start statement and a '{'
|
||||
4. Do not use a space between a function name and the '('
|
||||
5. Use spaces to enhance readability (a non objective rule but at least
|
||||
think about it)
|
||||
6. The '*' for pointers should be just before the variable name with no
|
||||
space.
|
||||
|
||||
GOOD EXAMPLES
|
||||
int function_name(int *par1, int par2, int par3)
|
||||
{
|
||||
if (var1==2 || var2==3) {
|
||||
|
||||
BAD EXAMPLES
|
||||
int function_name (int * par1 , int par2,int par3){
|
||||
if (var1==2||var2==3){
|
||||
5. The '*' for pointers should be just before the variable name with no space.
|
||||
6. Use spaces to enhance readability (a non objective rule but at least think about it)
|
||||
|
||||
--------------------
|
||||
RULE 7
|
||||
Comment your code but do not be verbose. Do not literally describe what
|
||||
the code does unless it would not be obvious to someone who knows C.
|
||||
|
||||
BAD EXAMPLES
|
||||
while (1) { /* 'Do forever' */
|
||||
|
||||
/*
|
||||
* Now we increment the index
|
||||
*/
|
||||
indx++;
|
||||
|
||||
RULE 6
|
||||
Comment the code where it isn't intuitive to new programmers.
|
||||
Use /* This style of comment for permament comments */ or
|
||||
/*
|
||||
* This style of comment for comments which
|
||||
* require more that one line
|
||||
*/
|
||||
Use // this style comments for something you add temporarily while testing and
|
||||
FIXME type comments. It is much easier to spot the temporary comments this way.
|
||||
Use // style comments for something you add temporarily while testing.
|
||||
|
||||
--------------------
|
||||
RULE 8
|
||||
RULE 7
|
||||
Use variable names that say what the variable is used for.
|
||||
Avoid x,t,vt type variable names.
|
||||
Use names like image, image_buffer, image_height, output_buffer
|
||||
Short names like i and j for loop index variable are a known good practice.
|
||||
Variable and function names are in lower case. Use '_' to separate words.
|
||||
Variable and function names are in lower case.
|
||||
Use '_' to separate words.
|
||||
MACROS are in uppercase.
|
||||
camelCase (mix of upper and lower case) is not allowed
|
||||
|
||||
RULE 9
|
||||
Break code into many smaller functions rather than one extremely long one.
|
||||
It is easier to follow the flow when functions are simple and concise.
|
||||
|
||||
--------------------
|
||||
|
||||
BEST PRACTICES
|
||||
Not rules, but these suggestions make code easier to read.
|
||||
|
||||
Use white space and empty lines to group code.
|
||||
For example, large if statements are easier to read when there is an empty
|
||||
line before and after them.
|
||||
|
||||
Use an empty line before a comment which describes the code lines below.
|
||||
|
||||
Always use spaces in statements like
|
||||
thisvar->thismember>thisvar->thisothermember (bad)
|
||||
thisvar->thismember > thisvar->thisothermember (good)
|
||||
|
||||
if (cnt->event_nr==cnt->prev_event||cnt->makemovie) (bad)
|
||||
if (cnt->event_nr == cnt->prev_event || cnt->makemovie) (good)
|
||||
|
||||
frame_delay=(1000000L/cnt->conf.low_cpu)-frame_delay-elapsedtime; (bad)
|
||||
frame_delay = (1000000L / cnt->conf.low_cpu) - frame_delay - elapsedtime; (good)
|
||||
Follow the naming scheme for functions
|
||||
|
||||
|
||||
--------------------
|
||||
|
||||
This document can probably be enhanced more as time goes by.
|
||||
Hope it helps developers to understand the ideas.
|
||||
|
||||
Please help the developers by at least trying to follow the spirit of this document. We all have our coding preferences, but
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 854 B |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
@@ -1,911 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link href="motion.png" rel="icon" type="image/png">
|
||||
<title>Motion</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" type="text/css" href="motion_stylesheet.css" media="screen">
|
||||
<script>
|
||||
function fnc_topnav() {
|
||||
var x = document.getElementById("id_topnav");
|
||||
if (x.className === "topnav") {
|
||||
x.className += " responsive";
|
||||
} else {
|
||||
x.className = "topnav";
|
||||
}
|
||||
}
|
||||
function fnc_subnav() {
|
||||
var x = document.getElementById("id_subnav");
|
||||
if (x.className === "subnav") {
|
||||
x.className += " responsive";
|
||||
} else {
|
||||
x.className = "subnav";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="topnav" id="id_topnav">
|
||||
<img class="logoimg" src="motion.gif">
|
||||
|
||||
<a class="topnav-d" href="https://motion-project.github.io/motion_support.html">Support</a>
|
||||
<a class="topnav-d" href="https://motion-project.github.io/motion_news.html" >News</a>
|
||||
<a class="topnav-d" href="https://motion-project.github.io/motion_guide.html" >Documentation</a>
|
||||
<a class="topnav-d" href="https://motion-project.github.io/motion_download.html">Download</a>
|
||||
<a class="topnav-d" href="https://motion-project.github.io/index.html">Home</a>
|
||||
|
||||
<a class="topnav-m" href="https://motion-project.github.io/index.html">Home</a>
|
||||
<a class="topnav-m" href="https://motion-project.github.io/motion_download.html">Download</a>
|
||||
<a class="topnav-m" href="https://motion-project.github.io/motion_guide.html" >Documentation</a>
|
||||
<a class="topnav-m" href="https://motion-project.github.io/motion_news.html" >News</a>
|
||||
<a class="topnav-m" href="https://motion-project.github.io/motion_support.html">Support</a>
|
||||
|
||||
<a href="javascript:void(0);" class="icon" onclick="fnc_topnav()">☰</a>
|
||||
</div>
|
||||
<section class="page-header">
|
||||
<h1>
|
||||
Installing and Building from Source
|
||||
</h1>
|
||||
</section>
|
||||
<div class="subnav" id="id_subnav">
|
||||
<div class="dropdown">
|
||||
<button class="dropbtn">Installing</button>
|
||||
<div class="dropdown-content">
|
||||
<a href="#Install_Apt"> Installing with apt</a>
|
||||
<a href="#Install_Deb"> Installing with a release deb package</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dropdown">
|
||||
<button class="dropbtn">Abbreviated Building</button>
|
||||
<div class="dropdown-content">
|
||||
<a href="#Build_Deb"> Building a deb package</a>
|
||||
<a href="#Abbreviated_Building"> Abbreviated Building Guide</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dropdown">
|
||||
<button class="dropbtn">Distribution Specific Building</button>
|
||||
<div class="dropdown-content">
|
||||
<a href="#Preparation_For_Building"> Preparation For Building </a>
|
||||
<a href="#BUILD_DEBIAN">Debian/Ubuntu/Raspberry Pi OS</a>
|
||||
<a href="#BUILD_FREEBSD">Free BSD</a>
|
||||
<a href="#BUILD_CENTOS">CentOS</a>
|
||||
<a href="#BUILD_MACOSX">MacOSX </a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dropdown">
|
||||
<button class="dropbtn">Configure/Make Options</button>
|
||||
<div class="dropdown-content">
|
||||
<a href="#Configure_Script"> Configure Script </a>
|
||||
<a href="#Make"> Make </a>
|
||||
<a href="#Make_Install"> Make Install </a>
|
||||
<a href="#Un_Install"> Un-install </a>
|
||||
<a href="#Additional_Make_Options"> Additional Make Options </a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dropdown">
|
||||
<button class="dropbtn">Upgrading/Translations</button>
|
||||
<div class="dropdown-content">
|
||||
<a href="#Upgrading_From_Older_Version"> Upgrading From Older Version </a>
|
||||
<a href="#Translations"> Native Language Support(Translations)</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="javascript:void(0);" class="icon" onclick="fnc_subnav()">menu⇓   </a>
|
||||
</div>
|
||||
|
||||
<section class="main-content" style="padding:0.5em 0.1em;height:1000px;font-size: 0.90em;">
|
||||
|
||||
<h3><a name="Install_Apt"></a> Installing with apt </h3>
|
||||
<ul>
|
||||
<p></p>
|
||||
Motion is part of the Debian, Ubuntu and Raspberry Pi OS repositories and can be installed with the apt tool. The
|
||||
version included with apt will be the version that was available when the distribution version
|
||||
was initially deployed and therefore may not represent the latest release.
|
||||
<p></p>
|
||||
To install via apt, open up a terminal window and type: <code><strong>sudo apt-get install motion</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
|
||||
<h3><a name="Install_Deb"></a> Installing with a release deb package </h3>
|
||||
<ul>
|
||||
Motion can also be installed from the release deb files which may provide a more recent version than what
|
||||
is available via apt.
|
||||
<p></p>
|
||||
Determine the deb file name that is appropriate for the distribution and platform from
|
||||
the <a href="https://github.com/Motion-Project/motion/releases">Releases</a> page
|
||||
and open up a terminal window and type:
|
||||
<p></p>
|
||||
<ul>
|
||||
<code><strong>wget https://github.com/Motion-Project/motion/releases/{deb package name} </strong></code>
|
||||
</ul>
|
||||
<p></p>
|
||||
Next, install the retrieved deb package. Below is a sample method to install that
|
||||
uses the gdebi tool. The author prefers this tool since it will automatically retrieve
|
||||
any dependency packages and yet still can be run without graphical interface.
|
||||
<p></p>
|
||||
<ul>
|
||||
<code><strong>sudo apt-get install gdebi-core</strong></code>
|
||||
<p></p>
|
||||
<code><strong>sudo gdebi {deb package name}</strong></code>
|
||||
</ul>
|
||||
<p></p>
|
||||
</ul>
|
||||
|
||||
<h3><a name="Build_Deb"></a> Building a deb package </h3>
|
||||
<ul>
|
||||
Users can also build their own deb package from source. It is often preferable to build and install a
|
||||
deb package rather than using the build from source options below since it is much easier to upgrade from
|
||||
and un-install Motion. The script that builds the deb packages released can be used to do this. Open
|
||||
a terminal window and type:
|
||||
<code><strong>wget https://raw.githubusercontent.com/Motion-Project/motion-packaging/master/builddeb.sh </strong></code>
|
||||
Since this is a script file, once it is downloaded open the file with a text viewer and review
|
||||
the script to see what it does. Never ever run a script without reviewing what it does!.
|
||||
<p></p>
|
||||
Within the script, you will see that it takes a few parameters which are optional.
|
||||
<code><strong> Username, EmailAddress, branch, install, arch</strong></code>
|
||||
If the parameters are not provided, the script will create defaults.
|
||||
<p></p>
|
||||
The general flow of the script is as follows:
|
||||
<ul>
|
||||
<li>Validate input parameters and set defaults as needed.</li>
|
||||
<li>Validate the required packages are installed and notify which ones are missing.</li>
|
||||
<li>Create temporary directories in /tmp</li>
|
||||
<li>Clone the Motion source code and packaging code to the temporary directories</li>
|
||||
<li>Switch to the branch specified in the parameter (or master if not specified)</li>
|
||||
<li>Build the debian package</li>
|
||||
<li>Clean up temporary directories</li>
|
||||
</ul>
|
||||
Once you have reviewed the script and determined that it is OK to run, close out of the editor and then
|
||||
run the command <code>chmod +x ./builddeb.sh</code> to make the script executable.
|
||||
<p></p>
|
||||
Run the script <code>./builddeb.sh myname myemail master n any</code>
|
||||
<p></p>
|
||||
The script will validate the dependencies and report any additional dependencies which must be installed or if
|
||||
all the dependencies are installed, it will create a deb package. Note that this may take a bit of time on
|
||||
slower computers.
|
||||
<p></p>
|
||||
Once the deb file is created, install it via the gdebi tool as described above.
|
||||
<p></p>
|
||||
</ul>
|
||||
|
||||
<h3><a name="Abbreviated_Building"></a> Abbreviated Building Guide </a> </h3>
|
||||
<ul>
|
||||
|
||||
<p></p>
|
||||
<p></p>
|
||||
If you are familiar with the building of applications, then the following is a basic build / install
|
||||
script. If errors occur during the process or you wish to customize the build, please
|
||||
review the extended building instructions further below.
|
||||
<p></p>
|
||||
Debian / Ubuntu / Raspberry Pi OS Packages
|
||||
<ul>
|
||||
<code><strong>sudo apt-get install autoconf automake autopoint build-essential pkgconf libtool libzip-dev
|
||||
libjpeg-dev git libavformat-dev libavcodec-dev libavutil-dev libswscale-dev libavdevice-dev
|
||||
libwebp-dev gettext libmicrohttpd-dev libcamera-tools libcamera-dev libcamera-v4l2</strong></code>
|
||||
<p></p>
|
||||
<code><strong>cd ~</strong></code>
|
||||
<br /><code><strong>git clone https://github.com/Motion-Project/motion.git</strong></code>
|
||||
<br /><code><strong>cd motion</strong></code>
|
||||
<br /><code><strong>autoreconf -fiv</strong></code>
|
||||
<br /><code><strong>./configure</strong></code>
|
||||
<br /><code><strong>make</strong></code>
|
||||
<br /><code><strong>make install</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
FreeBSD
|
||||
<ul>
|
||||
<code><strong>sudo pkg install autoconf pkgconf automake git ffmpeg gettext libmicrohttpd </strong></code>
|
||||
<p></p>
|
||||
<code><strong>cd ~</strong></code>
|
||||
<br /><code><strong>git clone https://github.com/Motion-Project/motion.git</strong></code>
|
||||
<br /><code><strong>cd motion</strong></code>
|
||||
<br /><code><strong>autoreconf -fiv</strong></code>
|
||||
<br /><code><strong>./configure</strong></code>
|
||||
<br /><code><strong>make</strong></code>
|
||||
<br /><code><strong>sudo make install</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
Mac OS X
|
||||
<ul>
|
||||
<code><strong>brew install ffmpeg pkg-config libjpeg libmicrohttpd automake</strong></code>
|
||||
<p></p>
|
||||
<code><strong>export PATH="/usr/local/opt/gettext/bin:/usr/local/bin:$PATH"</strong></code>
|
||||
<p></p>
|
||||
<code><strong>cd ~</strong></code>
|
||||
<br /><code><strong>git clone https://github.com/Motion-Project/motion.git</strong></code>
|
||||
<br /><code><strong>cd motion</strong></code>
|
||||
<br /><code><strong>autoreconf -fiv</strong></code>
|
||||
<br /><code><strong>./configure</strong></code>
|
||||
<br /><code><strong>make</strong></code>
|
||||
<br /><code><strong>make install</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<p></p>
|
||||
<p></p>
|
||||
|
||||
</ul>
|
||||
|
||||
<h3><a name="Preparation_For_Building"></a> Preparation For Building</a> </h3>
|
||||
<ul>
|
||||
<p></p>
|
||||
<p></p>
|
||||
In order to build Motion from source many shared libraries must be installed.
|
||||
The particular libraries needed will vary depending upon the features desired.
|
||||
<p></p>
|
||||
When you install software using pre-compiled binaries (Redhat type RPMs, Debian debs etc)
|
||||
you normally only get what is needed to run the programs themselves. In order to compile programs
|
||||
from source that use these libraries you also need to install the development packages.
|
||||
These are normally called the same name as the package suffixed by -devel or -dev. These development
|
||||
packages contain the header files (xxx.h) that Motion needs to build. If
|
||||
you build a library from sources you already have these header files. It is recommended to simply
|
||||
install the pre-compiled binary packages and their development brothers.
|
||||
<p></p>
|
||||
Open a terminal and run the following commands to install the packages.
|
||||
<p></p>
|
||||
<p></p>
|
||||
<p></p>
|
||||
|
||||
<h4><a name="BUILD_DEBIAN"></a>Debian/Ubuntu/Raspberry Pi OS</a> </h4>
|
||||
<ul>
|
||||
<li>Required</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo apt-get install autoconf automake autopoint build-essential pkgconf libtool libzip-dev
|
||||
libjpeg-dev git gettext libmicrohttpd-dev </strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<p></p>
|
||||
<li>Optional Packages</li>
|
||||
<ul>
|
||||
<li>FFMpeg Functionality(Required for creating movies, using network cameras, etc.)</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo apt-get install libavformat-dev libavcodec-dev libavutil-dev libswscale-dev libavdevice-dev</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>MySQL database functionality</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo apt-get install libmysqlclient-dev</strong></code>
|
||||
<p></p>
|
||||
or (depends upon your distribution and version)
|
||||
<p></p>
|
||||
<code><strong>sudo apt-get install default-libmysqlclient-dev</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>MariaDB database functionality</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo apt-get install libmariadb-dev</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>PostgreSQL database functionality</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo apt-get install libpq-dev</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>SQLite3 database functionality</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo apt-get install libsqlite3-dev</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>libcamera</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo apt-get install libcamera-tools libcamera-dev libcamera-v4l2</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>Webp Image Support</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo apt-get install libwebp-dev</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
|
||||
</ul>
|
||||
</ul>
|
||||
<p></p>
|
||||
<p></p>
|
||||
|
||||
<h4><a name="BUILD_FREEBSD"></a>FreeBSD</a> </h4>
|
||||
<ul>
|
||||
<li>Required packages</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong> sudo pkg install autoconf pkgconf automake git gettext libmicrohttpd</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>Optional packages</li>
|
||||
<ul>
|
||||
<li>FFMpeg Functionality(Required for creating movies, using network cameras, etc.)</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo pkg install ffmpeg</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>MySQL database functionality</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo pkg install mysql57-client openssl</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>MariaDB database functionality</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>Not known by author</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>PostgreSQL database functionality</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo pkg install postgresql95-contrib</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>SQLite3 database functionality</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo pkg install sqlite3</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>Webcam Support</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo pkg install v4l_compat webcamd</strong></code>
|
||||
<p></p>
|
||||
<li>Add cuse_load="YES" in /boot/loader.conf</li>
|
||||
<li>Add webcamd_enable="YES" in the /etc/rc.conf</li>
|
||||
<li>chmod 666 /dev/video0</li>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>Webp Image Support</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo pkg install libwebp</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>Temorary bktr Support</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo kldload bktr_mem.ko</strong></code><p></p>
|
||||
<code><strong>sudo kldload bktr.ko</strong></code><p></p>
|
||||
<code><strong>sudo sysctl hw.bt848.card=1</strong></code> ( Miro pctv )<p></p>
|
||||
<code><strong>sudo sysctl hw.bt848.tuner=10</strong></code> ( PHILIPS_FR1216_PAL )<p></p>
|
||||
<code><strong>sudo sysctl hw.bt848.format=0</strong></code> ( PAL )<p></p>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>Persistent bktr Support</li>
|
||||
<ul>
|
||||
<li>Add <code><strong>bktr_mem_load="YES"</strong></code> in /boot/loader.conf</li>
|
||||
<li>Add <code><strong>bktr_load="YES"</strong></code> in /boot/loader.conf</li>
|
||||
<li>Add <code><strong>hw.bt848.card=1</strong></code> in /etc/sysctl.conf</li>
|
||||
<li>Add <code><strong>hw.bt848.tuner=10</strong></code> in /etc/sysctl.conf</li>
|
||||
<li>Add <code><strong>hw.bt848.format=0</strong></code> in /etc/sysctl.conf</li>
|
||||
</ul>
|
||||
</ul>
|
||||
</ul>
|
||||
<p></p>
|
||||
<p></p>
|
||||
|
||||
<h4><a name="BUILD_CENTOS"></a>CentOS 8</a> </h4>
|
||||
<ul>
|
||||
<li>Required</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo yum install dnf-plugins-core</strong></code>
|
||||
<code><strong>yum config-manager --set-enabled PowerTools</strong></code>
|
||||
<code><strong>sudo yum groupinstall 'Development Tools'</strong></code>
|
||||
<p></p>
|
||||
<code><strong>sudo yum install libjpeg-turbo libjpeg-turbo-devel gettext libmicrohttpd-devel</strong></code>
|
||||
<p></p>
|
||||
<code><strong>sudo yum install libzip-devel</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<p></p>
|
||||
<li>Optional Packages</li>
|
||||
<ul>
|
||||
<li>FFMpeg Functionality(Required for creating movies, using network cameras, etc. SEE NOTE BELOW!)</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo yum localinstall --nogpgcheck https://download1.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm https://download1.rpmfusion.org/nonfree/el/rpmfusion-nonfree-release-8.noarch.rpm</strong></code>
|
||||
<p></p>
|
||||
<code><strong>sudo yum install ffmpeg ffmpeg-devel</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>MySQL database functionality</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>Not known by author</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>MariaDB database functionality</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo yum install mariadb-devel</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>PostgreSQL database functionality</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo yum install postgresql-devel</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>SQLite3 database functionality</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo yum install sqlite-devel</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<li>Webp Image Support</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>sudo yum install libwebp-devel</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
</ul>
|
||||
Important ffmpeg note: The ffmpeg libraries indicated above are provided by a external repository. This may
|
||||
change in the future. Validate that the repository is still valid when doing the install on CentOS systems.
|
||||
The default for the configure is to require that ffmpeg is installed. Use the configure option to
|
||||
compile without the ffmpeg functionality.
|
||||
</ul>
|
||||
<p></p>
|
||||
<p></p>
|
||||
|
||||
<h4><a name="BUILD_MACOSX"></a>MacOSX</a> </h4>
|
||||
<ul>
|
||||
<li>Required</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<li>Install brew as described on https://brew.sh</li>
|
||||
<p></p>
|
||||
<code><strong>brew upgrade ffmpeg pkg-config jpeg libmicrohttpd-dev</strong></code>
|
||||
<p></p>
|
||||
<code><strong>brew install ffmpeg pkg-config libjpeg libmicrohttpd </strong></code>
|
||||
<p></p>
|
||||
<code><strong>export PATH="/usr/local/opt/gettext/bin:/usr/local/bin:$PATH"</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
<p></p>
|
||||
<li>Optional Packages</li>
|
||||
<ul>
|
||||
<li>PostgreSQL database functionality</li>
|
||||
<ul>
|
||||
<p></p>
|
||||
<code><strong>brew upgrade postgresql</strong></code>
|
||||
<code><strong>brew install postgresql</strong></code>
|
||||
<p></p>
|
||||
</ul>
|
||||
</ul>
|
||||
</ul>
|
||||
<p></p>
|
||||
<p></p>
|
||||
|
||||
</ul>
|
||||
|
||||
<h3><a name="Configure_Script"></a> Configure Script</a> </h3>
|
||||
<ul>
|
||||
Motion uses a set tools called the "autotools" in order to generate the required scripts in order to
|
||||
compile and install Motion. The next step after installing all of the required and desired libraries is to
|
||||
have the autotools create a configure script. To do this open a terminal and change to the directory with
|
||||
the source code and type
|
||||
<p></p>
|
||||
<code>autoreconf </code>
|
||||
<p></p>
|
||||
If the 'configure' file exists and contains a valid script, the tool will return immediately since no additional work
|
||||
needs to be completed. If the script needs updating, then it will take a moment to return. Once it has been executed,
|
||||
a file called 'configure' will exist in the directory. Note that if the command is run as
|
||||
<p></p>
|
||||
<code>autoreconf -f</code>
|
||||
<p></p>
|
||||
The -f parameter instructs it to force a new configure file to be created. This can be preferable in certain
|
||||
situations so that the configure script gets updated with the correct version number.
|
||||
Once the 'configure' file is created, we can execute it. What the script does is interrogate the system and look
|
||||
for all the needed items in order to compile Motion. In this process it looks to determine which optional components
|
||||
have been installed on the system and if found sets flags to indicate for them to be included. If a particular library
|
||||
is required by Motion and is not found, the configure script will issue an error. The error means that the library was
|
||||
not found because it was either not installed or that it was installed into a location that the script could not find.
|
||||
With the Motion configure script, once it has ended it also lists out all of the optional components that were located.
|
||||
Note that if you KNOW that a particular component is installed yet the configure script reports it as not installed, then
|
||||
it may be necessary to use one or more of the configure options described below to tell the script where to find
|
||||
the particular component.
|
||||
|
||||
<p></p>
|
||||
To run the configure your current directory must be the motion directory. You type
|
||||
<p></p>
|
||||
<code>./configure</code>
|
||||
<p></p>
|
||||
You can add the parameter <code>./configure --help</code> to get help on the different switches.
|
||||
<p></p>
|
||||
When the configure script finishes you should validate that the options desired
|
||||
were correctly identified by the configure. In particular, the ffmpeg option is occasionally not
|
||||
found even if it is actually installed. Various users have indicated this to be a particular
|
||||
problem with the PI. If using a PI and have this issue, you can use the following option
|
||||
<p></p>
|
||||
<code>./configure --with-ffmpeg=/usr/lib/arm-linux-gnueabihf</code>
|
||||
<p></p>
|
||||
For a long term option, you can edit the file
|
||||
<code>$HOME/.bashrc</code>
|
||||
and within it place the following two lines at the end
|
||||
<code>PKG_CONFIG_PATH=/usr/lib/arm-linux-gnueabihf:$PKG_CONFIG_PATH</code>
|
||||
<code>export PKG_CONFIG_PATH</code> This option will however only become
|
||||
effective the next time you open the terminal shell.
|
||||
<p></p>
|
||||
<p></p>
|
||||
The following options can be specified with the configure script to customize
|
||||
how Motion is built.
|
||||
<div class="tblconfig">
|
||||
<table border="1" class="fixed" >
|
||||
<colgroup>
|
||||
<col width="200px">
|
||||
<col width="500px">
|
||||
<col width="700px">
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Options</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Description <br /> Defaults for the options are specified in brackets [ ]</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Editors comment </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > -h, --help </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > display this help and exit</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --help=short</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > display options specific to this package </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > This command shows the options special to Motion.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --help=recursive </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > display the short help of all the included packages </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >-V, --version </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > display version information and exit</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Provides the version number of the source code and autotools </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > -q, --quiet, --silent </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > do not print `checking...' messages </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Illustrates only the results of the script. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --cache-file=FILE </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > cache test results in FILE. [disabled] </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > No function</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > -C, --config-cach </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > alias for `--cache-file=config.cache' </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > No function </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > -n, --no-create</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > do not create output files </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Used for testing if other switches produce error - without writing anything to the disk </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --srcdir=DIR</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > find the sources in DIR. [configure dir or `..'] </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > DIR is a directory path. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Installation directories:</td>
|
||||
<th bgcolor="#edf4f9" word-wrap:break-word > </th>
|
||||
<th bgcolor="#edf4f9" word-wrap:break-word > </th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --prefix=PREFIX </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > install architecture-independent files in PREFIX <br /> [/usr/local]</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > The default /usr/local means that
|
||||
<br /><br />The executable binary "motion" is installed in /usr/local/bin
|
||||
<br /> The manual page in /usr/local/man/man1
|
||||
<br />The document files in /usr/local/docs/motion
|
||||
<br />The configuration file in /usr/local/etc/motion
|
||||
<br />The example config files in /usr/local/motion/examples
|
||||
<br /><br />If you are experimenting with many parallel versions it may be desirable to set the PREFIX to e.g. /usr/local/motion and then add /usr/local/motion/bin to your search path (or simply cd /usr/local/motion/bin before execution).
|
||||
<br /><br />This way you can change version just by changing the symbolic link in /usr/local/motion.
|
||||
<br /><br />If you are installing the software on a machine where you do not have access to the /usr/local but have write access to a home directory, then you should change this to point to a directory within your home tree.
|
||||
<br /><br />Example: --prefix=$HOME </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --exec-prefix=EPREFIX </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > install architecture-dependent files in EPREFIX <br /> [PREFIX] </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > This defines an alternative installation directory for the executable binary. <br /> Note: The executable binary will be placed in a directory "bin" below the directory specified by this option <br /> Author recommends leaving this as default (i.e. not setting it). </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --bindir=DIR</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > user executables [EPREFIX/bin] </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > With this option you can control exactly which directory the executable binary is installed. The previous option automatically adds the bin directory. Here you are in full control of the directory. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --sbindir=DIR </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > System admin executables [EPREFIX/sbin] </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Not used by Motion. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --libexecdir=DIR</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > program executables [EPREFIX/libexec] </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Not used by Motion. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --datadir=DIR</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > read-only architecture-independent data [PREFIX/share] </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Not used by Motion. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --sysconfdir=DIR</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > read-only single-machine data [PREFIX/etc] </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >
|
||||
This is where Motion both installs the default configuration file and also where it will later search for it. <br />
|
||||
Motion searches for the configuration file "motion.conf" in the following order:
|
||||
<br />
|
||||
<UL> <br />1. Current directory from where Motion was invoked
|
||||
<br />2. $HOME/.motion
|
||||
<br />3. The motion subdirectory inside the sysconfig directory set by this switch. If not defined the default is /usr/local/etc/ <br />
|
||||
</UL> <br /> Editor recommends leaving this at default. Be careful if you run "make install" again.
|
||||
This will overwrite the motion-dist.conf file that you may have edited.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --sharedstatedir=DIR </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > modifiable architecture-independent data [PREFIX/com] </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Not used by Motion. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --localstatedir=DIR </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > modifiable single-machine data [PREFIX/var] </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Not used by Motion. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --libdir=DIR </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > object code libraries [EPREFIX/lib]</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Not used by Motion. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --includedir=DIR</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > C header files [PREFIX/include] </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Not used by Motion. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --oldincludedir=DIR</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > C header files for non-gcc [/usr/include] </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Not used by Motion. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --infodir=DIR </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > info documentation [PREFIX/info] </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Not used by Motion. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --mandir=DIR</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > man documentation [PREFIX/man]</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Editor recommends the default.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th bgcolor="#edf4f9" word-wrap:break-word > Optional Packages: </th>
|
||||
<th bgcolor="#edf4f9" word-wrap:break-word > </th>
|
||||
<th bgcolor="#edf4f9" word-wrap:break-word > </th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --without-bktr </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Exclude bktr video subsystem devices </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > ONLY used in *BSD </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --without-v4l2 </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Exclude using v4l2 (video4linux2) subsystem. Makes Motion so it only supports network cameras. </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Can be used if you do not need support or lack some of the libraries for it. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --without-webp </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Compile without webp image support</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --with-ffmpeg=DIR </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Specify the path for the directory prefix in which the
|
||||
library and headers are installed.
|
||||
<br /> If not specified configure will search in /usr/ and /usr/local/ </td>
|
||||
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > DIR is the directory PREFIX in which
|
||||
the ffmpeg shared libraries and their headers are installed.
|
||||
<br /> If you install ffmpeg from sources and use the default directories or
|
||||
if ffmpeg is installed as a binary package (RPM or deb) you may not need to specify the directory prefix.
|
||||
Configure should find the libraries automatically.
|
||||
<br />If you installed ffmpeg from sources and specified a different --prefix when building f
|
||||
fmpeg you must use the same value for the DIR ( --with-ffmpeg=DIR)
|
||||
or export that location to be included in the PKG_CONFIG_PATH
|
||||
<br />The option of --with-ffmpeg is the default for Motion. If the required libraries are not located, the
|
||||
configure script will stop at the ffmpeg section and report which libraries need to be installed.
|
||||
Once the required libraries are installed, run the script again. As noted previously, make sure
|
||||
to install the -dev versions.
|
||||
<br />For more information on FFmpeg see the documentation for the FFmpeg project.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --without-ffmpeg </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Do not compile with ffmpeg </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Use this if you do not want to compile with ffmpeg. If ffmpeg is not installed you must specify this option for Motion to build without ffmpeg. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --without-mysql </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Do not compile with MySQL support </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Use this if you do not want to include MySQL support in the package. <br /> This can also be useful if you get compilation errors related to MySQL and you actually do not need the feature anyway. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --without-mariadb </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Do not compile with MariaDB support </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Use this if you do not want to include MariaDB support in the package. <br /> This can also be useful if you get compilation errors related to MariaDB and you actually do not need the feature anyway. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --without-pgsql </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Do not compile with PostgreSQL support </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Use this if you do not want to include PostgreSQL support in the package. <br /> This can also be useful if you get compilation errors related to PostgreSQL and you actually do not need the feature anyway. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --without-sqlite3 </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Disable sqlite3 support in motion. </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Use this if you do not want to include SQLite3 support in the package. <br /> This can also be useful if you get compilation errors related to SQLite3 and you actually do not need the feature anyway. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --without-optimizecpu </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Exclude autodetecting platform and cpu type. This will disable the compilation of gcc optimizing code by platform and cpu. </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Use this if the optimization causes problems. Not typically needed. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --with-developer-flags </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Add additional warning flags for the compiler. </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > This option is for developers only. It applies many compiler flags and errors on all warnings.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > --with-prototype-flags </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > Add additional warning flags for the compiler. </td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word > This option is similar to --with-developer-flags but does not include flags for prototypes. </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p></p>
|
||||
<p></p>
|
||||
</ul>
|
||||
|
||||
<h3><a name="Make"></a> Make </h3>
|
||||
<ul>
|
||||
Once the configure script has successfully finished and indicates all options desired, a 'makefile' is created.
|
||||
The makefile builds the Motion program and links in all of the required libraries. To run the makefile on most
|
||||
distributions, type: <code>make</code>
|
||||
<p></p>
|
||||
The makefile will go through each of the files and compile them. Depending upon the source code obtained, there may be
|
||||
warnings or usually none.
|
||||
<p></p>
|
||||
If the notifications indicate undefined references, then it is most likely that
|
||||
an additional library needs to be added in via the configure switches. Many of these additional missing libraries
|
||||
issues may be related to the version of ffmpeg and how it was built or installed. The following is a sample of some
|
||||
of the extra ffmpeg libraries that may need to be added to pkg-config <strong><code>.pc</code></strong> files that are
|
||||
located in the ffmpeg /lib/pkgconfig directory.
|
||||
<p></p>
|
||||
<code>
|
||||
-lavformat -lswscale -lavcodec -lavutil -lfdk-aac -lswresample -lm -lopus -lz -lva -lvpx -lx264 -lmp3lame -lbz2 -ldl -lvorbisenc -lvorbis -ltheoraenc -ltheoradec
|
||||
</code>
|
||||
<p></p>
|
||||
|
||||
<p></p>
|
||||
Once the makefile has completed correctly, it will report 'build complete'.
|
||||
<p></p>
|
||||
If you have run <code>make</code> before, you should run a <code>make clean</code> before
|
||||
running <code>make</code> again. This cleans out all the object files that were
|
||||
generated the previous time you ran <code>make</code>. If you do not run <code>make clean</code> first
|
||||
before you rebuild Motion you may not get the additional feature included.
|
||||
For example: If you built Motion without ffmpeg support and then add it later and rebuild Motion
|
||||
without running <code>make clean</code> first the ffmpeg feature does not get compiled into the Motion binary.
|
||||
<p></p>
|
||||
The first time you build Motion run <code>./configure</code>, <code>make</code>, <code>make install</code>.
|
||||
If you need to build it again (to run with different configure options) run <code>./configure</code>,
|
||||
<code>make clean</code>, <code>make</code>, <code>make install</code>.
|
||||
<p></p>
|
||||
</ul>
|
||||
|
||||
<h3><a name="Make_Install"></a> Make Install </h3>
|
||||
<ul>
|
||||
Type <code>make install</code> to install the files.
|
||||
<p></p>
|
||||
These commands create the required directories and copy the files into the following locations. (default directories):
|
||||
<ul>
|
||||
<li>/usr/local/bin</li>
|
||||
<li>/usr/local/etc/motion</li>
|
||||
<li>/usr/local/share/man/man1</li>
|
||||
<li>/usr/local/share/doc/motion</li>
|
||||
<li>/usr/local/share/locale</li>
|
||||
</ul>
|
||||
<p></p>
|
||||
The contents of what gets copied into each directory is as follows:
|
||||
(assuming the default PREFIX /usr/local was used when running configure. Otherwise adjust to the actual directory specified during the configure step.)
|
||||
<ul>
|
||||
<li> Executable binary "motion" to /usr/local/bin</li>
|
||||
<li> Manual page "motion.1" to /usr/local/share/man/man1</li>
|
||||
<li> Document files to /usr/local/share/doc/motion</li>
|
||||
<li> Example configuration files "*.conf" to /usr/local/etc/motion</li>
|
||||
<li> Translation files to /usr/local/share/locale/*/LC_MESSAGES</li>
|
||||
</ul>
|
||||
|
||||
Note that any existing files are overwritten. The default configuration file motion-dist.conf is named like
|
||||
this so that you do not get your working motion.conf file overwritten when you upgrade Motion.
|
||||
|
||||
<p></p>
|
||||
</ul>
|
||||
|
||||
<h3><a name="Un_Install"></a> Un-install </h3>
|
||||
<ul>
|
||||
From the Motion base installation directory run <code>make uninstall</code>
|
||||
<p></p>
|
||||
And delete the base installation directory in /usr/local and any link pointing to it. If you have forgotten where
|
||||
you installed it or someone else did it for you, simply search for the files and directories starting with Motion.
|
||||
If the filenames and the directories match the names described in the "Make Install" section of this document, you
|
||||
can safely delete them.
|
||||
<p></p>
|
||||
</ul>
|
||||
|
||||
<h3><a name="Additional_Make_Options"></a> Additional Make Options </h3>
|
||||
<ul>
|
||||
The make command can be run with several options.
|
||||
<code>make</code>,
|
||||
<code>make install</code> and
|
||||
<code>make uninstall</code> has already been described above.
|
||||
<p></p>
|
||||
<dl>
|
||||
<dt> <strong>make clean</strong> </dt>
|
||||
<dd> deletes all the binary files (object files) and the motion binary generated by make. It also deletes temporary files and any jpg files that motion has saved in the motion source directory. It is very important to always run <code>make clean</code> before you run <code>make</code> if you change the configuration (like adding features such as ffmpeg) and rebuild motion.</dd>
|
||||
</dl>
|
||||
<p></p>
|
||||
<dl>
|
||||
<dt> <strong>make distclean</strong> </dt>
|
||||
<dd> deletes the files: config.status, config.log, config.cache, Makefile, and motion.spec.</dd>
|
||||
</dl>
|
||||
<p></p>
|
||||
<dl>
|
||||
<dt> <strong>make cleanall</strong> </dt>
|
||||
<dd> Removes files created by autoreconf and runs a make clean. Resets to only files provided from source</dd>
|
||||
</dl>
|
||||
<p></p>
|
||||
<dl>
|
||||
<dt> <strong>maintainer-check</strong> </dt>
|
||||
<dd> Executes multiple configure and make using the developer flags for various combinations of the configure flags</dd>
|
||||
</dl>
|
||||
<p></p>
|
||||
<p></p>
|
||||
</ul>
|
||||
|
||||
<h3><a name="Upgrading_From_Older_Version"></a> Upgrading From Older Version </h3>
|
||||
<ul>
|
||||
If you are upgrading from an older version of Motion many options have been renamed, added or removed.
|
||||
The author recommends that you start by copying the configuration files from the older version to a safe
|
||||
location for reference only. Then start with a clean copy of the new motion-dist.conf installed and make changes to it.
|
||||
<p></p>
|
||||
<p></p>
|
||||
</ul>
|
||||
|
||||
<h3><a name="Translations"></a> Native Language Support(Translations)</h3>
|
||||
<ul>
|
||||
Motion now supports limited translations of message printed to the log or displayed on the web control
|
||||
page using the <code>gettext</code> application.
|
||||
<p></p>
|
||||
Translations should appear automatically based upon the LANG environment variable set on the
|
||||
machine running Motion. To see the LANG code for your machine, open a terminal and type
|
||||
<code>locale</code>. If the log and web control still display in English, then this means
|
||||
that translations have not been completed for that language. The Motion developers rely on
|
||||
the community to provide these translations to the project. Even those that do not how to
|
||||
program can assist in this process by editing the files in the po directory.
|
||||
<p></p>
|
||||
<p></p>
|
||||
</ul>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</section>
|
||||
</body>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,676 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link href="motion.png" rel="icon" type="image/png">
|
||||
<title>Motion</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" type="text/css" href="motion_stylesheet.css" media="screen">
|
||||
<script>
|
||||
function fnc_topnav() {
|
||||
var x = document.getElementById("id_topnav");
|
||||
if (x.className === "topnav") {
|
||||
x.className += " responsive";
|
||||
} else {
|
||||
x.className = "topnav";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="topnav" id="id_topnav">
|
||||
<img class="logoimg" src="motion.gif">
|
||||
|
||||
<a class="topnav-d" href="https://motion-project.github.io/motion_support.html">Support</a>
|
||||
<a class="topnav-d" href="https://motion-project.github.io/motion_news.html" >News</a>
|
||||
<a class="topnav-d" href="https://motion-project.github.io/motion_guide.html" >Documentation</a>
|
||||
<a class="topnav-d" href="https://motion-project.github.io/motion_download.html">Download</a>
|
||||
<a class="topnav-d" href="https://motion-project.github.io/index.html">Home</a>
|
||||
|
||||
<a class="topnav-m" href="https://motion-project.github.io/index.html">Home</a>
|
||||
<a class="topnav-m" href="https://motion-project.github.io/motion_download.html">Download</a>
|
||||
<a class="topnav-m" href="https://motion-project.github.io/motion_guide.html" >Documentation</a>
|
||||
<a class="topnav-m" href="https://motion-project.github.io/motion_news.html" >News</a>
|
||||
<a class="topnav-m" href="https://motion-project.github.io/motion_support.html">Support</a>
|
||||
|
||||
<a href="javascript:void(0);" class="icon" onclick="fnc_topnav()">☰</a>
|
||||
</div>
|
||||
<section class="page-header">
|
||||
<h1>
|
||||
Examples
|
||||
</h1>
|
||||
</section>
|
||||
<section class="main-content">
|
||||
|
||||
<h3><a name="Examples"></a> Examples</h3>
|
||||
<ul>
|
||||
The following provides some sample configuration options and examples for Motion.
|
||||
<li> <a href="#persistent_device"> Persistent v4l2 device name </a></li>
|
||||
<li> <a href="#extpipe_commands"> Sample extpipe commands </a></li>
|
||||
<li> <a href="#loopback_setup">Loopback device setup</a></li>
|
||||
<li> <a href="#ffmpeg_input_device">FFmpeg as input device</a></li>
|
||||
<li> <a href="#webcontrol_pages">Webcontrol pages</a></li>
|
||||
<li> <a href="#database_setup">Database setup</a></li>
|
||||
<li> <a href="#haar_setup">Haar setup</a></li>
|
||||
<li> <a href="#hog_setup">HOG setup</a></li>
|
||||
<li> <a href="#dnn_setup">DNN setup</a></li>
|
||||
<li> <a href="#haar_train">Haar Model Training</a></li>
|
||||
<li> <a href="#sound_sample">Sound Frequency Sample</a></li>
|
||||
<li> <a href="#fail2ban">Fail2Ban example</a></li>
|
||||
<li> <a href="#ptz">PTZ command examples</a></li>
|
||||
<p></p>
|
||||
<p></p>
|
||||
</ul>
|
||||
<p></p>
|
||||
<p></p>
|
||||
|
||||
<h3><a name="persistent_device"></a> Persistent v4l2 device name </h3>
|
||||
<ul>
|
||||
Since the exact device number is set by the kernel upon boot, when there is more than one video device
|
||||
it is possible that the particular cameras that were assigned to /dev/video0 and /dev/video1 may switch. In
|
||||
order to set up Motion so that a particular camera is always assigned the same way, users can set up
|
||||
a symbolic link using udev rules. To do this a unique attribute must be identified for each camera. The
|
||||
camera attributes can be viewed by using the command
|
||||
<code>udevadm info -a -p $(udevadm info -q path -n /dev/video0) </code> while the camera is attached. Usually
|
||||
a serial number can be used. ("Usually" because some cameras have been observed to have the same serial
|
||||
number for different cameras)
|
||||
<p></p>
|
||||
Once a unique attribute has been identified for each camera, edit or create the file
|
||||
<code>/etc/udev/rules.d/99-local.rules</code>.
|
||||
<p></p>
|
||||
Assuming that the unique attribute for the camera was name and was
|
||||
<code>ATTR{name}=="Philips SPC 900NC webcam"</code> you would add the following line to the
|
||||
99-local.rules file:
|
||||
<code> KERNEL=="video[0-9]*", ATTR{name}=="Philips\ SPC\ 900NC*", SYMLINK+="video-webcam0"</code>
|
||||
<p></p>
|
||||
Once the change has been made and saved, reboot the computer and there should now be a "sticky" device called
|
||||
/dev/video-webcam0
|
||||
<p></p>
|
||||
</ul>
|
||||
|
||||
<h3><a name="extpipe_commands"></a>Sample extpipe commands</h3>
|
||||
<ul>
|
||||
The following are some sample extpipe commands
|
||||
<p></p>
|
||||
<code>
|
||||
movie_extpipe mencoder -demuxer rawvideo -rawvideo w=%w:h=%h:i420 -ovc x264 -x264encopts bframes=4:frameref=1:subq=1:scenecut=-1:nob_adapt:threads=1:keyint=1000:8x8dct:vbv_bufsize=4000:crf=24:partitions=i8x8,i4x4:vbv_maxrate=800:no-chroma-me -vf denoise3d=16:12:48:4,pp=lb -of avi -o %f.avi - -fps %{fps}
|
||||
</code>
|
||||
<p></p>
|
||||
<code>
|
||||
movie_extpipe x264 - --input-res %wx%h --fps %{fps} --bitrate 2000 --preset ultrafast --quiet -o %f.mp4
|
||||
</code>
|
||||
<p></p>
|
||||
<code>
|
||||
movie_extpipe mencoder -demuxer rawvideo -rawvideo w=%w:h=%h:fps=%{fps} -ovc x264 -x264encopts preset=ultrafast -of lavf -o %f.mp4 - -fps %{fps}
|
||||
</code>
|
||||
<p></p>
|
||||
<code>
|
||||
movie_extpipe ffmpeg -y -f rawvideo -pix_fmt yuv420p -video_size %wx%h -framerate %{fps} -i pipe:0 -vcodec libx264 -preset ultrafast -f mp4 %f.mp4
|
||||
</code>
|
||||
<p></p>
|
||||
</ul>
|
||||
|
||||
<h3><a name="loopback_setup"></a>Loopback device setup</h3>
|
||||
<ul>
|
||||
The video loopback device can be added installed via apt in many distributions. The package tested
|
||||
with Motion is v4l2loopback-dkms. Once the package is installed, you just need to run
|
||||
<code>sudo modprobe v4l2loopback</code>. This will add a new video device that you
|
||||
can use for the loopback. It is believed that there are additional options associated with the
|
||||
v4l2loopback that allows for adding more than one device. See the documentation of the v4l2loopback
|
||||
project for additional details.
|
||||
<p></p>
|
||||
To activate the vloopback device in Motion set the 'video_pipe' option in the motion.conf file to the
|
||||
device name associated with the one created by v4l2loopback.
|
||||
<br />You can also view the special motion pictures where you see the changed pixels by setting the option
|
||||
'video_pipe_motion' in motion.conf. When setting the video_pipe and/or video_pipe_motion options
|
||||
specify the input device as e.g. /dev/video1.
|
||||
<p></p>
|
||||
De-activating should be done with this command
|
||||
<p></p>
|
||||
<code>sudo modprobe -r v4l2loopback</code>
|
||||
<p></p>
|
||||
</ul>
|
||||
|
||||
<h3><a name="ffmpeg_input_device"></a>Use ffmpeg as input device</h3>
|
||||
<ul>
|
||||
Sometimes the particular device is not function for Motion but does work with FFmpeg. In
|
||||
this situation the device can be setup to be used in Motion using FFMpeg as an intermediate
|
||||
application. The process would be to set up a loopback device and then have FFmpeg feed the
|
||||
video into that device and then Motion can read from it. The following are some examples. First set up
|
||||
the loopback device and set it to /dev/video0. Then start ffmpeg using options such as the following.
|
||||
<code> ffmpeg -re -i mymovie.mp4 -f v4l2 /dev/video0 </code> Then in a separate terminal, start Motion
|
||||
with it set to use the <code>/dev/video0</code> device as input. This method can can also be used to
|
||||
reformat the content to a different format. The following outputs the original movie into a gray pixel format.
|
||||
<code> ffmpeg -re -i mymovie.mp4 -f v4l2 -pix_fmt gray /dev/video0 </code>
|
||||
</ul>
|
||||
|
||||
<h3><a name="database_setup"></a>Database Setup</h3>
|
||||
<ul>
|
||||
If a database is specified in the Motion configuration, upon start up, Motion will check for a table in
|
||||
the database called "motion" and if it is not found, it will create it. This Motion specific table is
|
||||
required so that movies can be displayed on the webcontrol page. It tracks the movies created by Motion along
|
||||
with the various metadata about the movies. The following is a brief overview of how to create a simple database
|
||||
and specify it within the Motion parameters so recordings can be downloaded from the webcontrol.
|
||||
<ul>
|
||||
<div>
|
||||
<i><h4>sqlite3</h4></i>
|
||||
This database type is by far the easiest to set up since it is file based. Simply provide the
|
||||
parameters in the Motion configuration parameters
|
||||
<ul>
|
||||
<small><small><code>
|
||||
database_type sqlite3
|
||||
<br>database_dbname /full/path/and/file/name.db
|
||||
</code></small></small>
|
||||
</ul>
|
||||
While this is the easiest to set up, it has also been observed that it can at times be unstable. This
|
||||
is especially true if the database file is included as part of a archive process while in use by Motion.
|
||||
</div>
|
||||
<p></p>
|
||||
|
||||
<div>
|
||||
<i><h4>mariadb</h4></i>
|
||||
The following describes the process to set up a Mariadb database. If your machine already has a Mariadb database,
|
||||
adjust as appropriate to the situation that exists on your computer. Those with more experience with MariaDb are
|
||||
invited to provide suggestions and corrections to these steps.
|
||||
<small><small><code>
|
||||
<ul>
|
||||
sudo apt install libmariadb-dev libmariadb3 mariadb-client mariadb-client-core mariadb-common mariadb-server
|
||||
<br>sudo mariadb
|
||||
<ul>
|
||||
GRANT ALL ON *.* TO 'YourUserNameHere'@'localhost' IDENTIFIED BY 'YourPasswordHere' WITH GRANT OPTION;
|
||||
<br>FLUSH PRIVILEGES;
|
||||
<br>exit
|
||||
</ul>
|
||||
mariadb -u YourUserNameHere -p
|
||||
<ul>
|
||||
{enter YourPasswordHere}
|
||||
<br>create database motion;
|
||||
<br>use motion;
|
||||
<br>quit;
|
||||
</ul>
|
||||
</code></small></small>
|
||||
</ul>
|
||||
|
||||
Once the database is set up, check the status of Mariadb via systemctl.
|
||||
<ul>
|
||||
<small><small><code>
|
||||
sudo systemctl status mariadb
|
||||
</code></small></small>
|
||||
</ul>
|
||||
|
||||
Specify the following in the Motion configuration parameters.
|
||||
<ul>
|
||||
<small><small><code>
|
||||
database_type mariadb
|
||||
<br>database_dbname motion
|
||||
<br>database_host localhost
|
||||
<br>database_port 3306
|
||||
<br>database_user YourUserNameHere
|
||||
<br>database_password YourPasswordHere
|
||||
</code></small></small>
|
||||
</ul>
|
||||
</div>
|
||||
<p></p>
|
||||
|
||||
<div>
|
||||
<i><h4>postgresql</h4></i>
|
||||
The following describes the process to set up a PostgreSQL database.
|
||||
If your machine already has a PostgreSQL database,
|
||||
adjust as appropriate to the situation that exists on your computer.
|
||||
Those with more experience with PostgreSQL are
|
||||
invited to provide suggestions and corrections to these steps.
|
||||
<small><small><code>
|
||||
<ul>
|
||||
sudo apt install postgresql postgresql-contrib
|
||||
<br>sudo -u postgres psql
|
||||
<ul>
|
||||
CREATE ROLE 'your_username_here' LOGIN PASSWORD 'YourPasswordHere';
|
||||
<br>CREATE DATABASE motion WITH OWNER = your_username_here;
|
||||
<br>GRANT ALL PRIVILEGES ON DATABASE motion TO your_username_here;
|
||||
<br>\quit
|
||||
</ul>
|
||||
</code></small></small>
|
||||
</ul>
|
||||
|
||||
Once the database is set up, check the status via systemctl.
|
||||
<ul>
|
||||
<small><small><code>
|
||||
sudo systemctl status postgresql
|
||||
</code></small></small>
|
||||
</ul>
|
||||
|
||||
Check the login information via the following command line. (note that the
|
||||
username only seems to accept lowercase)
|
||||
<ul>
|
||||
<small><small><code>
|
||||
psql -h localhost -d motion -U your_username_here -p 5432
|
||||
</code></small></small>
|
||||
|
||||
Specify the following in the Motion configuration parameters.
|
||||
<ul>
|
||||
<small><small><code>
|
||||
database_type postgresql
|
||||
<br>database_dbname motion
|
||||
<br>database_host localhost
|
||||
<br>database_port 5432
|
||||
<br>database_user your_username_here
|
||||
<br>database_password YourPasswordHere
|
||||
</code></small></small>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<p></p>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</ul>
|
||||
|
||||
<h3><a name="webcontrol_pages"></a>Webcontrol pages</h3>
|
||||
<ul>
|
||||
<li><code>{IP}:{port0}/</code> Home html page with streams for all cameras</li>
|
||||
|
||||
The following JSON pages are available via the webcontrol.
|
||||
<ul>
|
||||
<li><code>{IP}:{port0}/0/config.json</code> JSON object with the configuration information for all cameras</li>
|
||||
<li><code>{IP}:{port0}/0/status.json</code> JSON object with information about status of all cameras</li>
|
||||
<li><code>{IP}:{port0}/0/movies.json</code> JSON object with information about all movies</li>
|
||||
</ul>
|
||||
The following mjpg streams are available via the webcontrol. (Update automatically). Specify {camid}
|
||||
as 0 to obtain a consolidated mjpg stream of all cameras.
|
||||
<ul>
|
||||
<li><code>{IP}:{port0}/{camid}/mjpg</code> Primary stream for the camera updated as a mjpg</li>
|
||||
<li><code>{IP}:{port0}/{camid}/mjpg/substream</code> Substream for the camera updated as a mjpg</li>
|
||||
<li><code>{IP}:{port0}/{camid}/mjpg/motion</code> Stream of motion images for the camera as a mjpg</li>
|
||||
<li><code>{IP}:{port0}/{camid}/mjpg/source</code> Source image stream of the camera as a mjpg</li>
|
||||
<li><code>{IP}:{port0}/{camid}/mjpg/secondary</code> Image from secondary detection stream (if active) as a mjpg</li>
|
||||
</ul>
|
||||
The following mpegts streams are available via the webcontrol. (Update automatically) Specify {camid}
|
||||
as 0 to obtain a consolidated mpegts stream of all cameras.
|
||||
<ul>
|
||||
<li><code>{IP}:{port0}/{camid}/mpegts</code> Primary stream for the camera updated as a mpeg transport stream</li>
|
||||
<li><code>{IP}:{port0}/{camid}/mpegts/substream</code> Substream for the camera updated as a mpeg transport stream</li>
|
||||
<li><code>{IP}:{port0}/{camid}/mpegts/motion</code> Stream of motion images for the camera as a mpeg transport stream</li>
|
||||
<li><code>{IP}:{port0}/{camid}/mpegts/source</code> Source image stream of the camera as a mpeg transport stream</li>
|
||||
<li><code>{IP}:{port0}/{camid}/mpegts/secondary</code> Image from secondary detection stream (if active) as a mpeg transport stream</li>
|
||||
</ul>
|
||||
The following static pages are available via the webcontrol. (Update manually) Specify {camid}
|
||||
as 0 to obtain a consolidated image of all cameras.
|
||||
<ul>
|
||||
<li><code>{IP}:{port0}/{camid}/static</code> Primary image for the camera</li>
|
||||
<li><code>{IP}:{port0}/{camid}/static/substream</code> Substream image for the camera</li>
|
||||
<li><code>{IP}:{port0}/{camid}/static/motion</code> Motion image for the camera</li>
|
||||
<li><code>{IP}:{port0}/{camid}/static/source</code> Source image of the camera</li>
|
||||
<li><code>{IP}:{port0}/{camid}/static/secondary</code> Image from secondary detection stream (if active)</li>
|
||||
</ul>
|
||||
The following actions can be executed by sending post request.
|
||||
<ul>
|
||||
<li><code>eventstart</code>Start an event</li>
|
||||
<li><code>eventend</code>End an event</li>
|
||||
<li><code>snapshot</code>Invoke a snapshot</li>
|
||||
<li><code>pause_on</code>Pause motion detection</li>
|
||||
<li><code>pause_off</code>Enable motion detection</li>
|
||||
<li><code>pause_schedule</code>Allow schedule to pause or enable motion detection</li>
|
||||
<li><code>restart</code>Restart camera</li>
|
||||
<li><code>stop</code>Stop camera</li>
|
||||
<li><code>config_write</code>Write out the configuration to file. User account running Motion must have write access to directory</li>
|
||||
<li><code>camera_add</code>Add a camera</li>
|
||||
<li><code>camera_delete</code>Delete camera</li>
|
||||
<li><code>config</code>Set configuration item</li>
|
||||
<li><code>action_user</code>Execute the on_action_user command. Provide as needed the additional parameter of action_user</li>
|
||||
<li><code>pan_left</code>Execute the ptz_pan_left command</li>
|
||||
<li><code>pan_right</code>Execute the ptz_pan_left command</li>
|
||||
<li><code>tilt_up</code>Execute the ptz_tilt_up</li>
|
||||
<li><code>tilt_down</code>Execute the ptz_tilt_down</li>
|
||||
<li><code>zoom_in</code>Execute ptz_zoom_in command</li>
|
||||
<li><code>zoom_out</code>Execute the ptz_zoom_out command</li>
|
||||
</ul>
|
||||
Sample commands
|
||||
<ul>
|
||||
<li><code>curl -s -o -X POST {IP}:{port0} --data "camid={camid}" --data "command=eventstart" 1>/dev/null</code></li>
|
||||
<li><code>curl -s -o -X POST {IP}:{port0} --data "camid={camid}" --data "command=config" --data "framerate=12" 1>/dev/null</code></li>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<h3><a name="haar_setup"></a>HAAR setup</h3>
|
||||
<ul>
|
||||
<li>Set the following Motion items within the secondardy_params</li>
|
||||
<ul>
|
||||
<li><code>frame_interval</code>Default: 5 | The number of images between each secondary detection</li>
|
||||
<li><code>image_type</code>Default: full | Type of image to process through secondary detection</li>
|
||||
<li><code>model_file</code>Default: None | Full path and file name for the haar model</li>
|
||||
<li><code>rotate</code>Default: 0 | Degrees of rotation of the image when processing through secondary detection </li>
|
||||
<li><code>threshold</code>Default: 1.10 | weights of detected values </li>
|
||||
</ul>
|
||||
<li>Set the following parameters to the OpenCV function <code>CascadeClassifier::detectMultScale</code> within the secondardy_params</li>
|
||||
</u>
|
||||
<li><code>scalefactor</code>Default: 1.10 | Scale factor to apply to the image</li>
|
||||
<li><code>flags</code>Default: 0 | </li>
|
||||
<li><code>maxsize</code>Default: 1024 | </li>
|
||||
<li><code>minsize</code>Default: 8 | </li>
|
||||
<li><code>minneighbors</code>Default: 8 | </li>
|
||||
</ul>
|
||||
|
||||
</ul>
|
||||
|
||||
<h3><a name="hog_device"></a>HOG setup</h3>
|
||||
<ul>
|
||||
<li>Set the following items within the secondardy_params</li>
|
||||
<ul>
|
||||
<li><code>frame_interval</code>Default: 5 | The number of images between each secondary detection</li>
|
||||
<li><code>image_type</code>Default: full | Type of image to process through secondary detection</li>
|
||||
<li><code>model_file</code>Default: None | Full path and file name for the haar model</li>
|
||||
<li><code>rotate</code>Default: 0 | Degrees of rotation of the image when processing through secondary detection </li>
|
||||
<li><code>threshold</code>Default: 1.10 | Weights of detected values</li>
|
||||
</ul>
|
||||
<li>Set the following parameters to the OpenCV function <code>HOGDescriptor::detectMultScale</code> within the secondardy_params</li>
|
||||
<ul>
|
||||
<li><code>threshold_model</code>Default: 2.00 | </li>
|
||||
<li><code>scalefactor</code>Default: 1.05 | </li>
|
||||
<li><code>padding</code>Default: 8 | </li>
|
||||
<li><code>winstride</code>Default: 8 | </li>
|
||||
</ul>
|
||||
|
||||
</ul>
|
||||
|
||||
<h3><a name="dnn_setup"></a>DNN setup</h3>
|
||||
<ul>
|
||||
<li>Set the following items within the secondardy_params</li>
|
||||
<ul>
|
||||
<li><code>model_file</code>Default: None | Full path and file name for the haar model</li>
|
||||
<li><code>frame_interval</code>Default: 5 | The number of images between each secondary detection</li>
|
||||
<li><code>image_type</code>Default: full | Type of image to process through secondary detection</li>
|
||||
<li><code>rotate</code>Default: 0 | Degrees of rotation of the image when processing through secondary detection </li>
|
||||
<li><code>threshold</code>Default: 0.75 | Confidence threshold</li>
|
||||
<li><code>scalefactor</code>Default: 1.05 | </li>
|
||||
|
||||
<li><code>backend</code>Default: 0(DNN_BACKEND_DEFAULT) | </li>
|
||||
<li><code>target</code>Default: 0(DNN_TARGET_CPU) | </li>
|
||||
<li><code>width</code>Default: none | Width for the model (not the source image)</li>
|
||||
<li><code>height</code>Default: none | Height for the model (not the source image)</li>
|
||||
<li><code>scale</code>Default: none | Scale used in the model</li>
|
||||
<li><code>config</code>Default: none | </li>
|
||||
<li><code>classes_file</code>Default: none | Full path and name for a file with the names of the classes </li>
|
||||
<li><code>framework</code>Default: none | </li>
|
||||
</ul>
|
||||
|
||||
</ul>
|
||||
|
||||
<h3><a name="haar_train"></a>Haar Model Training</h3>
|
||||
<ul>
|
||||
The OpenCV documentation is the definitive source for instructions on how to train
|
||||
a Haar model. This brief introduction only provides a few scripts that may be
|
||||
helpful in using Motion to get positive and negative images to feed into the
|
||||
training process.
|
||||
<br>
|
||||
<br>Start with creating positive images movie as input file.
|
||||
<br>Run with picture_output_motion roi
|
||||
<br>Remove any pictures that are not desired.
|
||||
<br>Run the script to create the positive file list
|
||||
<br>Run while in the directory with the positive images.
|
||||
<small><code><ul>
|
||||
opencv_createsamples -vec posfiles.vec -info poslist.txt -num 350 -h 96 -w 96
|
||||
</ul></code></small>
|
||||
Next get a sample file that does not have desired positives.
|
||||
<br>Change to picture_output on and turn off motion roi
|
||||
<br>Change threshold to tiny number and run to create negatives
|
||||
<small><code><ul>
|
||||
opencv_traincascade -data ./model -vec ./pos/posfiles.vec -bg neglist.txt -numPos 350 -numNeg 325
|
||||
</ul></code></small>
|
||||
The following are the simple scripts to create positive and negative list files for training
|
||||
<small><small><code>
|
||||
<ul>
|
||||
!/bin/bash
|
||||
<br>FILES=./pos/*.jpg
|
||||
<br>for FULLNAME in $FILES
|
||||
<br>do
|
||||
<br>HW=$(identify -format '%w %h' $FULLNAME)
|
||||
<br>printf "$FULLNAME 1 0 0 $HW \n" >>poslist.txt
|
||||
<br>done
|
||||
</ul>
|
||||
<ul>
|
||||
<br>!/bin/bash
|
||||
<br>FILES=./neg/*.jpg
|
||||
<br>for FULLNAME in $FILES
|
||||
<br>do
|
||||
<br> printf "$FULLNAME \n" >>neglist.txt
|
||||
<br>done
|
||||
</ul>
|
||||
</code></small></small>
|
||||
|
||||
</ul>
|
||||
|
||||
<h3><a name="sound_sample"></a>Sound Frequency Sample</h3>
|
||||
<ul>
|
||||
Since sound frequency processing is new to Motion, the following provides an illustrative sample of setting
|
||||
up the sound and the associated alerts processing. This example will use ALSA. For PulseAudio, Motion uses
|
||||
the default audio recording device. Although Motion has parameters for the PulseAudio server and device,
|
||||
the set up is not straight forward and it is just recommended to change the PulseAudio default.
|
||||
<br>
|
||||
<br>Go to the command prompt and use <small><code>arecord -l</code></small> to get the
|
||||
device name such as <small><code>hw:1,0</code></small>
|
||||
<br>Specify log_level 8 in Motion.conf
|
||||
<br>Do not specify a log file so that it is console output.
|
||||
<br>Specify snd_device and snd_show in the sound configuration file such as
|
||||
<br><small><code>snd_device hw:1,0</code></small>
|
||||
<br><small><code>snd_show on</code></small>
|
||||
<br>Start Motion and make a noise to test the output.
|
||||
<br>Once Motion responds to sounds, press the test button on the device to be monitored.
|
||||
<br>Note that while the various devices being monitored may be the same, the detected frequency from
|
||||
each may be slightly different. Care should be taken to not be too precise in the setting of the alert
|
||||
range for Motion. For example, the frequency may be reported as 3402.2456 and Motion can be
|
||||
set up to look for that precise number but devices age and the frequency may change. Also, note that the
|
||||
frequency resolution of Motion is limited by the sample rate and frames from the audio device.
|
||||
The maximum resolution is determined by the following formula. Sample Rate / (frames * 2). So with the
|
||||
default sample rate of 44100hz, and frames of 2048, the maximum resolution is appoximately 10.7666hz. This
|
||||
means that the frequencies detected around the range reported above would be 3413.0122, 3402.2456
|
||||
or 3391.4790 and no values between.
|
||||
<br>Once the frequencies of all the devices have been logged, set up the alerts in the sound configuration
|
||||
file as well as the on_sound_alert and turn off the showing of frequencies. (The frequencies in this sample
|
||||
are random)
|
||||
<small><code><ul>
|
||||
<br>snd_alerts alert_id=01,volume_level=01,volume_count=10,freq_low=2976,freq_high=2977,alert_nm=smokedown1
|
||||
<br>snd_alerts alert_id=02,volume_level=01,volume_count=10,freq_low=3400,freq_high=3450,alert_nm=smokelr
|
||||
<br>snd_alerts alert_id=03,volume_level=01,volume_count=10,freq_low=3388,freq_high=3399,alert_nm=smokebr1
|
||||
<br>snd_alerts alert_id=11,volume_level=01,volume_count=10,freq_low=3378,freq_high=3379,alert_nm=furnace
|
||||
<br>snd_alerts alert_id=22,volume_level=01,volume_count=10,freq_low=3281,freq_high=3399,alert_nm=waterheater
|
||||
<br>snd_alerts alert_id=22,volume_level=01,volume_count=10,freq_low=3270,freq_high=3279,alert_nm=kitchBath
|
||||
<br>snd_show off
|
||||
<br>on_sound_alert %{trig_nbr} %{trig_nm} %{trig_freq}
|
||||
<br>
|
||||
</ul></code></small>
|
||||
Then you can set up a script to send email or text messages using the sendemail
|
||||
application like below
|
||||
<small><small><code>
|
||||
<ul>
|
||||
<br>#!/bin/bash
|
||||
<br> ALRTNBR=$1
|
||||
<br> ALRTNM=$2
|
||||
<br> FREQ=$3
|
||||
<br> ATCH=$4
|
||||
<br> MYSTR=""
|
||||
<br> MYSTR=$MYSTR" -f \"Friendly Name <SendingEmailAddress@gwhatever.com>\" "
|
||||
<br> MYSTR=$MYSTR" -t \"DestinationEmailAddress@gwhatever.com\" "
|
||||
<br> MYSTR=$MYSTR" -u \"Motion Notification\" "
|
||||
<br> MYSTR=$MYSTR" -s \"smtp.gwhatever.com:587\" "
|
||||
<br> MYSTR=$MYSTR" -xu \"SendingEmailAddress@gwhatever.com\" "
|
||||
<br> MYSTR=$MYSTR" -xp \"SendingEmailPassword\" "
|
||||
<br> BODY=""
|
||||
<br> if [[ "$ALRTNBR" -ge 1 && "$ALRTNBR" -le 9 ]]; then
|
||||
<br> BODY="So, hey. Sorry to bother you. But thought I'd just let"
|
||||
<br> BODY=$BODY" you know that your house is burning down. The neighbors"
|
||||
<br> BODY=$BODY" may get annoyed so you should think about doing something. "
|
||||
<br> BODY=$BODY" The "$ALRTNM" alert numbered "$ALRTNBR" was triggered with "
|
||||
<br> BODY=$BODY" frequency "$FREQ
|
||||
<br> elif [[ "$ALRTNBR" -ge 10 && "$ALRTNBR" -le 19 ]]; then
|
||||
<br> BODY="Hi. So I noticed that the natural gas leak alarm is going off."
|
||||
<br> BODY=$BODY" Nothing too urgent or anything but when you get home, you"
|
||||
<br> BODY=$BODY" may want to hold off making any sparks to avoid blowing yourself up."
|
||||
<br> BODY=$BODY" The "$ALRTNM" alert numbered "$ALRTNBR" was triggered with "
|
||||
<br> BODY=$BODY" frequency "$FREQ
|
||||
<br> elif [[ "$ALRTNBR" -ge 20 && "$ALRTNBR" -le 29 ]]; then
|
||||
<br> BODY="Ahoy! Your house is going to be next water park attraction in"
|
||||
<br> BODY=$BODY" the neighborhood!!! The water is filling it up and the"
|
||||
<br> BODY=$BODY" children will be splashing around in it soon."
|
||||
<br> BODY=$BODY" The "$ALRTNM" alert numbered "$ALRTNBR" was triggered with "
|
||||
<br> BODY=$BODY" frequency "$FREQ
|
||||
<br> fi
|
||||
<br> if [ "$BODY" != "" ]; then
|
||||
<br> MYSTR=$MYSTR" -m \""$BODY"\" "
|
||||
<br> if [ -f "$ATCH" ]; then
|
||||
<br> MYSTR=$MYSTR" -m \""$ATCH"\" "
|
||||
<br> fi
|
||||
<br> sendemail $MYSTR
|
||||
<br> fi
|
||||
<br>exit 0
|
||||
</ul>
|
||||
</code></small></small>
|
||||
|
||||
</ul>
|
||||
|
||||
<h3><a name="fail2ban"></a>Fail2Ban Example</h3>
|
||||
<ul>
|
||||
The following are example files to use with the fail2ban application. This allows users to ban IPs that
|
||||
may be attempting to get in. This example was created using Debian 11. Adjust as appropriate for other
|
||||
distros and versions.
|
||||
<br>
|
||||
Install fail2ban and create the following files:
|
||||
<br>File 1:
|
||||
<small><small><code><ul>
|
||||
<br> # Fail2Ban configuration file: /etc/fail2ban/filter.d/motion.conf
|
||||
<br> # Author: Mr Dave
|
||||
<br> #
|
||||
<br> [INCLUDES]
|
||||
<br> # Read common prefixes. If any customizations available -- read them from common.local
|
||||
<br> before = common.conf
|
||||
<br>
|
||||
<br> [Definition]
|
||||
<br> daemon = nsd
|
||||
<br>
|
||||
<br> # Option: failregex
|
||||
<br> # Notes.:
|
||||
<br> # regex to match the log in failures messages in the logfile. The
|
||||
<br> # host must be matched by a group named "host". The tag "<HOST>" can
|
||||
<br> # be used for standard IP/hostname matching and is only an alias for
|
||||
<br> # (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
|
||||
<br> # Sample: Jul 01 02:50:32 [EMG][STR][00:wc00] webu_failauth_check: Ignoring connection from: 192.168.1.10
|
||||
<br> # Values: TEXT
|
||||
<br>
|
||||
<br> failregex = ^.*Ignoring connection from: <HOST>$
|
||||
<br>
|
||||
<br> ignoreregex =
|
||||
<br>
|
||||
<br> datepattern = {^LN-BEG}Epoch
|
||||
<br> {^LN-BEG}
|
||||
<br>
|
||||
</ul></code></small></small>
|
||||
<br>File2:
|
||||
<small><small><code><ul>
|
||||
<br> #Fail2Ban Jail Configuration File: /etc/fail2ban/jail.d/motion-jail.conf
|
||||
<br> [motion]
|
||||
<br> enabled = true
|
||||
<br> filter = motion
|
||||
<br> logpath = /var/log/motion/motion.log
|
||||
<br> bantime = 23h
|
||||
<br> banaction = iptables-allports[blocktype="DROP"]
|
||||
<br> maxretry = 0
|
||||
<br> port = 0:65535
|
||||
</ul></code></small></small>
|
||||
<br>Make sure to adjust the log file location indicated in the jail file as well as how long to ban the IP address.
|
||||
</ul>
|
||||
|
||||
<h3><a name="ptz"></a>PTZ command examples</h3>
|
||||
<ul>
|
||||
The following are some example sources and scripts to send PTZ (Pan Tilt Zoom) commands to cameras.
|
||||
<br><br>
|
||||
<a href="https://github.com/667bdrm/sofiactl">sofiactl</a> is a Perl script that can control many imported inexpensive cameras.
|
||||
<br> Adjust script location, timing, cameraip, user, etc as appropriate.
|
||||
<small><small><code><ul>
|
||||
<br> #!/bin/bash
|
||||
<br> sofiactl.pl --user admin --host cameraip --port 34567 --command OPPTZControl --sd ZoomTile --s2 0.5
|
||||
<br> sofiactl.pl --user admin --host cameraip --port 34567 --command OPPTZControl --sd ZoomWide --s2 0.5
|
||||
<br> sofiactl.pl --user admin --host cameraip --port 34567 --command OPPTZControl --sd DirectionUp --s2 2.0
|
||||
<br> sofiactl.pl --user admin --host cameraip --port 34567 --command OPPTZControl --sd DirectionDown --s2 2.0
|
||||
<br> sofiactl.pl --user admin --host cameraip --port 34567 --command OPPTZControl --sd DirectionLeft --s2 2.0
|
||||
<br> sofiactl.pl --user admin --host cameraip --port 34567 --command OPPTZControl --sd DirectionRight --s2 2.0
|
||||
<br> exit
|
||||
</ul></code></small></small>
|
||||
|
||||
<br>
|
||||
<a href="https://github.com/Mr-Dave/camxmctl">camxmctl</a> is a c++ program with a sample HTML page that makes adjusting the parameters
|
||||
easier. It reuses some of the code from Motion and is based upon the JSON files and commands in the
|
||||
<a href="https://github.com/667bdrm/sofiactl">sofiactl</a> script.
|
||||
<br> Adjust location, timing, cameraip, user, etc as appropriate.
|
||||
<small><small><code><ul>
|
||||
<br> #!/bin/bash
|
||||
<br> tbd. Review sample page to see post commands.
|
||||
<br> exit
|
||||
</ul></code></small></small>
|
||||
|
||||
<br>
|
||||
curl scripts. Example 1
|
||||
<br> Adjust as appropriate.
|
||||
<small><small><code><ul>
|
||||
<br> #!/bin/bash
|
||||
<br> curl -X PUT -H "Content-Type: application/x-www-form-urlencoded" -d 'Param1=1' http://admin@cameraip:80/PTZ/1/TurnDown
|
||||
<br> sleep 2
|
||||
<br> curl -X PUT -H "Content-Type: application/x-www-form-urlencoded" -d 'Param1=0' http://admin@cameraip:80/PTZ/1/TurnDown
|
||||
<br> exit
|
||||
<br> #!/bin/bash
|
||||
<br> curl -X PUT -H "Content-Type: application/x-www-form-urlencoded" -d 'Param1=1' http://admin@cameraip:80/PTZ/1/TurnLeft
|
||||
<br> sleep 2
|
||||
<br> curl -X PUT -H "Content-Type: application/x-www-form-urlencoded" -d 'Param1=0' http://admin@cameraip:80/PTZ/1/TurnLeft
|
||||
<br> exit
|
||||
<br> #!/bin/bash
|
||||
<br> curl -X PUT -H "Content-Type: application/x-www-form-urlencoded" -d 'Param1=1' http://admin@cameraip:80/PTZ/1/TurnRight
|
||||
<br> sleep 2
|
||||
<br> curl -X PUT -H "Content-Type: application/x-www-form-urlencoded" -d 'Param1=0' http://admin@cameraip:80/PTZ/1/TurnRight
|
||||
<br> exit
|
||||
<br> #!/bin/bash
|
||||
<br> curl -X PUT -H "Content-Type: application/x-www-form-urlencoded" -d 'Param1=1' http://admin@cameraip:80/PTZ/1/TurnUp
|
||||
<br> sleep 2
|
||||
<br> curl -X PUT -H "Content-Type: application/x-www-form-urlencoded" -d 'Param1=0' http://admin@cameraip:80/PTZ/1/TurnUp
|
||||
<br> exit
|
||||
</ul></code></small></small>
|
||||
|
||||
<br>
|
||||
curl scripts. Example 2
|
||||
<br> Adjust as appropriate.
|
||||
<small><small><code><ul>
|
||||
<br> #!/bin/bash
|
||||
<br> curl 'http://admin:admin@cameraip:80/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=left&-speed=45'
|
||||
<br> sleep 1
|
||||
<br> curl 'http://admin:admin@cameraip:80/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=stop&-speed=45'
|
||||
<br> exit
|
||||
<br> #!/bin/bash
|
||||
<br> curl 'http://admin:admin@cameraip:80/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=right&-speed=45'
|
||||
<br> sleep 1
|
||||
<br> curl 'http://admin:admin@cameraip:80/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=stop&-speed=45'
|
||||
<br> exit
|
||||
<br> #!/bin/bash
|
||||
<br> curl 'http://admin:admin@cameraip:80/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=down&-speed=45'
|
||||
<br> sleep 1
|
||||
<br> curl 'http://admin:admin@cameraip:80/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=stop&-speed=45'
|
||||
<br> exit
|
||||
<br> #!/bin/bash
|
||||
<br> curl 'http://admin:admin@cameraip:80/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=up&-speed=45'
|
||||
<br> sleep 1
|
||||
<br> curl 'http://admin:admin@cameraip:80/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=stop&-speed=45'
|
||||
<br> exit
|
||||
<br> #!/bin/bash
|
||||
<br> curl 'http://admin:admin@cameraip:80/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=zoomin&-speed=45'
|
||||
<br> sleep 1
|
||||
<br> curl 'http://admin:admin@cameraip:80/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=stop&-speed=45'
|
||||
<br> exit
|
||||
<br> #!/bin/bash
|
||||
<br> curl 'http://admin:admin@cameraip:80/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=zoomout&-speed=45'
|
||||
<br> sleep 1
|
||||
<br> curl 'http://admin:admin@cameraip:80/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=stop&-speed=45'
|
||||
<br> exit
|
||||
</ul></code></small></small>
|
||||
</ul>
|
||||
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+14
-219
@@ -42,233 +42,28 @@
|
||||
</section>
|
||||
<section class="main-content">
|
||||
|
||||
<h3><a name="Current_Release"></a> Latest Stable Release</h3>
|
||||
<ul>
|
||||
<li> <a href="motion_build.html"> Building from source </a></li>
|
||||
<li> <a href="motion_config.html"> Configuration Options </a></li>
|
||||
<li> <a href="motion_examples.html"> Examples</a></li>
|
||||
<p></p>
|
||||
<p></p>
|
||||
</ul>
|
||||
<p></p>
|
||||
The links below provide the documentation associated with the various releases of the Motion and MotionPlus software.
|
||||
<p></p>
|
||||
Short videos demonstrating the Motion software can also be viewed
|
||||
<a href="https://www.youtube.com/channel/UCZpOjUMnc-uO3qIyZAD_4lg/videos"> here</a>.
|
||||
<p></p>
|
||||
|
||||
|
||||
<h3><a name="Current_Release"></a>Documentation For Latest Releases</h3>
|
||||
<div class="tblreleasecurrent">
|
||||
<table style="border-width:0.5px; text-align: center;" cellspacing="0" cellpadding="0" >
|
||||
<colgroup>
|
||||
<col width="300px">
|
||||
<col width="300px">
|
||||
<col width="300px">
|
||||
</colgroup>
|
||||
<thead >
|
||||
<tr >
|
||||
<th word-wrap:break-word > Motion </th>
|
||||
<td word-wrap:break-word > </td>
|
||||
<th word-wrap:break-word > MotionPlus </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td word-wrap:break-word > <a href="motion_build.html">Installing and building from source </a></td>
|
||||
<td word-wrap:break-word > </td>
|
||||
<td word-wrap:break-word > <a href="motionplus_build.html">Installing and building from source </a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td word-wrap:break-word > <a href="motion_config.html">Configuration</a></td>
|
||||
<td word-wrap:break-word > </td>
|
||||
<td word-wrap:break-word > <a href="motionplus_config.html">Configuration</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td word-wrap:break-word > </a></td>
|
||||
<td word-wrap:break-word > </td>
|
||||
<td word-wrap:break-word > <a href="motionplus_examples.html">Examples</a></td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<p></p>
|
||||
<p></p>
|
||||
<p></p>
|
||||
<p></p>
|
||||
<h3><a name="Prior"></a> Prior Release Versions</h3>
|
||||
<ul>
|
||||
|
||||
<h3><a name="Comparison"></a>Comparison Of Motion vs MotionPlus</h3>
|
||||
<div>
|
||||
<table class="tblcomp" >
|
||||
<colgroup>
|
||||
<col width="300px">
|
||||
<col width="300px">
|
||||
<col width="300px">
|
||||
</colgroup>
|
||||
<thead >
|
||||
<tr >
|
||||
<th bgcolor="#edf4f9" word-wrap:break-word >Motion</th>
|
||||
<th bgcolor="#edf4f9" word-wrap:break-word >Description</th>
|
||||
<th bgcolor="#edf4f9" word-wrap:break-word >MotionPlus</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >None</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Enhancements</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Optional</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >FFmpeg Libraries</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Required</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Supported</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Multiple input v4l2 cards(RoundRobin)</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Not Supported</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Supported</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Brooktree video cards</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Not Supported</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Internal partial legacy</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Camera Tracking</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >External scripts only</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Optional</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Multiple ports for web control and streams</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Single port only</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >-</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >OpenCV Cascades/HOG/DNN</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >-</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Pi camera controls</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >-</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Sound recording from passthrough cameras</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >-</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Sound frequency detection</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >-</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Enhanced webcontrol<ul>
|
||||
<li> Download/Play movies</li>
|
||||
<li> Ability to change configuration parameters</li>
|
||||
<li> Optional user developed web page</li>
|
||||
<li> Add/delete cameras</li>
|
||||
<li> Consolidated single image stream of all cameras</li>
|
||||
<li> MpegTS video stream feeds</li>
|
||||
<li> Execution of custom events/actions</li>
|
||||
<li> Live feed of Motionplus log messages</li>
|
||||
</ul></td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >-</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Additional Motion detection measures</td>
|
||||
<td bgcolor="#edf4f9" word-wrap:break-word >Yes</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</ul>
|
||||
<p></p>
|
||||
<p></p>
|
||||
<p></p>
|
||||
<p></p>
|
||||
|
||||
<h3><a name="Prior"></a>Documentation For Prior Releases</h3>
|
||||
<p></p>
|
||||
The documentation is provided as it was included in each release.
|
||||
<p></p>
|
||||
<p></p>
|
||||
|
||||
<div class="tblreleaseprior">
|
||||
<table style="border-width:0.5px; text-align: center;" cellspacing="0" cellpadding="0" >
|
||||
<colgroup>
|
||||
<col width="500px">
|
||||
<col width="500px">
|
||||
</colgroup>
|
||||
<thead >
|
||||
<tr >
|
||||
<th word-wrap:break-word > Motion </th>
|
||||
<th word-wrap:break-word > MotionPlus </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td word-wrap:break-word > <a href="4.6.0/motion_config.html"> Version 4.6.0</a> </td>
|
||||
<td word-wrap:break-word > <a href="mp0.1.0/motionplus_config.html"> Version 0.2.0</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td word-wrap:break-word > <a href="4.5.1/motion_config.html"> Version 4.5.1</a> </td>
|
||||
<td word-wrap:break-word > <a href="mp0.1.0/motionplus_config.html"> Version 0.1.0</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td word-wrap:break-word > <a href="4.5.0/motion_config.html"> Version 4.5.0</a> </td>
|
||||
<td word-wrap:break-word > </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td word-wrap:break-word > <a href="4.4.0/motion_config.html"> Version 4.4.0</a> </td>
|
||||
<td word-wrap:break-word > </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td word-wrap:break-word > <a href="4.3.2/motion_config.html"> Version 4.3.2</a> </td>
|
||||
<td word-wrap:break-word > </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td word-wrap:break-word > <a href="4.3.1/motion_config.html"> Version 4.3.1</a></td>
|
||||
<td word-wrap:break-word > </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td word-wrap:break-word > <a href="4.3.0/motion_config.html"> Version 4.3.0</a></td>
|
||||
<td word-wrap:break-word > </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td word-wrap:break-word ><a href="4.2.2/motion_config.html"> Version 4.2.2</a> </td>
|
||||
<td word-wrap:break-word > </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td word-wrap:break-word ><a href="4.2.1/motion_config.html"> Version 4.2.1</a> </td>
|
||||
<td word-wrap:break-word > </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td word-wrap:break-word ><a href="4.2/motion_config.html"> Version 4.2</a> </td>
|
||||
<td word-wrap:break-word > </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td word-wrap:break-word ><a href="4.1.1/motion_guide.html"> Version 4.1.1</a> </td>
|
||||
<td word-wrap:break-word > </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td word-wrap:break-word ><a href="4.1/motion_guide.html"> Version 4.1</a></td>
|
||||
<td word-wrap:break-word > </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td word-wrap:break-word ><a href="4.0.1/motion_guide.html"> Version 4.0.1</a> </td>
|
||||
<td word-wrap:break-word > </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td word-wrap:break-word > <a href="4.0/motion_guide.html"> Version 4.0</a></td>
|
||||
<td word-wrap:break-word > </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td word-wrap:break-word ><a href="3.4.1/motion_guide.html"> Version 3.4.1</a> </td>
|
||||
<td word-wrap:break-word > </td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
</ul>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,7 +10,7 @@ body {
|
||||
line-height: 1.5;
|
||||
color: #606c71; }
|
||||
a {
|
||||
color: #1e6bb8;
|
||||
color: #0f7040;
|
||||
text-decoration: none;}
|
||||
a:hover {
|
||||
text-decoration: underline; }
|
||||
@@ -34,8 +34,8 @@ a:hover {
|
||||
.page-header {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
background-color: #159957;
|
||||
background-image: linear-gradient(120deg, #155799, #159957); }
|
||||
background-color: #155799;
|
||||
background-image: linear-gradient(120deg, #159957, #155799); }
|
||||
.page-header h1 {
|
||||
margin-bottom: 0.1em;
|
||||
margin-top: 0.1em;}
|
||||
@@ -253,8 +253,8 @@ a:hover {
|
||||
|
||||
.subnav {
|
||||
overflow: hidden;
|
||||
background-color: #159957;
|
||||
background-image: linear-gradient(120deg, #155799, #159957);
|
||||
background-color: #155799;
|
||||
background-image: linear-gradient(120deg, #159957, #155799);
|
||||
border-top: 2px solid black;
|
||||
}
|
||||
.subnav a {
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.9 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB |
+1253
File diff suppressed because it is too large
Load Diff
+314
-213
@@ -1,6 +1,6 @@
|
||||
.TH MOTION 1 2020-10-19 "Motion" "Motion Options and Config Files"
|
||||
.TH MOTION 1 2022-03-13 "Motion" "Motion Options and Config Files"
|
||||
.SH NAME
|
||||
motion \- Detect motion using a video4linux device or network camera
|
||||
Motion \- Detect motion using a video4linux device or network camera
|
||||
.SH SYNOPSIS
|
||||
.B motion [ \-hbnsm ] [ \-c config file path ] [ \-d level ] [ \-k level ] [ \-p pid_file ][ \-l log_file ]
|
||||
.SH DESCRIPTION
|
||||
@@ -62,19 +62,6 @@ When specified as ON, Motion goes into daemon (background process) mode and rele
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B setup_mode
|
||||
.RS
|
||||
.nf
|
||||
Values: on/off
|
||||
Default: off
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
Start in Setup-Mode, daemon disabled.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B pid_file
|
||||
.RS
|
||||
@@ -154,7 +141,7 @@ Use this option to enable native language on the webcontrol and log message. Sp
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B camera_name
|
||||
.B device_name
|
||||
.RS
|
||||
.nf
|
||||
Values: User specified string
|
||||
@@ -162,16 +149,16 @@ Default: Not Defined
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
User specified string to describe the camera.
|
||||
User specified string to describe the device.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B camera_id
|
||||
.B device_id
|
||||
.RS
|
||||
.nf
|
||||
Values: Numeric identification number for the camera
|
||||
Default: The order in which the camera is opened by Motion
|
||||
Values: Numeric identification number for the device
|
||||
Default: The order in which the device is opened by Motion
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
@@ -205,7 +192,7 @@ camera config files.
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B camera_dir
|
||||
.B config_dir
|
||||
.RS
|
||||
.nf
|
||||
Values: User specified string
|
||||
@@ -213,7 +200,7 @@ Default: Not Defined
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
This option specifies the optional subdirectory that contains the camera config files.
|
||||
This option specifies the optional subdirectory that contains the configuration files.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
@@ -234,22 +221,7 @@ This option accepts the conversion specifiers included at the end of this manual
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B video_device
|
||||
.RS
|
||||
.nf
|
||||
Values: User specified string
|
||||
Default: /dev/video0
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
String to specify the video device to be used for capturing.
|
||||
The format is usually /dev/videoX where X varies depending upon the video devices connected to the computer.
|
||||
For FreeBSD certain devices use the bktr subsystem and they will use /dev/bktr0.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B video_params
|
||||
.B v4l2_device
|
||||
.RS
|
||||
.nf
|
||||
Values: User specified string
|
||||
@@ -257,12 +229,114 @@ Default: None
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
String to specify the parameters to pass in for a video_device. The parameters
|
||||
String to specify the videodevice to be used for capturing.
|
||||
The format is usually /dev/videoX where X varies depending upon the video devices connected to the computer.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B vid_control_params
|
||||
.RS
|
||||
.nf
|
||||
Values: User specified string
|
||||
Default: None
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
String to specify the parameters to pass in for a videodevice. The parameters
|
||||
permitted are dependent upon the device. This only applies to V4L2 devices. The
|
||||
Motion log reports all the available options for the device.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B v4l2_palette
|
||||
.RS
|
||||
.nf
|
||||
Values: 0 to 21
|
||||
.RS
|
||||
V4L2_PIX_FMT_SN9C10X : 0 'S910'
|
||||
V4L2_PIX_FMT_SBGGR16 : 1 'BYR2'
|
||||
V4L2_PIX_FMT_SBGGR8 : 2 'BA81'
|
||||
V4L2_PIX_FMT_SPCA561 : 3 'S561'
|
||||
V4L2_PIX_FMT_SGBRG8 : 4 'GBRG'
|
||||
V4L2_PIX_FMT_SGRBG8 : 5 'GRBG'
|
||||
V4L2_PIX_FMT_PAC207 : 6 'P207'
|
||||
V4L2_PIX_FMT_PJPG : 7 'PJPG'
|
||||
V4L2_PIX_FMT_MJPEG : 8 'MJPEG'
|
||||
V4L2_PIX_FMT_JPEG : 9 'JPEG'
|
||||
V4L2_PIX_FMT_RGB24 : 10 'RGB3'
|
||||
V4L2_PIX_FMT_SPCA501 : 11 'S501'
|
||||
V4L2_PIX_FMT_SPCA505 : 12 'S505'
|
||||
V4L2_PIX_FMT_SPCA508 : 13 'S508'
|
||||
V4L2_PIX_FMT_UYVY : 14 'UYVY'
|
||||
V4L2_PIX_FMT_YUYV : 15 'YUYV'
|
||||
V4L2_PIX_FMT_YUV422P : 16 '422P'
|
||||
V4L2_PIX_FMT_YUV420 : 17 'YU12'
|
||||
V4L2_PIX_FMT_Y10 : 18 'Y10'
|
||||
V4L2_PIX_FMT_Y12 : 19 'Y12'
|
||||
V4L2_PIX_FMT_GREY : 20 'GREY'
|
||||
V4L2_PIX_FMT_H264 : 21 'H264'
|
||||
.RE
|
||||
Default: 17
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
The v4l2_palette option allows users to choose the preferred palette to be use by Motion to capture from the video device.
|
||||
If the preferred palette is not available from the video device, Motion will attempt to use palettes that are supported.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B input
|
||||
.RS
|
||||
.nf
|
||||
Values:
|
||||
.RS
|
||||
\-1 : USB Cameras
|
||||
0 : video/TV cards or uvideo(4) on OpenBSD
|
||||
1 : video/TV cards
|
||||
.RE
|
||||
Default: \-1
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
The video input to be used.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B norm
|
||||
.RS
|
||||
.nf
|
||||
Values:
|
||||
.RS
|
||||
0 (PAL)
|
||||
1 (NTSC)
|
||||
2 (SECAM)
|
||||
3 (PAL NC no colour)
|
||||
.RE
|
||||
Default: 0 (PAL)
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
The video norm to use when capturing from TV tuner cards
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B frequency
|
||||
.RS
|
||||
.nf
|
||||
Values: Dependent upon video device
|
||||
Default: 0
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
The frequency to set the tuner in kHz when using a TV tuner card.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B auto_brightness
|
||||
.RS
|
||||
@@ -279,7 +353,7 @@ Only recommended for cameras without auto brightness.
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B tuner_device
|
||||
.B tunerdevice
|
||||
.RS
|
||||
.nf
|
||||
Values: User Specified String
|
||||
@@ -341,12 +415,15 @@ Description:
|
||||
.fi
|
||||
.RS
|
||||
Full connection URL string to use to connect to a network camera.
|
||||
In addition to standard camera protocols, the following prefixes are
|
||||
added by the Motion application.
|
||||
The URL must provide a stream of images instead of only a static image.
|
||||
The following prefixes are recognized
|
||||
|
||||
.RS
|
||||
http://
|
||||
ftp://
|
||||
mjpg://
|
||||
rtsp://
|
||||
rtmp://
|
||||
mjpeg://
|
||||
file://
|
||||
v4l2://
|
||||
@@ -354,24 +431,12 @@ v4l2://
|
||||
|
||||
The connection string is camera specific.
|
||||
It is usually the same as what other video playing applications would use to connect to the camera stream.
|
||||
Authentication can be specified in the URL or via the netcam_userpass option.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B netcam_params
|
||||
.RS
|
||||
.nf
|
||||
Values: User specified string
|
||||
Default: Not Defined
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
User specified parameters for the network camera.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B netcam_high_url
|
||||
.B netcam_highres
|
||||
.RS
|
||||
.nf
|
||||
Values: User specified string
|
||||
@@ -390,26 +455,10 @@ rtmp://
|
||||
|
||||
The connection string is camera specific.
|
||||
It is usually the same as what other video playing applications would use to connect to the camera stream.
|
||||
Motion currently only supports basic authentication for the cameras.
|
||||
Digest is not currently supported.
|
||||
Basic authentication can be specified in the URL or via the netcam_userpass option.
|
||||
Authentication can be specified in the URL or via the netcam_userpass option.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B netcam_high_params
|
||||
.RS
|
||||
.nf
|
||||
Values: User specified string
|
||||
Default: Not Defined
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
User specified parameters for the network camera.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
|
||||
.TP
|
||||
.B netcam_userpass
|
||||
.RS
|
||||
@@ -425,6 +474,78 @@ Format is in user:password format when both a user name and password are require
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B netcam_keepalive
|
||||
.RS
|
||||
.nf
|
||||
Values:
|
||||
.RS
|
||||
.fi
|
||||
off: The historical implementation using HTTP/1.0, closing the socket after each http request.
|
||||
.nf
|
||||
|
||||
.fi
|
||||
force: Use HTTP/1.0 requests with keep alive header to reuse the same connection.
|
||||
.nf
|
||||
|
||||
.fi
|
||||
on: Use HTTP/1.1 requests that support keep alive as default.
|
||||
.nf
|
||||
.RE
|
||||
Default: off
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
This setting is to keep-alive (open) the network socket between requests.
|
||||
When used, this option should improve performance on compatible net cameras.
|
||||
This option is not applicable for the rtsp://, rtmp:// and mjpeg:// formats.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B netcam_proxy
|
||||
.RS
|
||||
.nf
|
||||
Values: User specified string
|
||||
Default: Not defined
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
If required, the URL to use for a netcam proxy server.
|
||||
For example, "http://myproxy".
|
||||
If a port number other than 80 is needed, append to the specification.
|
||||
For examplet, "http://myproxy:1234".
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B netcam_tolerant_check
|
||||
.RS
|
||||
.nf
|
||||
Values: on/off
|
||||
Default: off
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
Use a less strict jpeg validation for network cameras.
|
||||
This can assist with cameras that have poor or buggy firmware.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B netcam_use_tcp
|
||||
.RS
|
||||
.nf
|
||||
Values: on/off
|
||||
Default: on
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
When using a RTSP/RTMP connection for a network camera, use a TCP transport instead of UDP.
|
||||
The UDP transport frequently results in "smeared" corrupt images.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B width
|
||||
.RS
|
||||
@@ -466,21 +587,6 @@ Typical video devices have a maximum rate of 30.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B minimum_frame_time
|
||||
.RS
|
||||
.nf
|
||||
Values: 0 to unlimited
|
||||
Default: 0
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
The minimum time in seconds between capturing picture frames from the camera.
|
||||
The default of 0 disables this option and relies upon the capture rate of the camera.
|
||||
This option is used when you want to capture images at a rate lower than 2 per second.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B rotate
|
||||
.RS
|
||||
@@ -589,7 +695,7 @@ Description:
|
||||
.fi
|
||||
.RS
|
||||
When specified, draw the number of changed pixed on the images.
|
||||
This option will normally be set to off except when you setup and adjust the motion settings.
|
||||
This option will normally be set to off except when you setup and adjust the Motion settings.
|
||||
The text is placed in upper right corner of the image.
|
||||
.RE
|
||||
.RE
|
||||
@@ -637,19 +743,6 @@ Always save images even if there was no motion.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B pause
|
||||
.RS
|
||||
.nf
|
||||
Values: on/off
|
||||
Default: off
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
When Motion is started, pause the motion detection.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B threshold
|
||||
.RS
|
||||
@@ -883,7 +976,7 @@ Description:
|
||||
.RS
|
||||
The number of pre-captured (buffered) pictures from before motion was detected that will be output upon motion detection.
|
||||
The recommended range is 0 to 5.
|
||||
It is not recommended to use large values since it will cause Motion to skip frames.
|
||||
It is not recommended to use large values since it will cause skipped frames.
|
||||
To smooth movies use larger values of post_capture instead.
|
||||
.RE
|
||||
.RE
|
||||
@@ -958,7 +1051,7 @@ Output pictures with only the pixels moving object (ghost images)
|
||||
.B picture_type
|
||||
.RS
|
||||
.nf
|
||||
Values: jpeg/ppm/webp/grey
|
||||
Values: jpeg/ppm/webp
|
||||
Default: jpeg
|
||||
Description:
|
||||
.fi
|
||||
@@ -1114,7 +1207,7 @@ A value of 1 is worst quality versus a value of 100 is best quality.
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B movie_codec
|
||||
.B movie_container
|
||||
.RS
|
||||
.nf
|
||||
Values:
|
||||
@@ -1276,9 +1369,9 @@ Default: mpg
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
For mpg timelapse videos, if motion is shutdown and restarted, new pics will be appended
|
||||
For mpg timelapse videos, if Motion is shutdown and restarted, new pics will be appended
|
||||
to any previously created file with name indicated for timelapse.
|
||||
For mpeg4 timelapse videos, if motion is shutdown and restarted, new pics will create a
|
||||
For mpeg4 timelapse videos, if Motion is shutdown and restarted, new pics will create a
|
||||
new file with the name indicated for timelapse.
|
||||
.RE
|
||||
.RE
|
||||
@@ -1468,7 +1561,7 @@ The full path to the SSL key file for webcontrol
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B webcontrol_header_params
|
||||
.B webcontrol_cors_header
|
||||
.RS
|
||||
.nf
|
||||
Values: User specified string
|
||||
@@ -1476,46 +1569,7 @@ Default: Not defined
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
The comma separated header=value pairs to use for the webcontrol responses.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B webcontrol_lock_attempts
|
||||
.RS
|
||||
.nf
|
||||
Values: integer
|
||||
Default: 5
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
The number of failed authentication attempts before IP is locked out.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B webcontrol_lock_minutes
|
||||
.RS
|
||||
.nf
|
||||
Values: integer
|
||||
Default: 5
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
The number of minutes a failed authentication IP is locked out.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B webcontrol_lock_max_ips
|
||||
.RS
|
||||
.nf
|
||||
Values: integer
|
||||
Default: 5
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
The maximum number of concurrent IPs that can be locked out.
|
||||
The header to add for cross orgin on the webcontrol
|
||||
.RE
|
||||
.RE
|
||||
|
||||
@@ -1591,7 +1645,7 @@ When specified as on, use SSL/TLS for the stream port.
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B stream_header_params
|
||||
.B stream_cors_header
|
||||
.RS
|
||||
.nf
|
||||
Values: User specified string
|
||||
@@ -1599,7 +1653,10 @@ Default: Not defined
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
The comma separated header=value pairs to send for the stream responses.
|
||||
The Access-Control-Allow-Origin header value to be sent with the stream.
|
||||
If unspecified, no Access-Control-Allow-Origin header is sent.
|
||||
The header allows browsers to access the stream via cross-origin resource sharing (CORS).
|
||||
For example, * allows access from browser client code served from any domain.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
@@ -1700,7 +1757,7 @@ Limit stream to 1 fps when no motion is being detected.
|
||||
.B database_type
|
||||
.RS
|
||||
.nf
|
||||
Values: mysql, mariadb, postgresql, sqlite3
|
||||
Values: mariadb, postgresql, sqlite3
|
||||
Default: Not defined
|
||||
Description:
|
||||
.fi
|
||||
@@ -1718,8 +1775,7 @@ Default: Not defined
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
The name of the database being used (dbname).
|
||||
For SQLite3, the full path to the database.
|
||||
The name of the database being used (dbname). For Sqlite3, the full path to the database.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
@@ -1732,9 +1788,7 @@ Default: localhost
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
The hostname, DNS name, or IP address at which the database is running.
|
||||
Optionally for PostgreSQL, full path of the local directory containing its Unix domain pipe.
|
||||
For SQLite3, ignored.
|
||||
The name of the host on which the database is running.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
@@ -1747,9 +1801,8 @@ Default: Not defined
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
TCP port number used for database access.
|
||||
For SQLite3, ignored.
|
||||
Default ports used by DBMSs: MySQL & MariaDB, 3306; PostgreSQL, 5432.
|
||||
The port to use in order to access the database.
|
||||
Default ports: mariadb 3306 , postgresql 5432
|
||||
.RE
|
||||
.RE
|
||||
|
||||
@@ -1763,8 +1816,7 @@ Default: Not Defined
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
The username to access the database.
|
||||
For SQLite3, ignored.
|
||||
The username to access the database
|
||||
.RE
|
||||
.RE
|
||||
|
||||
@@ -1778,7 +1830,6 @@ Description:
|
||||
.fi
|
||||
.RS
|
||||
The database password for the user to access the database.
|
||||
For SQLite3, ignored.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
@@ -1791,7 +1842,7 @@ Default: 0
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
SQLite3 only: database wait time in milliseconds for locked database to be unlocked before returning database locked error
|
||||
Database wait time in milliseconds for locked database to be unlocked before returning database locked error
|
||||
.RE
|
||||
.RE
|
||||
|
||||
@@ -1847,36 +1898,6 @@ Log to the database when creating timelapse movies file
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B sql_query
|
||||
.RS
|
||||
.nf
|
||||
Values: User defined string
|
||||
Default: Not defined
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
SQL statement to execute when Motion saves an image file or begins recording a movie and the corresponding file type's sql_log_* configuration option is set on.
|
||||
Use same conversion specifiers as for text features.
|
||||
Additional special conversion specifiers are:
|
||||
.RS
|
||||
%n = the number representing the file_type
|
||||
%f = filename with full path
|
||||
.RE
|
||||
Sample table set up (not sql_query):
|
||||
.RS
|
||||
Mysql: CREATE TABLE security (camera INTEGER NOT NULL, filename CHAR(80) NOT NULL, frame INTEGER, file_type INTEGER NOT NULL, time_stamp DATETIME NOT NULL, text_event CHAR(255));
|
||||
.RE
|
||||
.RS
|
||||
Postgresql: CREATE TABLE security (camera INTEGER NOT NULL, filename VARCHAR NOT NULL, frame INTEGER, file_type INTEGER NOT NULL, time_stamp TIMESTAMP NOT NULL, text_event VARCHAR);
|
||||
.RE
|
||||
Sample sql_query
|
||||
.RS
|
||||
INSERT INTO security(camera, filename, frame, file_type, time_stamp, text_event) VALUES(%t, '%f', %q, %n, '%Y-%m-%d %T', '%C')
|
||||
.RE
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B sql_query_start
|
||||
.RS
|
||||
@@ -1886,9 +1907,7 @@ Default: Not defined
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
SQL statement to execute at the start of a motion event.
|
||||
When the related table schema (and, for PostgreSQL, a RETURNING clause included in this statement) provide for it, the database generates a table-unique event ID that is returned and substituted for the %{dbeventid} conversion specifier.
|
||||
When no valid value is returned, %{dbeventid} is replaced by zero.
|
||||
SQL statement to execute at the start of a event.
|
||||
.RE
|
||||
.RE
|
||||
.RE
|
||||
@@ -1902,7 +1921,37 @@ Default: Not defined
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
SQL statement to execute upon closure of a motion event movie or timelapse movie file, provided the corresponding file type's sql_log_* configuration option is set on.
|
||||
SQL statement to execute at the end of a event.
|
||||
.RE
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B sql_query
|
||||
.RS
|
||||
.nf
|
||||
Values: User defined string
|
||||
Default: Not defined
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
SQL statement to execute when a event occurs.
|
||||
Use same conversion specifiers as for text features
|
||||
Additional special conversion specifiers are
|
||||
.RS
|
||||
%n = the number representing the file_type
|
||||
%f = filename with full path
|
||||
.RE
|
||||
Sample table set up (not sql_query):
|
||||
.RS
|
||||
MariaDB: CREATE TABLE security (camera int, filename char(80) not null, frame int, file_type int, time_stamp timestamp(14), event_time_stamp timestamp(14));
|
||||
.RE
|
||||
.RS
|
||||
Postgresql: CREATE TABLE security (camera int, filename char(80) not null, frame int, file_type int, time_stamp timestamp without time zone, event_time_stamp timestamp without time zone);
|
||||
.RE
|
||||
Sample sql_query
|
||||
.RS
|
||||
insert into security(camera, filename, frame, file_type, time_stamp, text_event) values('%t', '%f', '%q', '%n', '%Y-%m-%d %T', '%C')
|
||||
.RE
|
||||
.RE
|
||||
.RE
|
||||
@@ -1992,8 +2041,70 @@ Full path and file name for the script to execute to move a camera in generic tr
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B snd_device
|
||||
.RS
|
||||
.nf
|
||||
Values: User specified string
|
||||
Default: Not defined
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
Sound device.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B snd_params
|
||||
.RS
|
||||
.nf
|
||||
Values: User specified string
|
||||
Default: Not defined
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
Device parameters for sound device.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B snd_alerts
|
||||
.RS
|
||||
.nf
|
||||
Values: User specified string
|
||||
Default: Not defined
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
Comma separated parameters for the sound alert.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B snd_window
|
||||
.RS
|
||||
.nf
|
||||
Values: User specified string
|
||||
Default: hamming
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
Sound frequency detection window.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B snd_show
|
||||
.RS
|
||||
.nf
|
||||
Values: Boolean
|
||||
Default: off
|
||||
Description:
|
||||
.fi
|
||||
.RS
|
||||
Show the sound frequencies being detected.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.SH SIGNALS
|
||||
Motion responds to the following signals:
|
||||
@@ -2002,7 +2113,7 @@ Motion responds to the following signals:
|
||||
The config file will be reread.
|
||||
.TP
|
||||
.B SIGTERM
|
||||
If needed motion will create an movie file of the last event and exit
|
||||
If needed Motion will create an movie file of the last event and exit
|
||||
.TP
|
||||
.B SIGUSR1
|
||||
Motion will create an movie file of the current event.
|
||||
@@ -2022,11 +2133,11 @@ If Motion was invoked with command line option \-c pathname Motion will expect t
|
||||
.br
|
||||
If you do not specify \-c or the filename you give Motion does not exist, Motion will search for the configuration file called 'motion.conf' in the following order:
|
||||
.br
|
||||
1. Current directory from where motion was invoked
|
||||
1. Current directory from where Motion was invoked
|
||||
.br
|
||||
2. Then in a directory called '.motion' in the current users home directory (shell environment variable $HOME). E.g. /home/goofy/.motion/motion.conf
|
||||
.br
|
||||
3. The motion/ subdirectory inside the directory defined by the \-\-sysconfdir=DIR when running .configure during installation of Motion (If this option was not defined the default is /usr/local/etc/)
|
||||
3. The motion subdirectory inside the directory defined by the \-\-sysconfdir=DIR when running .configure during installation of Motion (If this option was not defined the default is /usr/local/etc/)
|
||||
.br
|
||||
If you have write access to /usr/local/etc/motion then the editor recommends having only one motion.conf file in the default /usr/local/etc/motion directory.
|
||||
.br
|
||||
@@ -2058,9 +2169,9 @@ Motion reads its configuration parameters in the following sequence. If the same
|
||||
.br
|
||||
So always call the camera config files in the end of the motion.conf file. If you define options in motion.conf AFTER the camera file calls, the same options in the camera files will never be used. So always put the camera file call at the end of motion.conf.
|
||||
.br
|
||||
If motion is built without specific features such as ffmpeg, mysql etc it will ignore the options that belongs to these features. You do not have to remove them or comment them out.
|
||||
If Motion is built without specific features such as ffmpeg, MariaDB etc it will ignore the options that belongs to these features. You do not have to remove them or comment them out.
|
||||
.br
|
||||
If you run the http control command http://host:port/0/config/writeyes, motion will overwrite motion.conf and all the camera.conf files by autogenerated config files neatly formatted and only with the features included that Motion was built with. If you later re-build Motion with more features or upgrade to a new version, you can use your old config files, run the motion.conf.write command, and you will have new config files with the new options included all set to their default values. This makes upgrading very easy to do.
|
||||
If you run the http control command http://host:port/0/config/writeyes, Motion will overwrite motion.conf and all the camera.conf files by autogenerated config files neatly formatted and only with the features included that Motion was built with. If you later re-build Motion with more features or upgrade to a new version, you can use your old config files, run the motion.conf.write command, and you will have new config files with the new options included all set to their default values. This makes upgrading very easy to do.
|
||||
.TP
|
||||
.B Conversion Specifiers for Advanced Filename and Text Features
|
||||
The table below shows all the supported Conversion Specifiers you can use in the options text_left, text_right, snapshot_filename, jpeg_filename, ffmpeg_filename, timelapse_filename, on_event_start, on_event_end, on_picture_save, on_movie_start, on_movie_end, and on_motion_detected.
|
||||
@@ -2221,9 +2332,6 @@ The computer host name
|
||||
.B %{fps}
|
||||
The frame per seconds.
|
||||
.TP
|
||||
.B %{dbeventid}
|
||||
The id number returned from mysql_insert_id.
|
||||
.TP
|
||||
.B %{ver}
|
||||
The version number of Motion.
|
||||
|
||||
@@ -2231,14 +2339,7 @@ The version number of Motion.
|
||||
|
||||
.TP
|
||||
.B More information
|
||||
Motion homepage: https://motion-project.github.io/
|
||||
Motion homepage: TBD
|
||||
|
||||
Motion Guide (user and installation guide):
|
||||
.br /usr/share/doc/motion/motion_guide.html
|
||||
.SH AUTHORS
|
||||
Jeroen Vreeken (pe1rxq@amsat.org),
|
||||
Folkert van Heusden,
|
||||
Kenneth Lavrsen (kenneth@lavrsen.dk),
|
||||
Juan Angulo Moreno <juan@apuntale.com>,
|
||||
the motion-project team,
|
||||
and many others
|
||||
|
||||
@@ -10,6 +10,5 @@ li
|
||||
nl
|
||||
no
|
||||
pt
|
||||
sk
|
||||
sv
|
||||
zh
|
||||
+1
-1
@@ -41,7 +41,7 @@ PACKAGE_GNU =
|
||||
# It can be your email address, or a mailing list address where translators
|
||||
# can write to without being subscribed, or the URL of a web page through
|
||||
# which the translators can contact you.
|
||||
MSGID_BUGS_ADDRESS = https://motion-project.github.io
|
||||
MSGID_BUGS_ADDRESS =
|
||||
|
||||
# This is the list of locale categories, beyond LC_MESSAGES, for which the
|
||||
# message catalogs shall be used. It is usually empty.
|
||||
|
||||
+19
-23
@@ -1,30 +1,26 @@
|
||||
# main sources
|
||||
src/alg.cpp
|
||||
src/conf.cpp
|
||||
src/dbse.cpp
|
||||
src/draw.cpp
|
||||
src/event.cpp
|
||||
src/ffmpeg.cpp
|
||||
src/movie.cpp
|
||||
src/video_convert.cpp
|
||||
src/webu_json.cpp
|
||||
src/alg_sec.cpp
|
||||
src/jpegutils.cpp
|
||||
src/logger.cpp
|
||||
src/motion.cpp
|
||||
src/netcam.cpp
|
||||
src/netcam_ftp.cpp
|
||||
src/netcam_http.cpp
|
||||
src/netcam_jpeg.cpp
|
||||
src/netcam_rtsp.cpp
|
||||
src/netcam_wget.cpp
|
||||
src/picture.cpp
|
||||
src/rotate.cpp
|
||||
src/track.cpp
|
||||
src/translate.cpp
|
||||
src/util.cpp
|
||||
src/video_bktr.cpp
|
||||
src/video_common.cpp
|
||||
src/video_loopback.cpp
|
||||
src/webu_post.cpp
|
||||
src/conf.cpp
|
||||
src/libcam.cpp
|
||||
src/picture.cpp
|
||||
src/video_v4l2.cpp
|
||||
src/webu.cpp
|
||||
src/webu_html.cpp
|
||||
src/webu_status.cpp
|
||||
src/webu_stream.cpp
|
||||
src/webu_text.cpp
|
||||
src/dbse.cpp
|
||||
src/logger.cpp
|
||||
src/rotate.cpp
|
||||
src/webu.cpp
|
||||
src/draw.cpp
|
||||
src/camera.cpp
|
||||
src/sound.cpp
|
||||
src/webu_file.cpp
|
||||
src/motion.cpp
|
||||
src/util.cpp
|
||||
src/webu_html.cpp
|
||||
|
||||
+10
-2
@@ -1,10 +1,14 @@
|
||||
#!/bin/sh
|
||||
<<<<<<< HEAD
|
||||
BASE_VERSION="4.7.0"
|
||||
=======
|
||||
BASE_VERSION="5.0.0"
|
||||
>>>>>>> 5.0
|
||||
if [ -d .git ]; then
|
||||
if test "`git diff --name-only`" = "" ; then
|
||||
GIT_COMMIT="git"
|
||||
GIT_COMMIT="git-"
|
||||
else
|
||||
GIT_COMMIT="dirty"
|
||||
GIT_COMMIT="dirty-"
|
||||
fi
|
||||
GIT_COMMIT=$GIT_COMMIT`git show -s --date=format:'%Y%m%d' --format=%cd-%h` 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
@@ -14,5 +18,9 @@ else
|
||||
GIT_COMMIT="gitUNKNOWN"
|
||||
fi
|
||||
#printf "$BASE_VERSION"
|
||||
<<<<<<< HEAD
|
||||
printf "$BASE_VERSION+$GIT_COMMIT"
|
||||
=======
|
||||
printf "$BASE_VERSION"-"$GIT_COMMIT"
|
||||
>>>>>>> 5.0
|
||||
|
||||
|
||||
+54
-31
@@ -1,37 +1,60 @@
|
||||
AM_CPPFLAGS= -Dsysconfdir=\"$(sysconfdir)/motion\" -DLOCALEDIR=\"$(localedir)\"
|
||||
#/*
|
||||
# * This file is part of Motion.
|
||||
# *
|
||||
# * Motion 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 3 of the License, or
|
||||
# * (at your option) any later version.
|
||||
# *
|
||||
# * Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
# *
|
||||
# */
|
||||
|
||||
|
||||
AM_CPPFLAGS= \
|
||||
-Dconfigdir=\"$(localstatedir)/lib/@PACKAGE@\" \
|
||||
-Dsysconfdir=\"$(sysconfdir)/motion\" \
|
||||
-DLOCALEDIR=\"$(localedir)\"
|
||||
|
||||
LDADD = $(LIBINTL)
|
||||
|
||||
bin_PROGRAMS = motion
|
||||
|
||||
motion_SOURCES = \
|
||||
alg.hpp alg.cpp \
|
||||
conf.hpp conf.cpp \
|
||||
dbse.hpp dbse.cpp \
|
||||
draw.hpp draw.cpp \
|
||||
event.hpp event.cpp \
|
||||
ffmpeg.hpp ffmpeg.cpp \
|
||||
jpegutils.hpp jpegutils.cpp \
|
||||
logger.hpp logger.cpp \
|
||||
motion.hpp motion.cpp \
|
||||
netcam.hpp netcam.cpp \
|
||||
netcam_ftp.hpp netcam_ftp.cpp \
|
||||
netcam_http.hpp netcam_http.cpp \
|
||||
netcam_jpeg.hpp netcam_jpeg.cpp \
|
||||
netcam_rtsp.hpp netcam_rtsp.cpp \
|
||||
netcam_wget.hpp netcam_wget.cpp \
|
||||
picture.hpp picture.cpp \
|
||||
rotate.hpp rotate.cpp \
|
||||
track.hpp track.cpp \
|
||||
translate.hpp translate.cpp \
|
||||
util.hpp util.cpp \
|
||||
video_bktr.hpp video_bktr.cpp \
|
||||
video_common.hpp video_common.cpp \
|
||||
video_loopback.hpp video_loopback.cpp \
|
||||
video_v4l2.hpp video_v4l2.cpp \
|
||||
webu.hpp webu.cpp \
|
||||
webu_html.hpp webu_html.cpp \
|
||||
webu_status.hpp webu_status.cpp \
|
||||
webu_stream.hpp webu_stream.cpp \
|
||||
webu_text.hpp webu_text.cpp \
|
||||
mmx.hpp pwc-ioctl.hpp
|
||||
alg.hpp alg.cpp \
|
||||
alg_sec.hpp alg_sec.cpp \
|
||||
conf.hpp conf.cpp \
|
||||
dbse.hpp dbse.cpp \
|
||||
draw.hpp draw.cpp \
|
||||
jpegutils.hpp jpegutils.cpp \
|
||||
libcam.hpp libcam.cpp \
|
||||
logger.hpp logger.cpp \
|
||||
motion.hpp motion.cpp \
|
||||
allcam.hpp allcam.cpp \
|
||||
schedule.hpp schedule.cpp \
|
||||
camera.hpp camera.cpp \
|
||||
movie.hpp movie.cpp \
|
||||
netcam.hpp netcam.cpp \
|
||||
picture.hpp picture.cpp \
|
||||
rotate.hpp rotate.cpp \
|
||||
sound.hpp sound.cpp \
|
||||
util.hpp util.cpp \
|
||||
video_v4l2.hpp video_v4l2.cpp \
|
||||
video_convert.hpp video_convert.cpp \
|
||||
video_loopback.hpp video_loopback.cpp \
|
||||
webu.hpp webu.cpp \
|
||||
webu_ans.hpp webu_ans.cpp \
|
||||
webu_file.hpp webu_file.cpp \
|
||||
webu_html.hpp webu_html.cpp \
|
||||
webu_json.hpp webu_json.cpp \
|
||||
webu_post.hpp webu_post.cpp \
|
||||
webu_stream.hpp webu_stream.cpp \
|
||||
webu_getimg.hpp webu_getimg.cpp \
|
||||
webu_mpegts.hpp webu_mpegts.cpp
|
||||
|
||||
|
||||
+736
-944
File diff suppressed because it is too large
Load Diff
+59
-55
@@ -1,62 +1,66 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* alg.h
|
||||
* Detect changes in a video stream.
|
||||
* Copyright 2001 by Jeroen Vreeken (pe1rxq@amsat.org)
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_ALG_H
|
||||
#define _INCLUDE_ALG_H
|
||||
#ifndef _INCLUDE_ALG_HPP_
|
||||
#define _INCLUDE_ALG_HPP_
|
||||
#define THRESHOLD_TUNE_LENGTH 256
|
||||
|
||||
#include "motion.hpp"
|
||||
class cls_alg {
|
||||
public:
|
||||
cls_alg(cls_camera *p_cam);
|
||||
~cls_alg();
|
||||
void diff();
|
||||
void noise_tune();
|
||||
void threshold_tune();
|
||||
void tune_smartmask();
|
||||
void ref_frame_update();
|
||||
void ref_frame_reset();
|
||||
void stddev();
|
||||
void location();
|
||||
u_char *smartmask_final;
|
||||
private:
|
||||
cls_camera *cam;
|
||||
int smartmask_count;
|
||||
u_char *smartmask;
|
||||
int *smartmask_buffer;
|
||||
int diffs_last[THRESHOLD_TUNE_LENGTH];
|
||||
bool calc_stddev;
|
||||
|
||||
struct coord {
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
int minx;
|
||||
int maxx;
|
||||
int miny;
|
||||
int maxy;
|
||||
};
|
||||
int iflood(int x, int y, int width, int height,
|
||||
u_char *out, int *labels, int newvalue, int oldvalue);
|
||||
int labeling();
|
||||
int dilate9(u_char *img, int width, int height, void *buffer);
|
||||
int dilate5(u_char *img, int width, int height, void *buffer);
|
||||
int erode9(u_char *img, int width, int height, void *buffer, u_char flag);
|
||||
int erode5(u_char *img, int width, int height, void *buffer, u_char flag);
|
||||
void despeckle();
|
||||
void diff_nomask();
|
||||
void diff_mask();
|
||||
void diff_smart();
|
||||
void diff_masksmart();
|
||||
bool diff_fast();
|
||||
void diff_standard();
|
||||
void lightswitch();
|
||||
void location_center();
|
||||
void location_dist_stddev();
|
||||
void location_dist_basic();
|
||||
void location_minmax();
|
||||
|
||||
struct segment {
|
||||
struct coord coord;
|
||||
int width;
|
||||
int height;
|
||||
int open;
|
||||
int count;
|
||||
};
|
||||
};
|
||||
|
||||
void alg_locate_center_size(struct images *imgs, int width, int height, struct coord *cent);
|
||||
void alg_draw_location(struct coord *cent, struct images *imgs, int width, unsigned char *new,
|
||||
int style, int mode, int process_thisframe);
|
||||
void alg_draw_red_location(struct coord *cent, struct images *imgs, int width, unsigned char *new,
|
||||
int style, int mode, int process_thisframe);
|
||||
void alg_noise_tune(struct context *cnt, unsigned char *new);
|
||||
void alg_threshold_tune(struct context *cnt, int diffs, int motion);
|
||||
int alg_despeckle(struct context *cnt, int olddiffs);
|
||||
void alg_tune_smartmask(struct context *cnt);
|
||||
int alg_diff_standard(struct context *cnt, unsigned char *new);
|
||||
int alg_diff(struct context *cnt, unsigned char *new);
|
||||
int alg_lightswitch(struct context *cnt, int diffs);
|
||||
int alg_switchfilter(struct context *cnt, int diffs, unsigned char *newimg);
|
||||
void alg_update_reference_frame(struct context *cnt, int action);
|
||||
|
||||
#endif /* _INCLUDE_ALG_H */
|
||||
#endif /* _INCLUDE_ALG_HPP_ */
|
||||
|
||||
+775
@@ -0,0 +1,775 @@
|
||||
/*
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "motion.hpp"
|
||||
#include "util.hpp"
|
||||
#include "camera.hpp"
|
||||
#include "conf.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "alg_sec.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCV
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#include <opencv2/objdetect.hpp>
|
||||
#include <opencv2/dnn.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/imgcodecs.hpp>
|
||||
#include <opencv2/videoio.hpp>
|
||||
#include <opencv2/video.hpp>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
using namespace cv;
|
||||
using namespace dnn;
|
||||
|
||||
static void *algsec_handler(void *arg)
|
||||
{
|
||||
((cls_algsec *)arg)->handler();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void cls_algsec::debug_notice(Mat &mat_dst, bool isdetect)
|
||||
{
|
||||
if (handler_stop == true) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cfg_log_level >= DBG) {
|
||||
if (first_pass == true) {
|
||||
MOTPLS_LOG(DBG, TYPE_ALL, NO_ERRNO
|
||||
, "Secondary detect and debug enabled.");
|
||||
MOTPLS_LOG(DBG, TYPE_ALL, NO_ERRNO
|
||||
, "Saving source and detected images to %s"
|
||||
, cfg_target_dir.c_str());
|
||||
first_pass = false;
|
||||
}
|
||||
if (isdetect == true) {
|
||||
imwrite(cfg_target_dir + "/detect_" + method + ".jpg"
|
||||
, mat_dst);
|
||||
} else {
|
||||
imwrite(cfg_target_dir + "/src_" + method + ".jpg"
|
||||
, mat_dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cls_algsec::image_show(Mat &mat_dst)
|
||||
{
|
||||
std::vector<uchar> buff;
|
||||
std::vector<int> param(2);
|
||||
|
||||
if (handler_stop == true) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* We check the size so that we at least fill in the first image so the
|
||||
* web stream will have something to start with. After feeding in at least
|
||||
* the first image, we rely upon the connection count to tell us whether we
|
||||
* need to expend the CPU to compress and load the secondary images */
|
||||
if ((cam->stream.secondary.jpg_cnct >0) ||
|
||||
(cam->imgs.size_secondary == 0) ||
|
||||
(cfg_log_level >= DBG)) {
|
||||
|
||||
debug_notice(mat_dst, detected);
|
||||
|
||||
param[0] = cv::IMWRITE_JPEG_QUALITY;
|
||||
param[1] = 75;
|
||||
cv::imencode(".jpg", mat_dst, buff, param);
|
||||
pthread_mutex_lock(&mutex);
|
||||
std::copy(buff.begin(), buff.end(), cam->imgs.image_secondary);
|
||||
cam->imgs.size_secondary = (int)buff.size();
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cls_algsec::label_image(Mat &mat_dst
|
||||
, std::vector<Rect> &src_pos, std::vector<double> &src_weights)
|
||||
{
|
||||
std::vector<Rect> fltr_pos;
|
||||
std::vector<double> fltr_weights;
|
||||
std::string testdir;
|
||||
std::size_t indx0, indx1;
|
||||
std::vector<uchar> buff;
|
||||
std::vector<int> param(2);
|
||||
char wstr[10];
|
||||
|
||||
try {
|
||||
detected = false;
|
||||
|
||||
debug_notice(mat_dst, detected);
|
||||
|
||||
for (indx0=0; indx0<src_pos.size(); indx0++) {
|
||||
Rect r = src_pos[indx0];
|
||||
double w = src_weights[indx0];
|
||||
|
||||
for (indx1=0; indx1<src_pos.size(); indx1++) {
|
||||
if (indx1 != indx0 && (r & src_pos[indx1])==r) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((indx1==src_pos.size()) && (w > threshold)) {
|
||||
fltr_pos.push_back(r);
|
||||
fltr_weights.push_back(w);
|
||||
detected = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (detected) {
|
||||
for (indx0=0; indx0<fltr_pos.size(); indx0++) {
|
||||
Rect r = fltr_pos[indx0];
|
||||
r.x += cvRound(r.width*0.1);
|
||||
r.width = cvRound(r.width*0.8);
|
||||
r.y += cvRound(r.height*0.06);
|
||||
r.height = cvRound(r.height*0.9);
|
||||
rectangle(mat_dst, r.tl(), r.br(), cv::Scalar(0,255,0), 2);
|
||||
snprintf(wstr, 10, "%.4f", fltr_weights[indx0]);
|
||||
putText(mat_dst, wstr, Point(r.x,r.y), FONT_HERSHEY_PLAIN, 1, 255, 1);
|
||||
}
|
||||
}
|
||||
|
||||
image_show(mat_dst);
|
||||
|
||||
} catch ( cv::Exception& e ) {
|
||||
const char* err_msg = e.what();
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Error %s"),err_msg);
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Disabling secondary detection"));
|
||||
method = "none";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cls_algsec::label_image(Mat &mat_dst, double confidence, Point classIdPoint)
|
||||
{
|
||||
std::string label;
|
||||
|
||||
try {
|
||||
detected = false;
|
||||
debug_notice(mat_dst, detected);
|
||||
|
||||
if (confidence < threshold) {
|
||||
return;
|
||||
}
|
||||
|
||||
detected = true;
|
||||
label = format("%s: %.4f"
|
||||
, (dnn_classes.empty() ?
|
||||
format("Class #%d", classIdPoint.x).c_str() :
|
||||
dnn_classes[(uint)classIdPoint.x].c_str())
|
||||
, confidence);
|
||||
|
||||
putText(mat_dst , label, Point(0, 15)
|
||||
, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0));
|
||||
|
||||
image_show(mat_dst);
|
||||
|
||||
} catch ( cv::Exception& e ) {
|
||||
const char* err_msg = e.what();
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Error %s"),err_msg);
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Disabling secondary detection"));
|
||||
method = "none";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cls_algsec::get_image_roi(Mat &mat_src, Mat &mat_dst)
|
||||
{
|
||||
cv::Rect roi;
|
||||
|
||||
roi.x = cam->current_image->location.minx;
|
||||
roi.y = cam->current_image->location.miny;
|
||||
roi.width = cam->current_image->location.width;
|
||||
roi.height = cam->current_image->location.height;
|
||||
|
||||
/* Images smaller than 100 cause seg faults. 112 is the nearest
|
||||
multiple of 16 greater than 100*/
|
||||
if (roi.height < 112) {
|
||||
roi.height = 112;
|
||||
}
|
||||
if ((roi.y + roi.height) > (height-112)) {
|
||||
roi.y = height - roi.height;
|
||||
} else if ((roi.y + roi.height) > height) {
|
||||
roi.height = height - roi.y;
|
||||
}
|
||||
|
||||
if (roi.width < 112) {
|
||||
roi.width = 112;
|
||||
}
|
||||
if ((roi.x + roi.width) > (width-112)) {
|
||||
roi.x = width - roi.width;
|
||||
} else {
|
||||
roi.width = width - roi.x;
|
||||
}
|
||||
|
||||
/*
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO, "Base %d %d (%dx%d) img(%dx%d)"
|
||||
,cam->current_image->location.minx
|
||||
,cam->current_image->location.miny
|
||||
,cam->current_image->location.width
|
||||
,cam->current_image->location.height
|
||||
,width,height);
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO, "Opencv %d %d %d %d"
|
||||
,roi.x,roi.y,roi.width,roi.height);
|
||||
*/
|
||||
mat_dst = mat_src(roi);
|
||||
|
||||
}
|
||||
|
||||
void cls_algsec::get_image(Mat &mat_dst)
|
||||
{
|
||||
Mat mat_src;
|
||||
|
||||
if (image_type == "grey") {
|
||||
mat_dst = Mat(cam->imgs.height, cam->imgs.width
|
||||
, CV_8UC1, (void*)image_norm);
|
||||
} else if ((image_type == "roi") || (image_type == "greyroi")) {
|
||||
/*Discard really small and large images */
|
||||
if ((cam->current_image->location.width < 64) ||
|
||||
(cam->current_image->location.height < 64) ||
|
||||
((cam->current_image->location.width/cam->imgs.width) > 0.7) ||
|
||||
((cam->current_image->location.height/cam->imgs.height) > 0.7)) {
|
||||
return;
|
||||
}
|
||||
if (image_type == "roi") {
|
||||
mat_src = Mat(cam->imgs.height*3/2, cam->imgs.width
|
||||
, CV_8UC1, (void*)image_norm);
|
||||
cvtColor(mat_src, mat_src, COLOR_YUV2RGB_YV12);
|
||||
} else {
|
||||
mat_src = Mat(cam->imgs.height, cam->imgs.width
|
||||
, CV_8UC1, (void*)image_norm);
|
||||
}
|
||||
get_image_roi(mat_src, mat_dst);
|
||||
} else {
|
||||
mat_src = Mat(cam->imgs.height*3/2, cam->imgs.width
|
||||
, CV_8UC1, (void*)image_norm);
|
||||
cvtColor(mat_src, mat_dst, COLOR_YUV2RGB_YV12);
|
||||
}
|
||||
}
|
||||
|
||||
void cls_algsec::detect_hog()
|
||||
{
|
||||
std::vector<double> detect_weights;
|
||||
std::vector<Rect> detect_pos;
|
||||
Mat mat_dst;
|
||||
|
||||
try {
|
||||
get_image(mat_dst);
|
||||
if (mat_dst.empty() == true) {
|
||||
return;
|
||||
}
|
||||
equalizeHist(mat_dst, mat_dst);
|
||||
|
||||
hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());
|
||||
|
||||
hog.detectMultiScale(mat_dst, detect_pos, detect_weights, 0
|
||||
,Size(hog_winstride, hog_winstride)
|
||||
,Size(hog_padding, hog_padding)
|
||||
,scalefactor
|
||||
,hog_threshold_model
|
||||
,false);
|
||||
|
||||
label_image(mat_dst, detect_pos, detect_weights);
|
||||
|
||||
} catch ( cv::Exception& e ) {
|
||||
const char* err_msg = e.what();
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Error %s"),err_msg);
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Disabling secondary detection"));
|
||||
method = "none";
|
||||
}
|
||||
}
|
||||
|
||||
void cls_algsec::detect_haar()
|
||||
{
|
||||
std::vector<double> detect_weights;
|
||||
std::vector<Rect> detect_pos;
|
||||
std::vector<int> levels;
|
||||
Mat mat_dst;
|
||||
|
||||
try {
|
||||
get_image(mat_dst);
|
||||
if (mat_dst.empty() == true) {
|
||||
return;
|
||||
}
|
||||
equalizeHist(mat_dst, mat_dst);
|
||||
|
||||
haar_cascade.detectMultiScale(
|
||||
mat_dst, detect_pos, levels, detect_weights
|
||||
,scalefactor, haar_minneighbors,haar_flags
|
||||
, Size(haar_minsize,haar_minsize)
|
||||
, Size(haar_maxsize,haar_maxsize), true);
|
||||
|
||||
label_image(mat_dst, detect_pos, detect_weights);
|
||||
|
||||
} catch ( cv::Exception& e ) {
|
||||
const char* err_msg = e.what();
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Error %s"),err_msg);
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Disabling secondary detection"));
|
||||
method = "none";
|
||||
}
|
||||
}
|
||||
|
||||
void cls_algsec::detect_dnn()
|
||||
{
|
||||
Mat mat_dst, softmaxProb;
|
||||
double confidence;
|
||||
float maxProb = 0.0, sum = 0.0;
|
||||
Point classIdPoint;
|
||||
|
||||
try {
|
||||
get_image(mat_dst);
|
||||
if (mat_dst.empty() == true) {
|
||||
return;
|
||||
}
|
||||
|
||||
Mat blob = blobFromImage(mat_dst
|
||||
, dnn_scale
|
||||
, Size(dnn_width, dnn_height)
|
||||
, Scalar());
|
||||
net.setInput(blob);
|
||||
Mat prob = net.forward();
|
||||
|
||||
maxProb = *std::max_element(prob.begin<float>(), prob.end<float>());
|
||||
cv::exp(prob-maxProb, softmaxProb);
|
||||
sum = (float)cv::sum(softmaxProb)[0];
|
||||
softmaxProb /= sum;
|
||||
cv::minMaxLoc(softmaxProb.reshape(1, 1), 0, &confidence, 0, &classIdPoint);
|
||||
|
||||
label_image(mat_dst, confidence, classIdPoint);
|
||||
|
||||
} catch ( cv::Exception& e ) {
|
||||
const char* err_msg = e.what();
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Error %s"),err_msg);
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Disabling secondary detection"));
|
||||
method = "none";
|
||||
}
|
||||
}
|
||||
|
||||
void cls_algsec::load_haar()
|
||||
{
|
||||
try {
|
||||
if (model_file == "") {
|
||||
method = "none";
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("No secondary model specified."));
|
||||
return;
|
||||
}
|
||||
if (haar_cascade.load(model_file) == false) {
|
||||
/* Loading failed, reset method*/
|
||||
method = "none";
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Failed loading model %s")
|
||||
,model_file.c_str());
|
||||
}
|
||||
} catch ( cv::Exception& e ) {
|
||||
const char* err_msg = e.what();
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Error %s"),err_msg);
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Failed loading model %s")
|
||||
, model_file.c_str());
|
||||
method = "none";
|
||||
}
|
||||
}
|
||||
|
||||
void cls_algsec::load_hog()
|
||||
{
|
||||
if (image_type == "roi") {
|
||||
image_type = "greyroi";
|
||||
} else if (
|
||||
(image_type != "grey") &&
|
||||
(image_type != "greyroi")) {
|
||||
image_type = "grey";
|
||||
}
|
||||
}
|
||||
|
||||
void cls_algsec::load_dnn()
|
||||
{
|
||||
std::string line;
|
||||
std::ifstream ifs;
|
||||
|
||||
try {
|
||||
if (model_file == "") {
|
||||
method = "none";
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("No secondary model specified."));
|
||||
return;
|
||||
}
|
||||
net = readNet(
|
||||
model_file
|
||||
, dnn_config
|
||||
, dnn_framework);
|
||||
net.setPreferableBackend(dnn_backend);
|
||||
net.setPreferableTarget(dnn_target);
|
||||
|
||||
ifs.open(dnn_classes_file.c_str());
|
||||
if (ifs.is_open() == false) {
|
||||
method = "none";
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("Classes file not found: %s")
|
||||
,dnn_classes_file.c_str());
|
||||
return;
|
||||
}
|
||||
while (std::getline(ifs, line)) {
|
||||
dnn_classes.push_back(line);
|
||||
}
|
||||
ifs.close();
|
||||
|
||||
} catch ( cv::Exception& e ) {
|
||||
const char* err_msg = e.what();
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Error %s"),err_msg);
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Failed loading model %s")
|
||||
, model_file.c_str());
|
||||
method = "none";
|
||||
}
|
||||
}
|
||||
|
||||
void cls_algsec::params_log()
|
||||
{
|
||||
ctx_params_item *itm;
|
||||
int indx;
|
||||
|
||||
if (method != "none") {
|
||||
for (indx=0;indx<params->params_cnt;indx++) {
|
||||
itm = ¶ms->params_array[indx];
|
||||
MOTPLS_SHT(INF, TYPE_ALL, NO_ERRNO, "%-25s %s"
|
||||
,itm->param_name.c_str(),itm->param_value.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cls_algsec::params_model()
|
||||
{
|
||||
ctx_params_item *itm;
|
||||
int indx;
|
||||
|
||||
for (indx=0;indx<params->params_cnt;indx++) {
|
||||
itm = ¶ms->params_array[indx];
|
||||
if (itm->param_name == "model_file") {
|
||||
model_file = itm->param_value;
|
||||
} else if (itm->param_name == "frame_interval") {
|
||||
frame_interval = mtoi(itm->param_value);
|
||||
} else if (itm->param_name == "image_type") {
|
||||
image_type = itm->param_value;
|
||||
} else if (itm->param_name == "threshold") {
|
||||
threshold = mtof(itm->param_value);
|
||||
} else if (itm->param_name == "scalefactor") {
|
||||
scalefactor = mtof(itm->param_value);
|
||||
} else if (itm->param_name == "rotate") {
|
||||
rotate = mtoi(itm->param_value);
|
||||
}
|
||||
|
||||
if (method == "hog") {
|
||||
if (itm->param_name =="padding") {
|
||||
hog_padding = mtoi(itm->param_value);
|
||||
} else if (itm->param_name =="threshold_model") {
|
||||
hog_threshold_model = mtof(itm->param_value);
|
||||
} else if (itm->param_name =="winstride") {
|
||||
hog_winstride = mtoi(itm->param_value);
|
||||
}
|
||||
} else if (method == "haar") {
|
||||
if (itm->param_name =="flags") {
|
||||
haar_flags = mtoi(itm->param_value);
|
||||
} else if (itm->param_name =="maxsize") {
|
||||
haar_maxsize = mtoi(itm->param_value);
|
||||
} else if (itm->param_name =="minsize") {
|
||||
haar_minsize = mtoi(itm->param_value);
|
||||
} else if (itm->param_name =="minneighbors") {
|
||||
haar_minneighbors = mtoi(itm->param_value);
|
||||
}
|
||||
} else if (method == "dnn") {
|
||||
if (itm->param_name == "config") {
|
||||
dnn_config = itm->param_value;
|
||||
} else if (itm->param_name == "classes_file") {
|
||||
dnn_classes_file = itm->param_value;
|
||||
} else if (itm->param_name =="framework") {
|
||||
dnn_framework = itm->param_value;
|
||||
} else if (itm->param_name =="backend") {
|
||||
dnn_backend = mtoi(itm->param_value);
|
||||
} else if (itm->param_name =="target") {
|
||||
dnn_target = mtoi(itm->param_value);
|
||||
} else if (itm->param_name =="scale") {
|
||||
dnn_scale = mtof(itm->param_value);
|
||||
} else if (itm->param_name =="width") {
|
||||
dnn_width = mtoi(itm->param_value);
|
||||
} else if (itm->param_name =="height") {
|
||||
dnn_height = mtoi(itm->param_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cls_algsec::params_defaults()
|
||||
{
|
||||
util_parms_add_default(params, "model_file", "");
|
||||
util_parms_add_default(params, "frame_interval", "5");
|
||||
util_parms_add_default(params, "image_type", "full");
|
||||
util_parms_add_default(params, "rotate", "0");
|
||||
|
||||
if (method == "haar") {
|
||||
util_parms_add_default(params, "threshold", "1.1");
|
||||
util_parms_add_default(params, "scalefactor", "1.1");
|
||||
util_parms_add_default(params, "flags", "0");
|
||||
util_parms_add_default(params, "maxsize", "1024");
|
||||
util_parms_add_default(params, "minsize", "8");
|
||||
util_parms_add_default(params, "minneighbors", "8");
|
||||
} else if (method == "hog") {
|
||||
util_parms_add_default(params, "threshold", "1.1");
|
||||
util_parms_add_default(params, "threshold_model", "2");
|
||||
util_parms_add_default(params, "scalefactor", "1.05");
|
||||
util_parms_add_default(params, "padding", "8");
|
||||
util_parms_add_default(params, "winstride", "8");
|
||||
} else if (method == "dnn") {
|
||||
util_parms_add_default(params, "backend", DNN_BACKEND_DEFAULT);
|
||||
util_parms_add_default(params, "target", DNN_TARGET_CPU);
|
||||
util_parms_add_default(params, "threshold", "0.75");
|
||||
util_parms_add_default(params, "width", cam->imgs.width);
|
||||
util_parms_add_default(params, "height", cam->imgs.height);
|
||||
util_parms_add_default(params, "scale", "1.0");
|
||||
}
|
||||
}
|
||||
|
||||
/**Load the parms from the config to algsec struct */
|
||||
void cls_algsec::load_params()
|
||||
{
|
||||
method = cam->cfg->secondary_method;
|
||||
image_norm = nullptr;
|
||||
params = nullptr;
|
||||
detected = false;
|
||||
height = cam->imgs.height;
|
||||
width = cam->imgs.width;
|
||||
frame_missed = 0;
|
||||
frame_cnt = 0;
|
||||
too_slow = 0;
|
||||
in_process = false;
|
||||
first_pass = true;
|
||||
handler_stop = false;
|
||||
|
||||
cfg_framerate = cam->cfg->framerate;
|
||||
cfg_log_level = cam->app->cfg->log_level;
|
||||
cfg_target_dir = cam->cfg->target_dir;
|
||||
|
||||
if (method == "none") {
|
||||
return;
|
||||
}
|
||||
|
||||
image_norm = (u_char*)mymalloc((size_t)cam->imgs.size_norm);
|
||||
|
||||
params = new ctx_params;
|
||||
util_parms_parse(params, "secondary_params", cam->cfg->secondary_params);
|
||||
|
||||
params_defaults();
|
||||
|
||||
params_log();
|
||||
|
||||
params_model();
|
||||
|
||||
frame_cnt = frame_interval;
|
||||
|
||||
if (method == "haar") {
|
||||
load_haar();
|
||||
} else if (method == "hog") {
|
||||
load_hog();
|
||||
} else if (method == "dnn") {
|
||||
load_dnn();
|
||||
} else {
|
||||
method = "none";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**Detection thread processing loop */
|
||||
void cls_algsec::handler()
|
||||
{
|
||||
long interval;
|
||||
|
||||
mythreadname_set("cv",cam->cfg->device_id, cam->cfg->device_name.c_str());
|
||||
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO,_("Secondary detection starting."));
|
||||
|
||||
handler_running = true;
|
||||
handler_stop = false;
|
||||
|
||||
load_params();
|
||||
|
||||
interval = 1000000L / cfg_framerate;
|
||||
is_started = true;
|
||||
while ((handler_stop == false) && (method != "none")) {
|
||||
if (in_process){
|
||||
if (method == "haar") {
|
||||
detect_haar();
|
||||
} else if (method == "hog") {
|
||||
detect_hog();
|
||||
} else if (method == "dnn") {
|
||||
detect_dnn();
|
||||
}
|
||||
in_process = false;
|
||||
} else {
|
||||
SLEEP(0,interval)
|
||||
}
|
||||
}
|
||||
is_started = false;
|
||||
handler_stop = false;
|
||||
handler_running = false;
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO,_("Secondary detection stopped."));
|
||||
|
||||
pthread_exit(nullptr);
|
||||
}
|
||||
|
||||
void cls_algsec::handler_startup()
|
||||
{
|
||||
int retcd;
|
||||
pthread_attr_t thread_attr;
|
||||
|
||||
if (cam->cfg->secondary_method == "none") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (handler_running == false) {
|
||||
handler_running = true;
|
||||
handler_stop = false;
|
||||
pthread_attr_init(&thread_attr);
|
||||
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
|
||||
retcd = pthread_create(&handler_thread, &thread_attr, &algsec_handler, this);
|
||||
if (retcd != 0) {
|
||||
MOTPLS_LOG(WRN, TYPE_ALL, NO_ERRNO,_("Unable to start secondary detection"));
|
||||
handler_running = false;
|
||||
handler_stop = true;
|
||||
}
|
||||
pthread_attr_destroy(&thread_attr);
|
||||
}
|
||||
}
|
||||
|
||||
void cls_algsec::handler_shutdown()
|
||||
{
|
||||
int waitcnt;
|
||||
|
||||
if (handler_running == true) {
|
||||
handler_stop = true;
|
||||
waitcnt = 0;
|
||||
while ((handler_running == true) && (waitcnt < cam->cfg->watchdog_tmo)){
|
||||
SLEEP(1,0)
|
||||
waitcnt++;
|
||||
}
|
||||
if (waitcnt == cam->cfg->watchdog_tmo) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("Normal shutdown of camera failed"));
|
||||
if (cam->cfg->watchdog_kill > 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
,_("Waiting additional %d seconds (watchdog_kill).")
|
||||
,cam->cfg->watchdog_kill);
|
||||
waitcnt = 0;
|
||||
while ((handler_running == true) && (waitcnt < cam->cfg->watchdog_kill)){
|
||||
SLEEP(1,0)
|
||||
waitcnt++;
|
||||
}
|
||||
if (waitcnt == cam->cfg->watchdog_kill) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("No response to shutdown. Killing it."));
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("Memory leaks will occur."));
|
||||
pthread_kill(handler_thread, SIGVTALRM);
|
||||
}
|
||||
} else {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("watchdog_kill set to terminate application."));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
handler_running = false;
|
||||
}
|
||||
|
||||
myfree(image_norm);
|
||||
mydelete(params);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*Invoke the secondary detetction method*/
|
||||
void cls_algsec::detect()
|
||||
{
|
||||
#ifdef HAVE_OPENCV
|
||||
if (method == "none") {
|
||||
return;
|
||||
}
|
||||
if (is_started == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (frame_cnt > 0) {
|
||||
frame_cnt--;
|
||||
}
|
||||
|
||||
if (frame_cnt == 0){
|
||||
if (in_process){
|
||||
frame_missed++;
|
||||
} else {
|
||||
memcpy(image_norm
|
||||
, cam->imgs.image_virgin
|
||||
, (uint)cam->imgs.size_norm);
|
||||
|
||||
/*Set the bool to detect on the new image and reset interval */
|
||||
in_process = true;
|
||||
frame_cnt = frame_interval;
|
||||
if (frame_missed >10){
|
||||
if (too_slow == 0) {
|
||||
MOTPLS_LOG(WRN, TYPE_ALL, NO_ERRNO
|
||||
,_("Your computer is too slow for these settings."));
|
||||
} else if (too_slow == 10){
|
||||
MOTPLS_LOG(WRN, TYPE_ALL, NO_ERRNO
|
||||
,_("Missed many frames for secondary detection."));
|
||||
MOTPLS_LOG(WRN, TYPE_ALL, NO_ERRNO
|
||||
,_("Your computer is too slow."));
|
||||
}
|
||||
too_slow++;
|
||||
}
|
||||
frame_missed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the method was changed to none, an error occurred*/
|
||||
if (method == "none") {
|
||||
handler_shutdown();
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
cls_algsec::cls_algsec(cls_camera *p_cam)
|
||||
{
|
||||
#ifdef HAVE_OPENCV
|
||||
cam = p_cam;
|
||||
handler_running = false;
|
||||
handler_stop = true;
|
||||
image_norm = nullptr;
|
||||
params = nullptr;
|
||||
method = "none";
|
||||
is_started = false;
|
||||
pthread_mutex_init(&mutex, NULL);
|
||||
handler_startup();
|
||||
#else
|
||||
(void)p_cam;
|
||||
#endif
|
||||
}
|
||||
|
||||
cls_algsec::~cls_algsec()
|
||||
{
|
||||
#ifdef HAVE_OPENCV
|
||||
handler_shutdown();
|
||||
pthread_mutex_destroy(&mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
|
||||
/*
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_ALG_SEC_HPP_
|
||||
#define _INCLUDE_ALG_SEC_HPP_
|
||||
|
||||
#ifdef HAVE_OPENCV
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#include <opencv2/objdetect.hpp>
|
||||
#include <opencv2/dnn.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/imgcodecs.hpp>
|
||||
#include <opencv2/videoio.hpp>
|
||||
#include <opencv2/video.hpp>
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
class cls_algsec {
|
||||
public:
|
||||
cls_algsec(cls_camera *p_cam);
|
||||
~cls_algsec();
|
||||
|
||||
void detect();
|
||||
bool detected;
|
||||
|
||||
std::string method;
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
bool handler_stop;
|
||||
bool handler_running;
|
||||
pthread_t handler_thread;
|
||||
void handler();
|
||||
|
||||
private:
|
||||
#ifdef HAVE_OPENCV
|
||||
cls_camera *cam;
|
||||
bool in_process;
|
||||
bool is_started;
|
||||
bool first_pass;
|
||||
int frame_cnt;
|
||||
int frame_missed;
|
||||
int too_slow;
|
||||
u_char *image_norm;
|
||||
int width;
|
||||
int height;
|
||||
int cfg_framerate;
|
||||
int cfg_log_level;
|
||||
std::string cfg_target_dir;
|
||||
|
||||
void handler_startup();
|
||||
void handler_shutdown();
|
||||
|
||||
void load_params();
|
||||
void params_defaults();
|
||||
void params_model();
|
||||
void params_log();
|
||||
|
||||
void load_dnn();
|
||||
void load_haar();
|
||||
void load_hog();
|
||||
void detect_dnn();
|
||||
void detect_haar();
|
||||
void detect_hog();
|
||||
void get_image(cv::Mat &mat_dst);
|
||||
void get_image_roi(cv::Mat &mat_src, cv::Mat &mat_dst);
|
||||
void label_image(cv::Mat &mat_dst, double confidence, cv::Point classIdPoint);
|
||||
void label_image(cv::Mat &mat_dst, std::vector<cv::Rect> &src_pos
|
||||
, std::vector<double> &src_weights);
|
||||
void image_show(cv::Mat &mat_dst);
|
||||
void debug_notice(cv::Mat &mat_dst,bool isdetect);
|
||||
|
||||
std::string config;
|
||||
ctx_params *params;
|
||||
|
||||
std::string model_file;
|
||||
int frame_interval;
|
||||
std::string image_type;
|
||||
int rotate;
|
||||
|
||||
double scalefactor;
|
||||
double threshold;
|
||||
|
||||
double hog_threshold_model;
|
||||
int hog_winstride;
|
||||
int hog_padding;
|
||||
|
||||
int haar_minneighbors;
|
||||
int haar_flags;
|
||||
int haar_minsize;
|
||||
int haar_maxsize;
|
||||
|
||||
std::string dnn_config;
|
||||
std::string dnn_framework;
|
||||
std::string dnn_classes_file;
|
||||
|
||||
int dnn_backend;
|
||||
int dnn_target;
|
||||
std::vector<std::string> dnn_classes;
|
||||
int dnn_width;
|
||||
int dnn_height;
|
||||
double dnn_scale;
|
||||
|
||||
cv::CascadeClassifier haar_cascade; /*Haar Cascade (if applicable) */
|
||||
cv::HOGDescriptor hog;
|
||||
cv::dnn::Net net;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif /*_INCLUDE_ALG_SEC_HPP_*/
|
||||
+857
@@ -0,0 +1,857 @@
|
||||
/*
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "motion.hpp"
|
||||
#include "util.hpp"
|
||||
#include "conf.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "allcam.hpp"
|
||||
#include "camera.hpp"
|
||||
#include "jpegutils.hpp"
|
||||
|
||||
|
||||
static void *allcam_handler(void *arg)
|
||||
{
|
||||
((cls_allcam *)arg)->handler();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void cls_allcam::getsizes_img(cls_camera *p_cam)
|
||||
{
|
||||
int src_w, src_h, dst_w, dst_h;
|
||||
|
||||
src_w = p_cam->all_sizes.src_w;
|
||||
src_h = p_cam->all_sizes.src_h;
|
||||
|
||||
dst_w = ((p_cam->all_loc.scale * src_w) / 100);
|
||||
if ((dst_w % 8) != 0) {
|
||||
dst_w = dst_w - (dst_w % 8) + 8;
|
||||
}
|
||||
if (dst_w < 64){
|
||||
dst_w = 64;
|
||||
}
|
||||
p_cam->all_sizes.dst_w = dst_w;
|
||||
|
||||
dst_h = ((p_cam->all_loc.scale * src_h) / 100);
|
||||
if ((dst_h % 8) != 0) {
|
||||
dst_h = dst_h - (dst_h % 8) + 8;
|
||||
}
|
||||
if (dst_h < 64) {
|
||||
dst_h = 64;
|
||||
}
|
||||
p_cam->all_sizes.dst_h = dst_h;
|
||||
p_cam->all_sizes.dst_sz = (dst_w * dst_h * 3)/2;
|
||||
}
|
||||
|
||||
void cls_allcam::getimg_src(cls_camera *p_cam, std::string imgtyp, u_char *dst_img, u_char *src_img)
|
||||
{
|
||||
int indx;
|
||||
ctx_stream_data *strm_c;
|
||||
|
||||
if (imgtyp == "norm") {
|
||||
strm_c = &p_cam->stream.norm;
|
||||
} else if (imgtyp == "motion") {
|
||||
strm_c = &p_cam->stream.motion;
|
||||
} else if (imgtyp == "source") {
|
||||
strm_c = &p_cam->stream.source;
|
||||
} else if (imgtyp == "secondary") {
|
||||
strm_c = &p_cam->stream.secondary;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&p_cam->stream.mutex);
|
||||
indx=0;
|
||||
while (indx < 1000) {
|
||||
if (strm_c->img_data == nullptr) {
|
||||
if (strm_c->all_cnct == 0){
|
||||
strm_c->all_cnct++;
|
||||
}
|
||||
pthread_mutex_unlock(&p_cam->stream.mutex);
|
||||
SLEEP(0, 1000);
|
||||
pthread_mutex_lock(&p_cam->stream.mutex);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
indx++;
|
||||
}
|
||||
if ((p_cam->imgs.height != p_cam->all_sizes.src_h) ||
|
||||
(p_cam->imgs.width != p_cam->all_sizes.src_w)) {
|
||||
MOTPLS_LOG(NTC, TYPE_STREAM, NO_ERRNO
|
||||
, "Image has changed. Device: %d"
|
||||
, p_cam->cfg->device_id);
|
||||
memset(src_img, 0x00, (uint)p_cam->all_sizes.src_sz);
|
||||
p_cam->all_sizes.reset = true;
|
||||
} else if (strm_c->img_data == nullptr) {
|
||||
MOTPLS_LOG(DBG, TYPE_STREAM, NO_ERRNO
|
||||
, "Could not get image for device %d"
|
||||
, p_cam->cfg->device_id);
|
||||
memset(src_img, 0x00, (uint)p_cam->all_sizes.src_sz);
|
||||
} else {
|
||||
memcpy(src_img, strm_c->img_data, (uint)p_cam->all_sizes.src_sz);
|
||||
}
|
||||
pthread_mutex_unlock(&p_cam->stream.mutex);
|
||||
|
||||
util_resize(src_img, p_cam->all_sizes.src_w, p_cam->all_sizes.src_h
|
||||
, dst_img, p_cam->all_sizes.dst_w, p_cam->all_sizes.dst_h);
|
||||
|
||||
}
|
||||
|
||||
void cls_allcam::getimg(ctx_stream_data *strm_a, std::string imgtyp)
|
||||
{
|
||||
int a_y, a_u, a_v; /* all img y,u,v */
|
||||
int c_y, c_u, c_v; /* camera img y,u,v */
|
||||
int img_orow, img_ocol;
|
||||
int indx, row, dst_w, dst_h;
|
||||
u_char *dst_img, *src_img, *all_img;
|
||||
cls_camera *p_cam;
|
||||
|
||||
getsizes();
|
||||
|
||||
a_y = 0;
|
||||
a_u = (all_sizes.src_w * all_sizes.src_h);
|
||||
a_v = a_u + (a_u / 4);
|
||||
|
||||
all_img = (unsigned char*) mymalloc((uint)all_sizes.src_sz);
|
||||
memset(all_img , 0x80, (size_t)a_u);
|
||||
memset(all_img + a_u, 0x80, (size_t)(a_u/2));
|
||||
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
dst_w = p_cam->all_sizes.dst_w;
|
||||
dst_h = p_cam->all_sizes.dst_h;
|
||||
|
||||
img_orow = p_cam->all_loc.offset_row;
|
||||
img_ocol = p_cam->all_loc.offset_col;
|
||||
|
||||
dst_img = (unsigned char*) mymalloc((uint)p_cam->all_sizes.dst_sz);
|
||||
src_img = (unsigned char*) mymalloc((uint)p_cam->all_sizes.src_sz);
|
||||
|
||||
getimg_src(p_cam, imgtyp, dst_img, src_img);
|
||||
|
||||
a_y = (img_orow * all_sizes.src_w) + img_ocol;
|
||||
a_u =(all_sizes.src_h * all_sizes.src_w) +
|
||||
((img_orow / 4) * all_sizes.src_w) + (img_ocol / 2) ;
|
||||
a_v = a_u + ((all_sizes.src_h * all_sizes.src_w) / 4);
|
||||
|
||||
c_y = 0;
|
||||
c_u = (dst_w * dst_h);
|
||||
c_v = c_u + (c_u / 4);
|
||||
|
||||
for (row=0; row<dst_h; row++) {
|
||||
memcpy(all_img + a_y, dst_img + c_y, (uint)dst_w);
|
||||
a_y += all_sizes.src_w;
|
||||
c_y += dst_w;
|
||||
if (row % 2) {
|
||||
memcpy(all_img + a_u, dst_img + c_u, (uint)dst_w / 2);
|
||||
//mymemset(all_img + a_u, 0xFA, dst_w/2);
|
||||
a_u += (all_sizes.src_w / 2);
|
||||
c_u += (dst_w / 2);
|
||||
memcpy(all_img + a_v, dst_img + c_v, (uint)dst_w / 2);
|
||||
a_v += (all_sizes.src_w / 2);
|
||||
c_v += (dst_w / 2);
|
||||
}
|
||||
}
|
||||
|
||||
myfree(dst_img);
|
||||
myfree(src_img);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&stream.mutex);
|
||||
memset(strm_a->img_data, 0x80, (size_t)all_sizes.dst_sz);
|
||||
util_resize(all_img, all_sizes.src_w, all_sizes.src_h
|
||||
, strm_a->img_data, all_sizes.dst_w, all_sizes.dst_h);
|
||||
myfree(all_img);
|
||||
|
||||
strm_a->jpg_sz = jpgutl_put_yuv420p(
|
||||
strm_a->jpg_data, all_sizes.dst_sz, strm_a->img_data
|
||||
, all_sizes.dst_w, all_sizes.dst_h
|
||||
, 70, NULL,NULL,NULL);
|
||||
|
||||
strm_a->consumed = false;
|
||||
pthread_mutex_unlock(&stream.mutex);
|
||||
|
||||
}
|
||||
|
||||
void cls_allcam::stream_free()
|
||||
{
|
||||
int indx;
|
||||
ctx_stream_data *strm;
|
||||
|
||||
for (indx=0;indx<5;indx++) {
|
||||
if (indx == 0) {
|
||||
strm = &stream.norm;
|
||||
} else if (indx == 1) {
|
||||
strm = &stream.motion;
|
||||
} else if (indx == 2) {
|
||||
strm = &stream.secondary;
|
||||
} else if (indx == 3) {
|
||||
strm = &stream.source;
|
||||
} else if (indx == 4) {
|
||||
strm = &stream.sub;
|
||||
}
|
||||
myfree(strm->img_data);
|
||||
myfree(strm->jpg_data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cls_allcam::stream_alloc()
|
||||
{
|
||||
int indx;
|
||||
ctx_stream_data *strm;
|
||||
|
||||
for (indx=0;indx<5;indx++) {
|
||||
if (indx == 0) {
|
||||
strm = &stream.norm;
|
||||
} else if (indx == 1) {
|
||||
strm = &stream.motion;
|
||||
} else if (indx == 2) {
|
||||
strm = &stream.secondary;
|
||||
} else if (indx == 3) {
|
||||
strm = &stream.source;
|
||||
} else if (indx == 4) {
|
||||
strm = &stream.sub;
|
||||
}
|
||||
strm->img_data = (unsigned char*)
|
||||
mymalloc((size_t)all_sizes.dst_sz);
|
||||
strm->jpg_data = (unsigned char*)
|
||||
mymalloc((size_t)all_sizes.dst_sz);
|
||||
strm->consumed = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cls_allcam::getsizes_scale()
|
||||
{
|
||||
int indx, row, mx_h;
|
||||
bool dflt_scale;
|
||||
cls_camera *p_cam;
|
||||
|
||||
dflt_scale = false;
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
if (p_cam->all_loc.scale == -1) {
|
||||
dflt_scale = true;
|
||||
}
|
||||
}
|
||||
if (dflt_scale) {
|
||||
for (row=1; row<=max_row; row++) {
|
||||
mx_h = 0;
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
if (row == p_cam->all_loc.row) {
|
||||
if (mx_h < p_cam->all_sizes.src_h) {
|
||||
mx_h = p_cam->all_sizes.src_h;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
if (row == p_cam->all_loc.row) {
|
||||
p_cam->all_loc.scale = (int)((float)(mx_h*100 / p_cam->all_sizes.src_h));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
getsizes_img(p_cam);
|
||||
MOTPLS_LOG(DBG, TYPE_STREAM, NO_ERRNO
|
||||
, "Device %d Original Size %dx%d Scale %d New Size %dx%d"
|
||||
, p_cam->cfg->device_id
|
||||
, p_cam->all_sizes.src_w, p_cam->all_sizes.src_h
|
||||
, p_cam->all_loc.scale
|
||||
, p_cam->all_sizes.dst_w, p_cam->all_sizes.dst_h);
|
||||
}
|
||||
}
|
||||
|
||||
void cls_allcam::getsizes_alignv()
|
||||
{
|
||||
int indx, row, col;
|
||||
int chk_sz;
|
||||
int mx_h;
|
||||
cls_camera *p_cam;
|
||||
|
||||
for (row=1; row<=max_row; row++) {
|
||||
chk_sz = 0;
|
||||
mx_h = 0;
|
||||
for (col=1; col<=max_col; col++) {
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
if ((row == p_cam->all_loc.row) &&
|
||||
(col == p_cam->all_loc.col)) {
|
||||
p_cam->all_loc.offset_col = chk_sz;
|
||||
chk_sz += p_cam->all_sizes.dst_w;
|
||||
if (mx_h < p_cam->all_sizes.dst_h) {
|
||||
mx_h = p_cam->all_sizes.dst_h;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Align/center vert. the images in each row*/
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
if (p_cam->all_loc.row == row) {
|
||||
p_cam->all_loc.offset_row =
|
||||
all_sizes.src_h +
|
||||
((mx_h - p_cam->all_sizes.dst_h)/2) ;
|
||||
}
|
||||
}
|
||||
all_sizes.src_h += mx_h;
|
||||
if (all_sizes.src_w < chk_sz) {
|
||||
all_sizes.src_w = chk_sz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cls_allcam::getsizes_alignh()
|
||||
{
|
||||
int indx, col;
|
||||
int chk_sz, chk_w, mx_w;
|
||||
cls_camera *p_cam;
|
||||
|
||||
/* Align/center horiz. the images within each column area */
|
||||
chk_w = 0;
|
||||
for (col=1; col<=max_col; col++) {
|
||||
chk_sz = 0;
|
||||
mx_w = 0;
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
if (p_cam->all_loc.col == col) {
|
||||
if (p_cam->all_loc.offset_col < chk_w) {
|
||||
p_cam->all_loc.offset_col = chk_w;
|
||||
}
|
||||
if (chk_sz < p_cam->all_loc.offset_col) {
|
||||
chk_sz = p_cam->all_loc.offset_col;
|
||||
}
|
||||
if (mx_w < p_cam->all_sizes.dst_w) {
|
||||
mx_w = p_cam->all_sizes.dst_w;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
|
||||
if (p_cam->all_loc.col == col) {
|
||||
p_cam->all_loc.offset_col =
|
||||
chk_sz + ((mx_w - p_cam->all_sizes.dst_w) /2) ;
|
||||
}
|
||||
}
|
||||
chk_w = mx_w + chk_sz;
|
||||
if (all_sizes.src_w < chk_w) {
|
||||
all_sizes.src_w = chk_w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cls_allcam::getsizes_offset_user()
|
||||
{
|
||||
int indx, chk_sz;
|
||||
cls_camera *p_cam;
|
||||
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
|
||||
chk_sz = p_cam->all_loc.offset_col + p_cam->all_loc.offset_user_col;
|
||||
if (chk_sz < 0) {
|
||||
MOTPLS_LOG(DBG, TYPE_STREAM, NO_ERRNO
|
||||
, "Device %d invalid image column offset. (%d + %d) less than zero "
|
||||
, p_cam->cfg->device_id
|
||||
, p_cam->all_loc.offset_col
|
||||
, p_cam->all_loc.offset_user_col);
|
||||
} else if ((chk_sz + p_cam->all_sizes.dst_w) > all_sizes.src_w) {
|
||||
MOTPLS_LOG(DBG, TYPE_STREAM, NO_ERRNO
|
||||
, "Device %d invalid image column offset. (%d + %d) over image size"
|
||||
, p_cam->cfg->device_id
|
||||
, p_cam->all_loc.offset_col
|
||||
, p_cam->all_loc.offset_user_col);
|
||||
} else {
|
||||
p_cam->all_loc.offset_col = chk_sz;
|
||||
}
|
||||
|
||||
chk_sz = p_cam->all_loc.offset_row + p_cam->all_loc.offset_user_row;
|
||||
if (chk_sz < 0 ) {
|
||||
MOTPLS_LOG(DBG, TYPE_STREAM, NO_ERRNO
|
||||
, "Device %d invalid image row offset. (%d + %d) less than zero "
|
||||
, p_cam->cfg->device_id
|
||||
, p_cam->all_loc.offset_row
|
||||
, p_cam->all_loc.offset_user_row);
|
||||
} else if ((chk_sz + p_cam->all_sizes.dst_h) > all_sizes.src_h) {
|
||||
MOTPLS_LOG(DBG, TYPE_STREAM, NO_ERRNO
|
||||
, "Device %d invalid image row offset. (%d + %d) over image size"
|
||||
, p_cam->cfg->device_id
|
||||
, p_cam->all_loc.offset_row
|
||||
, p_cam->all_loc.offset_user_row);
|
||||
} else {
|
||||
p_cam->all_loc.offset_row = chk_sz;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool cls_allcam::getsizes_reset()
|
||||
{
|
||||
int indx;
|
||||
bool reset;
|
||||
cls_camera *p_cam;
|
||||
|
||||
if (all_sizes.reset == true) {
|
||||
reset = true;
|
||||
} else {
|
||||
reset = false;
|
||||
}
|
||||
|
||||
active_cam.clear();
|
||||
active_cnt = 0;
|
||||
for (indx=0;indx<app->cam_cnt;indx++) {
|
||||
p_cam = app->cam_list[indx];
|
||||
if (p_cam->device_status == STATUS_OPENED) {
|
||||
if (p_cam->all_sizes.reset == true) {
|
||||
reset = true;
|
||||
p_cam->all_sizes.reset = false;
|
||||
}
|
||||
active_cnt++;
|
||||
active_cam.push_back(p_cam);
|
||||
}
|
||||
}
|
||||
return reset;
|
||||
}
|
||||
|
||||
void cls_allcam::getsizes_pct()
|
||||
{
|
||||
int indx, dst_w, dst_h, dst_scale;
|
||||
cls_camera *p_cam;
|
||||
|
||||
if ((all_sizes.src_h ==0) || (all_sizes.src_w == 0)) {
|
||||
all_sizes.src_w = 320;
|
||||
all_sizes.src_h = 240;
|
||||
}
|
||||
all_sizes.src_sz =((all_sizes.src_h * all_sizes.src_w * 3)/2);
|
||||
all_sizes.reset = false;
|
||||
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
p_cam->all_loc.xpct_st = ((p_cam->all_loc.offset_col * 100) /all_sizes.src_w);
|
||||
p_cam->all_loc.xpct_en =
|
||||
(((p_cam->all_loc.offset_col+p_cam->all_sizes.dst_w) * 100) /all_sizes.src_w);
|
||||
p_cam->all_loc.ypct_st = ((p_cam->all_loc.offset_row * 100) /all_sizes.src_h);
|
||||
p_cam->all_loc.ypct_en =
|
||||
(((p_cam->all_loc.offset_row+p_cam->all_sizes.dst_h) * 100) /all_sizes.src_h);
|
||||
}
|
||||
|
||||
dst_scale = app->cfg->stream_preview_scale;
|
||||
|
||||
dst_w = ((dst_scale * all_sizes.src_w) / 100);
|
||||
if ((dst_w % 8) != 0) {
|
||||
dst_w = dst_w - (dst_w % 8) + 8;
|
||||
}
|
||||
if (dst_w < 64){
|
||||
dst_w = 64;
|
||||
}
|
||||
all_sizes.dst_w = dst_w;
|
||||
|
||||
dst_h = ((dst_scale * all_sizes.src_h) / 100);
|
||||
if ((dst_h % 8) != 0) {
|
||||
dst_h = dst_h - (dst_h % 8) + 8;
|
||||
}
|
||||
if (dst_h < 64) {
|
||||
dst_h = 64;
|
||||
}
|
||||
all_sizes.dst_h = dst_h;
|
||||
all_sizes.dst_sz = (dst_w * dst_h * 3)/2;
|
||||
|
||||
MOTPLS_LOG(DBG, TYPE_STREAM, NO_ERRNO
|
||||
, "Combined Image Original Size %dx%d Scale %d New Size %dx%d"
|
||||
, all_sizes.src_w, all_sizes.src_h
|
||||
, dst_scale
|
||||
, all_sizes.dst_w, all_sizes.dst_h);
|
||||
|
||||
}
|
||||
|
||||
void cls_allcam::init_params()
|
||||
{
|
||||
int indx, indx1;
|
||||
ctx_params *params;
|
||||
ctx_params_item *itm;
|
||||
cls_camera *p_cam;
|
||||
|
||||
memset(&all_sizes, 0, sizeof(ctx_all_sizes));
|
||||
|
||||
params = new ctx_params;
|
||||
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
p_cam->all_loc.row = -1;
|
||||
p_cam->all_loc.col = -1;
|
||||
p_cam->all_loc.offset_user_col = 0;
|
||||
p_cam->all_loc.offset_user_row = 0;
|
||||
p_cam->all_loc.scale = p_cam->cfg->stream_preview_scale;
|
||||
|
||||
util_parms_parse(params
|
||||
, "stream_preview_params"
|
||||
, p_cam->cfg->stream_preview_params);
|
||||
|
||||
for (indx1=0;indx1<params->params_cnt;indx1++) {
|
||||
itm = ¶ms->params_array[indx1];
|
||||
if (itm->param_name == "row") {
|
||||
p_cam->all_loc.row = mtoi(itm->param_value);
|
||||
}
|
||||
if (itm->param_name == "col") {
|
||||
p_cam->all_loc.col = mtoi(itm->param_value);
|
||||
}
|
||||
if (itm->param_name == "offset_col") {
|
||||
p_cam->all_loc.offset_user_col =
|
||||
mtoi(itm->param_value);
|
||||
}
|
||||
if (itm->param_name == "offset_row") {
|
||||
p_cam->all_loc.offset_user_row =
|
||||
mtoi(itm->param_value);
|
||||
}
|
||||
}
|
||||
params->params_array.clear();
|
||||
}
|
||||
|
||||
mydelete(params);
|
||||
|
||||
}
|
||||
|
||||
void cls_allcam::init_validate()
|
||||
{
|
||||
int indx, indx1;
|
||||
int row, col, mx_row, mx_col, col_chk;
|
||||
bool cfg_valid, chk;
|
||||
std::string cfg_row, cfg_col;
|
||||
cls_camera *p_cam, *p_cam1;
|
||||
|
||||
mx_row = 0;
|
||||
mx_col = 0;
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
if (mx_col < p_cam->all_loc.col) {
|
||||
mx_col = p_cam->all_loc.col;
|
||||
}
|
||||
if (mx_row < p_cam->all_loc.row) {
|
||||
mx_row = p_cam->all_loc.row;
|
||||
}
|
||||
}
|
||||
|
||||
cfg_valid = true;
|
||||
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
if ((p_cam->all_loc.col == -1) ||
|
||||
(p_cam->all_loc.row == -1)) {
|
||||
cfg_valid = false;
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO
|
||||
, "No stream_preview_params for cam %d"
|
||||
, p_cam->cfg->device_id);
|
||||
} else {
|
||||
for (indx1=0; indx1<active_cnt; indx1++) {
|
||||
p_cam1 = active_cam[indx1];
|
||||
if ((p_cam->all_loc.col == p_cam1->all_loc.col) &&
|
||||
(p_cam->all_loc.row == p_cam1->all_loc.row) &&
|
||||
(indx != indx1)) {
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO
|
||||
, "Duplicate stream_preview_params "
|
||||
" cam %d, cam %d row %d col %d"
|
||||
, p_cam->cfg->device_id
|
||||
, p_cam1->cfg->device_id
|
||||
, p_cam->all_loc.row
|
||||
, p_cam->all_loc.col);
|
||||
cfg_valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (p_cam->all_loc.row == 0) {
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO
|
||||
, "Invalid stream_preview_params row cam %d, row %d"
|
||||
, p_cam->cfg->device_id
|
||||
, p_cam->all_loc.row);
|
||||
cfg_valid = false;
|
||||
}
|
||||
if (p_cam->all_loc.col == 0) {
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO
|
||||
, "Invalid stream_preview_params col cam %d, col %d"
|
||||
, p_cam->cfg->device_id
|
||||
, p_cam->all_loc.col);
|
||||
cfg_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (row=1; row<=mx_row; row++) {
|
||||
chk = false;
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
if (row == p_cam->all_loc.row) {
|
||||
chk = true;
|
||||
}
|
||||
}
|
||||
if (chk == false) {
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO
|
||||
, "Invalid stream_preview_params combination. "
|
||||
" Missing row %d", row);
|
||||
cfg_valid = false;
|
||||
}
|
||||
col_chk = 0;
|
||||
for (col=1; col<=mx_col; col++) {
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
if ((row == p_cam->all_loc.row) &&
|
||||
(col == p_cam->all_loc.col)) {
|
||||
if ((col_chk+1) == col) {
|
||||
col_chk = col;
|
||||
} else {
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO
|
||||
, "Invalid stream_preview_params combination. "
|
||||
" Missing row %d column %d", row, col_chk+1);
|
||||
cfg_valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg_valid == false) {
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO
|
||||
,"Creating default stream preview values");
|
||||
row = 0;
|
||||
col = 0;
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
if (col == 1) {
|
||||
col++;
|
||||
} else {
|
||||
row++;
|
||||
col = 1;
|
||||
}
|
||||
p_cam->all_loc.col = col;
|
||||
p_cam->all_loc.row = row;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cls_allcam::init_cams()
|
||||
{
|
||||
int indx;
|
||||
cls_camera *p_cam;
|
||||
|
||||
init_params();
|
||||
init_validate();
|
||||
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
MOTPLS_LOG(DBG, TYPE_ALL, NO_ERRNO
|
||||
,"stream_preview_params values. Device %d row %d col %d"
|
||||
, p_cam->cfg->device_id
|
||||
, p_cam->all_loc.row
|
||||
, p_cam->all_loc.col);
|
||||
}
|
||||
|
||||
all_sizes.src_w = 0;
|
||||
all_sizes.src_h = 0;
|
||||
all_sizes.src_sz = 0;
|
||||
|
||||
max_row = 1;
|
||||
max_col = 1;
|
||||
for (indx=0; indx<active_cnt; indx++) {
|
||||
p_cam = active_cam[indx];
|
||||
p_cam->all_sizes.src_w = p_cam->imgs.width;
|
||||
p_cam->all_sizes.src_h = p_cam->imgs.height;
|
||||
p_cam->all_sizes.src_sz = ((p_cam->imgs.height * p_cam->imgs.width * 3)/2);
|
||||
if (max_row < p_cam->all_loc.row) {
|
||||
max_row = p_cam->all_loc.row;
|
||||
}
|
||||
if (max_col < p_cam->all_loc.col) {
|
||||
max_col = p_cam->all_loc.col;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cls_allcam::getsizes()
|
||||
{
|
||||
if (getsizes_reset() == false) {
|
||||
return;
|
||||
}
|
||||
init_cams();
|
||||
getsizes_scale();
|
||||
getsizes_alignv();
|
||||
getsizes_alignh();
|
||||
getsizes_offset_user();
|
||||
getsizes_pct();
|
||||
stream_free();
|
||||
stream_alloc();
|
||||
|
||||
}
|
||||
|
||||
void cls_allcam::timing()
|
||||
{
|
||||
struct timespec ts2;
|
||||
int64_t sleeptm;
|
||||
|
||||
if ((restart == true) || (handler_stop == true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts2);
|
||||
|
||||
sleeptm = ((1000000L / app->cfg->stream_maxrate) -
|
||||
(1000000L * (ts2.tv_sec - curr_ts.tv_sec)) -
|
||||
((ts2.tv_nsec - curr_ts.tv_nsec)/1000))*1000;
|
||||
|
||||
/* If over 1 second, just do one*/
|
||||
if (sleeptm > 999999999L) {
|
||||
SLEEP(1, 0);
|
||||
} else if (sleeptm > 0) {
|
||||
SLEEP(0, sleeptm);
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &curr_ts);
|
||||
|
||||
}
|
||||
|
||||
void cls_allcam::handler()
|
||||
{
|
||||
mythreadname_set("ac", 0, "allcam");
|
||||
|
||||
while (handler_stop == false) {
|
||||
if ((stream.norm.all_cnct > 0) &&
|
||||
(stream.norm.consumed == true)) {
|
||||
getimg(&stream.norm,"norm");
|
||||
}
|
||||
if ((stream.sub.all_cnct > 0) &&
|
||||
(stream.sub.consumed == true)) {
|
||||
getimg(&stream.sub,"norm");
|
||||
}
|
||||
if ((stream.motion.all_cnct > 0) &&
|
||||
(stream.motion.consumed == true)) {
|
||||
getimg(&stream.motion,"motion");
|
||||
}
|
||||
if ((stream.source.all_cnct > 0) &&
|
||||
(stream.source.consumed == true)) {
|
||||
getimg(&stream.source,"source");
|
||||
}
|
||||
if ((stream.secondary.all_cnct > 0) &&
|
||||
(stream.secondary.consumed == true)) {
|
||||
getimg(&stream.secondary,"secondary");
|
||||
}
|
||||
timing();
|
||||
}
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("All camera closed"));
|
||||
|
||||
handler_running = false;
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
void cls_allcam::handler_startup()
|
||||
{
|
||||
int retcd;
|
||||
pthread_attr_t thread_attr;
|
||||
|
||||
if (handler_running == false) {
|
||||
handler_running = true;
|
||||
handler_stop = false;
|
||||
restart = false;
|
||||
pthread_attr_init(&thread_attr);
|
||||
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
|
||||
retcd = pthread_create(&handler_thread, &thread_attr, &allcam_handler, this);
|
||||
if (retcd != 0) {
|
||||
MOTPLS_LOG(WRN, TYPE_ALL, NO_ERRNO,_("Unable to start all camera thread."));
|
||||
handler_running = false;
|
||||
handler_stop = true;
|
||||
}
|
||||
pthread_attr_destroy(&thread_attr);
|
||||
}
|
||||
}
|
||||
|
||||
void cls_allcam::handler_shutdown()
|
||||
{
|
||||
int waitcnt;
|
||||
|
||||
if (handler_running == true) {
|
||||
handler_stop = true;
|
||||
waitcnt = 0;
|
||||
while ((handler_running == true) && (waitcnt < app->cfg->watchdog_tmo)){
|
||||
SLEEP(1,0)
|
||||
waitcnt++;
|
||||
}
|
||||
if (waitcnt == app->cfg->watchdog_tmo) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("Normal shutdown of all camera failed"));
|
||||
if (app->cfg->watchdog_kill > 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
,_("Waiting additional %d seconds (watchdog_kill).")
|
||||
,app->cfg->watchdog_kill);
|
||||
waitcnt = 0;
|
||||
while ((handler_running == true) && (waitcnt < app->cfg->watchdog_kill)){
|
||||
SLEEP(1,0)
|
||||
waitcnt++;
|
||||
}
|
||||
if (waitcnt == app->cfg->watchdog_kill) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("No response to shutdown. Killing it."));
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("Memory leaks will occur."));
|
||||
pthread_kill(handler_thread, SIGVTALRM);
|
||||
}
|
||||
} else {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("watchdog_kill set to terminate application."));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
handler_running = false;
|
||||
watchdog = app->cfg->watchdog_tmo;
|
||||
}
|
||||
}
|
||||
|
||||
cls_allcam::cls_allcam(cls_motapp *p_app)
|
||||
{
|
||||
app = p_app;
|
||||
|
||||
watchdog = app->cfg->watchdog_tmo;
|
||||
handler_running = false;
|
||||
handler_stop = true;
|
||||
finish = false;
|
||||
memset(&all_sizes, 0, sizeof(ctx_all_sizes));
|
||||
memset(&stream, 0, sizeof(ctx_stream));
|
||||
all_sizes.reset = true;
|
||||
pthread_mutex_init(&stream.mutex, NULL);
|
||||
stream.motion.consumed = true;
|
||||
stream.norm.consumed = true;
|
||||
stream.secondary.consumed = true;
|
||||
stream.source.consumed = true;
|
||||
stream.sub.consumed = true;
|
||||
clock_gettime(CLOCK_MONOTONIC, &curr_ts);
|
||||
active_cnt = 0;
|
||||
active_cam.clear();
|
||||
|
||||
handler_startup();
|
||||
}
|
||||
|
||||
cls_allcam::~cls_allcam()
|
||||
{
|
||||
finish = true;
|
||||
handler_shutdown();
|
||||
pthread_mutex_destroy(&stream.mutex);
|
||||
stream_free();
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_ALLCAM_HPP_
|
||||
#define _INCLUDE_ALLCAM_HPP_
|
||||
|
||||
class cls_allcam {
|
||||
public:
|
||||
cls_allcam(cls_motapp *p_app);
|
||||
~cls_allcam();
|
||||
|
||||
bool handler_stop;
|
||||
bool handler_running;
|
||||
pthread_t handler_thread;
|
||||
void handler();
|
||||
ctx_stream stream;
|
||||
ctx_all_sizes all_sizes;
|
||||
|
||||
bool restart;
|
||||
bool finish;
|
||||
|
||||
private:
|
||||
cls_motapp *app;
|
||||
|
||||
std::vector<cls_camera*> active_cam;
|
||||
int active_cnt;
|
||||
int watchdog;
|
||||
int max_col;
|
||||
int max_row;
|
||||
struct timespec curr_ts;
|
||||
|
||||
void handler_startup();
|
||||
void handler_shutdown();
|
||||
void timing();
|
||||
void stream_free();
|
||||
void stream_alloc();
|
||||
void getsizes_img(cls_camera *p_cam);
|
||||
void getsizes_scale();
|
||||
void getsizes_alignv();
|
||||
void getsizes_alignh();
|
||||
void getsizes_offset_user();
|
||||
bool getsizes_reset();
|
||||
void getsizes_pct();
|
||||
void getsizes();
|
||||
void init_params();
|
||||
void init_validate();
|
||||
void init_cams();
|
||||
void getimg_src(cls_camera *p_cam, std::string imgtyp, u_char *dst_img, u_char *src_img);
|
||||
void getimg(ctx_stream_data *strm_a, std::string imgtyp);
|
||||
|
||||
};
|
||||
|
||||
#endif /*_INCLUDE_ALLCAM_HPP_*/
|
||||
+2058
File diff suppressed because it is too large
Load Diff
+280
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_CAMERA_HPP_
|
||||
#define _INCLUDE_CAMERA_HPP_
|
||||
|
||||
#define IMAGE_MOTION 1
|
||||
#define IMAGE_TRIGGER 2
|
||||
#define IMAGE_SAVE 4
|
||||
#define IMAGE_SAVED 8
|
||||
#define IMAGE_PRECAP 16
|
||||
#define IMAGE_POSTCAP 32
|
||||
|
||||
enum CAMERA_TYPE {
|
||||
CAMERA_TYPE_UNKNOWN,
|
||||
CAMERA_TYPE_V4L2,
|
||||
CAMERA_TYPE_LIBCAM,
|
||||
CAMERA_TYPE_NETCAM
|
||||
};
|
||||
|
||||
enum CAPTURE_RESULT {
|
||||
CAPTURE_SUCCESS,
|
||||
CAPTURE_FAILURE,
|
||||
CAPTURE_ATTEMPTED
|
||||
};
|
||||
|
||||
struct ctx_coord {
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
int minx;
|
||||
int maxx;
|
||||
int miny;
|
||||
int maxy;
|
||||
int stddev_x;
|
||||
int stddev_y;
|
||||
int stddev_xy;
|
||||
};
|
||||
|
||||
struct ctx_image_data {
|
||||
u_char *image_norm;
|
||||
u_char *image_high;
|
||||
int diffs;
|
||||
int diffs_raw;
|
||||
int diffs_ratio;
|
||||
int64_t idnbr_norm;
|
||||
int64_t idnbr_high;
|
||||
struct timespec imgts; /* Realtime for display */
|
||||
struct timespec monots; /* Montonic clock for timing */
|
||||
int shot; /* Sub second timestamp count */
|
||||
unsigned long cent_dist; /* Movement center to img center distance * Note: Dist is calculated distX*distX + distY*distY */
|
||||
unsigned int flags; /* See IMAGE_* defines */
|
||||
ctx_coord location; /* coordinates for center and size of last motion detection*/
|
||||
int total_labels;
|
||||
};
|
||||
|
||||
struct ctx_images {
|
||||
ctx_image_data *image_ring; /* The base address of the image ring buffer */
|
||||
ctx_image_data image_motion; /* Picture buffer for motion images */
|
||||
ctx_image_data image_preview; /* Picture buffer for best image when enables */
|
||||
|
||||
u_char *ref; /* The reference frame */
|
||||
u_char *ref_next; /* The reference frame */
|
||||
u_char *mask; /* Buffer for the mask file */
|
||||
u_char *common_buffer;
|
||||
u_char *image_substream;
|
||||
u_char *image_virgin; /* Last picture frame with no text or locate overlay */
|
||||
u_char *image_vprvcy; /* Virgin image with the privacy mask applied */
|
||||
u_char *mask_privacy; /* Buffer for the privacy mask values */
|
||||
u_char *mask_privacy_uv; /* Buffer for the privacy U&V values */
|
||||
u_char *mask_privacy_high; /* Buffer for the privacy mask values */
|
||||
u_char *mask_privacy_high_uv; /* Buffer for the privacy U&V values */
|
||||
u_char *image_secondary; /* Buffer for JPG from alg_sec methods */
|
||||
|
||||
int ring_size;
|
||||
int ring_in; /* Index in image ring buffer we last added a image into */
|
||||
int ring_out; /* Index in image ring buffer we want to process next time */
|
||||
|
||||
int *ref_dyn; /* Dynamic objects to be excluded from reference frame */
|
||||
int *labels;
|
||||
int *labelsize;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
int size_norm; /* Number of bytes for normal size image */
|
||||
|
||||
int width_high;
|
||||
int height_high;
|
||||
int size_high; /* Number of bytes for high resolution image */
|
||||
|
||||
int motionsize;
|
||||
int labelgroup_max;
|
||||
int labels_above;
|
||||
int labelsize_max;
|
||||
int largest_label;
|
||||
int size_secondary; /* Size of the jpg put into image_secondary*/
|
||||
|
||||
};
|
||||
|
||||
struct ctx_schedule_data {
|
||||
int st_hr;
|
||||
int st_min;
|
||||
int en_hr;
|
||||
int en_min;
|
||||
bool detect;
|
||||
std::string action;
|
||||
};
|
||||
|
||||
struct ctx_cleandir {
|
||||
struct timespec next_ts;
|
||||
std::string freq;
|
||||
std::string action;
|
||||
std::string script;
|
||||
std::string runtime;
|
||||
bool removedir;
|
||||
std::string dur_unit;
|
||||
int dur_val;
|
||||
};
|
||||
|
||||
class cls_camera {
|
||||
public:
|
||||
cls_camera(cls_motapp *p_app);
|
||||
~cls_camera();
|
||||
|
||||
cls_motapp *app;
|
||||
cls_config *cfg;
|
||||
cls_config *conf_src;
|
||||
ctx_images imgs;
|
||||
ctx_stream stream;
|
||||
ctx_image_data *current_image;
|
||||
cls_alg *alg;
|
||||
cls_algsec *algsec;
|
||||
cls_rotate *rotate;
|
||||
cls_netcam *netcam;
|
||||
cls_netcam *netcam_high;
|
||||
ctx_all_loc all_loc;
|
||||
ctx_all_sizes all_sizes;
|
||||
cls_draw *draw;
|
||||
cls_picture *picture;
|
||||
|
||||
bool handler_stop;
|
||||
bool handler_running;
|
||||
pthread_t handler_thread;
|
||||
void handler();
|
||||
void handler_startup();
|
||||
void handler_shutdown();
|
||||
|
||||
bool restart;
|
||||
bool finish;
|
||||
int threadnr;
|
||||
int noise;
|
||||
bool detecting_motion;
|
||||
int event_curr_nbr;
|
||||
int event_prev_nbr;
|
||||
int threshold;
|
||||
int lastrate;
|
||||
int frame_skip;
|
||||
bool lost_connection;
|
||||
int text_scale;
|
||||
int watchdog;
|
||||
bool movie_passthrough;
|
||||
char eventid[20];
|
||||
char text_event_string[PATH_MAX];
|
||||
char hostname[PATH_MAX];
|
||||
char action_user[40];
|
||||
int movie_fps;
|
||||
bool passflag;
|
||||
int pipe;
|
||||
int mpipe;
|
||||
bool pause;
|
||||
std::string user_pause;
|
||||
int missing_frame_counter;
|
||||
|
||||
uint64_t info_diff_tot;
|
||||
uint64_t info_diff_cnt;
|
||||
int info_sdev_min;
|
||||
int info_sdev_max;
|
||||
uint64_t info_sdev_tot;
|
||||
std::vector<std::vector<ctx_schedule_data>> schedule;
|
||||
ctx_cleandir *cleandir;
|
||||
|
||||
bool action_snapshot; /* Make a snapshot */
|
||||
bool event_stop; /* Boolean for whether to stop a event */
|
||||
bool event_user; /* Boolean for whether to user triggered an event */
|
||||
|
||||
enum DEVICE_STATUS device_status;
|
||||
enum CAMERA_TYPE camera_type;
|
||||
struct timespec connectionlosttime;
|
||||
|
||||
private:
|
||||
cls_movie *movie_norm;
|
||||
cls_movie *movie_motion;
|
||||
cls_movie *movie_timelapse;
|
||||
cls_movie *movie_extpipe;
|
||||
cls_v4l2cam *v4l2cam;
|
||||
cls_libcam *libcam;
|
||||
|
||||
pthread_t thread_id;
|
||||
int track_posx;
|
||||
int track_posy;
|
||||
int threshold_maximum;
|
||||
|
||||
int postcap; /* downcounter, frames left to to send post event */
|
||||
int shots_mt; /* Monotonic clock shots count*/
|
||||
int shots_rt; /* Realtime clock shots count*/
|
||||
struct timespec frame_curr_ts;
|
||||
struct timespec frame_last_ts;
|
||||
time_t lasttime;
|
||||
time_t movie_start_time;
|
||||
int startup_frames;
|
||||
int area_minx[9], area_miny[9], area_maxx[9], area_maxy[9];
|
||||
int areadetect_eventnbr;
|
||||
int previous_diffs, previous_location_x, previous_location_y;
|
||||
|
||||
void ring_resize();
|
||||
void ring_destroy();
|
||||
void ring_process_debug();
|
||||
void ring_process_image();
|
||||
void ring_process();
|
||||
void info_reset();
|
||||
void movie_start();
|
||||
void movie_end();
|
||||
void detected_trigger();
|
||||
void track_center();
|
||||
void track_move();
|
||||
void detected();
|
||||
void mask_privacy();
|
||||
void cam_close();
|
||||
void cam_start();
|
||||
int cam_next(ctx_image_data *img_data);
|
||||
void init_camera_type();
|
||||
void init_firstimage();
|
||||
void check_szimg();
|
||||
void init_areadetect();
|
||||
void init_buffers();
|
||||
void init_values();
|
||||
void init_cam_start();
|
||||
void init_ref();
|
||||
void init_schedule();
|
||||
void init_cleandir_runtime();
|
||||
void init_cleandir_default();
|
||||
void init_cleandir();
|
||||
void cleanup();
|
||||
void init();
|
||||
void areadetect();
|
||||
void prepare();
|
||||
void resetimages();
|
||||
int capture();
|
||||
void detection();
|
||||
void tuning();
|
||||
void overlay();
|
||||
void actions_emulate();
|
||||
void actions_motion();
|
||||
void actions_event();
|
||||
void actions();
|
||||
void snapshot();
|
||||
void timelapse();
|
||||
void loopback();
|
||||
void check_schedule();
|
||||
void frametiming();
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE_CAMERA_HPP_ */
|
||||
+4114
-3044
File diff suppressed because it is too large
Load Diff
+503
-213
@@ -1,239 +1,529 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* conf.h
|
||||
* Originally written for the dproxy package by Matthew Pratt.
|
||||
* Copyright 2000 Jeroen Vreeken (pe1rxq@chello.nl)
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_CONF_H
|
||||
#define _INCLUDE_CONF_H
|
||||
|
||||
/*
|
||||
* More parameters may be added later.
|
||||
*/
|
||||
struct config {
|
||||
/* Overall system configuration parameters */
|
||||
/* daemon is directly cast into the cnt context rather than conf */
|
||||
int setup_mode;
|
||||
char *pid_file;
|
||||
char *log_file;
|
||||
int log_level;
|
||||
char *log_type;
|
||||
int quiet;
|
||||
int native_language;
|
||||
int watchdog_tmo;
|
||||
int watchdog_kill;
|
||||
const char *camera_name;
|
||||
int camera_id;
|
||||
const char *camera_dir;
|
||||
const char *target_dir;
|
||||
#ifndef _INCLUDE_CONF_HPP_
|
||||
#define _INCLUDE_CONF_HPP_
|
||||
|
||||
/* Capture device configuration parameters */
|
||||
const char *video_device;
|
||||
char *video_params;
|
||||
int auto_brightness;
|
||||
const char *tuner_device;
|
||||
int roundrobin_frames;
|
||||
int roundrobin_skip;
|
||||
int roundrobin_switchfilter;
|
||||
/* Categories for he edits and display on web interface*/
|
||||
enum PARM_CAT{
|
||||
PARM_CAT_00 /* system */
|
||||
,PARM_CAT_01 /* camera */
|
||||
,PARM_CAT_02 /* source */
|
||||
,PARM_CAT_03 /* image */
|
||||
,PARM_CAT_04 /* overlay */
|
||||
,PARM_CAT_05 /* method */
|
||||
,PARM_CAT_06 /* masks */
|
||||
,PARM_CAT_07 /* detect */
|
||||
,PARM_CAT_08 /* scripts */
|
||||
,PARM_CAT_09 /* picture */
|
||||
,PARM_CAT_10 /* movies */
|
||||
,PARM_CAT_11 /* timelapse */
|
||||
,PARM_CAT_12 /* pipes */
|
||||
,PARM_CAT_13 /* webcontrol */
|
||||
,PARM_CAT_14 /* streams */
|
||||
,PARM_CAT_15 /* database */
|
||||
,PARM_CAT_16 /* sql */
|
||||
,PARM_CAT_17 /* tracking */
|
||||
,PARM_CAT_18 /* sound */
|
||||
,PARM_CAT_MAX
|
||||
};
|
||||
enum PARM_TYP{
|
||||
PARM_TYP_STRING
|
||||
, PARM_TYP_INT
|
||||
, PARM_TYP_LIST
|
||||
, PARM_TYP_BOOL
|
||||
, PARM_TYP_ARRAY
|
||||
};
|
||||
enum PARM_LEVEL{
|
||||
PARM_LEVEL_ALWAYS = 0
|
||||
,PARM_LEVEL_LIMITED = 1
|
||||
,PARM_LEVEL_ADVANCED = 2
|
||||
,PARM_LEVEL_RESTRICTED = 3
|
||||
,PARM_LEVEL_NEVER = 99
|
||||
};
|
||||
|
||||
const char *netcam_url;
|
||||
char *netcam_params;
|
||||
const char *netcam_high_url;
|
||||
char *netcam_high_params;
|
||||
const char *netcam_userpass;
|
||||
/** Current parameters in the config file */
|
||||
struct ctx_parm {
|
||||
const std::string parm_name; /* name for this parameter */
|
||||
enum PARM_TYP parm_type; /* enum of parm_typ for bool,int or string. */
|
||||
enum PARM_CAT parm_cat; /* enum of parm_cat for grouping. */
|
||||
int webui_level; /* Enum to display in webui: 0,1,2,3,99(always to never)*/
|
||||
};
|
||||
|
||||
/* Image processing configuration parameters */
|
||||
int width;
|
||||
int height;
|
||||
int framerate;
|
||||
int minimum_frame_time;
|
||||
int rotate;
|
||||
const char *flip_axis;
|
||||
const char *locate_motion_mode;
|
||||
const char *locate_motion_style;
|
||||
const char *text_left;
|
||||
const char *text_right;
|
||||
int text_changes;
|
||||
int text_scale;
|
||||
const char *text_event;
|
||||
enum PARM_ACT{
|
||||
PARM_ACT_DFLT
|
||||
, PARM_ACT_SET
|
||||
, PARM_ACT_GET
|
||||
, PARM_ACT_LIST
|
||||
};
|
||||
|
||||
/* Motion detection configuration parameters */
|
||||
int pause;
|
||||
int emulate_motion;
|
||||
int threshold;
|
||||
int threshold_maximum;
|
||||
int threshold_tune;
|
||||
int noise_level;
|
||||
int noise_tune;
|
||||
const char *despeckle_filter;
|
||||
const char *area_detect;
|
||||
const char *mask_file;
|
||||
const char *mask_privacy;
|
||||
int smart_mask_speed;
|
||||
int lightswitch_percent;
|
||||
int lightswitch_frames;
|
||||
int minimum_motion_frames;
|
||||
int event_gap;
|
||||
int pre_capture;
|
||||
int post_capture;
|
||||
/** Deprecated parameters in the config file */
|
||||
struct ctx_parm_depr{
|
||||
const std::string parm_name; /* Name of the deprecated option */
|
||||
const std::string last_version; /* Last version this option was used in */
|
||||
const std::string info; /* Short text on why it was deprecated (removed, replaced with, etc) */
|
||||
const std::string newname; /* Name of the new parameter */
|
||||
};
|
||||
|
||||
/* Script execution configuration parameters */
|
||||
char *on_event_start;
|
||||
char *on_event_end;
|
||||
char *on_picture_save;
|
||||
char *on_area_detected;
|
||||
char *on_motion_detected;
|
||||
char *on_movie_start;
|
||||
char *on_movie_end;
|
||||
char *on_camera_lost;
|
||||
char *on_camera_found;
|
||||
extern struct ctx_parm config_parms[];
|
||||
extern struct ctx_parm_depr config_parms_depr[];
|
||||
|
||||
/* Picture output configuration parameters */
|
||||
const char *picture_output;
|
||||
int picture_output_motion;
|
||||
const char *picture_type;
|
||||
int picture_quality;
|
||||
const char *picture_exif;
|
||||
const char *picture_filename;
|
||||
class cls_config {
|
||||
public:
|
||||
cls_config(cls_motapp *p_app);
|
||||
~cls_config();
|
||||
|
||||
/* Snapshot configuration parameters */
|
||||
int snapshot_interval;
|
||||
const char *snapshot_filename;
|
||||
/* Overall system configuration parameters */
|
||||
std::string conf_filename;
|
||||
bool from_conf_dir;
|
||||
|
||||
/* Movie output configuration parameters */
|
||||
int movie_output;
|
||||
int movie_output_motion;
|
||||
int movie_max_time;
|
||||
int movie_bps;
|
||||
int movie_quality;
|
||||
const char *movie_codec;
|
||||
int movie_duplicate_frames;
|
||||
int movie_passthrough;
|
||||
const char *movie_filename;
|
||||
int movie_extpipe_use;
|
||||
const char *movie_extpipe;
|
||||
/* Overall application parameters */
|
||||
bool daemon;
|
||||
std::string pid_file;
|
||||
std::string log_file;
|
||||
std::string log_type_str;
|
||||
int log_level;
|
||||
int log_fflevel;
|
||||
int log_type;
|
||||
bool native_language;
|
||||
|
||||
/* Timelapse movie configuration parameters */
|
||||
int timelapse_interval;
|
||||
const char *timelapse_mode;
|
||||
int timelapse_fps;
|
||||
const char *timelapse_codec;
|
||||
const char *timelapse_filename;
|
||||
std::string device_name;
|
||||
int device_id;
|
||||
std::string config_dir;
|
||||
std::string target_dir;
|
||||
int watchdog_tmo;
|
||||
int watchdog_kill;
|
||||
int device_tmo;
|
||||
std::string pause;
|
||||
std::string schedule_params;
|
||||
std::string cleandir_params;
|
||||
|
||||
/* Loopback device configuration parameters */
|
||||
const char *video_pipe;
|
||||
const char *video_pipe_motion;
|
||||
/* Capture device configuration parameters */
|
||||
std::string v4l2_device;
|
||||
std::string v4l2_params;
|
||||
|
||||
/* Webcontrol configuration parameters */
|
||||
int webcontrol_port;
|
||||
int webcontrol_ipv6;
|
||||
int webcontrol_localhost;
|
||||
int webcontrol_parms;
|
||||
int webcontrol_interface;
|
||||
int webcontrol_auth_method;
|
||||
const char *webcontrol_authentication;
|
||||
int webcontrol_tls;
|
||||
const char *webcontrol_cert;
|
||||
const char *webcontrol_key;
|
||||
char *webcontrol_header_params;
|
||||
int webcontrol_lock_minutes;
|
||||
int webcontrol_lock_attempts;
|
||||
int webcontrol_lock_max_ips;
|
||||
std::string netcam_url;
|
||||
std::string netcam_params;
|
||||
std::string netcam_high_url;
|
||||
std::string netcam_high_params;
|
||||
std::string netcam_userpass;
|
||||
|
||||
/* Live stream configuration parameters */
|
||||
int stream_port;
|
||||
int stream_localhost;
|
||||
int stream_auth_method;
|
||||
const char *stream_authentication;
|
||||
int stream_tls;
|
||||
char *stream_header_params;
|
||||
int stream_preview_scale;
|
||||
int stream_preview_newline;
|
||||
int stream_preview_method;
|
||||
int stream_quality;
|
||||
int stream_grey;
|
||||
int stream_motion;
|
||||
int stream_maxrate;
|
||||
int stream_limit;
|
||||
std::string libcam_device;
|
||||
std::string libcam_params;
|
||||
|
||||
/* Database and SQL configuration parameters */
|
||||
const char *database_type;
|
||||
const char *database_dbname;
|
||||
const char *database_host;
|
||||
int database_port;
|
||||
const char *database_user;
|
||||
const char *database_password;
|
||||
int database_busy_timeout;
|
||||
/* Image processing configuration parameters */
|
||||
int width;
|
||||
int height;
|
||||
int framerate;
|
||||
int rotate;
|
||||
std::string flip_axis;
|
||||
std::string locate_motion_mode;
|
||||
std::string locate_motion_style;
|
||||
std::string text_left;
|
||||
std::string text_right;
|
||||
bool text_changes;
|
||||
int text_scale;
|
||||
std::string text_event;
|
||||
|
||||
int sql_log_picture;
|
||||
int sql_log_snapshot;
|
||||
int sql_log_movie;
|
||||
int sql_log_timelapse;
|
||||
const char *sql_query_start;
|
||||
const char *sql_query_stop;
|
||||
const char *sql_query;
|
||||
/* Motion detection configuration parameters */
|
||||
bool emulate_motion;
|
||||
int threshold;
|
||||
int threshold_maximum;
|
||||
int threshold_sdevx;
|
||||
int threshold_sdevy;
|
||||
int threshold_sdevxy;
|
||||
int threshold_ratio;
|
||||
int threshold_ratio_change;
|
||||
bool threshold_tune;
|
||||
std::string secondary_method;
|
||||
std::string secondary_params;
|
||||
int noise_level;
|
||||
bool noise_tune;
|
||||
std::string despeckle_filter;
|
||||
std::string area_detect;
|
||||
std::string mask_file;
|
||||
std::string mask_privacy;
|
||||
int smart_mask_speed;
|
||||
int lightswitch_percent;
|
||||
int lightswitch_frames;
|
||||
int minimum_motion_frames;
|
||||
int static_object_time;
|
||||
int event_gap;
|
||||
int pre_capture;
|
||||
int post_capture;
|
||||
|
||||
/* Command line parameters */
|
||||
int argc;
|
||||
char **argv;
|
||||
};
|
||||
/* Script execution configuration parameters */
|
||||
std::string on_event_start;
|
||||
std::string on_event_end;
|
||||
std::string on_picture_save;
|
||||
std::string on_area_detected;
|
||||
std::string on_motion_detected;
|
||||
std::string on_movie_start;
|
||||
std::string on_movie_end;
|
||||
std::string on_camera_lost;
|
||||
std::string on_camera_found;
|
||||
std::string on_secondary_detect;
|
||||
std::string on_action_user;
|
||||
std::string on_sound_alert;
|
||||
|
||||
struct context;
|
||||
/**
|
||||
* typedef for a param copy function.
|
||||
*/
|
||||
typedef void (* conf_copy_func)(struct context *, char *, int);
|
||||
typedef const char *(* conf_print_func)(struct context **, char **, int, unsigned int);
|
||||
/* Picture output configuration parameters */
|
||||
std::string picture_output;
|
||||
std::string picture_output_motion;
|
||||
std::string picture_type;
|
||||
int picture_quality;
|
||||
std::string picture_exif;
|
||||
std::string picture_filename;
|
||||
|
||||
/**
|
||||
* description for parameters in the config file
|
||||
*/
|
||||
typedef struct {
|
||||
const char *param_name; /* name for this parameter */
|
||||
const char *param_help; /* short explanation for parameter */
|
||||
unsigned int main_thread; /* belong only to main thread when value>0 */
|
||||
int conf_value; /* pointer to a field in struct context */
|
||||
conf_copy_func copy; /* a function to set the value in 'config' */
|
||||
conf_print_func print; /* a function to output the value to a file */
|
||||
int webui_level; /* Enum to display in webui: 0,1,2,3,99(always to never)*/
|
||||
} config_param;
|
||||
/* Snapshot configuration parameters */
|
||||
int snapshot_interval;
|
||||
std::string snapshot_filename;
|
||||
|
||||
extern config_param config_params[];
|
||||
/* Movie output configuration parameters */
|
||||
bool movie_output;
|
||||
bool movie_output_motion;
|
||||
int movie_max_time;
|
||||
int movie_bps;
|
||||
int movie_quality;
|
||||
std::string movie_container;
|
||||
bool movie_passthrough;
|
||||
std::string movie_filename;
|
||||
std::string movie_retain;
|
||||
bool movie_extpipe_use;
|
||||
std::string movie_extpipe;
|
||||
|
||||
/**
|
||||
* description for deprecated parameters in the config file
|
||||
*/
|
||||
typedef struct {
|
||||
const char *name; /* Name of the deprecated option */
|
||||
const char *last_version; /* Last version this option was used in */
|
||||
const char *info; /* Short text on why it was deprecated (removed, replaced with, etc) */
|
||||
int conf_value; /* Pointer to the replacement field in struct context */
|
||||
const char *newname; /* Name of the new parameter */
|
||||
conf_copy_func copy; /* Function to set the replacement value */
|
||||
} dep_config_param;
|
||||
/* Timelapse movie configuration parameters */
|
||||
int timelapse_interval;
|
||||
std::string timelapse_mode;
|
||||
int timelapse_fps;
|
||||
std::string timelapse_container;
|
||||
std::string timelapse_filename;
|
||||
|
||||
extern dep_config_param dep_config_params[];
|
||||
/* Loopback device configuration parameters */
|
||||
std::string video_pipe;
|
||||
std::string video_pipe_motion;
|
||||
|
||||
struct context **conf_cmdparse(struct context **cnt, char *cmd, char *arg1);
|
||||
void conf_print(struct context **cnt);
|
||||
struct context **conf_load(struct context **cnt);
|
||||
void conf_output_parms(struct context **cnt);
|
||||
void copy_string(struct context *cnt, char *str, int val_ptr);
|
||||
/* Webcontrol configuration parameters */
|
||||
int webcontrol_port;
|
||||
int webcontrol_port2;
|
||||
std::string webcontrol_base_path;
|
||||
bool webcontrol_ipv6;
|
||||
bool webcontrol_localhost;
|
||||
int webcontrol_parms;
|
||||
std::string webcontrol_interface;
|
||||
std::string webcontrol_auth_method;
|
||||
std::string webcontrol_authentication;
|
||||
bool webcontrol_tls;
|
||||
std::string webcontrol_cert;
|
||||
std::string webcontrol_key;
|
||||
std::string webcontrol_headers;
|
||||
std::string webcontrol_html;
|
||||
std::string webcontrol_actions;
|
||||
int webcontrol_lock_minutes;
|
||||
int webcontrol_lock_attempts;
|
||||
std::string webcontrol_lock_script;
|
||||
|
||||
#endif /* _INCLUDE_CONF_H */
|
||||
/* Live stream configuration parameters */
|
||||
int stream_preview_scale;
|
||||
bool stream_preview_newline;
|
||||
std::string stream_preview_params;
|
||||
std::string stream_preview_method;
|
||||
bool stream_preview_ptz;
|
||||
int stream_quality;
|
||||
bool stream_grey;
|
||||
bool stream_motion;
|
||||
int stream_maxrate;
|
||||
int stream_scan_time;
|
||||
int stream_scan_scale;
|
||||
|
||||
/* Database and SQL configuration parameters */
|
||||
std::string database_type;
|
||||
std::string database_dbname;
|
||||
std::string database_host;
|
||||
int database_port;
|
||||
std::string database_user;
|
||||
std::string database_password;
|
||||
int database_busy_timeout;
|
||||
|
||||
std::string sql_event_start;
|
||||
std::string sql_event_end;
|
||||
std::string sql_movie_start;
|
||||
std::string sql_movie_end;
|
||||
std::string sql_pic_save;
|
||||
|
||||
bool ptz_auto_track; /* Bool to enable auto tracking */
|
||||
int ptz_wait; /* Frames to wait after a PTZ move */
|
||||
std::string ptz_move_track; /* Auto tracking command */
|
||||
std::string ptz_pan_left; /* Pan left command */
|
||||
std::string ptz_pan_right; /* Pan right command */
|
||||
std::string ptz_tilt_up; /* Tilt up command */
|
||||
std::string ptz_tilt_down; /* Tilt down command */
|
||||
std::string ptz_zoom_in; /* Zoom in command */
|
||||
std::string ptz_zoom_out; /* Zoom out command */
|
||||
|
||||
/* Sound processing parameters */
|
||||
std::string snd_device;
|
||||
std::string snd_params;
|
||||
std::list<std::string> snd_alerts;
|
||||
std::string snd_window;
|
||||
bool snd_show;
|
||||
|
||||
void camera_add(std::string fname, bool srcdir);
|
||||
void sound_add(std::string fname, bool srcdir);
|
||||
void camera_filenm();
|
||||
void sound_filenm();
|
||||
void process();
|
||||
|
||||
void edit_set(std::string parm_nm, std::string parm_val);
|
||||
void edit_get(std::string parm_nm, std::string &parm_val, enum PARM_CAT parm_cat);
|
||||
void edit_get(std::string parm_nm, std::list<std::string> &parm_val, enum PARM_CAT parm_cat);
|
||||
void edit_list(std::string parm_nm, std::string &parm_val, enum PARM_CAT parm_cat);
|
||||
|
||||
std::string type_desc(enum PARM_TYP ptype);
|
||||
std::string cat_desc(enum PARM_CAT pcat, bool shrt);
|
||||
void usage();
|
||||
void init();
|
||||
void parms_log();
|
||||
void parms_write();
|
||||
void parms_copy(cls_config *src);
|
||||
void parms_copy(cls_config *src, PARM_CAT p_cat);
|
||||
|
||||
private:
|
||||
cls_motapp *app;
|
||||
void cmdline();
|
||||
void defaults();
|
||||
int get_next_devid();
|
||||
void config_dir_parm(std::string confdir);
|
||||
|
||||
void parms_log_parm(std::string parm_nm, std::string parm_vl);
|
||||
void parms_write_app();
|
||||
void parms_write_cam();
|
||||
void parms_write_parms(FILE *conffile, std::string parm_nm, std::string parm_vl, enum PARM_CAT parm_ct, bool reset);
|
||||
void parms_write_snd();
|
||||
|
||||
int edit_set_active(std::string parm_nm, std::string parm_val);
|
||||
int edit_set_depr(std::string &parm_nm, std::string &parm_val);
|
||||
void edit_depr_tdbl(std::string newname, std::string &parm_val);
|
||||
void edit_depr_vid(std::string parm_nm, std::string newname, std::string parm_val);
|
||||
void edit_depr_web(std::string newname, std::string &parm_val);
|
||||
void edit_config_dir(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_get_bool(std::string &parm_dest, bool &parm_in);
|
||||
void edit_set_bool(bool &parm_dest, std::string &parm_in);
|
||||
|
||||
void edit_cat(std::string parm_nm, std::list<std::string> &parm_val, enum PARM_ACT pact, enum PARM_CAT pcat);
|
||||
void edit_cat(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact, enum PARM_CAT pcat);
|
||||
void edit_cat00(std::string cmd, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat01(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat02(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat03(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat04(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat05(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat06(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat07(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat08(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat09(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat10(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat11(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat12(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat13(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat14(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat15(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat16(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat17(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat18(std::string parm_nm, std::string &parm_val, enum PARM_ACT pact);
|
||||
void edit_cat18(std::string parm_nm,std::list<std::string> &parm_val, enum PARM_ACT pact);
|
||||
|
||||
void edit_daemon(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_conf_filename(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_pid_file(std::string &parm, int pact);
|
||||
void edit_log_file(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_log_level(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_log_fflevel(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_log_type(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_native_language(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
void edit_device_name(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_device_id(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_device_tmo(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_pause(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_schedule_params(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_cleandir_params(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_target_dir(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_watchdog_kill(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_watchdog_tmo(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
void edit_v4l2_device(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_v4l2_params(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_netcam_high_params(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_netcam_high_url(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_netcam_params(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_netcam_url(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_netcam_userpass(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_libcam_device(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_libcam_params(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
void edit_width(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_height(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_framerate(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_rotate(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_flip_axis(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
void edit_locate_motion_mode(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_locate_motion_style(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_text_changes(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_text_event(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_text_left(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_text_right(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_text_scale(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
void edit_emulate_motion(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_threshold(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_threshold_maximum(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_threshold_ratio(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_threshold_ratio_change(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_threshold_sdevx(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_threshold_sdevxy(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_threshold_sdevy(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_threshold_tune(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_secondary_method(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_secondary_params(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
void edit_noise_level(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_noise_tune(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_despeckle_filter(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_area_detect(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_mask_file(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_mask_privacy(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_smart_mask_speed(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
void edit_lightswitch_frames(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_lightswitch_percent(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_minimum_motion_frames(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_event_gap(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_static_object_time(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_post_capture(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_pre_capture(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
void edit_on_action_user(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_on_area_detected(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_on_camera_found(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_on_camera_lost(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_on_event_end(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_on_event_start(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_on_motion_detected(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_on_movie_end(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_on_movie_start(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_on_picture_save(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_on_secondary_detect(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_on_sound_alert(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
void edit_picture_exif(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_picture_filename(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_picture_output(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_picture_output_motion(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_picture_quality(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_picture_type(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_snapshot_filename(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_snapshot_interval(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
void edit_movie_bps(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_movie_container(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_movie_extpipe(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_movie_extpipe_use(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_movie_filename(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_movie_max_time(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_movie_output(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_movie_output_motion(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_movie_passthrough(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_movie_quality(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_movie_retain(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
void edit_timelapse_container(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_timelapse_filename(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_timelapse_fps(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_timelapse_interval(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_timelapse_mode(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
void edit_video_pipe(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_video_pipe_motion(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
void edit_webcontrol_actions(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_webcontrol_auth_method(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_webcontrol_authentication(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_webcontrol_base_path(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_webcontrol_cert(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_webcontrol_headers(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_webcontrol_html(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_webcontrol_interface(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_webcontrol_ipv6(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_webcontrol_key(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_webcontrol_localhost(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_webcontrol_lock_attempts(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_webcontrol_lock_minutes(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_webcontrol_lock_script(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_webcontrol_parms(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_webcontrol_port(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_webcontrol_port2(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_webcontrol_tls(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
void edit_stream_grey(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_stream_maxrate(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_stream_motion(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_stream_preview_params(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_stream_preview_method(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_stream_preview_newline(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_stream_preview_ptz(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_stream_preview_scale(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_stream_quality(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_stream_scan_scale(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_stream_scan_time(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
void edit_database_busy_timeout(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_database_dbname(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_database_host(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_database_password(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_database_port(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_database_type(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_database_user(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
void edit_sql_event_end(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_sql_event_start(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_sql_movie_end(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_sql_movie_start(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_sql_pic_save(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
void edit_ptz_auto_track(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_ptz_move_track(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_ptz_pan_left(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_ptz_pan_right(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_ptz_tilt_down(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_ptz_tilt_up(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_ptz_wait(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_ptz_zoom_in(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_ptz_zoom_out(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
void edit_snd_device(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_snd_params(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_snd_alerts(std::list<std::string> &parm, enum PARM_ACT pact);
|
||||
void edit_snd_alerts(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_snd_show(std::string &parm, enum PARM_ACT pact);
|
||||
void edit_snd_window(std::string &parm, enum PARM_ACT pact);
|
||||
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE_CONF_HPP_ */
|
||||
|
||||
+1290
-515
File diff suppressed because it is too large
Load Diff
+157
-32
@@ -1,37 +1,162 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* dbse.h
|
||||
* Headers associated with functions in the dbse.c module.
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_DBSE_H
|
||||
#define _INCLUDE_DBSE_H
|
||||
|
||||
void dbse_global_init(struct context **cntlist);
|
||||
void dbse_global_deinit(struct context **cntlist);
|
||||
|
||||
int dbse_init(struct context *cnt);
|
||||
void dbse_deinit(struct context *cnt);
|
||||
|
||||
void dbse_sqlmask_update(struct context *cnt);
|
||||
void dbse_firstmotion(struct context *cnt);
|
||||
void dbse_newfile(struct context *cnt, char *filename, int sqltype, struct timeval *tv1);
|
||||
void dbse_fileclose(struct context *cnt, char *filename, int sqltype, struct timeval *tv1);
|
||||
|
||||
#ifndef _INCLUDE_DBSE_HPP_
|
||||
#define _INCLUDE_DBSE_HPP_
|
||||
|
||||
#ifdef HAVE_MARIADB
|
||||
#include <mysql.h>
|
||||
#ifndef HAVE_DBSE
|
||||
#define HAVE_DBSE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SQLITE3DB
|
||||
#include <sqlite3.h>
|
||||
#ifndef HAVE_DBSE
|
||||
#define HAVE_DBSE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PGSQLDB
|
||||
#include <libpq-fe.h>
|
||||
#ifndef HAVE_DBSE
|
||||
#define HAVE_DBSE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
enum DBSE_ACT {
|
||||
DBSE_TBL_CHECK,
|
||||
DBSE_TBL_CREATE,
|
||||
DBSE_MOV_SELECT,
|
||||
DBSE_COLS_LIST,
|
||||
DBSE_COLS_CURRENT,
|
||||
DBSE_COLS_ADD,
|
||||
DBSE_COLS_RENAME,
|
||||
DBSE_END
|
||||
};
|
||||
|
||||
/* Record structure of table */
|
||||
struct ctx_file_item {
|
||||
bool found; /*Bool for whether the file exists*/
|
||||
int64_t record_id; /*record_id*/
|
||||
int device_id; /*camera id */
|
||||
std::string file_typ; /*type of file (pic/movie)*/
|
||||
std::string file_nm; /*Name of the file*/
|
||||
std::string file_dir; /*Directory of the file */
|
||||
std::string full_nm; /*Full name of the file with dir*/
|
||||
int64_t file_sz; /*Size of the file in bytes*/
|
||||
int file_dtl; /*Date in yyyymmdd format for the file*/
|
||||
std::string file_tmc; /*File time 12h format*/
|
||||
std::string file_tml; /*File time 24h format*/
|
||||
int diff_avg; /*Average diffs for motion frames */
|
||||
int sdev_min; /*std dev min */
|
||||
int sdev_max; /*std dev max */
|
||||
int sdev_avg; /*std dev average */
|
||||
};
|
||||
typedef std::vector<ctx_file_item> vec_files;
|
||||
|
||||
/* Column item attributes in the motion table */
|
||||
struct ctx_col_item {
|
||||
bool found; /*Bool for whether the col in existing db*/
|
||||
std::string col_nm; /*Name of the column*/
|
||||
std::string col_typ; /*Data type of the column*/
|
||||
int col_idx; /*Sequence index*/
|
||||
};
|
||||
typedef std::vector<ctx_col_item> vec_cols;
|
||||
|
||||
class cls_dbse {
|
||||
public:
|
||||
cls_dbse(cls_motapp *p_app);
|
||||
~cls_dbse();
|
||||
void sqlite3db_cb (int arg_nb, char **arg_val, char **col_nm);
|
||||
pthread_mutex_t mutex_dbse;
|
||||
void exec(cls_camera *cam, std::string filename, std::string cmd);
|
||||
void exec_sql(std::string sql);
|
||||
void filelist_add(cls_camera *cam, timespec *ts1, std::string ftyp
|
||||
,std::string filenm, std::string fullnm, std::string dirnm);
|
||||
void filelist_get(std::string sql, vec_files &p_flst);
|
||||
bool restart;
|
||||
bool finish;
|
||||
void shutdown();
|
||||
void startup();
|
||||
|
||||
bool handler_stop;
|
||||
bool handler_running;
|
||||
pthread_t handler_thread;
|
||||
void handler();
|
||||
|
||||
private:
|
||||
#ifdef HAVE_SQLITE3DB
|
||||
sqlite3 *database_sqlite3db;
|
||||
void sqlite3db_exec(std::string sql);
|
||||
void sqlite3db_cols_verify();
|
||||
void sqlite3db_cols_rename();
|
||||
void sqlite3db_init();
|
||||
void sqlite3db_close();
|
||||
void sqlite3db_filelist(std::string sql);
|
||||
#endif
|
||||
#ifdef HAVE_MARIADB
|
||||
MYSQL *database_mariadb;
|
||||
void mariadb_exec(std::string sql);
|
||||
void mariadb_recs(std::string sql);
|
||||
void mariadb_cols_verify();
|
||||
void mariadb_cols_rename();
|
||||
void mariadb_setup();
|
||||
void mariadb_init();
|
||||
void mariadb_close();
|
||||
void mariadb_filelist(std::string sql);
|
||||
#endif
|
||||
#ifdef HAVE_PGSQLDB
|
||||
PGconn *database_pgsqldb;
|
||||
void pgsqldb_exec(std::string sql);
|
||||
void pgsqldb_recs(std::string sql);
|
||||
void pgsqldb_cols_verify();
|
||||
void pgsqldb_cols_rename();
|
||||
void pgsqldb_setup();
|
||||
void pgsqldb_init();
|
||||
void pgsqldb_close();
|
||||
void pgsqldb_filelist(std::string sql);
|
||||
#endif
|
||||
cls_motapp *app;
|
||||
enum DBSE_ACT dbse_action; /* action to perform with query*/
|
||||
bool table_ok; /* bool of whether table exists*/
|
||||
bool is_open;
|
||||
|
||||
vec_cols col_names;
|
||||
vec_files filelist;
|
||||
ctx_file_item file_item;
|
||||
|
||||
void handler_startup();
|
||||
void handler_shutdown();
|
||||
void timing();
|
||||
bool check_exit();
|
||||
void dbse_clean();
|
||||
void dbse_edits();
|
||||
bool dbse_open();
|
||||
|
||||
void cols_vec_add(std::string nm, std::string typ);
|
||||
void cols_vec_create();
|
||||
void item_default();
|
||||
void item_assign(std::string col_nm, std::string col_val);
|
||||
|
||||
void sql_motpls(std::string &sql);
|
||||
void sql_motpls(std::string &sql, std::string col_p1, std::string col_p2);
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE_DBSE_HPP_ */
|
||||
|
||||
+395
-51
@@ -1,41 +1,32 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* draw.c
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Routines for drawing text on images
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Copyright 2000, Jeroen Vreeken
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include "motion.hpp"
|
||||
#include "util.hpp"
|
||||
#include "camera.hpp"
|
||||
#include "conf.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "alg.hpp"
|
||||
#include "draw.hpp"
|
||||
|
||||
/* Highest ascii value is 126 (~) */
|
||||
#define ASCII_MAX 127
|
||||
|
||||
unsigned char *char_arr_ptr[ASCII_MAX];
|
||||
|
||||
struct draw_char {
|
||||
unsigned char ascii;
|
||||
unsigned char pix[8][7];
|
||||
u_char ascii;
|
||||
u_char pix[8][7];
|
||||
};
|
||||
|
||||
struct draw_char draw_table[]= {
|
||||
@@ -1081,16 +1072,14 @@ struct draw_char draw_table[]= {
|
||||
}
|
||||
};
|
||||
|
||||
#define NEWLINE "\\n"
|
||||
/**
|
||||
* draw_textn
|
||||
*/
|
||||
static int draw_textn(unsigned char *image, int startx, int starty, int width, const char *text, int len, int factor)
|
||||
int cls_draw::textn(u_char *image
|
||||
, int startx, int starty, int width
|
||||
, const char *text, int len, int factor)
|
||||
{
|
||||
|
||||
int x, y;
|
||||
int pos, line_offset, next_char_offs;
|
||||
unsigned char *image_ptr, *char_ptr;
|
||||
u_char *image_ptr, *char_ptr;
|
||||
|
||||
if (startx > width / 2) {
|
||||
startx -= len * (6 * factor);
|
||||
@@ -1112,14 +1101,16 @@ static int draw_textn(unsigned char *image, int startx, int starty, int width,
|
||||
for (pos = 0; pos < len; pos++) {
|
||||
int pos_check = (int)text[pos];
|
||||
|
||||
if ((pos_check <0) || (pos_check >127)) {
|
||||
pos_check = 45; /* Use a - for non ascii characters*/
|
||||
}
|
||||
|
||||
char_ptr = char_arr_ptr[pos_check];
|
||||
|
||||
for (y = 0; y < 8 * factor; y++) {
|
||||
for (x = 0; x < 7 * factor; x++) {
|
||||
|
||||
if (pos_check < 0) {
|
||||
image_ptr++;
|
||||
continue;
|
||||
}
|
||||
|
||||
char_ptr = char_arr_ptr[pos_check] + y/factor*7 + x/factor;
|
||||
|
||||
switch(*char_ptr) {
|
||||
@@ -1143,10 +1134,9 @@ static int draw_textn(unsigned char *image, int startx, int starty, int width,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* draw_text
|
||||
*/
|
||||
int draw_text(unsigned char *image, int width, int height, int startx, int starty, const char *text, int factor)
|
||||
int cls_draw::text(u_char *image
|
||||
, int width, int height, int startx, int starty
|
||||
, const char *text, int factor)
|
||||
{
|
||||
int num_nl = 0;
|
||||
const char *end, *begin;
|
||||
@@ -1157,14 +1147,14 @@ int draw_text(unsigned char *image, int width, int height, int startx, int start
|
||||
txtlen = 0;
|
||||
while ((end = strstr(end, NEWLINE))) {
|
||||
if ((end - begin)>txtlen) {
|
||||
txtlen = (end - begin);
|
||||
txtlen = (int)(end - begin);
|
||||
}
|
||||
num_nl++;
|
||||
end += sizeof(NEWLINE)-1;
|
||||
begin = end;
|
||||
}
|
||||
if (txtlen == 0) {
|
||||
txtlen = strlen(text);
|
||||
txtlen = (int)strlen(text);
|
||||
}
|
||||
|
||||
/* Adjust the factor if it is out of bounds
|
||||
@@ -1191,23 +1181,20 @@ int draw_text(unsigned char *image, int width, int height, int startx, int start
|
||||
begin = end = text;
|
||||
|
||||
while ((end = strstr(end, NEWLINE))) {
|
||||
int len = end-begin;
|
||||
int len = (int)(end-begin);
|
||||
|
||||
draw_textn(image, startx, starty, width, begin, len, factor);
|
||||
textn(image, startx, starty, width, begin, len, factor);
|
||||
end += sizeof(NEWLINE)-1;
|
||||
begin = end;
|
||||
starty += line_space;
|
||||
}
|
||||
|
||||
draw_textn(image, startx, starty, width, begin, strlen(begin), factor);
|
||||
textn(image, startx, starty, width, begin, (int)strlen(begin), factor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize_chars
|
||||
*/
|
||||
int initialize_chars(void)
|
||||
void cls_draw::init_chars(void)
|
||||
{
|
||||
unsigned int i;
|
||||
size_t draw_table_size;
|
||||
@@ -1224,6 +1211,363 @@ int initialize_chars(void)
|
||||
char_arr_ptr[(int)draw_table[i].ascii] = &draw_table[i].pix[0][0];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cls_draw::init_scale()
|
||||
{
|
||||
cam->text_scale = cam->cfg->text_scale;
|
||||
if (cam->text_scale <= 0) {
|
||||
cam->text_scale = 1;
|
||||
}
|
||||
|
||||
if ((cam->text_scale * 10 * 2) > (cam->imgs.width / 4)) {
|
||||
cam->text_scale = (cam->imgs.width / (4 * 10 * 2));
|
||||
if (cam->text_scale <= 0) {
|
||||
cam->text_scale = 1;
|
||||
}
|
||||
MOTPLS_LOG(WRN, TYPE_ALL, NO_ERRNO
|
||||
,_("Invalid text scale. Adjusted to %d"), cam->text_scale);
|
||||
}
|
||||
|
||||
if ((cam->text_scale * 10 * 2) > (cam->imgs.height / 4)) {
|
||||
cam->text_scale = (cam->imgs.height / (4 * 10 * 2));
|
||||
if (cam->text_scale <= 0) {
|
||||
cam->text_scale = 1;
|
||||
}
|
||||
MOTPLS_LOG(WRN, TYPE_ALL, NO_ERRNO
|
||||
,_("Invalid text scale. Adjusted to %d"), cam->text_scale);
|
||||
}
|
||||
|
||||
/* If we had to modify the scale, change conf so we don't get another message */
|
||||
cam->cfg->text_scale = cam->text_scale;
|
||||
|
||||
}
|
||||
|
||||
void cls_draw::location(ctx_coord *cent, ctx_images *imgs
|
||||
, int width, u_char *new_var)
|
||||
{
|
||||
u_char *out = imgs->image_motion.image_norm;
|
||||
int x, y, centy;
|
||||
int width_miny, width_maxy;
|
||||
int width_miny_x, width_maxy_x;
|
||||
int width_minx_y, width_maxx_y;
|
||||
|
||||
out = imgs->image_motion.image_norm;
|
||||
|
||||
width_miny = width * cent->miny;
|
||||
width_maxy = width * cent->maxy;
|
||||
for (x = cent->minx; x <= cent->maxx; x++) {
|
||||
width_miny_x = x + width_miny;
|
||||
width_maxy_x = x + width_maxy;
|
||||
out[width_miny_x] =~out[width_miny_x];
|
||||
out[width_maxy_x] =~out[width_maxy_x];
|
||||
}
|
||||
|
||||
for (y = cent->miny; y <= cent->maxy; y++) {
|
||||
width_minx_y = cent->minx + y * width;
|
||||
width_maxx_y = cent->maxx + y * width;
|
||||
|
||||
out[width_minx_y] =~out[width_minx_y];
|
||||
out[width_maxx_y] =~out[width_maxx_y];
|
||||
}
|
||||
|
||||
if (cam->cfg->locate_motion_style == "box") {
|
||||
width_miny = width * cent->miny;
|
||||
width_maxy = width * cent->maxy;
|
||||
|
||||
for (x = cent->minx; x <= cent->maxx; x++) {
|
||||
width_miny_x = x + width_miny;
|
||||
width_maxy_x = x + width_maxy;
|
||||
new_var[width_miny_x] =~new_var[width_miny_x];
|
||||
new_var[width_maxy_x] =~new_var[width_maxy_x];
|
||||
}
|
||||
|
||||
for (y = cent->miny; y <= cent->maxy; y++) {
|
||||
width_minx_y = cent->minx + y * width;
|
||||
width_maxx_y = cent->maxx + y * width;
|
||||
new_var[width_minx_y] =~new_var[width_minx_y];
|
||||
new_var[width_maxx_y] =~new_var[width_maxx_y];
|
||||
}
|
||||
} else if (cam->cfg->locate_motion_style == "cross") {
|
||||
centy = cent->y * width;
|
||||
for (x = cent->x - 10; x <= cent->x + 10; x++) {
|
||||
new_var[centy + x] =~new_var[centy + x];
|
||||
out[centy + x] =~out[centy + x];
|
||||
}
|
||||
for (y = cent->y - 10; y <= cent->y + 10; y++) {
|
||||
new_var[cent->x + y * width] =~new_var[cent->x + y * width];
|
||||
out[cent->x + y * width] =~out[cent->x + y * width];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cls_draw::red_location(ctx_coord *cent
|
||||
, ctx_images *imgs, int width, u_char *new_var)
|
||||
{
|
||||
u_char *out = imgs->image_motion.image_norm;
|
||||
u_char *new_u, *new_v;
|
||||
int x, y, v, cwidth, cblock;
|
||||
int width_miny, width_maxy;
|
||||
int width_miny_x, width_maxy_x;
|
||||
int width_minx_y, width_maxx_y;
|
||||
int cwidth_miny, cwidth_maxy;
|
||||
int cwidth_miny_x, cwidth_maxy_x;
|
||||
int cwidth_minx_y,cwidth_maxx_y;
|
||||
|
||||
cwidth = width / 2;
|
||||
cblock = imgs->motionsize / 4;
|
||||
x = imgs->motionsize;
|
||||
v = x + cblock;
|
||||
out = imgs->image_motion.image_norm;
|
||||
new_u = new_var + x;
|
||||
new_v = new_var + v;
|
||||
|
||||
width_miny = width * cent->miny;
|
||||
width_maxy = width * cent->maxy;
|
||||
|
||||
for (x = cent->minx; x <= cent->maxx; x++) {
|
||||
width_miny_x = x + width_miny;
|
||||
width_maxy_x = x + width_maxy;
|
||||
out[width_miny_x] =~out[width_miny_x];
|
||||
out[width_maxy_x] =~out[width_maxy_x];
|
||||
}
|
||||
|
||||
for (y = cent->miny; y <= cent->maxy; y++) {
|
||||
width_minx_y = cent->minx + y * width;
|
||||
width_maxx_y = cent->maxx + y * width;
|
||||
|
||||
out[width_minx_y] =~out[width_minx_y];
|
||||
out[width_maxx_y] =~out[width_maxx_y];
|
||||
}
|
||||
|
||||
if (cam->cfg->locate_motion_style == "redbox") {
|
||||
width_miny = width * cent->miny;
|
||||
width_maxy = width * cent->maxy;
|
||||
cwidth_miny = cwidth * (cent->miny / 2);
|
||||
cwidth_maxy = cwidth * (cent->maxy / 2);
|
||||
|
||||
for (x = cent->minx + 2; x <= cent->maxx - 2; x += 2) {
|
||||
width_miny_x = x + width_miny;
|
||||
width_maxy_x = x + width_maxy;
|
||||
cwidth_miny_x = x / 2 + cwidth_miny;
|
||||
cwidth_maxy_x = x / 2 + cwidth_maxy;
|
||||
|
||||
new_u[cwidth_miny_x] = 128;
|
||||
new_u[cwidth_maxy_x] = 128;
|
||||
new_v[cwidth_miny_x] = 255;
|
||||
new_v[cwidth_maxy_x] = 255;
|
||||
|
||||
new_var[width_miny_x] = 128;
|
||||
new_var[width_maxy_x] = 128;
|
||||
|
||||
new_var[width_miny_x + 1] = 128;
|
||||
new_var[width_maxy_x + 1] = 128;
|
||||
|
||||
new_var[width_miny_x + width] = 128;
|
||||
new_var[width_maxy_x + width] = 128;
|
||||
|
||||
new_var[width_miny_x + 1 + width] = 128;
|
||||
new_var[width_maxy_x + 1 + width] = 128;
|
||||
}
|
||||
|
||||
for (y = cent->miny; y <= cent->maxy; y += 2) {
|
||||
width_minx_y = cent->minx + y * width;
|
||||
width_maxx_y = cent->maxx + y * width;
|
||||
cwidth_minx_y = (cent->minx / 2) + (y / 2) * cwidth;
|
||||
cwidth_maxx_y = (cent->maxx / 2) + (y / 2) * cwidth;
|
||||
|
||||
new_u[cwidth_minx_y] = 128;
|
||||
new_u[cwidth_maxx_y] = 128;
|
||||
new_v[cwidth_minx_y] = 255;
|
||||
new_v[cwidth_maxx_y] = 255;
|
||||
|
||||
new_var[width_minx_y] = 128;
|
||||
new_var[width_maxx_y] = 128;
|
||||
|
||||
new_var[width_minx_y + width] = 128;
|
||||
new_var[width_maxx_y + width] = 128;
|
||||
|
||||
new_var[width_minx_y + 1] = 128;
|
||||
new_var[width_maxx_y + 1] = 128;
|
||||
|
||||
new_var[width_minx_y + width + 1] = 128;
|
||||
new_var[width_maxx_y + width + 1] = 128;
|
||||
}
|
||||
} else if (cam->cfg->locate_motion_style == "redcross") {
|
||||
cwidth_maxy = cwidth * (cent->y / 2);
|
||||
|
||||
for (x = cent->x - 10; x <= cent->x + 10; x += 2) {
|
||||
cwidth_maxy_x = x / 2 + cwidth_maxy;
|
||||
new_u[cwidth_maxy_x] = 128;
|
||||
new_v[cwidth_maxy_x] = 255;
|
||||
}
|
||||
|
||||
for (y = cent->y - 10; y <= cent->y + 10; y += 2) {
|
||||
cwidth_minx_y = (cent->x / 2) + (y / 2) * cwidth;
|
||||
new_u[cwidth_minx_y] = 128;
|
||||
new_v[cwidth_minx_y] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cls_draw::locate()
|
||||
{
|
||||
ctx_images *imgs;
|
||||
ctx_coord *p_loc;
|
||||
u_char *image_norm;
|
||||
|
||||
if (cam->cfg->locate_motion_mode == "preview") {
|
||||
imgs = &cam->imgs;
|
||||
p_loc = &cam->imgs.image_preview.location;
|
||||
image_norm = cam->imgs.image_preview.image_norm;
|
||||
} else if (cam->cfg->locate_motion_mode == "on") {
|
||||
imgs = &cam->imgs;
|
||||
p_loc = &cam->current_image->location;
|
||||
image_norm = cam->current_image->image_norm;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((cam->cfg->locate_motion_style == "box") ||
|
||||
(cam->cfg->locate_motion_style == "cross")) {
|
||||
location(p_loc, imgs, imgs->width, image_norm);
|
||||
} else if ((cam->cfg->locate_motion_style == "redbox")||
|
||||
(cam->cfg->locate_motion_style == "redcross")) {
|
||||
red_location(p_loc, imgs, imgs->width, image_norm);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cls_draw::smartmask()
|
||||
{
|
||||
int i, x, v, width, height, line;
|
||||
ctx_images *imgs = &cam->imgs;
|
||||
u_char *mask_final = cam->alg->smartmask_final;
|
||||
u_char *out_y, *out_u, *out_v;
|
||||
u_char *out = cam->imgs.image_motion.image_norm;
|
||||
|
||||
i = imgs->motionsize;
|
||||
v = i + ((imgs->motionsize) / 4);
|
||||
width = imgs->width;
|
||||
height = imgs->height;
|
||||
|
||||
/* Set V to 255 to make smartmask appear red. */
|
||||
out_v = out + v;
|
||||
out_u = out + i;
|
||||
for (i = 0; i < height; i += 2) {
|
||||
line = i * width;
|
||||
for (x = 0; x < width; x += 2) {
|
||||
if (mask_final[line + x] == 0 || mask_final[line + x + 1] == 0 ||
|
||||
mask_final[line + width + x] == 0 ||
|
||||
mask_final[line + width + x + 1] == 0) {
|
||||
|
||||
*out_v = 255;
|
||||
*out_u = 128;
|
||||
}
|
||||
out_v++;
|
||||
out_u++;
|
||||
}
|
||||
}
|
||||
out_y = out;
|
||||
/* Set colour intensity for smartmask. */
|
||||
for (i = 0; i < imgs->motionsize; i++) {
|
||||
if (mask_final[i] == 0) {
|
||||
*out_y = 0;
|
||||
}
|
||||
out_y++;
|
||||
}
|
||||
}
|
||||
|
||||
void cls_draw::fixed_mask()
|
||||
{
|
||||
int i, x, v, width, height, line;
|
||||
ctx_images *imgs = &cam->imgs;
|
||||
u_char *mask = imgs->mask;
|
||||
u_char *out_y, *out_u, *out_v;
|
||||
u_char *out = cam->imgs.image_motion.image_norm;
|
||||
|
||||
i = imgs->motionsize;
|
||||
v = i + ((imgs->motionsize) / 4);
|
||||
width = imgs->width;
|
||||
height = imgs->height;
|
||||
|
||||
/* Set U and V to 0 to make fixed mask appear green. */
|
||||
out_v = out + v;
|
||||
out_u = out + i;
|
||||
for (i = 0; i < height; i += 2) {
|
||||
line = i * width;
|
||||
for (x = 0; x < width; x += 2) {
|
||||
if (mask[line + x] == 0 || mask[line + x + 1] == 0 ||
|
||||
mask[line + width + x] == 0 ||
|
||||
mask[line + width + x + 1] == 0) {
|
||||
|
||||
*out_v = 0;
|
||||
*out_u = 0;
|
||||
}
|
||||
out_v++;
|
||||
out_u++;
|
||||
}
|
||||
}
|
||||
out_y = out;
|
||||
/* Set colour intensity for mask. */
|
||||
for (i = 0; i < imgs->motionsize; i++) {
|
||||
if (mask[i] == 0) {
|
||||
*out_y = 0;
|
||||
}
|
||||
out_y++;
|
||||
}
|
||||
}
|
||||
|
||||
void cls_draw::largest_label()
|
||||
{
|
||||
int i, x, v, width, height, line;
|
||||
ctx_images *imgs = &cam->imgs;
|
||||
int *labels = imgs->labels;
|
||||
u_char *out_y, *out_u, *out_v;
|
||||
u_char *out = cam->imgs.image_motion.image_norm;
|
||||
|
||||
i = imgs->motionsize;
|
||||
v = i + ((imgs->motionsize) / 4);
|
||||
width = imgs->width;
|
||||
height = imgs->height;
|
||||
|
||||
/* Set U to 255 to make label appear blue. */
|
||||
out_u = out + i;
|
||||
out_v = out + v;
|
||||
for (i = 0; i < height; i += 2) {
|
||||
line = i * width;
|
||||
for (x = 0; x < width; x += 2) {
|
||||
if (labels[line + x] & 32768 || labels[line + x + 1] & 32768 ||
|
||||
labels[line + width + x] & 32768 ||
|
||||
labels[line + width + x + 1] & 32768) {
|
||||
|
||||
*out_u = 255;
|
||||
*out_v = 128;
|
||||
}
|
||||
out_u++;
|
||||
out_v++;
|
||||
}
|
||||
}
|
||||
out_y = out;
|
||||
/* Set intensity for coloured label to have better visibility. */
|
||||
for (i = 0; i < imgs->motionsize; i++) {
|
||||
if (*labels++ & 32768) {
|
||||
*out_y = 0;
|
||||
}
|
||||
out_y++;
|
||||
}
|
||||
}
|
||||
|
||||
cls_draw::cls_draw(cls_camera *p_cam)
|
||||
{
|
||||
cam = p_cam;
|
||||
init_chars();
|
||||
init_scale();
|
||||
|
||||
}
|
||||
|
||||
cls_draw::~cls_draw()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
+46
-23
@@ -1,30 +1,53 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* draw.h
|
||||
* Headers associated with functions in the draw.c module.
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_DRAW_H
|
||||
#define _INCLUDE_DRAW_H
|
||||
#ifndef _INCLUDE_DRAW_HPP_
|
||||
#define _INCLUDE_DRAW_HPP_
|
||||
#define ASCII_MAX 127
|
||||
#define NEWLINE "\\n"
|
||||
|
||||
int initialize_chars(void);
|
||||
class cls_draw {
|
||||
public:
|
||||
cls_draw(cls_camera *p_cam);
|
||||
~cls_draw();
|
||||
int text(u_char *image
|
||||
, int width, int height, int startx, int starty
|
||||
, const char *text, int factor);
|
||||
void locate();
|
||||
void smartmask();
|
||||
void fixed_mask();
|
||||
void largest_label();
|
||||
|
||||
int draw_text(unsigned char *image, int width, int height, int startx, int starty, const char *text, int factor);
|
||||
private:
|
||||
cls_camera *cam;
|
||||
|
||||
u_char *char_arr_ptr[ASCII_MAX];
|
||||
|
||||
#endif
|
||||
int textn(u_char *image
|
||||
, int startx, int starty, int width
|
||||
, const char *text, int len, int factor);
|
||||
void init_chars(void);
|
||||
void init_scale();
|
||||
void location(ctx_coord *cent
|
||||
, ctx_images *imgs, int width, u_char *new_var);
|
||||
void red_location(ctx_coord *cent
|
||||
, ctx_images *imgs, int width, u_char *new_var);
|
||||
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE_DRAW_HPP_ */
|
||||
-1429
File diff suppressed because it is too large
Load Diff
+411
-119
@@ -1,95 +1,383 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* jpegutils.c: Some Utility programs for dealing with JPEG encoded images
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
|
||||
* Copyright (C) 2001 pHilipp Zabel <pzabel@gmx.de>
|
||||
* Copyright (C) 2008 Angel Carpintero <motiondevelop@gmail.com>
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* based on jdatasrc.c and jdatadst.c from the Independent
|
||||
* JPEG Group's software by Thomas G. Lane
|
||||
* Motion 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* jpegutils.c
|
||||
* Purpose:
|
||||
* Decompress jpeg data into images for use in other parts of program.
|
||||
* Currently this module only decompresses and it is only called from
|
||||
* the vid_mjpegtoyuv420p function
|
||||
* Functional Prefixes
|
||||
* All functions within the module will use the prefix "jpgutl" for identification
|
||||
* Module Level Variables:
|
||||
* EOI_data Constant value to indicate the end of an image.
|
||||
* Module Level Structures:
|
||||
* jpgutl_error_mgr Used by the JPEG libraries as the error manager to catch/trap messages from library.
|
||||
* Static Functions:
|
||||
* The following functions are required by the JPEG library to decompress images.
|
||||
* jpgutl_init_source
|
||||
* jpgutl_fill_input_buffer
|
||||
* jpgutl_skip_data
|
||||
* jpgutl_term_source
|
||||
* jpgutl_buffer_src
|
||||
* jpgutl_error_exit
|
||||
* jpgutl_emit_message
|
||||
* Exposed Functions
|
||||
* jpgutl_decode_jpeg
|
||||
*/
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "motion.hpp"
|
||||
#include "config.hpp"
|
||||
#include "translate.hpp"
|
||||
#include "util.hpp"
|
||||
#include "camera.hpp"
|
||||
#include "conf.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "jpegutils.hpp"
|
||||
#include "picture.hpp" /* For the prepare_exif */
|
||||
#include <setjmp.h>
|
||||
|
||||
|
||||
/* This is a workaround regarding these defines. The config.h file defines
|
||||
* HAVE_STDLIB_H as 1 whereas the jpeglib.h just defines it without a value.
|
||||
* this causes massive warnings/error on mis-matched definitions. We do not
|
||||
* control either of these so we have to suffer through this workaround hack
|
||||
*/
|
||||
#if (HAVE_STDLIB_H == 1)
|
||||
#undef HAVE_STDLIB_H
|
||||
#define HAVE_STDLIB_H_ORIG 1
|
||||
#endif
|
||||
|
||||
#include <jpeglib.h>
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#ifdef HAVE_STDLIB_H_ORIG
|
||||
#undef HAVE_STDLIB_H
|
||||
#undef HAVE_STDLIB_H_ORIG
|
||||
#define HAVE_STDLIB_H 1
|
||||
#else
|
||||
#undef HAVE_STDLIB_H
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include <jerror.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* EXIF image data is always in TIFF format, even if embedded in another
|
||||
* file type. This consists of a constant header (TIFF file header,
|
||||
* IFD header) followed by the tags in the IFD and then the data
|
||||
* from any tags which do not fit inline in the IFD.
|
||||
*
|
||||
* The tags we write in the main IFD are:
|
||||
* 0x010E Image description
|
||||
* 0x8769 Exif sub-IFD
|
||||
* 0x882A Time zone of time stamps
|
||||
* and in the Exif sub-IFD:
|
||||
* 0x9000 Exif version
|
||||
* 0x9003 File date and time
|
||||
* 0x9291 File date and time subsecond info
|
||||
* But we omit any empty IFDs.
|
||||
*/
|
||||
|
||||
#define TIFF_TAG_IMAGE_DESCRIPTION 0x010E
|
||||
#define TIFF_TAG_DATETIME 0x0132
|
||||
#define TIFF_TAG_EXIF_IFD 0x8769
|
||||
#define TIFF_TAG_TZ_OFFSET 0x882A
|
||||
|
||||
#define EXIF_TAG_EXIF_VERSION 0x9000
|
||||
#define EXIF_TAG_ORIGINAL_DATETIME 0x9003
|
||||
#define EXIF_TAG_SUBJECT_AREA 0x9214
|
||||
#define EXIF_TAG_TIFF_DATETIME_SS 0x9290
|
||||
#define EXIF_TAG_ORIGINAL_DATETIME_SS 0x9291
|
||||
|
||||
#define TIFF_TYPE_ASCII 2 /* ASCII text */
|
||||
#define TIFF_TYPE_USHORT 3 /* Unsigned 16-bit int */
|
||||
#define TIFF_TYPE_LONG 4 /* Unsigned 32-bit int */
|
||||
#define TIFF_TYPE_UNDEF 7 /* Byte blob */
|
||||
#define TIFF_TYPE_SSHORT 8 /* Signed 16-bit int */
|
||||
|
||||
static const uint8_t EOI_data[2] = { 0xFF, 0xD9 };
|
||||
|
||||
static const char exif_marker_start[14] = {
|
||||
'E', 'x', 'i', 'f', 0, 0, /* EXIF marker signature */
|
||||
'M', 'M', 0, 42, /* TIFF file header (big-endian) */
|
||||
0, 0, 0, 8, /* Offset to first toplevel IFD */
|
||||
};
|
||||
|
||||
static u_char exif_version_tag[12] = {
|
||||
0x90, 0x00, /* EXIF version tag, 0x9000 */
|
||||
0x00, 0x07, /* Data type 7 = "unknown" (raw byte blob) */
|
||||
0x00, 0x00, 0x00, 0x04, /* Data length */
|
||||
0x30, 0x32, 0x32, 0x30 /* Inline data, EXIF version 2.2 */
|
||||
};
|
||||
|
||||
static u_char exif_subifd_tag[8] = {
|
||||
0x87, 0x69, /* EXIF Sub-IFD tag */
|
||||
0x00, 0x04, /* Data type 4 = uint32 */
|
||||
0x00, 0x00, 0x00, 0x01, /* Number of values */
|
||||
};
|
||||
|
||||
static u_char exif_tzoffset_tag[12] = {
|
||||
0x88, 0x2A, /* TIFF/EP time zone offset tag */
|
||||
0x00, 0x08, /* Data type 8 = sint16 */
|
||||
0x00, 0x00, 0x00, 0x01, /* Number of values */
|
||||
0, 0, 0, 0 /* Dummy data */
|
||||
};
|
||||
|
||||
static void put_uint16(JOCTET *buf, uint value)
|
||||
{
|
||||
buf[0] = (u_char)(( value & 0xFF00 ) >> 8);
|
||||
buf[1] = (u_char)(( value & 0x00FF ));
|
||||
}
|
||||
|
||||
static void put_sint16(JOCTET *buf, int value)
|
||||
{
|
||||
buf[0] = (u_char)(( value & 0xFF00 ) >> 8);
|
||||
buf[1] = (u_char)(( value & 0x00FF ));
|
||||
}
|
||||
|
||||
static void put_uint32(JOCTET *buf, uint value)
|
||||
{
|
||||
buf[0] = (u_char)(( value & 0xFF000000 ) >> 24);
|
||||
buf[1] = (u_char)(( value & 0x00FF0000 ) >> 16);
|
||||
buf[2] = (u_char)(( value & 0x0000FF00 ) >> 8);
|
||||
buf[3] = (u_char)(( value & 0x000000FF ));
|
||||
}
|
||||
|
||||
struct tiff_writing {
|
||||
JOCTET *base;
|
||||
JOCTET *buf;
|
||||
uint data_offset;
|
||||
};
|
||||
|
||||
static void put_direntry(struct tiff_writing *into, const char *data, uint length)
|
||||
{
|
||||
if (length <= 4) {
|
||||
/* Entries that fit in the directory entry are stored there */
|
||||
memset(into->buf, 0, 4);
|
||||
memcpy(into->buf, data, length);
|
||||
} else {
|
||||
/* Longer entries are stored out-of-line */
|
||||
uint offset = into->data_offset;
|
||||
|
||||
while ((offset & 0x03) != 0) { /* Alignment */
|
||||
into->base[offset] = 0;
|
||||
offset ++;
|
||||
}
|
||||
|
||||
put_uint32(into->buf, offset);
|
||||
memcpy(into->base + offset, data, length);
|
||||
into->data_offset = offset + length;
|
||||
}
|
||||
}
|
||||
|
||||
static void put_stringentry(struct tiff_writing *into, uint tag, const char *str, int with_nul)
|
||||
{
|
||||
uint stringlength = (uint)strlen(str) + (with_nul?1:0);
|
||||
|
||||
put_uint16(into->buf, tag);
|
||||
put_uint16(into->buf + 2, TIFF_TYPE_ASCII);
|
||||
put_uint32(into->buf + 4, stringlength);
|
||||
into->buf += 8;
|
||||
put_direntry(into, str, stringlength);
|
||||
into->buf += 4;
|
||||
}
|
||||
|
||||
static void put_subjectarea(struct tiff_writing *into, ctx_coord *box)
|
||||
{
|
||||
put_uint16(into->buf , EXIF_TAG_SUBJECT_AREA);
|
||||
put_uint16(into->buf + 2, TIFF_TYPE_USHORT);
|
||||
put_uint32(into->buf + 4, 4 /* Four USHORTs */);
|
||||
put_uint32(into->buf + 8, into->data_offset);
|
||||
into->buf += 12;
|
||||
JOCTET *ool = into->base + into->data_offset;
|
||||
put_uint16(ool , (uint)box->x); /* Center.x */
|
||||
put_uint16(ool+2, (uint)box->y); /* Center.y */
|
||||
put_uint16(ool+4, (uint)box->width);
|
||||
put_uint16(ool+6, (uint)box->height);
|
||||
into->data_offset += 8;
|
||||
}
|
||||
|
||||
struct ctx_exif_info {
|
||||
cls_camera *cam;
|
||||
timespec *ts_in1;
|
||||
ctx_coord *box;
|
||||
struct tm timestamp_tm;
|
||||
char *description;
|
||||
char *datetime;
|
||||
char *subtime;
|
||||
uint ifd0_tagcount;
|
||||
uint ifd1_tagcount;
|
||||
uint datasize;
|
||||
uint ifds_size;
|
||||
struct tiff_writing writing;
|
||||
};
|
||||
|
||||
void jpgutl_exif_date(ctx_exif_info *exif_info)
|
||||
{
|
||||
char tmpbuf[45];
|
||||
struct timespec ts1;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &ts1);
|
||||
if (exif_info->ts_in1 != NULL) {
|
||||
ts1.tv_sec = exif_info->ts_in1->tv_sec;
|
||||
ts1.tv_nsec = exif_info->ts_in1->tv_nsec;
|
||||
}
|
||||
|
||||
localtime_r(&ts1.tv_sec, &exif_info->timestamp_tm);
|
||||
/* Exif requires this exact format */
|
||||
/* The compiler is twitchy on truncating formats and the exif is twitchy
|
||||
* on the length of the whole string. So we do it in two steps of printing
|
||||
* into a large buffer which compiler wants, then print that into the smaller
|
||||
* buffer that exif wants..TODO Find better method
|
||||
*/
|
||||
snprintf(tmpbuf, 45, "%04d:%02d:%02d %02d:%02d:%02d",
|
||||
exif_info->timestamp_tm.tm_year + 1900,
|
||||
exif_info->timestamp_tm.tm_mon + 1,
|
||||
exif_info->timestamp_tm.tm_mday,
|
||||
exif_info->timestamp_tm.tm_hour,
|
||||
exif_info->timestamp_tm.tm_min,
|
||||
exif_info->timestamp_tm.tm_sec);
|
||||
|
||||
exif_info->datetime =(char*)mymalloc(PATH_MAX);
|
||||
snprintf(exif_info->datetime, 22,"%.21s",tmpbuf);
|
||||
|
||||
exif_info->subtime = nullptr;
|
||||
|
||||
if (exif_info->cam->cfg->picture_exif != "") {
|
||||
exif_info->description =(char*)mymalloc(PATH_MAX);
|
||||
mystrftime(exif_info->cam, exif_info->description, PATH_MAX-1
|
||||
, exif_info->cam->cfg->picture_exif.c_str(), NULL);
|
||||
} else {
|
||||
exif_info->description = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void jpgutl_exif_tags(ctx_exif_info *exif_info)
|
||||
{
|
||||
/* Count up the number of tags and max amount of OOL data */
|
||||
if (exif_info->description != nullptr) {
|
||||
exif_info->ifd0_tagcount ++;
|
||||
exif_info->datasize += 5 + (uint)strlen(exif_info->description); /* Add 5 for NUL and alignment */
|
||||
}
|
||||
|
||||
if (exif_info->datetime != nullptr) {
|
||||
/* We write this to both the TIFF datetime tag (which most programs
|
||||
* treat as "last-modified-date") and the EXIF "time of creation of
|
||||
* original image" tag (which many programs ignore). This is
|
||||
* redundant but seems to be the thing to do.
|
||||
*/
|
||||
exif_info->ifd0_tagcount++;
|
||||
exif_info->ifd1_tagcount++;
|
||||
/* We also write the timezone-offset tag in IFD0 */
|
||||
exif_info->ifd0_tagcount++;
|
||||
/* It would be nice to use the same offset for both tags' values,
|
||||
* but I don't want to write the bookkeeping for that right now */
|
||||
exif_info->datasize += 2 * (5 + (uint)strlen(exif_info->datetime));
|
||||
}
|
||||
|
||||
if (exif_info->subtime != nullptr) {
|
||||
exif_info->ifd1_tagcount++;
|
||||
exif_info->datasize += 5 + (uint)strlen(exif_info->subtime);
|
||||
}
|
||||
|
||||
if (exif_info->box) {
|
||||
exif_info->ifd1_tagcount++;
|
||||
exif_info->datasize += 2 * 4; /* Four 16-bit ints */
|
||||
}
|
||||
|
||||
if (exif_info->ifd1_tagcount > 0) {
|
||||
/* If we're writing the Exif sub-IFD, account for the
|
||||
* two tags that requires */
|
||||
exif_info->ifd0_tagcount ++; /* The tag in IFD0 that points to IFD1 */
|
||||
exif_info->ifd1_tagcount ++; /* The EXIF version tag */
|
||||
}
|
||||
/* Each IFD takes 12 bytes per tag, plus six more (the tag count and the
|
||||
* pointer to the next IFD, always zero in our case)
|
||||
*/
|
||||
exif_info->ifds_size =
|
||||
(exif_info->ifd1_tagcount > 0 ? ( 12 * exif_info->ifd1_tagcount + 6 ) : 0 ) +
|
||||
(exif_info->ifd0_tagcount > 0 ? ( 12 * exif_info->ifd0_tagcount + 6 ) : 0 );
|
||||
|
||||
}
|
||||
|
||||
void jpgutl_exif_writeifd0(ctx_exif_info *exif_info)
|
||||
{
|
||||
/* Note that tags are stored in numerical order */
|
||||
put_uint16(exif_info->writing.buf, (uint)exif_info->ifd0_tagcount);
|
||||
exif_info->writing.buf += 2;
|
||||
|
||||
if (exif_info->description) {
|
||||
put_stringentry(&exif_info->writing
|
||||
, TIFF_TAG_IMAGE_DESCRIPTION, exif_info->description, 1);
|
||||
}
|
||||
|
||||
if (exif_info->datetime) {
|
||||
put_stringentry(&exif_info->writing
|
||||
, TIFF_TAG_DATETIME, exif_info->datetime, 1);
|
||||
}
|
||||
|
||||
if (exif_info->ifd1_tagcount > 0) {
|
||||
/* Offset of IFD1 - TIFF header + IFD0 size. */
|
||||
uint ifd1_offset = 8 + 6 + ( 12 * (uint)exif_info->ifd0_tagcount);
|
||||
memcpy(exif_info->writing.buf, exif_subifd_tag, 8);
|
||||
put_uint32(exif_info->writing.buf + 8, ifd1_offset);
|
||||
exif_info->writing.buf += 12;
|
||||
}
|
||||
|
||||
if (exif_info->datetime) {
|
||||
memcpy(exif_info->writing.buf, exif_tzoffset_tag, 12);
|
||||
put_sint16(exif_info->writing.buf+8
|
||||
, (int)(exif_info->timestamp_tm.tm_gmtoff / 3600));
|
||||
exif_info->writing.buf += 12;
|
||||
}
|
||||
|
||||
put_uint32(exif_info->writing.buf, 0); /* Next IFD offset = 0 (no next IFD) */
|
||||
exif_info->writing.buf += 4;
|
||||
|
||||
}
|
||||
|
||||
void jpgutl_exif_writeifd1(ctx_exif_info *exif_info)
|
||||
{
|
||||
/* Write IFD 1 */
|
||||
if (exif_info->ifd1_tagcount > 0) {
|
||||
/* (remember that the tags in any IFD must be in numerical order by tag) */
|
||||
put_uint16(exif_info->writing.buf, (uint)exif_info->ifd1_tagcount);
|
||||
memcpy(exif_info->writing.buf + 2, exif_version_tag, 12); /* tag 0x9000 */
|
||||
exif_info->writing.buf += 14;
|
||||
|
||||
if (exif_info->datetime) {
|
||||
put_stringentry(&exif_info->writing
|
||||
, EXIF_TAG_ORIGINAL_DATETIME, exif_info->datetime, 1);
|
||||
}
|
||||
|
||||
if (exif_info->box) {
|
||||
put_subjectarea(&exif_info->writing, exif_info->box);
|
||||
}
|
||||
|
||||
if (exif_info->subtime) {
|
||||
put_stringentry(&exif_info->writing
|
||||
, EXIF_TAG_ORIGINAL_DATETIME_SS, exif_info->subtime, 0);
|
||||
}
|
||||
|
||||
put_uint32(exif_info->writing.buf, 0); /* Next IFD = 0 (no next IFD) */
|
||||
exif_info->writing.buf += 4;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint jpgutl_exif(u_char **exif, cls_camera *cam, timespec *ts_in1, ctx_coord *box)
|
||||
{
|
||||
struct ctx_exif_info *exif_info;
|
||||
uint buffer_size;
|
||||
uint marker_len;
|
||||
JOCTET *marker;
|
||||
|
||||
exif_info = (ctx_exif_info*)mymalloc(sizeof(ctx_exif_info));
|
||||
memset(exif_info, 0, sizeof(sizeof(ctx_exif_info)));
|
||||
exif_info->cam = cam;
|
||||
exif_info->ts_in1 = ts_in1;
|
||||
exif_info->box = box;
|
||||
|
||||
jpgutl_exif_date(exif_info);
|
||||
|
||||
jpgutl_exif_tags(exif_info);
|
||||
|
||||
if (exif_info->ifds_size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
buffer_size = 14 + /* EXIF and TIFF headers */
|
||||
exif_info->ifds_size + exif_info->datasize;
|
||||
|
||||
marker =(JOCTET *)mymalloc(buffer_size);
|
||||
memcpy(marker, exif_marker_start, 14); /* EXIF and TIFF headers */
|
||||
|
||||
exif_info->writing.base = marker + 6; /* base address for intra-TIFF offsets */
|
||||
exif_info->writing.buf = marker + 14; /* current write position */
|
||||
exif_info->writing.data_offset =(uint)(8 + exif_info->ifds_size); /* where to start storing data */
|
||||
|
||||
jpgutl_exif_writeifd0(exif_info);
|
||||
jpgutl_exif_writeifd1(exif_info);
|
||||
|
||||
marker_len = exif_info->writing.data_offset + 6;
|
||||
|
||||
myfree(exif_info->description);
|
||||
myfree(exif_info->datetime);
|
||||
|
||||
myfree(exif_info);
|
||||
|
||||
*exif = marker;
|
||||
|
||||
return marker_len;
|
||||
}
|
||||
|
||||
struct jpgutl_error_mgr {
|
||||
struct jpeg_error_mgr pub; /* "public" fields */
|
||||
jmp_buf setjmp_buffer; /* For return to caller */
|
||||
@@ -101,9 +389,8 @@ struct jpgutl_error_mgr {
|
||||
};
|
||||
|
||||
/* These huffman tables are required by the old jpeg libs included with 14.04 */
|
||||
static void add_huff_table(j_decompress_ptr dinfo, JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
|
||||
{
|
||||
/* Define a Huffman table */
|
||||
static void add_huff_table(j_decompress_ptr dinfo, JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val){
|
||||
/* Define a Huffman table */
|
||||
int nsymbols, len;
|
||||
|
||||
if (*htblptr == NULL) {
|
||||
@@ -120,21 +407,19 @@ static void add_huff_table(j_decompress_ptr dinfo, JHUFF_TBL **htblptr, const UI
|
||||
*/
|
||||
nsymbols = 0;
|
||||
|
||||
for (len = 1; len <= 16; len++) {
|
||||
for (len = 1; len <= 16; len++)
|
||||
nsymbols += bits[len];
|
||||
}
|
||||
|
||||
if (nsymbols < 1 || nsymbols > 256) {
|
||||
MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, _("%s: Given jpeg buffer was too small"));
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("%s: Given jpeg buffer was too small"));
|
||||
}
|
||||
|
||||
memcpy((*htblptr)->huffval, val, nsymbols * sizeof(UINT8));
|
||||
memcpy((*htblptr)->huffval, val, (uint)nsymbols * sizeof(UINT8));
|
||||
}
|
||||
|
||||
static void std_huff_tables (j_decompress_ptr dinfo)
|
||||
{
|
||||
/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
|
||||
/* IMPORTANT: these are only valid for 8-bit data precision! */
|
||||
static void std_huff_tables (j_decompress_ptr dinfo){
|
||||
/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
|
||||
/* IMPORTANT: these are only valid for 8-bit data precision! */
|
||||
|
||||
static const UINT8 bits_dc_luminance[17] =
|
||||
{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
|
||||
@@ -286,7 +571,7 @@ static void jpgutl_term_source(j_decompress_ptr cinfo)
|
||||
* Return values:
|
||||
* None
|
||||
*/
|
||||
static void jpgutl_buffer_src(j_decompress_ptr cinfo, unsigned char *buffer, long buffer_len)
|
||||
static void jpgutl_buffer_src(j_decompress_ptr cinfo, u_char *buffer, long buffer_len)
|
||||
{
|
||||
|
||||
if (cinfo->src == NULL) { /* First time for this JPEG object? */
|
||||
@@ -300,7 +585,7 @@ static void jpgutl_buffer_src(j_decompress_ptr cinfo, unsigned char *buffer, lon
|
||||
cinfo->src->skip_input_data = jpgutl_skip_data;
|
||||
cinfo->src->resync_to_restart = jpeg_resync_to_restart; /* Use default method */
|
||||
cinfo->src->term_source = jpgutl_term_source;
|
||||
cinfo->src->bytes_in_buffer = buffer_len;
|
||||
cinfo->src->bytes_in_buffer = (ulong)buffer_len;
|
||||
cinfo->src->next_input_byte = (JOCTET *) buffer;
|
||||
|
||||
|
||||
@@ -328,7 +613,7 @@ static void jpgutl_error_exit(j_common_ptr cinfo)
|
||||
*/
|
||||
(*cinfo->err->format_message) (cinfo, buffer);
|
||||
|
||||
MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, "%s", buffer);
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, "%s", buffer);
|
||||
|
||||
/* Return control to the setjmp point. */
|
||||
longjmp (myerr->setjmp_buffer, 1);
|
||||
@@ -357,7 +642,7 @@ static void jpgutl_emit_message(j_common_ptr cinfo, int msg_level)
|
||||
if ((cinfo->err->msg_code != JWRN_EXTRANEOUS_DATA) && (msg_level < 0) ) {
|
||||
myerr->warning_seen++ ;
|
||||
(*cinfo->err->format_message) (cinfo, buffer);
|
||||
MOTION_LOG(DBG, TYPE_VIDEO, NO_ERRNO, "msg_level: %d, %s", msg_level, buffer);
|
||||
MOTPLS_LOG(DBG, TYPE_VIDEO, NO_ERRNO, "msg_level: %d, %s", msg_level, buffer);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -424,7 +709,7 @@ static GLOBAL(void) _jpeg_mem_dest(j_compress_ptr cinfo, JOCTET* buf, size_t buf
|
||||
static GLOBAL(int) _jpeg_mem_size(j_compress_ptr cinfo)
|
||||
{
|
||||
mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
|
||||
return dest->jpegsize;
|
||||
return (int)dest->jpegsize;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -432,11 +717,11 @@ static GLOBAL(int) _jpeg_mem_size(j_compress_ptr cinfo)
|
||||
* It must be called after jpeg_start_compress() but before
|
||||
* any image data is written by jpeg_write_scanlines().
|
||||
*/
|
||||
static void put_jpeg_exif(j_compress_ptr cinfo, const struct context *cnt
|
||||
, const struct timeval *tv1, const struct coord *box)
|
||||
static void put_jpeg_exif(j_compress_ptr cinfo, cls_camera *cam,
|
||||
timespec *ts1, ctx_coord *box)
|
||||
{
|
||||
unsigned char *exif = NULL;
|
||||
unsigned exif_len = prepare_exif(&exif, cnt, tv1, box);
|
||||
u_char *exif = NULL;
|
||||
uint exif_len = jpgutl_exif(&exif, cam, ts1, box);
|
||||
|
||||
if(exif_len > 0) {
|
||||
/* EXIF data lives in a JPEG APP1 marker */
|
||||
@@ -460,14 +745,14 @@ static void put_jpeg_exif(j_compress_ptr cinfo, const struct context *cnt
|
||||
* Return Values
|
||||
* Success 0, Failure -1
|
||||
*/
|
||||
int jpgutl_decode_jpeg (unsigned char *jpeg_data_in, int jpeg_data_len
|
||||
, unsigned int width, unsigned int height, unsigned char *volatile img_out)
|
||||
int jpgutl_decode_jpeg (u_char *jpeg_data_in, int jpeg_data_len,
|
||||
uint width, uint height, u_char *volatile img_out)
|
||||
{
|
||||
JSAMPARRAY line; /* Array of decomp data lines */
|
||||
unsigned char *wline; /* Will point to line[0] */
|
||||
unsigned int i;
|
||||
unsigned char *img_y, *img_cb, *img_cr;
|
||||
unsigned char offset_y;
|
||||
u_char *wline; /* Will point to line[0] */
|
||||
uint i;
|
||||
u_char *img_y, *img_cb, *img_cr;
|
||||
u_char offset_y;
|
||||
|
||||
struct jpeg_decompress_struct dinfo;
|
||||
struct jpgutl_error_mgr jerr;
|
||||
@@ -500,13 +785,13 @@ int jpgutl_decode_jpeg (unsigned char *jpeg_data_in, int jpeg_data_len
|
||||
jpeg_start_decompress (&dinfo);
|
||||
|
||||
if ((dinfo.output_width == 0) || (dinfo.output_height == 0)) {
|
||||
MOTION_LOG(WRN, TYPE_VIDEO, NO_ERRNO,_("Invalid JPEG image dimensions"));
|
||||
MOTPLS_LOG(WRN, TYPE_VIDEO, NO_ERRNO,_("Invalid JPEG image dimensions"));
|
||||
jpeg_destroy_decompress(&dinfo);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((dinfo.output_width != width) || (dinfo.output_height != height)) {
|
||||
MOTION_LOG(WRN, TYPE_VIDEO, NO_ERRNO
|
||||
MOTPLS_LOG(WRN, TYPE_VIDEO, NO_ERRNO
|
||||
,_("JPEG image size %dx%d, JPEG was %dx%d")
|
||||
,width, height, dinfo.output_width, dinfo.output_height);
|
||||
jpeg_destroy_decompress(&dinfo);
|
||||
@@ -518,8 +803,9 @@ int jpgutl_decode_jpeg (unsigned char *jpeg_data_in, int jpeg_data_len
|
||||
img_cr = img_cb + (dinfo.output_width * dinfo.output_height) / 4;
|
||||
|
||||
/* Allocate space for one line. */
|
||||
line = (*dinfo.mem->alloc_sarray)((j_common_ptr) &dinfo, JPOOL_IMAGE,
|
||||
dinfo.output_width * dinfo.output_components, 1);
|
||||
line = (*dinfo.mem->alloc_sarray)
|
||||
((j_common_ptr) &dinfo, JPOOL_IMAGE
|
||||
,dinfo.output_width * (uint)dinfo.output_components, 1);
|
||||
|
||||
wline = line[0];
|
||||
offset_y = 0;
|
||||
@@ -559,8 +845,9 @@ int jpgutl_decode_jpeg (unsigned char *jpeg_data_in, int jpeg_data_len
|
||||
|
||||
}
|
||||
|
||||
int jpgutl_put_yuv420p(unsigned char *dest_image, int image_size, unsigned char *input_image, int width
|
||||
, int height, int quality, struct context *cnt, struct timeval *tv1, struct coord *box)
|
||||
int jpgutl_put_yuv420p(u_char *dest_image, int image_size,
|
||||
u_char *input_image, int width, int height, int quality,
|
||||
cls_camera *cam, timespec *ts1, ctx_coord *box)
|
||||
|
||||
{
|
||||
int i, j, jpeg_image_size;
|
||||
@@ -591,8 +878,8 @@ int jpgutl_put_yuv420p(unsigned char *dest_image, int image_size, unsigned char
|
||||
return -1;
|
||||
}
|
||||
|
||||
cinfo.image_width = width;
|
||||
cinfo.image_height = height;
|
||||
cinfo.image_width = (uint)width;
|
||||
cinfo.image_height = (uint)height;
|
||||
cinfo.input_components = 3;
|
||||
jpeg_set_defaults(&cinfo);
|
||||
|
||||
@@ -612,12 +899,13 @@ int jpgutl_put_yuv420p(unsigned char *dest_image, int image_size, unsigned char
|
||||
jpeg_set_quality(&cinfo, quality, TRUE);
|
||||
cinfo.dct_method = JDCT_FASTEST;
|
||||
|
||||
_jpeg_mem_dest(&cinfo, dest_image, image_size); // Data written to mem
|
||||
|
||||
_jpeg_mem_dest(&cinfo, dest_image, (uint)image_size);
|
||||
|
||||
jpeg_start_compress(&cinfo, TRUE);
|
||||
|
||||
put_jpeg_exif(&cinfo, cnt, tv1, box);
|
||||
if (cam != NULL) {
|
||||
put_jpeg_exif(&cinfo, cam, ts1, box);
|
||||
}
|
||||
|
||||
/* If the image is not a multiple of 16, this overruns the buffers
|
||||
* we'll just pad those last bytes with zeros
|
||||
@@ -646,8 +934,10 @@ int jpgutl_put_yuv420p(unsigned char *dest_image, int image_size, unsigned char
|
||||
return jpeg_image_size;
|
||||
}
|
||||
|
||||
int jpgutl_put_grey(unsigned char *dest_image, int image_size, unsigned char *input_image, int width
|
||||
, int height, int quality, struct context *cnt, struct timeval *tv1, struct coord *box)
|
||||
|
||||
int jpgutl_put_grey(u_char *dest_image, int image_size,
|
||||
u_char *input_image, int width, int height, int quality,
|
||||
cls_camera *cam, timespec *ts1, ctx_coord *box)
|
||||
{
|
||||
int y, dest_image_size;
|
||||
JSAMPROW row_ptr[1];
|
||||
@@ -670,8 +960,8 @@ int jpgutl_put_grey(unsigned char *dest_image, int image_size, unsigned char *in
|
||||
return -1;
|
||||
}
|
||||
|
||||
cjpeg.image_width = width;
|
||||
cjpeg.image_height = height;
|
||||
cjpeg.image_width = (uint)width;
|
||||
cjpeg.image_height = (uint)height;
|
||||
cjpeg.input_components = 1; /* One colour component */
|
||||
cjpeg.in_color_space = JCS_GRAYSCALE;
|
||||
|
||||
@@ -679,11 +969,13 @@ int jpgutl_put_grey(unsigned char *dest_image, int image_size, unsigned char *in
|
||||
|
||||
jpeg_set_quality(&cjpeg, quality, TRUE);
|
||||
cjpeg.dct_method = JDCT_FASTEST;
|
||||
_jpeg_mem_dest(&cjpeg, dest_image, image_size); // Data written to mem
|
||||
_jpeg_mem_dest(&cjpeg, dest_image, (uint)image_size);
|
||||
|
||||
jpeg_start_compress (&cjpeg, TRUE);
|
||||
|
||||
put_jpeg_exif(&cjpeg, cnt, tv1, box);
|
||||
if (cam != NULL) {
|
||||
put_jpeg_exif(&cjpeg, cam, ts1, box);
|
||||
}
|
||||
|
||||
row_ptr[0] = input_image;
|
||||
|
||||
|
||||
+28
-28
@@ -1,35 +1,35 @@
|
||||
/* This file is part of Motion.
|
||||
/*
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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.
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* jpegutils.h
|
||||
* Headers associated with functions in the jpegutils.c module.
|
||||
* Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
|
||||
* Copyright (C) 2001 pHilipp Zabel <pzabel@gmx.de>
|
||||
* Copyright (C) 2008 Angel Carpintero <motiondevelop@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __JPEGUTILS_H__
|
||||
#define __JPEGUTILS_H__
|
||||
#ifndef _INCLUDE_JPEGUTILS_HPP_
|
||||
#define _INCLUDE_JPEGUTILS_HPP_
|
||||
|
||||
int jpgutl_decode_jpeg (unsigned char *jpeg_data_in, int jpeg_data_len
|
||||
, unsigned int width, unsigned int height, unsigned char *volatile img_out);
|
||||
int jpgutl_put_yuv420p(unsigned char *dest_image, int image_size, unsigned char *input_image, int width
|
||||
, int height, int quality, struct context *cnt, struct timeval *tv1, struct coord *box);
|
||||
int jpgutl_put_grey(unsigned char *dest_image, int image_size, unsigned char *input_image, int width
|
||||
, int height, int quality, struct context *cnt, struct timeval *tv1, struct coord *box);
|
||||
int jpgutl_decode_jpeg (unsigned char *jpeg_data_in, int jpeg_data_len,
|
||||
unsigned int width, unsigned int height, unsigned char *volatile img_out);
|
||||
int jpgutl_put_yuv420p(unsigned char *dest_image, int image_size,
|
||||
unsigned char *input_image, int width, int height, int quality,
|
||||
cls_camera *cam, timespec *ts1, ctx_coord *box);
|
||||
int jpgutl_put_grey(unsigned char *dest_image, int image_size,
|
||||
unsigned char *input_image, int width, int height, int quality,
|
||||
cls_camera *cam, timespec *ts1, ctx_coord *box);
|
||||
uint jpgutl_exif(u_char **exif, cls_camera *cam
|
||||
, timespec *ts_in1, ctx_coord *box);
|
||||
|
||||
#endif
|
||||
#endif /* _INCLUDE_JPEGUTILS_HPP_ */
|
||||
|
||||
+894
@@ -0,0 +1,894 @@
|
||||
/*
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "motion.hpp"
|
||||
#include "util.hpp"
|
||||
#include "camera.hpp"
|
||||
#include "conf.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "rotate.hpp"
|
||||
#include "libcam.hpp"
|
||||
|
||||
#ifdef HAVE_LIBCAM
|
||||
|
||||
using namespace libcamera;
|
||||
|
||||
void cls_libcam::log_orientation()
|
||||
{
|
||||
#if (LIBCAMVER >= 2000)
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, "Libcamera Orientation Options:");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " Rotate0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " Rotate0Mirror");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " Rotate180");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " Rotate180Mirror");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " Rotate90");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " Rotate90Mirror");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " Rotate270");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " Rotate270Mirror");
|
||||
#else
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO, "Orientation Not available");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void cls_libcam::log_controls()
|
||||
{
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, "Libcamera Controls:");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AeEnable(bool)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AeLocked(bool)");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AeMeteringMode(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " MeteringCentreWeighted = 0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " MeteringSpot = 1");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " MeteringMatrix = 2");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " MeteringCustom = 3");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AeConstraintMode(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " ConstraintNormal = 0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " ConstraintHighlight = 1");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " ConstraintShadows = 2");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " ConstraintCustom = 3");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AeExposureMode(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " ExposureNormal = 0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " ExposureShort = 1");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " ExposureLong = 2");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " ExposureCustom = 3");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " ExposureValue(float)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " ExposureTime(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AnalogueGain(float)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " Brightness(float)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " Contrast(float)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " Lux(float)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AwbEnable(bool)");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AwbMode(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AwbAuto = 0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AwbIncandescent = 1");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AwbTungsten = 2");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AwbFluorescent = 3");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AwbIndoor = 4");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AwbDaylight = 5");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AwbCloudy = 6");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AwbCustom = 7");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AwbLocked(bool)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " ColourGains(Pipe delimited)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " Red | Blue");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " ColourTemperature(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " Saturation(float)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " SensorBlackLevels(Pipe delimited)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " var1|var2|var3|var4");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " Sharpness(float)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " FocusFoM(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " ColourCorrectionMatrix(Pipe delimited)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " var1|var2|...|var8|var9");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " ScalerCrop(Pipe delimited)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " x | y | h | w");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " DigitalGain(float)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " FrameDuration(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " FrameDurationLimits(Pipe delimited)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " min | max");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " SensorTemperature(float)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " SensorTimestamp(int)");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfMode(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfModeManual = 0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfModeAuto = 1");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfModeContinuous = 2");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfRange(0-2)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfRangeNormal = 0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfRangeMacro = 1");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfRangeFull = 2");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfSpeed(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfSpeedNormal = 0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfSpeedFast = 1");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfMetering(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfMeteringAuto = 0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfMeteringWindows = 1");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfWindows(Pipe delimited)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " x | y | h | w");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfTrigger(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfTriggerStart = 0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfTriggerCancel = 1");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfPause(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfPauseImmediate = 0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfPauseDeferred = 1");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfPauseResume = 2");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " LensPosition(float)");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfState(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfStateIdle = 0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfStateScanning = 1");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfStateFocused = 2");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfStateFailed = 3");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfPauseState(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfPauseStateRunning = 0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfPauseStatePausing = 1");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AfPauseStatePaused = 2");
|
||||
|
||||
}
|
||||
|
||||
void cls_libcam:: log_draft()
|
||||
{
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, "Libcamera Controls Draft:");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AePrecaptureTrigger(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AePrecaptureTriggerIdle = 0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AePrecaptureTriggerStart = 1");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AePrecaptureTriggerCancel = 2");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " NoiseReductionMode(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " NoiseReductionModeOff = 0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " NoiseReductionModeFast = 1");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " NoiseReductionModeHighQuality = 2");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " NoiseReductionModeMinimal = 3");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " NoiseReductionModeZSL = 4");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " ColorCorrectionAberrationMode(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " ColorCorrectionAberrationOff = 0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " ColorCorrectionAberrationFast = 1");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " ColorCorrectionAberrationHighQuality = 2");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AeState(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AeStateSearching = 1");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AeStateConverged = 2");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AeStateLocked = 3");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AeStateFlashRequired = 4");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AeStatePrecapture = 5");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AwbState(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AwbStateInactive = 0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AwbStateSearching = 1");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AwbConverged = 2");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " AwbLocked = 3");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " SensorRollingShutterSkew(int)");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " LensShadingMapMode(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " LensShadingMapModeOff = 0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " LensShadingMapModeOn = 1");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " PipelineDepth(int)");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " MaxLatency(int)");
|
||||
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " TestPatternMode(int)");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " TestPatternModeOff = 0");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " TestPatternModeSolidColor = 1");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " TestPatternModeColorBars = 2");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " TestPatternModeColorBarsFadeToGray = 3");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " TestPatternModePn9 = 4");
|
||||
MOTPLS_SHT(DBG, TYPE_VIDEO, NO_ERRNO, " TestPatternModeCustom1 = 256");
|
||||
|
||||
}
|
||||
|
||||
void cls_libcam::start_params()
|
||||
{
|
||||
ctx_params_item *itm;
|
||||
int indx;
|
||||
|
||||
params = new ctx_params;
|
||||
util_parms_parse(params,"libcam_params", cam->cfg->libcam_params);
|
||||
|
||||
for (indx=0;indx<params->params_cnt;indx++) {
|
||||
itm = ¶ms->params_array[indx];
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO, "%s : %s"
|
||||
,itm->param_name.c_str(), itm->param_value.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
int cls_libcam::start_mgr()
|
||||
{
|
||||
int retcd;
|
||||
std::string camid;
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO, "Starting.");
|
||||
|
||||
cam_mgr = std::make_unique<CameraManager>();
|
||||
retcd = cam_mgr->start();
|
||||
if (retcd != 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_VIDEO, NO_ERRNO
|
||||
, "Error starting camera manager. Return code: %d",retcd);
|
||||
return retcd;
|
||||
}
|
||||
started_mgr = true;
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO, "cam_mgr started.");
|
||||
|
||||
if (cam->cfg->libcam_device == "camera0"){
|
||||
if (cam_mgr->cameras().size() == 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_VIDEO, NO_ERRNO
|
||||
, "No camera devices found");
|
||||
return -1;
|
||||
}
|
||||
camid = cam_mgr->cameras()[0]->id();
|
||||
} else {
|
||||
MOTPLS_LOG(ERR, TYPE_VIDEO, NO_ERRNO
|
||||
, "Invalid libcam_device '%s'. The only name supported is 'camera0' "
|
||||
,cam->cfg->libcam_device.c_str());
|
||||
return -1;
|
||||
}
|
||||
camera = cam_mgr->get(camid);
|
||||
camera->acquire();
|
||||
started_aqr = true;
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO, "Finished.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cls_libcam::config_control_item(std::string pname, std::string pvalue)
|
||||
{
|
||||
if (pname == "AeEnable") {
|
||||
controls.set(controls::AeEnable, mtob(pvalue));
|
||||
}
|
||||
if (pname == "AeLocked") {
|
||||
controls.set(controls::AeLocked, mtob(pvalue));
|
||||
}
|
||||
if (pname == "AeMeteringMode") {
|
||||
controls.set(controls::AeMeteringMode, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "AeConstraintMode") {
|
||||
controls.set(controls::AeConstraintMode, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "AeExposureMode") {
|
||||
controls.set(controls::AeExposureMode, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "ExposureValue") {
|
||||
controls.set(controls::ExposureValue, mtof(pvalue));
|
||||
}
|
||||
if (pname == "ExposureTime") {
|
||||
controls.set(controls::ExposureTime, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "AnalogueGain") {
|
||||
controls.set(controls::AnalogueGain, mtof(pvalue));
|
||||
}
|
||||
if (pname == "Brightness") {
|
||||
controls.set(controls::Brightness, mtof(pvalue));
|
||||
}
|
||||
if (pname == "Contrast") {
|
||||
controls.set(controls::Contrast, mtof(pvalue));
|
||||
}
|
||||
if (pname == "Lux") {
|
||||
controls.set(controls::Lux, mtof(pvalue));
|
||||
}
|
||||
if (pname == "AwbEnable") {
|
||||
controls.set(controls::AwbEnable, mtob(pvalue));
|
||||
}
|
||||
if (pname == "AwbMode") {
|
||||
controls.set(controls::AwbMode, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "AwbLocked") {
|
||||
controls.set(controls::AwbLocked, mtob(pvalue));
|
||||
}
|
||||
if (pname == "ColourGains") {
|
||||
float cg[2];
|
||||
cg[0] = mtof(mtok(pvalue,"|"));
|
||||
cg[1] = mtof(mtok(pvalue,"|"));
|
||||
controls.set(controls::ColourGains, cg);
|
||||
}
|
||||
if (pname == "ColourTemperature") {
|
||||
controls.set(controls::ColourTemperature, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "Saturation") {
|
||||
controls.set(controls::Saturation, mtof(pvalue));
|
||||
}
|
||||
if (pname == "SensorBlackLevels") {
|
||||
int32_t sbl[4];
|
||||
sbl[0] = mtoi(mtok(pvalue,"|"));
|
||||
sbl[1] = mtoi(mtok(pvalue,"|"));
|
||||
sbl[2] = mtoi(mtok(pvalue,"|"));
|
||||
sbl[3] = mtoi(mtok(pvalue,"|"));
|
||||
controls.set(controls::SensorBlackLevels, sbl);
|
||||
}
|
||||
if (pname == "Sharpness") {
|
||||
controls.set(controls::Sharpness, mtof(pvalue));
|
||||
}
|
||||
if (pname == "FocusFoM") {
|
||||
controls.set(controls::FocusFoM, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "ColourCorrectionMatrix") {
|
||||
float ccm[9];
|
||||
ccm[0] = mtof(mtok(pvalue,"|"));
|
||||
ccm[1] = mtof(mtok(pvalue,"|"));
|
||||
ccm[2] = mtof(mtok(pvalue,"|"));
|
||||
ccm[3] = mtof(mtok(pvalue,"|"));
|
||||
ccm[4] = mtof(mtok(pvalue,"|"));
|
||||
ccm[5] = mtof(mtok(pvalue,"|"));
|
||||
ccm[6] = mtof(mtok(pvalue,"|"));
|
||||
ccm[7] = mtof(mtok(pvalue,"|"));
|
||||
ccm[8] = mtof(mtok(pvalue,"|"));
|
||||
controls.set(controls::ColourCorrectionMatrix, ccm);
|
||||
}
|
||||
if (pname == "ScalerCrop") {
|
||||
Rectangle crop;
|
||||
crop.x = mtoi(mtok(pvalue,"|"));
|
||||
crop.y = mtoi(mtok(pvalue,"|"));
|
||||
crop.width =(uint)mtoi(mtok(pvalue,"|"));
|
||||
crop.height =(uint)mtoi(mtok(pvalue,"|"));
|
||||
controls.set(controls::ScalerCrop, crop);
|
||||
}
|
||||
if (pname == "DigitalGain") {
|
||||
controls.set(controls::DigitalGain, mtof(pvalue));
|
||||
}
|
||||
if (pname == "FrameDuration") {
|
||||
controls.set(controls::FrameDuration, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "FrameDurationLimits") {
|
||||
int64_t fdl[2];
|
||||
fdl[0] = mtol(mtok(pvalue,"|"));
|
||||
fdl[1] = mtol(mtok(pvalue,"|"));
|
||||
controls.set(controls::FrameDurationLimits, fdl);
|
||||
}
|
||||
if (pname == "SensorTemperature") {
|
||||
controls.set(controls::SensorTemperature, mtof(pvalue));
|
||||
}
|
||||
if (pname == "SensorTimestamp") {
|
||||
controls.set(controls::SensorTimestamp, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "AfMode") {
|
||||
controls.set(controls::AfMode, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "AfRange") {
|
||||
controls.set(controls::AfRange, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "AfSpeed") {
|
||||
controls.set(controls::AfSpeed, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "AfMetering") {
|
||||
controls.set(controls::AfMetering, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "AfWindows") {
|
||||
Rectangle afwin[1];
|
||||
afwin[0].x = mtoi(mtok(pvalue,"|"));
|
||||
afwin[0].y = mtoi(mtok(pvalue,"|"));
|
||||
afwin[0].width = (uint)mtoi(mtok(pvalue,"|"));
|
||||
afwin[0].height = (uint)mtoi(mtok(pvalue,"|"));
|
||||
controls.set(controls::AfWindows, afwin);
|
||||
}
|
||||
if (pname == "AfTrigger") {
|
||||
controls.set(controls::AfTrigger, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "AfPause") {
|
||||
controls.set(controls::AfPause, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "LensPosition") {
|
||||
controls.set(controls::LensPosition, mtof(pvalue));
|
||||
}
|
||||
if (pname == "AfState") {
|
||||
controls.set(controls::AfState, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "AfPauseState") {
|
||||
controls.set(controls::AfPauseState, mtoi(pvalue));
|
||||
}
|
||||
|
||||
/* DRAFT*/
|
||||
if (pname == "AePrecaptureTrigger") {
|
||||
controls.set(controls::draft::AePrecaptureTrigger, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "NoiseReductionMode") {
|
||||
controls.set(controls::draft::NoiseReductionMode, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "ColorCorrectionAberrationMode") {
|
||||
controls.set(controls::draft::ColorCorrectionAberrationMode, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "AeState") {
|
||||
controls.set(controls::draft::AeState, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "AwbState") {
|
||||
controls.set(controls::draft::AwbState, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "SensorRollingShutterSkew") {
|
||||
controls.set(controls::draft::SensorRollingShutterSkew, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "LensShadingMapMode") {
|
||||
controls.set(controls::draft::LensShadingMapMode, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "PipelineDepth") {
|
||||
controls.set(controls::draft::PipelineDepth, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "MaxLatency") {
|
||||
controls.set(controls::draft::MaxLatency, mtoi(pvalue));
|
||||
}
|
||||
if (pname == "TestPatternMode") {
|
||||
controls.set(controls::draft::TestPatternMode, mtoi(pvalue));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cls_libcam::config_controls()
|
||||
{
|
||||
int retcd, indx;
|
||||
|
||||
for (indx=0;indx<params->params_cnt;indx++) {
|
||||
config_control_item(
|
||||
params->params_array[indx].param_name
|
||||
,params->params_array[indx].param_value);
|
||||
}
|
||||
|
||||
retcd = config->validate();
|
||||
if (retcd == CameraConfiguration::Adjusted) {
|
||||
MOTPLS_LOG(INF, TYPE_VIDEO, NO_ERRNO
|
||||
, "Configuration controls adjusted.");
|
||||
} else if (retcd == CameraConfiguration::Valid) {
|
||||
MOTPLS_LOG(DBG, TYPE_VIDEO, NO_ERRNO
|
||||
, "Configuration controls valid");
|
||||
} else if (retcd == CameraConfiguration::Invalid) {
|
||||
MOTPLS_LOG(ERR, TYPE_VIDEO, NO_ERRNO
|
||||
, "Configuration controls error");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cls_libcam:: config_orientation()
|
||||
{
|
||||
#if (LIBCAMVER >= 2000)
|
||||
int retcd, indx;
|
||||
std::string adjdesc;
|
||||
ctx_params_item *itm;
|
||||
|
||||
for (indx=0;indx<params->params_cnt;indx++) {
|
||||
itm = ¶ms->params_array[indx];
|
||||
if (itm->param_name == "orientation") {
|
||||
if (itm->param_value == "Rotate0") {
|
||||
config->orientation = Orientation::Rotate0;
|
||||
} else if (itm->param_value == "Rotate0Mirror") {
|
||||
config->orientation = Orientation::Rotate0Mirror;
|
||||
} else if (itm->param_value == "Rotate180") {
|
||||
config->orientation = Orientation::Rotate180;
|
||||
} else if (itm->param_value == "Rotate180Mirror") {
|
||||
config->orientation = Orientation::Rotate180Mirror;
|
||||
} else if (itm->param_value == "Rotate90") {
|
||||
config->orientation = Orientation::Rotate90;
|
||||
} else if (itm->param_value == "Rotate90Mirror") {
|
||||
config->orientation = Orientation::Rotate90Mirror;
|
||||
} else if (itm->param_value == "Rotate270") {
|
||||
config->orientation = Orientation::Rotate270;
|
||||
} else if (itm->param_value == "Rotate270Mirror") {
|
||||
config->orientation = Orientation::Rotate270Mirror;
|
||||
} else {
|
||||
MOTPLS_LOG(ERR, TYPE_VIDEO, NO_ERRNO
|
||||
, "Invalid Orientation option: %s."
|
||||
, itm->param_value.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retcd = config->validate();
|
||||
if (retcd == CameraConfiguration::Adjusted) {
|
||||
if (config->orientation == Orientation::Rotate0) {
|
||||
adjdesc = "Rotate0";
|
||||
} else if (config->orientation == Orientation::Rotate0Mirror) {
|
||||
adjdesc = "Rotate0Mirror";
|
||||
} else if (config->orientation == Orientation::Rotate90) {
|
||||
adjdesc = "Rotate90";
|
||||
} else if (config->orientation == Orientation::Rotate90Mirror) {
|
||||
adjdesc = "Rotate90Mirror";
|
||||
} else if (config->orientation == Orientation::Rotate180) {
|
||||
adjdesc = "Rotate180";
|
||||
} else if (config->orientation == Orientation::Rotate180Mirror) {
|
||||
adjdesc = "Rotate180Mirror";
|
||||
} else if (config->orientation == Orientation::Rotate270) {
|
||||
adjdesc = "Rotate270";
|
||||
} else if (config->orientation == Orientation::Rotate270Mirror) {
|
||||
adjdesc = "Rotate270Mirror";
|
||||
} else {
|
||||
adjdesc = "unknown";
|
||||
}
|
||||
MOTPLS_LOG(INF, TYPE_VIDEO, NO_ERRNO
|
||||
, "Configuration orientation adjusted to %s."
|
||||
, adjdesc.c_str());
|
||||
} else if (retcd == CameraConfiguration::Valid) {
|
||||
MOTPLS_LOG(DBG, TYPE_VIDEO, NO_ERRNO
|
||||
, "Configuration orientation valid");
|
||||
} else if (retcd == CameraConfiguration::Invalid) {
|
||||
MOTPLS_LOG(ERR, TYPE_VIDEO, NO_ERRNO
|
||||
, "Configuration orientation error");
|
||||
}
|
||||
#else
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO, "Orientation Not available");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int cls_libcam::start_config()
|
||||
{
|
||||
int retcd;
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO, "Starting.");
|
||||
|
||||
config = camera->generateConfiguration({ StreamRole::Viewfinder });
|
||||
|
||||
config->at(0).pixelFormat = PixelFormat::fromString("YUV420");
|
||||
|
||||
config->at(0).size.width = (uint)cam->cfg->width;
|
||||
config->at(0).size.height = (uint)cam->cfg->height;
|
||||
config->at(0).bufferCount = 1;
|
||||
config->at(0).stride = 0;
|
||||
|
||||
retcd = config->validate();
|
||||
if (retcd == CameraConfiguration::Adjusted) {
|
||||
if (config->at(0).pixelFormat != PixelFormat::fromString("YUV420")) {
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO
|
||||
, "Pixel format was adjusted to %s."
|
||||
, config->at(0).pixelFormat.toString().c_str());
|
||||
return -1;
|
||||
} else {
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO
|
||||
, "Configuration adjusted.");
|
||||
}
|
||||
} else if (retcd == CameraConfiguration::Valid) {
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO
|
||||
, "Configuration is valid");
|
||||
} else if (retcd == CameraConfiguration::Invalid) {
|
||||
MOTPLS_LOG(ERR, TYPE_VIDEO, NO_ERRNO
|
||||
, "Error setting configuration");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((config->at(0).size.width != (uint)cam->cfg->width) ||
|
||||
(config->at(0).size.height != (uint)cam->cfg->height)) {
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO
|
||||
, "Image size adjusted from %d x %d to %d x %d"
|
||||
, cam->cfg->width, cam->cfg->height
|
||||
, config->at(0).size.width, config->at(0).size.height);
|
||||
}
|
||||
|
||||
cam->imgs.width = (int)config->at(0).size.width;
|
||||
cam->imgs.height = (int)config->at(0).size.height;
|
||||
cam->imgs.size_norm = (cam->imgs.width * cam->imgs.height * 3) / 2;
|
||||
cam->imgs.motionsize = cam->imgs.width * cam->imgs.height;
|
||||
|
||||
log_orientation();
|
||||
log_controls();
|
||||
log_draft();
|
||||
|
||||
config_orientation();
|
||||
config_controls();
|
||||
|
||||
camera->configure(config.get());
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO, "Finished.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cls_libcam::req_add(Request *request)
|
||||
{
|
||||
int retcd;
|
||||
retcd = camera->queueRequest(request);
|
||||
return retcd;
|
||||
}
|
||||
|
||||
int cls_libcam::start_req()
|
||||
{
|
||||
int retcd, bytes, indx, width;
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO, "Starting.");
|
||||
|
||||
camera->requestCompleted.connect(this, &cls_libcam::req_complete);
|
||||
frmbuf = std::make_unique<FrameBufferAllocator>(camera);
|
||||
|
||||
retcd = frmbuf->allocate(config->at(0).stream());
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_VIDEO, NO_ERRNO
|
||||
, "Buffer allocation error.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::unique_ptr<Request> request = camera->createRequest();
|
||||
if (!request) {
|
||||
MOTPLS_LOG(ERR, TYPE_VIDEO, NO_ERRNO
|
||||
, "Create request error.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Stream *stream = config->at(0).stream();
|
||||
const std::vector<std::unique_ptr<FrameBuffer>> &buffers =
|
||||
frmbuf->buffers(stream);
|
||||
const std::unique_ptr<FrameBuffer> &buffer = buffers[0];
|
||||
|
||||
retcd = request->addBuffer(stream, buffer.get());
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_VIDEO, NO_ERRNO
|
||||
, "Add buffer for request error.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
started_req = true;
|
||||
|
||||
const FrameBuffer::Plane &plane0 = buffer->planes()[0];
|
||||
|
||||
bytes = 0;
|
||||
for (indx=0; indx<(int)buffer->planes().size(); indx++){
|
||||
bytes += buffer->planes()[(uint)indx].length;
|
||||
MOTPLS_LOG(DBG, TYPE_VIDEO, NO_ERRNO, "Plane %d of %d length %d"
|
||||
, indx, buffer->planes().size()
|
||||
, buffer->planes()[(uint)indx].length);
|
||||
}
|
||||
|
||||
if (bytes > cam->imgs.size_norm) {
|
||||
width = ((int)buffer->planes()[0].length / cam->imgs.height);
|
||||
if (((int)buffer->planes()[0].length != (width * cam->imgs.height)) ||
|
||||
(bytes > ((width * cam->imgs.height * 3)/2))) {
|
||||
MOTPLS_LOG(ERR, TYPE_VIDEO, NO_ERRNO
|
||||
, "Error setting image size. Plane 0 length %d, total bytes %d"
|
||||
, buffer->planes()[0].length, bytes);
|
||||
}
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO
|
||||
, "Image size adjusted from %d x %d to %d x %d"
|
||||
, cam->imgs.width,cam->imgs.height
|
||||
, width,cam->imgs.height);
|
||||
cam->imgs.width = width;
|
||||
cam->imgs.size_norm = (cam->imgs.width * cam->imgs.height * 3) / 2;
|
||||
cam->imgs.motionsize = cam->imgs.width * cam->imgs.height;
|
||||
}
|
||||
|
||||
membuf.buf = (uint8_t *)mmap(NULL, (uint)bytes, PROT_READ
|
||||
, MAP_SHARED, plane0.fd.get(), 0);
|
||||
membuf.bufsz = bytes;
|
||||
|
||||
requests.push_back(std::move(request));
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO, "Finished.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cls_libcam::start_capture()
|
||||
{
|
||||
int retcd;
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO, "Starting.");
|
||||
|
||||
retcd = camera->start(&this->controls);
|
||||
if (retcd) {
|
||||
MOTPLS_LOG(ERR, TYPE_VIDEO, NO_ERRNO
|
||||
, "Failed to start capture.");
|
||||
return -1;
|
||||
}
|
||||
controls.clear();
|
||||
|
||||
for (std::unique_ptr<Request> &request : requests) {
|
||||
retcd = req_add(request.get());
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_VIDEO, NO_ERRNO
|
||||
, "Failed to queue request.");
|
||||
if (started_cam) {
|
||||
camera->stop();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO, "Finished.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cls_libcam::req_complete(Request *request)
|
||||
{
|
||||
if (request->status() == Request::RequestCancelled) {
|
||||
return;
|
||||
}
|
||||
req_queue.push(request);
|
||||
}
|
||||
|
||||
int cls_libcam::libcam_start()
|
||||
{
|
||||
started_cam = false;
|
||||
started_mgr = false;
|
||||
started_aqr = false;
|
||||
started_req = false;
|
||||
|
||||
start_params();
|
||||
|
||||
if (start_mgr() != 0) {
|
||||
return -1;
|
||||
}
|
||||
if (start_config() != 0) {
|
||||
return -1;
|
||||
}
|
||||
if (start_req() != 0) {
|
||||
return -1;
|
||||
}
|
||||
if (start_capture() != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cam->watchdog = cam->cfg->watchdog_tmo;
|
||||
SLEEP(1,0);
|
||||
|
||||
started_cam = true;
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO, "Camera started");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cls_libcam::libcam_stop()
|
||||
{
|
||||
mydelete(params);
|
||||
|
||||
if (started_aqr) {
|
||||
camera->stop();
|
||||
}
|
||||
|
||||
if (started_req) {
|
||||
camera->requestCompleted.disconnect(this, &cls_libcam::req_complete);
|
||||
while (req_queue.empty() == false) {
|
||||
req_queue.pop();
|
||||
}
|
||||
requests.clear();
|
||||
|
||||
frmbuf->free(config->at(0).stream());
|
||||
frmbuf.reset();
|
||||
}
|
||||
|
||||
controls.clear();
|
||||
|
||||
if (started_aqr){
|
||||
camera->release();
|
||||
camera.reset();
|
||||
}
|
||||
if (started_mgr) {
|
||||
cam_mgr->stop();
|
||||
cam_mgr.reset();
|
||||
}
|
||||
cam->device_status = STATUS_CLOSED;
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO, "Camera stopped.");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void cls_libcam::noimage()
|
||||
{
|
||||
#ifdef HAVE_LIBCAM
|
||||
int slp_dur;
|
||||
|
||||
if (reconnect_count < 100) {
|
||||
reconnect_count++;
|
||||
} else {
|
||||
if (reconnect_count >= 500) {
|
||||
MOTPLS_LOG(NTC, TYPE_NETCAM, NO_ERRNO,_("Camera did not reconnect."));
|
||||
MOTPLS_LOG(NTC, TYPE_NETCAM, NO_ERRNO,_("Checking for camera every 2 hours."));
|
||||
slp_dur = 7200;
|
||||
} else if (reconnect_count >= 200) {
|
||||
MOTPLS_LOG(NTC, TYPE_NETCAM, NO_ERRNO,_("Camera did not reconnect."));
|
||||
MOTPLS_LOG(NTC, TYPE_NETCAM, NO_ERRNO,_("Checking for camera every 10 minutes."));
|
||||
reconnect_count++;
|
||||
slp_dur = 600;
|
||||
} else {
|
||||
MOTPLS_LOG(NTC, TYPE_NETCAM, NO_ERRNO,_("Camera did not reconnect."));
|
||||
MOTPLS_LOG(NTC, TYPE_NETCAM, NO_ERRNO,_("Checking for camera every 30 seconds."));
|
||||
reconnect_count++;
|
||||
slp_dur = 30;
|
||||
}
|
||||
cam->watchdog = slp_dur + (cam->cfg->watchdog_tmo * 3);
|
||||
SLEEP(slp_dur,0);
|
||||
libcam_stop();
|
||||
if (libcam_start() < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_VIDEO, NO_ERRNO,_("libcam failed to open"));
|
||||
libcam_stop();
|
||||
} else {
|
||||
cam->device_status = STATUS_OPENED;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int cls_libcam::next(ctx_image_data *img_data)
|
||||
{
|
||||
#ifdef HAVE_LIBCAM
|
||||
int indx;
|
||||
|
||||
if (started_cam == false) {
|
||||
return CAPTURE_FAILURE;
|
||||
}
|
||||
|
||||
cam->watchdog = cam->cfg->watchdog_tmo;
|
||||
/* Allow time for request to finish.*/
|
||||
indx=0;
|
||||
while ((req_queue.empty() == true) && (indx < 50)) {
|
||||
SLEEP(0,2000)
|
||||
indx++;
|
||||
}
|
||||
|
||||
cam->watchdog = cam->cfg->watchdog_tmo;
|
||||
if (req_queue.empty() == false) {
|
||||
Request *request = this->req_queue.front();
|
||||
|
||||
memcpy(img_data->image_norm, membuf.buf, (uint)membuf.bufsz);
|
||||
|
||||
this->req_queue.pop();
|
||||
request->reuse(Request::ReuseBuffers);
|
||||
req_add(request);
|
||||
|
||||
cam->rotate->process(img_data);
|
||||
reconnect_count = 0;
|
||||
|
||||
return CAPTURE_SUCCESS;
|
||||
|
||||
} else {
|
||||
return CAPTURE_FAILURE;
|
||||
}
|
||||
#else
|
||||
(void)img_data;
|
||||
return CAPTURE_FAILURE;
|
||||
#endif
|
||||
}
|
||||
|
||||
cls_libcam::cls_libcam(cls_camera *p_cam)
|
||||
{
|
||||
cam = p_cam;
|
||||
#ifdef HAVE_LIBCAM
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO,_("Opening libcam"));
|
||||
params = nullptr;
|
||||
reconnect_count = 0;
|
||||
cam->watchdog = cam->cfg->watchdog_tmo * 3; /* 3 is arbitrary multiplier to give startup more time*/
|
||||
if (libcam_start() < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_VIDEO, NO_ERRNO,_("libcam failed to open"));
|
||||
libcam_stop();
|
||||
} else {
|
||||
cam->device_status = STATUS_OPENED;
|
||||
}
|
||||
#else
|
||||
MOTPLS_LOG(NTC, TYPE_VIDEO, NO_ERRNO,_("libcam not available"));
|
||||
cam->device_status = STATUS_CLOSED;
|
||||
#endif
|
||||
}
|
||||
|
||||
cls_libcam::~cls_libcam()
|
||||
{
|
||||
#ifdef HAVE_LIBCAM
|
||||
libcam_stop();
|
||||
#endif
|
||||
cam->device_status = STATUS_CLOSED;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_LIBCAM_HPP_
|
||||
#define _INCLUDE_LIBCAM_HPP_
|
||||
#ifdef HAVE_LIBCAM
|
||||
#include <queue>
|
||||
#include <sys/mman.h>
|
||||
#include <libcamera/libcamera.h>
|
||||
|
||||
#define LIBCAMVER (LIBCAMERA_VERSION_MAJOR * 1000000)+(LIBCAMERA_VERSION_MINOR* 1000) + LIBCAMERA_VERSION_PATCH
|
||||
|
||||
/* Buffers and sizes for planes of image*/
|
||||
struct ctx_imgmap {
|
||||
uint8_t *buf;
|
||||
int bufsz;
|
||||
};
|
||||
|
||||
class cls_libcam {
|
||||
public:
|
||||
cls_libcam(cls_camera *p_cam);
|
||||
~cls_libcam();
|
||||
int next(ctx_image_data *img_data);
|
||||
void noimage();
|
||||
private:
|
||||
cls_camera *cam;
|
||||
ctx_params *params;
|
||||
|
||||
std::unique_ptr<libcamera::CameraManager> cam_mgr;
|
||||
std::shared_ptr<libcamera::Camera> camera;
|
||||
std::unique_ptr<libcamera::CameraConfiguration> config;
|
||||
std::unique_ptr<libcamera::FrameBufferAllocator> frmbuf;
|
||||
std::vector<std::unique_ptr<libcamera::Request>> requests;
|
||||
|
||||
std::queue<libcamera::Request *> req_queue;
|
||||
libcamera::ControlList controls;
|
||||
ctx_imgmap membuf;
|
||||
bool started_cam;
|
||||
bool started_mgr;
|
||||
bool started_aqr;
|
||||
bool started_req;
|
||||
int reconnect_count;
|
||||
void log_orientation();
|
||||
void log_controls();
|
||||
void log_draft();
|
||||
|
||||
int libcam_start();
|
||||
void libcam_stop();
|
||||
|
||||
void start_params();
|
||||
int start_mgr();
|
||||
int start_config();
|
||||
int start_req();
|
||||
int start_capture();
|
||||
void config_orientation();
|
||||
void config_controls();
|
||||
void config_control_item(std::string pname, std::string pvalue);
|
||||
void req_complete(libcamera::Request *request);
|
||||
int req_add(libcamera::Request *request);
|
||||
|
||||
|
||||
};
|
||||
#else
|
||||
#define LIBCAMVER 0
|
||||
class cls_libcam {
|
||||
public:
|
||||
cls_libcam(cls_camera *p_cam);
|
||||
~cls_libcam();
|
||||
int next(ctx_image_data *img_data);
|
||||
void noimage();
|
||||
private:
|
||||
cls_camera *cam;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* _INCLUDE_LIBCAM_HPP_ */
|
||||
+277
-288
@@ -1,328 +1,317 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* logger.c
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Logger for motion
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Copyright 2005, William M. Brack
|
||||
* Copyright 2008 by Angel Carpintero (motiondevelop@gmail.com)
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "logger.hpp" /* already includes motion.h */
|
||||
#include "motion.hpp"
|
||||
#include "util.hpp"
|
||||
#include <stdarg.h>
|
||||
#include "conf.hpp"
|
||||
#include "logger.hpp"
|
||||
|
||||
static int log_mode = LOGMODE_SYSLOG;
|
||||
static FILE *logfile;
|
||||
static unsigned int log_level = LEVEL_DEFAULT;
|
||||
static unsigned int log_type = TYPE_DEFAULT;
|
||||
cls_log *motlog;
|
||||
|
||||
static const char *log_type_str[] = {NULL, "COR", "STR", "ENC", "NET", "DBL", "EVT", "TRK", "VID", "ALL"};
|
||||
static const char *log_level_str[] = {"EMG", "ALR", "CRT", "ERR", "WRN", "NTC", "INF", "DBG", "ALL", NULL};
|
||||
const char *log_type_str[] = {NULL, "COR", "STR", "ENC", "NET", "DBS", "EVT", "TRK", "VID", "ALL"};
|
||||
const char *log_level_str[] = {NULL, "EMG", "ALR", "CRT", "ERR", "WRN", "NTC", "INF", "DBG", "ALL"};
|
||||
|
||||
|
||||
/**
|
||||
* get_log_type
|
||||
*
|
||||
*
|
||||
* Returns: index of log type or 0 if not valid type.
|
||||
*/
|
||||
int get_log_type(const char *type)
|
||||
void ff_log(void *var1, int errnbr, const char *fmt, va_list vlist)
|
||||
{
|
||||
unsigned int i, ret = 0;
|
||||
unsigned int maxtype = sizeof(log_type_str)/sizeof(const char *);
|
||||
(void)var1;
|
||||
char buff[1024];
|
||||
int fflvl;
|
||||
|
||||
for (i = 1;i < maxtype; i++) {
|
||||
if (!strncasecmp(type, log_type_str[i], 3)) {
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
vsnprintf(buff, sizeof(buff), fmt, vlist);
|
||||
|
||||
buff[strlen(buff)-1] = 0;
|
||||
|
||||
if (strstr(buff, "forced frame type") != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
AV_LOG_QUIET -8 1
|
||||
AV_LOG_PANIC 0 2
|
||||
AV_LOG_FATAL 8 3
|
||||
AV_LOG_ERROR 16 4
|
||||
AV_LOG_WARNING 24 5
|
||||
AV_LOG_INFO 32 6
|
||||
AV_LOG_VERBOSE 40 7
|
||||
AV_LOG_DEBUG 48 8
|
||||
AV_LOG_TRACE 56 9
|
||||
*/
|
||||
|
||||
/**
|
||||
* get_log_type_str
|
||||
* Gets string value for type log level.
|
||||
*
|
||||
* Returns: name of type log level.
|
||||
*/
|
||||
const char* get_log_type_str(unsigned int type)
|
||||
{
|
||||
return log_type_str[type];
|
||||
}
|
||||
fflvl = ((motlog->log_fflevel -2) * 8);
|
||||
|
||||
/**
|
||||
* set_log_type
|
||||
* Sets log type level.
|
||||
*
|
||||
* Returns: nothing.
|
||||
*/
|
||||
void set_log_type(unsigned int type)
|
||||
{
|
||||
log_type = type;
|
||||
//printf("set log type %d\n", type);
|
||||
}
|
||||
|
||||
/**
|
||||
* get_log_level_str
|
||||
* Gets string value for log level.
|
||||
*
|
||||
* Returns: name of log level.
|
||||
*/
|
||||
const char* get_log_level_str(unsigned int level)
|
||||
{
|
||||
return log_level_str[level];
|
||||
}
|
||||
|
||||
/**
|
||||
* set_log_level
|
||||
* Sets log level.
|
||||
*
|
||||
* Returns nothing.
|
||||
*/
|
||||
void set_log_level(unsigned int level)
|
||||
{
|
||||
log_level = level;
|
||||
//printf("set log level %d\n", level);
|
||||
}
|
||||
|
||||
/**
|
||||
* set_log_mode
|
||||
* Sets mode of logging, could be using syslog or files.
|
||||
*
|
||||
* Returns: nothing.
|
||||
*/
|
||||
void set_log_mode(int mode)
|
||||
{
|
||||
int prev_mode = log_mode;
|
||||
|
||||
log_mode = mode;
|
||||
//printf("set log mode %d\n", mode);
|
||||
|
||||
if (mode == LOGMODE_SYSLOG && prev_mode != LOGMODE_SYSLOG) {
|
||||
openlog("motion", LOG_PID, LOG_USER);
|
||||
}
|
||||
|
||||
if (mode != LOGMODE_SYSLOG && prev_mode == LOGMODE_SYSLOG) {
|
||||
closelog();
|
||||
if (errnbr <= fflvl ) {
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO,"%s",buff );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set_logfile
|
||||
* Sets logfile to be used instead of syslog.
|
||||
*
|
||||
* Returns: pointer to log file.
|
||||
*/
|
||||
FILE * set_logfile(const char *logfile_name)
|
||||
void cls_log::log_history_init()
|
||||
{
|
||||
/* Setup temporary to let log if myfopen fails */
|
||||
set_log_mode(LOGMODE_SYSLOG);
|
||||
int indx;
|
||||
ctx_log_item log_item;
|
||||
|
||||
logfile = myfopen(logfile_name, "ae");
|
||||
log_item.log_msg= "";
|
||||
for (indx=0;indx<200;indx++){
|
||||
log_item.log_nbr = indx;
|
||||
log_vec.push_back(log_item);
|
||||
}
|
||||
}
|
||||
|
||||
/* If logfile was opened correctly */
|
||||
if (logfile) {
|
||||
set_log_mode(LOGMODE_FILE);
|
||||
void cls_log::log_history_add(std::string msg)
|
||||
{
|
||||
int indx, mx;
|
||||
|
||||
mx = (int)log_vec.size();
|
||||
for (indx=0;indx<mx-1;indx++) {
|
||||
log_vec[indx].log_nbr = log_vec[indx+1].log_nbr;
|
||||
log_vec[indx].log_msg = log_vec[indx+1].log_msg;
|
||||
}
|
||||
|
||||
return logfile;
|
||||
/*Arbritrary large number*/
|
||||
if (log_vec[mx-1].log_nbr >50000000L) {
|
||||
log_history_init();
|
||||
}
|
||||
log_vec[mx-1].log_nbr++;
|
||||
log_vec[mx-1].log_msg = msg;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* str_time
|
||||
*
|
||||
* Return: string with human readable time
|
||||
*/
|
||||
static char *str_time(void)
|
||||
void cls_log::write_flood(int loglvl)
|
||||
{
|
||||
static char buffer[30]; /* Arbitrary length*/
|
||||
time_t now = 0;
|
||||
|
||||
now = time(0);
|
||||
strftime(buffer, sizeof(buffer), "%b %d %H:%M:%S", localtime(&now));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* MOTION_LOG
|
||||
*
|
||||
* This routine is used for printing all informational, debug or error
|
||||
* messages produced by any of the other motion functions. It always
|
||||
* produces a message of the form "[n] {message}", and (if the param
|
||||
* 'errno_flag' is set) follows the message with the associated error
|
||||
* message from the library.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* level logging level for the 'syslog' function
|
||||
*
|
||||
* type logging type.
|
||||
*
|
||||
* errno_flag if set, the log message should be followed by the
|
||||
* error message.
|
||||
* fmt the format string for producing the message
|
||||
* ap variable-length argument list
|
||||
*
|
||||
* Returns:
|
||||
* Nothing
|
||||
*/
|
||||
void motion_log(int level, unsigned int type, int errno_flag,int fncname, const char *fmt, ...)
|
||||
{
|
||||
int errno_save, n;
|
||||
char buf[1024];
|
||||
char usrfmt[1024];
|
||||
|
||||
/* GNU-specific strerror_r() */
|
||||
#if (!defined(XSI_STRERROR_R))
|
||||
char msg_buf[100];
|
||||
#endif
|
||||
va_list ap;
|
||||
int threadnr;
|
||||
|
||||
static int flood_cnt = 0;
|
||||
static char flood_msg[1024];
|
||||
char flood_repeats[1024];
|
||||
|
||||
|
||||
/* Exit if level is greater than log_level */
|
||||
if ((unsigned int)level > log_level) {
|
||||
if (flood_cnt <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Exit if type is not equal to log_type and not TYPE_ALL */
|
||||
if ((log_type != TYPE_ALL) && (type != log_type)) {
|
||||
return;
|
||||
}
|
||||
snprintf(flood_repeats, sizeof(flood_repeats)
|
||||
, "%s Above message repeats %d times\n"
|
||||
, msg_prefix, flood_cnt-1);
|
||||
|
||||
//printf("log_type %d, type %d level %d\n", log_type, type, level);
|
||||
|
||||
threadnr = (unsigned long)pthread_getspecific(tls_key_threadnr);
|
||||
|
||||
/*
|
||||
* First we save the current 'error' value. This is required because
|
||||
* the subsequent calls to vsnprintf could conceivably change it!
|
||||
*/
|
||||
errno_save = errno;
|
||||
|
||||
char threadname[32];
|
||||
util_threadname_get(threadname);
|
||||
|
||||
/*
|
||||
* Prefix the message with the thread number and name,
|
||||
* log level string, log type string, and time.
|
||||
* e.g. [1:enc] [ERR] [ALL] [Apr 03 00:08:44] blah
|
||||
*/
|
||||
if (log_mode == LOGMODE_FILE) {
|
||||
n = snprintf(buf, sizeof(buf), "[%d:%s] [%s] [%s] [%s] ",
|
||||
threadnr, threadname, get_log_level_str(level), get_log_type_str(type),
|
||||
str_time());
|
||||
fputs(flood_repeats, log_file_ptr);
|
||||
fflush(log_file_ptr);
|
||||
|
||||
} else { /* The syslog level values are one less*/
|
||||
syslog(loglvl-1, "%s", flood_repeats);
|
||||
fputs(flood_repeats, stderr);
|
||||
fflush(stderr);
|
||||
}
|
||||
log_history_add(flood_repeats);
|
||||
}
|
||||
|
||||
void cls_log::write_norm(int loglvl, uint prefixlen)
|
||||
{
|
||||
flood_cnt = 1;
|
||||
|
||||
if (snprintf(msg_flood, sizeof(msg_flood), "%s", &msg_full[prefixlen]) < 0) {
|
||||
return;
|
||||
}
|
||||
if (snprintf(msg_prefix, prefixlen, "%s", msg_full) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (log_mode == LOGMODE_FILE) {
|
||||
strcpy(msg_full + strlen(msg_full),"\n");
|
||||
fputs(msg_full, log_file_ptr);
|
||||
fflush(log_file_ptr);
|
||||
} else {
|
||||
/*
|
||||
* Prefix the message with the thread number and name,
|
||||
* log level string and log type string.
|
||||
* e.g. [1:trk] [DBG] [ALL] blah
|
||||
*/
|
||||
n = snprintf(buf, sizeof(buf), "[%d:%s] [%s] [%s] ",
|
||||
threadnr, threadname, get_log_level_str(level), get_log_type_str(type));
|
||||
syslog(loglvl-1, "%s", msg_full);
|
||||
strcpy(msg_full + strlen(msg_full),"\n");
|
||||
fputs(msg_full, stderr);
|
||||
fflush(stderr);
|
||||
}
|
||||
log_history_add(msg_full);
|
||||
}
|
||||
|
||||
void cls_log::add_errmsg(int flgerr, int err_save)
|
||||
{
|
||||
size_t errsz, msgsz;
|
||||
char err_buf[90];
|
||||
|
||||
if (flgerr == NO_ERRNO) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Prepend the format specifier for the function name */
|
||||
if (fncname) {
|
||||
snprintf(usrfmt, sizeof (usrfmt),"%s: %s", "%s", fmt);
|
||||
} else {
|
||||
snprintf(usrfmt, sizeof (usrfmt),"%s",fmt);
|
||||
}
|
||||
|
||||
/* Next add the user's message. */
|
||||
va_start(ap, fmt);
|
||||
n += vsnprintf(buf + n, sizeof(buf) - n, usrfmt, ap);
|
||||
va_end(ap);
|
||||
buf[1023] = '\0';
|
||||
|
||||
/* If errno_flag is set, add on the library error message. */
|
||||
if (errno_flag) {
|
||||
size_t buf_len = strlen(buf);
|
||||
|
||||
// just knock off 10 characters if we're that close...
|
||||
if (buf_len + 10 > 1024) {
|
||||
buf[1024 - 10] = '\0';
|
||||
buf_len = 1024 - 10;
|
||||
}
|
||||
|
||||
strncat(buf, ": ", 1024 - buf_len);
|
||||
n += 2;
|
||||
/*
|
||||
* This is bad - apparently gcc/libc wants to use the non-standard GNU
|
||||
* version of strerror_r, which doesn't actually put the message into
|
||||
* my buffer :-(. I have put in a 'hack' to get around this.
|
||||
*/
|
||||
#if defined(XSI_STRERROR_R)
|
||||
/* XSI-compliant strerror_r() */
|
||||
strerror_r(errno_save, buf + n, sizeof(buf) - n); /* 2 for the ': ' */
|
||||
#else
|
||||
/* GNU-specific strerror_r() */
|
||||
strncat(buf, strerror_r(errno_save, msg_buf, sizeof(msg_buf)), 1024 - strlen(buf));
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((mystreq(buf,flood_msg)) && (flood_cnt <= 5000)) {
|
||||
flood_cnt++;
|
||||
} else {
|
||||
if (flood_cnt > 1) {
|
||||
snprintf(flood_repeats,1024,"[%d:%s] [%s] [%s] Above message repeats %d times",
|
||||
threadnr, threadname, get_log_level_str(level)
|
||||
, get_log_type_str(type), flood_cnt-1);
|
||||
switch (log_mode) {
|
||||
case LOGMODE_FILE:
|
||||
strncat(flood_repeats, "\n", 1024 - strlen(flood_repeats));
|
||||
fputs(flood_repeats, logfile);
|
||||
fflush(logfile);
|
||||
break;
|
||||
|
||||
case LOGMODE_SYSLOG:
|
||||
syslog(level, "%s", flood_repeats);
|
||||
strncat(flood_repeats, "\n", 1024 - strlen(flood_repeats));
|
||||
fputs(flood_repeats, stderr);
|
||||
fflush(stderr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
flood_cnt = 1;
|
||||
snprintf(flood_msg,1024,"%s",buf);
|
||||
switch (log_mode) {
|
||||
case LOGMODE_FILE:
|
||||
strncat(buf, "\n", 1024 - strlen(buf));
|
||||
fputs(buf, logfile);
|
||||
fflush(logfile);
|
||||
break;
|
||||
|
||||
case LOGMODE_SYSLOG:
|
||||
syslog(level, "%s", buf);
|
||||
strncat(buf, "\n", 1024 - strlen(buf));
|
||||
fputs(buf, stderr);
|
||||
fflush(stderr);
|
||||
break;
|
||||
}
|
||||
memset(err_buf, 0, sizeof(err_buf));
|
||||
#if defined(XSI_STRERROR_R) /* XSI-compliant strerror_r() */
|
||||
(void)strerror_r(err_save, err_buf, sizeof(err_buf));
|
||||
#else/* GNU-specific strerror_r() */
|
||||
(void)snprintf(err_buf, sizeof(err_buf),"%s"
|
||||
, strerror_r(err_save, err_buf, sizeof(err_buf)));
|
||||
#endif
|
||||
errsz = strlen(err_buf);
|
||||
msgsz = strlen(msg_full);
|
||||
|
||||
if ((msgsz+errsz+2) >= sizeof(msg_full)) {
|
||||
msgsz = msgsz-errsz-2;
|
||||
memset(msg_full+msgsz, 0, sizeof(msg_full) - msgsz);
|
||||
}
|
||||
strcpy(msg_full+msgsz,": ");
|
||||
memcpy(msg_full+msgsz + 2, err_buf, errsz);
|
||||
|
||||
}
|
||||
|
||||
void cls_log::set_mode(int mode_new)
|
||||
{
|
||||
if ((log_mode != LOGMODE_SYSLOG) && (mode_new == LOGMODE_SYSLOG)) {
|
||||
openlog("motion", LOG_PID, LOG_USER);
|
||||
}
|
||||
if ((log_mode == LOGMODE_SYSLOG) && (mode_new != LOGMODE_SYSLOG)) {
|
||||
closelog();
|
||||
}
|
||||
log_mode = mode_new;
|
||||
}
|
||||
|
||||
void cls_log::set_log_file(std::string pname)
|
||||
{
|
||||
if ((pname == "") || (pname == "syslog")) {
|
||||
if (log_file_ptr != nullptr) {
|
||||
myfclose(log_file_ptr);
|
||||
log_file_ptr = nullptr;
|
||||
}
|
||||
if (log_file_name == "") {
|
||||
set_mode(LOGMODE_SYSLOG);
|
||||
log_file_name = "syslog";
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, "Logging to syslog");
|
||||
}
|
||||
|
||||
} else if ((pname != log_file_name) || (log_file_ptr == nullptr)) {
|
||||
if (log_file_ptr != nullptr) {
|
||||
myfclose(log_file_ptr);
|
||||
log_file_ptr = nullptr;
|
||||
}
|
||||
log_file_ptr = myfopen(pname.c_str(), "ae");
|
||||
if (log_file_ptr != nullptr) {
|
||||
log_file_name = pname;
|
||||
set_mode(LOGMODE_SYSLOG);
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, "Logging to file (%s)"
|
||||
,pname.c_str());
|
||||
set_mode(LOGMODE_FILE);
|
||||
} else {
|
||||
log_file_name = "syslog";
|
||||
set_mode(LOGMODE_SYSLOG);
|
||||
MOTPLS_LOG(EMG, TYPE_ALL, SHOW_ERRNO, "Cannot create log file %s"
|
||||
, pname.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cls_log::write_msg(int loglvl, int msg_type, int flgerr, int flgfnc, ...)
|
||||
{
|
||||
int err_save, n;
|
||||
uint prefixlen;
|
||||
std::string usrfmt;
|
||||
char msg_time[32];
|
||||
char threadname[32];
|
||||
va_list ap;
|
||||
time_t now;
|
||||
|
||||
if (loglvl > log_level) {
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mutex_log);
|
||||
|
||||
err_save = errno;
|
||||
memset(msg_full, 0, sizeof(msg_full));
|
||||
|
||||
mythreadname_get(threadname);
|
||||
|
||||
now = time(NULL);
|
||||
strftime(msg_time, sizeof(msg_time)
|
||||
, "%b %d %H:%M:%S", localtime(&now));
|
||||
|
||||
if (log_mode == LOGMODE_FILE) {
|
||||
n = snprintf(msg_full, sizeof(msg_full)
|
||||
, "%s [%s][%s][%s] ", msg_time
|
||||
, log_level_str[loglvl],log_type_str[msg_type], threadname );
|
||||
} else {
|
||||
n = snprintf(msg_full, sizeof(msg_full)
|
||||
, "[%s][%s][%s] "
|
||||
, log_level_str[loglvl],log_type_str[msg_type], threadname );
|
||||
}
|
||||
prefixlen = (uint)n;
|
||||
|
||||
/* flgfnc must be an int. Bool has compile error*/
|
||||
va_start(ap, flgfnc);
|
||||
usrfmt = va_arg(ap, char *);
|
||||
if (flgfnc == 1) {
|
||||
usrfmt.append(": ").append(va_arg(ap, char *));
|
||||
}
|
||||
n += vsnprintf(msg_full + n
|
||||
, sizeof(msg_full) - (uint)n - 1
|
||||
, usrfmt.c_str(), ap);
|
||||
va_end(ap);
|
||||
|
||||
add_errmsg(flgerr, err_save);
|
||||
|
||||
if ((flood_cnt <= 5000) &&
|
||||
mystreq(msg_flood, &msg_full[prefixlen])) {
|
||||
flood_cnt++;
|
||||
pthread_mutex_unlock(&mutex_log);
|
||||
return;
|
||||
}
|
||||
|
||||
write_flood(loglvl);
|
||||
|
||||
write_norm(loglvl, prefixlen);
|
||||
|
||||
pthread_mutex_unlock(&mutex_log);
|
||||
|
||||
}
|
||||
|
||||
void cls_log::shutdown()
|
||||
{
|
||||
if (log_file_ptr != nullptr) {
|
||||
myfclose(log_file_ptr);
|
||||
log_file_ptr = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void cls_log::startup()
|
||||
{
|
||||
motlog->log_level = app->cfg->log_level;
|
||||
motlog->log_fflevel = app->cfg->log_fflevel;
|
||||
motlog->set_log_file(app->cfg->log_file);
|
||||
}
|
||||
|
||||
cls_log::cls_log(cls_motapp *p_app)
|
||||
{
|
||||
app = p_app;
|
||||
log_mode = LOGMODE_NONE;
|
||||
log_level = LEVEL_DEFAULT;
|
||||
log_fflevel = 4;
|
||||
log_file_ptr = nullptr;
|
||||
log_file_name = "";
|
||||
flood_cnt = 0;
|
||||
restart = false;
|
||||
set_mode(LOGMODE_SYSLOG);
|
||||
pthread_mutex_init(&mutex_log, NULL);
|
||||
memset(msg_prefix,0,sizeof(msg_prefix));
|
||||
memset(msg_flood,0,sizeof(msg_flood));
|
||||
memset(msg_full,0,sizeof(msg_full));
|
||||
log_history_init();
|
||||
av_log_set_callback(ff_log);
|
||||
}
|
||||
|
||||
cls_log::~cls_log()
|
||||
{
|
||||
shutdown();
|
||||
pthread_mutex_destroy(&mutex_log);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+84
-65
@@ -1,76 +1,95 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* logger.h
|
||||
* Headers associated with functions in the logger.c module.
|
||||
* Copyright 2005, William M. Brack
|
||||
* Copyright 2008 by Angel Carpintero (motiondevelop@gmail.com)
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef _INCLUDE_LOGGER_HPP_
|
||||
#define _INCLUDE_LOGGER_HPP_
|
||||
extern cls_log *motlog;
|
||||
|
||||
#ifndef _INCLUDE_LOGGER_H_
|
||||
#define _INCLUDE_LOGGER_H_
|
||||
#define LOGMODE_NONE 0 /* No logging */
|
||||
#define LOGMODE_FILE 1 /* Log messages to file */
|
||||
#define LOGMODE_SYSLOG 2 /* Log messages to syslog */
|
||||
|
||||
#include "motion.hpp"
|
||||
#include <syslog.h>
|
||||
#define NO_ERRNO 0 /* Flag to avoid how message associated to errno */
|
||||
#define SHOW_ERRNO 1 /* Flag to show message associated to errno */
|
||||
|
||||
/* Logging mode */
|
||||
#define LOGMODE_NONE 0 /* No logging */
|
||||
#define LOGMODE_FILE 1 /* Log messages to file */
|
||||
#define LOGMODE_SYSLOG 2 /* Log messages to syslog */
|
||||
#define LOG_ALL 9
|
||||
#define EMG 1
|
||||
#define ALR 2
|
||||
#define CRT 3
|
||||
#define ERR 4
|
||||
#define WRN 5
|
||||
#define NTC 6
|
||||
#define INF 7
|
||||
#define DBG 8
|
||||
#define ALL 9
|
||||
#define LEVEL_DEFAULT NTC
|
||||
|
||||
#define NO_ERRNO 0 /* Flag to avoid how message associated to errno */
|
||||
#define SHOW_ERRNO 1 /* Flag to show message associated to errno */
|
||||
/* Log types */
|
||||
#define TYPE_CORE 1 /* Core logs */
|
||||
#define TYPE_STREAM 2 /* Stream logs */
|
||||
#define TYPE_ENCODER 3 /* Encoder logs */
|
||||
#define TYPE_NETCAM 4 /* Netcam logs */
|
||||
#define TYPE_DB 5 /* Database logs */
|
||||
#define TYPE_EVENTS 6 /* Events logs */
|
||||
#define TYPE_TRACK 7 /* Track logs */
|
||||
#define TYPE_VIDEO 8 /* V4L1/2 Bktr logs */
|
||||
#define TYPE_ALL 9 /* All type logs */
|
||||
#define TYPE_DEFAULT TYPE_ALL /* Default type */
|
||||
#define TYPE_DEFAULT_STR "ALL" /* Default name logs */
|
||||
|
||||
/* Log levels */
|
||||
#define LOG_ALL 9
|
||||
#define EMG LOG_EMERG /* syslog 0 motion 1 */
|
||||
#define ALR LOG_ALERT /* syslog 1 motion 2 */
|
||||
#define CRT LOG_CRIT /* syslog 2 motion 3 */
|
||||
#define ERR LOG_ERR /* syslog 3 motion 4 */
|
||||
#define WRN LOG_WARNING /* syslog 4 motion 5 */
|
||||
#define NTC LOG_NOTICE /* syslog 5 motion 6 */
|
||||
#define INF LOG_INFO /* syslog 6 motion 7 */
|
||||
#define DBG LOG_DEBUG /* syslog 7 motion 8 */
|
||||
#define ALL LOG_ALL /* syslog 8 motion 9 */
|
||||
#define LEVEL_DEFAULT NTC /* syslog 5 motion 6 default */
|
||||
#define SHOW_LEVEL_VALUE(x) (x+1)
|
||||
#define MOTPLS_LOG(x, y, z, ...) motlog->write_msg(x, y, z, 1, __FUNCTION__, __VA_ARGS__)
|
||||
#define MOTPLS_SHT(x, y, z, ...) motlog->write_msg(x, y, z, 0, __VA_ARGS__)
|
||||
|
||||
/* Log types */
|
||||
#define TYPE_CORE 1 /* Core logs */
|
||||
#define TYPE_STREAM 2 /* Stream logs */
|
||||
#define TYPE_ENCODER 3 /* Encoder logs */
|
||||
#define TYPE_NETCAM 4 /* Netcam logs */
|
||||
#define TYPE_DB 5 /* Database logs */
|
||||
#define TYPE_EVENTS 6 /* Events logs */
|
||||
#define TYPE_TRACK 7 /* Track logs */
|
||||
#define TYPE_VIDEO 8 /* V4L1/2 Bktr logs */
|
||||
#define TYPE_ALL 9 /* All type logs */
|
||||
#define TYPE_DEFAULT TYPE_ALL /* Default type */
|
||||
#define TYPE_DEFAULT_STR "ALL" /* Default name logs */
|
||||
struct ctx_log_item {
|
||||
uint64_t log_nbr;
|
||||
std::string log_msg;
|
||||
};
|
||||
|
||||
#define MOTION_LOG(x, y, z, format, args...) motion_log(x, y, z, 1, format, __FUNCTION__, ##args)
|
||||
class cls_log {
|
||||
public:
|
||||
cls_log(cls_motapp *p_app);
|
||||
~cls_log();
|
||||
int log_level;
|
||||
int log_fflevel;
|
||||
void set_log_file(std::string pname);
|
||||
void write_msg(int loglvl, int msg_type, int flgerr, int flgfnc, ...);
|
||||
pthread_mutex_t mutex_log;
|
||||
void shutdown();
|
||||
void startup();
|
||||
bool restart;
|
||||
std::vector<ctx_log_item> log_vec;
|
||||
private:
|
||||
cls_motapp *app;
|
||||
int log_mode;
|
||||
FILE *log_file_ptr;
|
||||
std::string log_file_name;
|
||||
char msg_prefix[512];
|
||||
char msg_flood[1024];
|
||||
char msg_full[1024];
|
||||
int flood_cnt;
|
||||
|
||||
int get_log_type(const char* type);
|
||||
const char* get_log_type_str(unsigned int type);
|
||||
void set_log_type(unsigned int type);
|
||||
const char* get_log_level_str(unsigned int level);
|
||||
void set_log_level(unsigned int level);
|
||||
void set_log_mode(int mode);
|
||||
FILE * set_logfile(const char *logfile_name);
|
||||
void motion_log(int level, unsigned int type, int errno_flag,int fncname, const char *fmt, ...);
|
||||
void set_mode(int mode);
|
||||
void write_flood(int loglvl);
|
||||
void write_norm(int loglvl, uint prefixlen);
|
||||
void add_errmsg(int flgerr, int err_save);
|
||||
void log_history_init();
|
||||
void log_history_add(std::string msg);
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#endif /* _INCLUDE_LOGGER_HPP_ */
|
||||
|
||||
-284
@@ -1,284 +0,0 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* mmx.h
|
||||
* Copyright (C) 1997-2001 H. Dietz and R. Fisher
|
||||
*/
|
||||
|
||||
#ifndef I386MMX_H
|
||||
#define I386MMX_H
|
||||
|
||||
/*
|
||||
* The type of an value that fits in an MMX register (note that long
|
||||
* long constant values MUST be suffixed by LL and unsigned long long
|
||||
* values by ULL, lest they be truncated by the compiler)
|
||||
*/
|
||||
|
||||
typedef union {
|
||||
long long q; /* Quadword (64-bit) value */
|
||||
unsigned long long uq; /* Unsigned Quadword */
|
||||
int d[2]; /* 2 Doubleword (32-bit) values */
|
||||
unsigned int ud[2]; /* 2 Unsigned Doubleword */
|
||||
short w[4]; /* 4 Word (16-bit) values */
|
||||
unsigned short uw[4]; /* 4 Unsigned Word */
|
||||
char b[8]; /* 8 Byte (8-bit) values */
|
||||
unsigned char ub[8]; /* 8 Unsigned Byte */
|
||||
float s[2]; /* Single-precision (32-bit) value */
|
||||
} mmx_t; /* On an 8-byte (64-bit) boundary */
|
||||
|
||||
|
||||
#define mmx_i2r(op,imm,reg) \
|
||||
__asm__ __volatile__ (#op " %0, %%" #reg \
|
||||
: /* nothing */ \
|
||||
: "i" (imm))
|
||||
|
||||
#define mmx_m2r(op,mem,reg) \
|
||||
__asm__ __volatile__ (#op " %0, %%" #reg \
|
||||
: /* nothing */ \
|
||||
: "m" (mem))
|
||||
|
||||
#define mmx_r2m(op,reg,mem) \
|
||||
__asm__ __volatile__ (#op " %%" #reg ", %0" \
|
||||
: "=m" (mem) \
|
||||
: /* nothing */ )
|
||||
|
||||
#define mmx_r2r(op,regs,regd) \
|
||||
__asm__ __volatile__ (#op " %" #regs ", %" #regd)
|
||||
|
||||
|
||||
#define emms() __asm__ __volatile__ ("emms")
|
||||
|
||||
#define movd_m2r(var,reg) mmx_m2r (movd, var, reg)
|
||||
#define movd_r2m(reg,var) mmx_r2m (movd, reg, var)
|
||||
#define movd_r2r(regs,regd) mmx_r2r (movd, regs, regd)
|
||||
|
||||
#define movq_m2r(var,reg) mmx_m2r (movq, var, reg)
|
||||
#define movq_r2m(reg,var) mmx_r2m (movq, reg, var)
|
||||
#define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd)
|
||||
|
||||
#define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg)
|
||||
#define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd)
|
||||
#define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg)
|
||||
#define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd)
|
||||
|
||||
#define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg)
|
||||
#define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd)
|
||||
|
||||
#define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg)
|
||||
#define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd)
|
||||
#define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg)
|
||||
#define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd)
|
||||
#define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg)
|
||||
#define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd)
|
||||
|
||||
#define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg)
|
||||
#define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd)
|
||||
#define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg)
|
||||
#define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd)
|
||||
|
||||
#define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg)
|
||||
#define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd)
|
||||
#define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg)
|
||||
#define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd)
|
||||
|
||||
#define pand_m2r(var,reg) mmx_m2r (pand, var, reg)
|
||||
#define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd)
|
||||
|
||||
#define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg)
|
||||
#define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd)
|
||||
|
||||
#define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg)
|
||||
#define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd)
|
||||
#define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg)
|
||||
#define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd)
|
||||
#define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg)
|
||||
#define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd)
|
||||
|
||||
#define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg)
|
||||
#define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd)
|
||||
#define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg)
|
||||
#define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd)
|
||||
#define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg)
|
||||
#define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd)
|
||||
|
||||
#define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg)
|
||||
#define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd)
|
||||
|
||||
#define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg)
|
||||
#define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd)
|
||||
|
||||
#define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg)
|
||||
#define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd)
|
||||
|
||||
#define por_m2r(var,reg) mmx_m2r (por, var, reg)
|
||||
#define por_r2r(regs,regd) mmx_r2r (por, regs, regd)
|
||||
|
||||
#define pslld_i2r(imm,reg) mmx_i2r (pslld, imm, reg)
|
||||
#define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg)
|
||||
#define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd)
|
||||
#define psllq_i2r(imm,reg) mmx_i2r (psllq, imm, reg)
|
||||
#define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg)
|
||||
#define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd)
|
||||
#define psllw_i2r(imm,reg) mmx_i2r (psllw, imm, reg)
|
||||
#define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg)
|
||||
#define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd)
|
||||
|
||||
#define psrad_i2r(imm,reg) mmx_i2r (psrad, imm, reg)
|
||||
#define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg)
|
||||
#define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd)
|
||||
#define psraw_i2r(imm,reg) mmx_i2r (psraw, imm, reg)
|
||||
#define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg)
|
||||
#define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd)
|
||||
|
||||
#define psrld_i2r(imm,reg) mmx_i2r (psrld, imm, reg)
|
||||
#define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg)
|
||||
#define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd)
|
||||
#define psrlq_i2r(imm,reg) mmx_i2r (psrlq, imm, reg)
|
||||
#define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg)
|
||||
#define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd)
|
||||
#define psrlw_i2r(imm,reg) mmx_i2r (psrlw, imm, reg)
|
||||
#define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg)
|
||||
#define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd)
|
||||
|
||||
#define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg)
|
||||
#define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd)
|
||||
#define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg)
|
||||
#define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd)
|
||||
#define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg)
|
||||
#define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd)
|
||||
|
||||
#define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg)
|
||||
#define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd)
|
||||
#define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg)
|
||||
#define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd)
|
||||
|
||||
#define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg)
|
||||
#define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd)
|
||||
#define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg)
|
||||
#define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd)
|
||||
|
||||
#define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg)
|
||||
#define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd)
|
||||
#define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg)
|
||||
#define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd)
|
||||
#define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg)
|
||||
#define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd)
|
||||
|
||||
#define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg)
|
||||
#define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd)
|
||||
#define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg)
|
||||
#define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd)
|
||||
#define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg)
|
||||
#define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd)
|
||||
|
||||
#define pxor_m2r(var,reg) mmx_m2r (pxor, var, reg)
|
||||
#define pxor_r2r(regs,regd) mmx_r2r (pxor, regs, regd)
|
||||
|
||||
|
||||
/* 3DNOW extensions */
|
||||
|
||||
#define pavgusb_m2r(var,reg) mmx_m2r (pavgusb, var, reg)
|
||||
#define pavgusb_r2r(regs,regd) mmx_r2r (pavgusb, regs, regd)
|
||||
|
||||
|
||||
/* AMD MMX extensions - also available in intel SSE */
|
||||
|
||||
|
||||
#define mmx_m2ri(op,mem,reg,imm) \
|
||||
__asm__ __volatile__ (#op " %1, %0, %%" #reg \
|
||||
: /* nothing */ \
|
||||
: "X" (mem), "X" (imm))
|
||||
#define mmx_r2ri(op,regs,regd,imm) \
|
||||
__asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \
|
||||
: /* nothing */ \
|
||||
: "X" (imm))
|
||||
|
||||
#define mmx_fetch(mem,hint) \
|
||||
__asm__ __volatile__ ("prefetch" #hint " %0" \
|
||||
: /* nothing */ \
|
||||
: "X" (mem))
|
||||
|
||||
|
||||
#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg)
|
||||
|
||||
#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var)
|
||||
|
||||
#define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg)
|
||||
#define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd)
|
||||
#define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg)
|
||||
#define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd)
|
||||
|
||||
#define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm)
|
||||
|
||||
#define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm)
|
||||
|
||||
#define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg)
|
||||
#define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd)
|
||||
|
||||
#define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg)
|
||||
#define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd)
|
||||
|
||||
#define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg)
|
||||
#define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd)
|
||||
|
||||
#define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg)
|
||||
#define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd)
|
||||
|
||||
#define pmovmskb(mmreg,reg) \
|
||||
__asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg)
|
||||
|
||||
#define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg)
|
||||
#define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd)
|
||||
|
||||
#define prefetcht0(mem) mmx_fetch (mem, t0)
|
||||
#define prefetcht1(mem) mmx_fetch (mem, t1)
|
||||
#define prefetcht2(mem) mmx_fetch (mem, t2)
|
||||
#define prefetchnta(mem) mmx_fetch (mem, nta)
|
||||
|
||||
#define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg)
|
||||
#define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd)
|
||||
|
||||
#define pshufw_m2r(var,reg,imm) mmx_m2ri(pshufw, var, reg, imm)
|
||||
#define pshufw_r2r(regs,regd,imm) mmx_r2ri(pshufw, regs, regd, imm)
|
||||
|
||||
#define sfence() __asm__ __volatile__ ("sfence\n\t")
|
||||
|
||||
/* SSE2 */
|
||||
#define pshufhw_m2r(var,reg,imm) mmx_m2ri(pshufhw, var, reg, imm)
|
||||
#define pshufhw_r2r(regs,regd,imm) mmx_r2ri(pshufhw, regs, regd, imm)
|
||||
#define pshuflw_m2r(var,reg,imm) mmx_m2ri(pshuflw, var, reg, imm)
|
||||
#define pshuflw_r2r(regs,regd,imm) mmx_r2ri(pshuflw, regs, regd, imm)
|
||||
|
||||
#define pshufd_r2r(regs,regd,imm) mmx_r2ri(pshufd, regs, regd, imm)
|
||||
|
||||
#define movdqa_m2r(var,reg) mmx_m2r (movdqa, var, reg)
|
||||
#define movdqa_r2m(reg,var) mmx_r2m (movdqa, reg, var)
|
||||
#define movdqa_r2r(regs,regd) mmx_r2r (movdqa, regs, regd)
|
||||
#define movdqu_m2r(var,reg) mmx_m2r (movdqu, var, reg)
|
||||
#define movdqu_r2m(reg,var) mmx_r2m (movdqu, reg, var)
|
||||
#define movdqu_r2r(regs,regd) mmx_r2r (movdqu, regs, regd)
|
||||
|
||||
#define pmullw_r2m(reg,var) mmx_r2m (pmullw, reg, var)
|
||||
|
||||
#define pslldq_i2r(imm,reg) mmx_i2r (pslldq, imm, reg)
|
||||
#define psrldq_i2r(imm,reg) mmx_i2r (psrldq, imm, reg)
|
||||
|
||||
#define punpcklqdq_r2r(regs,regd) mmx_r2r (punpcklqdq, regs, regd)
|
||||
#define punpckhqdq_r2r(regs,regd) mmx_r2r (punpckhqdq, regs, regd)
|
||||
|
||||
|
||||
#endif /* I386MMX_H */
|
||||
+475
-3313
File diff suppressed because it is too large
Load Diff
+166
-502
@@ -1,43 +1,32 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* motion.h
|
||||
* Headers associated with functions in the motion.c module.
|
||||
* Copyright 2000 by Jeroen Vreeken (pe1rxq@amsat.org)
|
||||
*/
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_MOTION_H
|
||||
#define _INCLUDE_MOTION_H
|
||||
|
||||
/* Forward declarations of structs */
|
||||
struct images;
|
||||
struct image_data;
|
||||
struct rtsp_context;
|
||||
struct ffmpeg;
|
||||
#ifndef _INCLUDE_MOTIONPLUS_HPP_
|
||||
#define _INCLUDE_MOTIONPLUS_HPP_
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
/* Includes */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef __USE_GNU
|
||||
#define __USE_GNU
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <syslog.h>
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
@@ -55,504 +44,179 @@ struct ffmpeg;
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
#include <microhttpd.h>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <regex.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <algorithm>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <thread>
|
||||
#include "zlib.h"
|
||||
|
||||
#if defined(HAVE_PTHREAD_NP_H)
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_MYSQL)
|
||||
#include <mysql.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_MARIADB)
|
||||
#include <mysql.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SQLITE3
|
||||
#include <sqlite3.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PGSQL
|
||||
// avoid libpq-fe.h collision with motion.h #define CONNECTION_OK (below)
|
||||
#define CONNECTION_OK PGSQL_CONNECTION_OK
|
||||
#include <libpq-fe.h>
|
||||
// avoid redefinition warning for motion.h #define CONNECTION_OK below
|
||||
#undef CONNECTION_OK
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
|
||||
#define MYFFVER (LIBAVFORMAT_VERSION_MAJOR * 1000)+LIBAVFORMAT_VERSION_MINOR
|
||||
|
||||
#include <errno.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
#include <libavutil/mathematics.h>
|
||||
#include <libavdevice/avdevice.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avio.h>
|
||||
#include <libavutil/avutil.h>
|
||||
#include <libswscale/swscale.h>
|
||||
#if (MYFFVER >= 57083)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
#include <libavutil/mathematics.h>
|
||||
#include <libavdevice/avdevice.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avio.h>
|
||||
#include <libswscale/swscale.h>
|
||||
#include <libavutil/avutil.h>
|
||||
#include "libavutil/buffer.h"
|
||||
#include "libavutil/error.h"
|
||||
#include "libavutil/hwcontext.h"
|
||||
#include "libavutil/mem.h"
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#ifdef HAVE_V4L2
|
||||
#if defined(HAVE_LINUX_VIDEODEV2_H)
|
||||
#include <linux/videodev2.h>
|
||||
#else
|
||||
#include <sys/videoio.h>
|
||||
#endif
|
||||
#else
|
||||
#define MYFFVER 0
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
class cls_motapp;
|
||||
class cls_camera;
|
||||
class cls_allcam;
|
||||
class cls_schedule;
|
||||
class cls_sound;
|
||||
class cls_algsec;
|
||||
class cls_alg;
|
||||
class cls_config;
|
||||
class cls_dbse;
|
||||
class cls_draw;
|
||||
class cls_log;
|
||||
class cls_movie;
|
||||
class cls_netcam;
|
||||
class cls_picture;
|
||||
class cls_rotate;
|
||||
class cls_v4l2cam;
|
||||
class cls_convert;
|
||||
class cls_libcam;
|
||||
class cls_webu;
|
||||
class cls_webu_ans;
|
||||
class cls_webu_file;
|
||||
class cls_webu_html;
|
||||
class cls_webu_json;
|
||||
class cls_webu_mpegts;
|
||||
class cls_webu_post;
|
||||
class cls_webu_common;
|
||||
class cls_webu_stream;
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
/* Due to the pointer magic method of conf, the conf.h and track.h must stay in here */
|
||||
#include "conf.hpp"
|
||||
#include "track.hpp"
|
||||
|
||||
|
||||
/*
|
||||
* The macro below defines a version of sleep using nanosleep
|
||||
* If a signal such as SIG_CHLD interrupts the sleep we just continue sleeping
|
||||
*/
|
||||
#define SLEEP(seconds, nanoseconds) { \
|
||||
struct timespec tv; \
|
||||
tv.tv_sec = (seconds); \
|
||||
tv.tv_nsec = (nanoseconds); \
|
||||
while (nanosleep(&tv, &tv) == -1); \
|
||||
}
|
||||
|
||||
/* Default picture settings */
|
||||
#define DEF_WIDTH 640
|
||||
#define DEF_HEIGHT 480
|
||||
#define DEF_QUALITY 75
|
||||
#define DEF_CHANGES 1500
|
||||
|
||||
#define DEF_MAXFRAMERATE 15
|
||||
#define DEF_NOISELEVEL 32
|
||||
|
||||
/* Minimum time between two 'actions' (email, sms, external) */
|
||||
#define DEF_EVENT_GAP 60 /* 1 minutes */
|
||||
|
||||
#define DEF_VIDEO_DEVICE "/dev/video0"
|
||||
|
||||
#define THRESHOLD_TUNE_LENGTH 256
|
||||
|
||||
#define MISSING_FRAMES_TIMEOUT 30 /* When failing to get picture frame from camera
|
||||
we reuse the previous frame until
|
||||
MISSING_FRAMES_TIMEOUT seconds has passed
|
||||
and then we show a grey image instead
|
||||
*/
|
||||
|
||||
#define CONNECTION_KO "Lost connection"
|
||||
#define CONNECTION_OK "Connection OK"
|
||||
|
||||
#define DEF_MAXSTREAMS 10 /* Maximum number of stream clients per camera */
|
||||
#define DEF_MAXWEBQUEUE 10 /* Maximum number of stream client in queue */
|
||||
|
||||
#define DEF_TIMESTAMP "%Y-%m-%d\\n%T"
|
||||
#define DEF_EVENTSTAMP "%Y%m%d%H%M%S"
|
||||
|
||||
#define DEF_SNAPPATH "%v-%Y%m%d%H%M%S-snapshot"
|
||||
#define DEF_IMAGEPATH "%v-%Y%m%d%H%M%S-%q"
|
||||
#define DEF_MOVIEPATH "%v-%Y%m%d%H%M%S"
|
||||
#define DEF_TIMEPATH "%Y%m%d-timelapse"
|
||||
|
||||
#define DEF_TIMELAPSE_MODE "daily"
|
||||
|
||||
/* OUTPUT Image types */
|
||||
#define IMAGE_TYPE_JPEG 0
|
||||
#define IMAGE_TYPE_PPM 1
|
||||
#define IMAGE_TYPE_WEBP 2
|
||||
#define IMAGE_TYPE_GREY 3
|
||||
|
||||
/* Filetype defines */
|
||||
#define FTYPE_IMAGE 1
|
||||
#define FTYPE_IMAGE_SNAPSHOT 2
|
||||
#define FTYPE_IMAGE_MOTION 4
|
||||
#define FTYPE_MPEG 8
|
||||
#define FTYPE_MPEG_MOTION 16
|
||||
#define FTYPE_MPEG_TIMELAPSE 32
|
||||
|
||||
#define FTYPE_MPEG_ANY (FTYPE_MPEG | FTYPE_MPEG_MOTION | FTYPE_MPEG_TIMELAPSE)
|
||||
#define FTYPE_IMAGE_ANY (FTYPE_IMAGE | FTYPE_IMAGE_SNAPSHOT | FTYPE_IMAGE_MOTION)
|
||||
|
||||
/* What types of images files do we want to have */
|
||||
#define NEWIMG_OFF 0
|
||||
#define NEWIMG_ON 1
|
||||
#define NEWIMG_FIRST 2
|
||||
#define NEWIMG_BEST 4
|
||||
#define NEWIMG_CENTER 8
|
||||
|
||||
#define LOCATE_OFF 0
|
||||
#define LOCATE_ON 1
|
||||
#define LOCATE_PREVIEW 2
|
||||
#define LOCATE_BOX 1
|
||||
#define LOCATE_REDBOX 2
|
||||
#define LOCATE_CROSS 4
|
||||
#define LOCATE_REDCROSS 8
|
||||
|
||||
#define LOCATE_NORMAL 1
|
||||
#define LOCATE_BOTH 2
|
||||
|
||||
#define UPDATE_REF_FRAME 1
|
||||
#define RESET_REF_FRAME 2
|
||||
|
||||
|
||||
/*
|
||||
* Structure to hold images information
|
||||
* The idea is that this should have all information about a picture e.g. diffs, timestamp etc.
|
||||
* The exception is the label information, it uses a lot of memory
|
||||
* When the image is stored all texts motion marks etc. is written to the image
|
||||
* so we only have to send it out when/if we want.
|
||||
*/
|
||||
|
||||
/* A image can have detected motion in it, but dosn't trigger an event, if we use minimum_motion_frames */
|
||||
#define IMAGE_MOTION 1
|
||||
#define IMAGE_TRIGGER 2
|
||||
#define IMAGE_SAVE 4
|
||||
#define IMAGE_SAVED 8
|
||||
#define IMAGE_PRECAP 16
|
||||
#define IMAGE_POSTCAP 32
|
||||
|
||||
enum CAMERA_TYPE {
|
||||
CAMERA_TYPE_UNKNOWN,
|
||||
CAMERA_TYPE_V4L2,
|
||||
CAMERA_TYPE_BKTR,
|
||||
CAMERA_TYPE_RTSP,
|
||||
CAMERA_TYPE_NETCAM
|
||||
enum MOTPLS_SIGNAL {
|
||||
MOTPLS_SIGNAL_NONE,
|
||||
MOTPLS_SIGNAL_ALARM,
|
||||
MOTPLS_SIGNAL_USR1,
|
||||
MOTPLS_SIGNAL_SIGHUP,
|
||||
MOTPLS_SIGNAL_SIGTERM
|
||||
};
|
||||
|
||||
enum WEBUI_LEVEL{
|
||||
WEBUI_LEVEL_ALWAYS = 0,
|
||||
WEBUI_LEVEL_LIMITED = 1,
|
||||
WEBUI_LEVEL_ADVANCED = 2,
|
||||
WEBUI_LEVEL_RESTRICTED = 3,
|
||||
WEBUI_LEVEL_NEVER = 99
|
||||
enum DEVICE_STATUS {
|
||||
STATUS_CLOSED, /* Device is closed */
|
||||
STATUS_INIT, /* First time initialize */
|
||||
STATUS_OPENED /* Successfully started the device */
|
||||
};
|
||||
|
||||
struct params_item_ctx {
|
||||
char *param_name; /* The name or description of the ID as requested by user*/
|
||||
char *param_value; /* The value that the user wants the control set to*/
|
||||
struct ctx_all_loc {
|
||||
int row;
|
||||
int col;
|
||||
int offset_row;
|
||||
int offset_col;
|
||||
int offset_user_row;
|
||||
int offset_user_col;
|
||||
int scale;
|
||||
int xpct_st; /*Starting x location of image on percentage basis*/
|
||||
int xpct_en; /*Ending x location of image on percentage basis*/
|
||||
int ypct_st; /*Starting y location of image on percentage basis*/
|
||||
int ypct_en; /*Ending y location of image on percentage basis*/
|
||||
};
|
||||
|
||||
struct params_context {
|
||||
struct params_item_ctx *params_array; /*Array of the controls the user specified*/
|
||||
int params_count; /*Count of the controls the user specified*/
|
||||
int update_params; /*Bool for whether to update the parameters on the device*/
|
||||
struct ctx_all_sizes {
|
||||
int src_w;
|
||||
int src_h;
|
||||
int src_sz;
|
||||
int dst_w;
|
||||
int dst_h;
|
||||
int dst_sz;
|
||||
bool reset;
|
||||
};
|
||||
|
||||
struct image_data {
|
||||
unsigned char *image_norm;
|
||||
unsigned char *image_high;
|
||||
int diffs;
|
||||
int64_t idnbr_norm;
|
||||
int64_t idnbr_high;
|
||||
struct timeval timestamp_tv;
|
||||
int shot; /* Sub second timestamp count */
|
||||
|
||||
/*
|
||||
* Movement center to img center distance
|
||||
* Note: Dist is calculated distX*distX + distY*distY
|
||||
*/
|
||||
unsigned long cent_dist;
|
||||
|
||||
unsigned int flags; /* Se IMAGE_* defines */
|
||||
|
||||
struct coord location; /* coordinates for center and size of last motion detection*/
|
||||
|
||||
int total_labels;
|
||||
|
||||
struct ctx_stream_data {
|
||||
u_char *jpg_data; /* Image compressed as JPG */
|
||||
int jpg_sz; /* The number of bytes for jpg */
|
||||
int consumed; /* Bool for whether the jpeg data was consumed*/
|
||||
u_char *img_data; /* The base data used for image */
|
||||
int jpg_cnct; /* Counter of the number of jpg connections*/
|
||||
int ts_cnct; /* Counter of the number of mpegts connections */
|
||||
int all_cnct; /* Counter of the number of all camera connections */
|
||||
};
|
||||
|
||||
struct stream_data {
|
||||
unsigned char *jpeg_data; /* Image compressed as JPG */
|
||||
long jpeg_size; /* The number of bytes for jpg */
|
||||
int cnct_count; /* Counter of the number of connections */
|
||||
struct ctx_stream {
|
||||
pthread_mutex_t mutex;
|
||||
ctx_stream_data norm; /* Copy of the image to use for web stream*/
|
||||
ctx_stream_data sub; /* Copy of the image to use for web stream*/
|
||||
ctx_stream_data motion; /* Copy of the image to use for web stream*/
|
||||
ctx_stream_data source; /* Copy of the image to use for web stream*/
|
||||
ctx_stream_data secondary; /* Copy of the image to use for web stream*/
|
||||
};
|
||||
|
||||
/*
|
||||
* DIFFERENCES BETWEEN imgs.width, conf.width AND rotate_data.cap_width
|
||||
* (and the corresponding height values, of course)
|
||||
* ===========================================================================
|
||||
* Location Purpose
|
||||
*
|
||||
* conf The values in conf reflect width and height set in the
|
||||
* configuration file. These can be set via http remote control,
|
||||
* but they are not used internally by Motion, so it won't break
|
||||
* anything. These values are transferred to imgs in vid_start.
|
||||
*
|
||||
* imgs The values in imgs are the actual output dimensions. Normally
|
||||
* the output dimensions are the same as the capture dimensions,
|
||||
* but for 90 or 270 degrees rotation, they are not. E.g., if
|
||||
* you capture at 320x240, and rotate 90 degrees, the output
|
||||
* dimensions are 240x320.
|
||||
* These values are set from the conf values in vid_start, or
|
||||
* from the first JPEG image in netcam_start. For 90 or 270
|
||||
* degrees rotation, they are swapped in rotate_init.
|
||||
*
|
||||
* rotate_data The values in rotate_data are named cap_width and cap_height,
|
||||
* and contain the capture dimensions. The difference between
|
||||
* capture and output dimensions is explained above.
|
||||
* These values are set in rotate_init.
|
||||
*/
|
||||
class cls_motapp {
|
||||
public:
|
||||
cls_motapp();
|
||||
~cls_motapp();
|
||||
|
||||
struct images {
|
||||
struct image_data *image_ring; /* The base address of the image ring buffer */
|
||||
int image_ring_size;
|
||||
int image_ring_in; /* Index in image ring buffer we last added a image into */
|
||||
int image_ring_out; /* Index in image ring buffer we want to process next time */
|
||||
std::vector<cls_camera*> cam_list;
|
||||
std::vector<cls_sound*> snd_list;
|
||||
|
||||
unsigned char *ref; /* The reference frame */
|
||||
struct image_data img_motion; /* Picture buffer for motion images */
|
||||
int *ref_dyn; /* Dynamic objects to be excluded from reference frame */
|
||||
struct image_data image_virgin; /* Last picture frame with no text or locate overlay */
|
||||
struct image_data image_vprvcy; /* Virgin image with the privacy mask applied */
|
||||
struct image_data preview_image; /* Picture buffer for best image when enables */
|
||||
unsigned char *mask; /* Buffer for the mask file */
|
||||
unsigned char *smartmask;
|
||||
unsigned char *smartmask_final;
|
||||
unsigned char *common_buffer;
|
||||
unsigned char *substream_image;
|
||||
bool reload_all;
|
||||
bool cam_add;
|
||||
int cam_delete;
|
||||
int cam_cnt;
|
||||
int snd_cnt;
|
||||
|
||||
unsigned char *mask_privacy; /* Buffer for the privacy mask values */
|
||||
unsigned char *mask_privacy_uv; /* Buffer for the privacy U&V values */
|
||||
int argc;
|
||||
char **argv;
|
||||
std::string user_pause;
|
||||
|
||||
unsigned char *mask_privacy_high; /* Buffer for the privacy mask values */
|
||||
unsigned char *mask_privacy_high_uv; /* Buffer for the privacy U&V values */
|
||||
cls_config *conf_src;
|
||||
cls_config *cfg;
|
||||
cls_webu *webu;
|
||||
cls_dbse *dbse;
|
||||
cls_allcam *allcam;
|
||||
cls_schedule *schedule;
|
||||
|
||||
int *smartmask_buffer;
|
||||
int *labels;
|
||||
int *labelsize;
|
||||
int width;
|
||||
int height;
|
||||
int type;
|
||||
int picture_type; /* Output picture type IMAGE_JPEG, IMAGE_PPM */
|
||||
int size_norm; /* Number of bytes for normal size image */
|
||||
pthread_mutex_t mutex_camlst; /* Lock the list of cams while adding/removing */
|
||||
pthread_mutex_t mutex_post; /* mutex to allow for processing of post actions*/
|
||||
|
||||
int width_high;
|
||||
int height_high;
|
||||
int size_high; /* Number of bytes for high resolution image */
|
||||
void signal_process();
|
||||
bool check_devices();
|
||||
void check_restart();
|
||||
void init(int p_argc, char *p_argv[]);
|
||||
void deinit();
|
||||
void camera_add();
|
||||
void camera_delete();
|
||||
|
||||
int motionsize;
|
||||
int labelgroup_max;
|
||||
int labels_above;
|
||||
int labelsize_max;
|
||||
int largest_label;
|
||||
private:
|
||||
void pid_write();
|
||||
void pid_remove();
|
||||
void daemon();
|
||||
void av_init();
|
||||
void av_deinit();
|
||||
void ntc();
|
||||
void watchdog(uint camindx);
|
||||
};
|
||||
|
||||
enum FLIP_TYPE {
|
||||
FLIP_TYPE_NONE,
|
||||
FLIP_TYPE_HORIZONTAL,
|
||||
FLIP_TYPE_VERTICAL
|
||||
};
|
||||
|
||||
/* Contains data for image rotation, see rotate.c. */
|
||||
struct rotdata {
|
||||
|
||||
unsigned char *buffer_norm; /* Temporary buffer for 90 and 270 degrees rotation of normal resolution image. */
|
||||
unsigned char *buffer_high; /* Temporary buffer for 90 and 270 degrees rotation of high resolution image. */
|
||||
int degrees; /* Degrees to rotate; copied from conf.rotate_deg. */
|
||||
enum FLIP_TYPE axis; /* Rotate image over the Horizontal or Vertical axis. */
|
||||
|
||||
int capture_width_norm; /* Capture width of normal resolution image */
|
||||
int capture_height_norm; /* Capture height of normal resolution image */
|
||||
|
||||
int capture_width_high; /* Capture width of high resolution image */
|
||||
int capture_height_high; /* Capture height of high resolution image */
|
||||
|
||||
};
|
||||
|
||||
struct context {
|
||||
FILE *extpipe;
|
||||
int extpipe_open;
|
||||
char conf_filename[PATH_MAX];
|
||||
int from_conf_dir;
|
||||
int threadnr;
|
||||
unsigned int daemon;
|
||||
char pid_file[PATH_MAX];
|
||||
char log_file[PATH_MAX];
|
||||
char log_type_str[6];
|
||||
int log_level;
|
||||
unsigned int log_type;
|
||||
|
||||
struct config conf;
|
||||
struct images imgs;
|
||||
struct trackoptions track;
|
||||
int track_posx;
|
||||
int track_posy;
|
||||
|
||||
enum CAMERA_TYPE camera_type;
|
||||
struct netcam_context *netcam;
|
||||
struct rtsp_context *rtsp; /* this structure contains the context for normal RTSP connection */
|
||||
struct rtsp_context *rtsp_high; /* this structure contains the context for high resolution RTSP connection */
|
||||
|
||||
struct params_context *vdev; /* Structure for v4l2 and bktr device information */
|
||||
|
||||
struct image_data *current_image; /* Pointer to a structure where the image, diffs etc is stored */
|
||||
unsigned int new_img;
|
||||
|
||||
int locate_motion_mode;
|
||||
int locate_motion_style;
|
||||
int process_thisframe;
|
||||
struct rotdata rotate_data; /* rotation data is thread-specific */
|
||||
|
||||
int noise;
|
||||
int threshold;
|
||||
int threshold_maximum;
|
||||
int diffs_last[THRESHOLD_TUNE_LENGTH];
|
||||
int smartmask_speed;
|
||||
|
||||
/* bktr and v4l2 params used for round robin */
|
||||
int param_input;
|
||||
long param_freq;
|
||||
int param_norm;
|
||||
|
||||
/* Commands to the motion thread */
|
||||
volatile unsigned int snapshot; /* Make a snapshot */
|
||||
volatile unsigned int event_stop; /* Boolean for whether to stop a event */
|
||||
volatile unsigned int event_user; /* Boolean for whether to user triggered an event */
|
||||
volatile unsigned int finish; /* End the thread */
|
||||
volatile unsigned int restart; /* Restart the thread when it ends */
|
||||
/* Is the motion thread running */
|
||||
volatile unsigned int running;
|
||||
/* Is the web control thread running */
|
||||
volatile unsigned int webcontrol_running;
|
||||
volatile unsigned int webcontrol_finish; /* End the thread */
|
||||
volatile int watchdog;
|
||||
|
||||
pthread_t thread_id;
|
||||
|
||||
int event_nr;
|
||||
int prev_event;
|
||||
char eventid[20]; /* Cam ID + Date/Time 99999yyyymmddhhmmss */
|
||||
unsigned int lightswitch_framecounter;
|
||||
char text_event_string[PATH_MAX]; /* The text for conv. spec. %C - */
|
||||
int text_scale;
|
||||
|
||||
int postcap; /* downcounter, frames left to to send post event */
|
||||
int shots;
|
||||
unsigned int detecting_motion;
|
||||
|
||||
struct timeval current_tv;
|
||||
struct timeval last_tv;
|
||||
struct timeval event_tv;
|
||||
struct timeval movie_tv;
|
||||
struct timeval lostconnection_tv; /* timestamp from connection lost */
|
||||
struct timeval lastframe_tv;
|
||||
|
||||
unsigned int lastrate;
|
||||
unsigned int startup_frames;
|
||||
unsigned int moved;
|
||||
unsigned int pause;
|
||||
int missing_frame_counter; /* counts failed attempts to fetch picture frame from camera */
|
||||
unsigned int lost_connection;
|
||||
|
||||
int video_dev;
|
||||
int pipe;
|
||||
int mpipe;
|
||||
|
||||
char hostname[PATH_MAX];
|
||||
|
||||
int sql_mask;
|
||||
|
||||
#ifdef HAVE_SQLITE3
|
||||
sqlite3 *database_sqlite3;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_MYSQL)
|
||||
MYSQL *database_mysql;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_MARIADB)
|
||||
MYSQL *database_mariadb;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PGSQL
|
||||
PGconn *database_pgsql;
|
||||
int eid_db_format; /* db event ID PQfformat() or PQgetlength() if binary */
|
||||
#define dbeid_undetermined -1 /* sql_query_start not present or not yet executed */
|
||||
#define dbeid_no_return -2 /* sql_query_start statement returned nothing */
|
||||
#define dbeid_not_valid -3 /* sql_query_start statement returned invalid value: */
|
||||
/* multiple values or value not a positive integer */
|
||||
#define dbeid_unk_format -4 /* PGgetlength() returned unexpected size for bin fmt */
|
||||
#define dbeid_use_error -5 /* %{dbeventid} used w/ no sql_query_start return val */
|
||||
#define dbeid_recovery -6 /* PGSQL session in recovery after session failure */
|
||||
#define dbeid_rec_fail -7 /* PQresetStart failed; keep trying */
|
||||
/* NB: for values < -1, event ID recording is skipped */
|
||||
/* unless lost session recovery or SIGHUP occur */
|
||||
#endif
|
||||
|
||||
int movie_fps;
|
||||
char newfilename[PATH_MAX];
|
||||
char extpipefilename[PATH_MAX];
|
||||
char extpipecmdline[PATH_MAX];
|
||||
int movie_last_shot;
|
||||
|
||||
struct ffmpeg *ffmpeg_output;
|
||||
struct ffmpeg *ffmpeg_output_motion;
|
||||
struct ffmpeg *ffmpeg_timelapse;
|
||||
int movie_passthrough;
|
||||
|
||||
char timelapsefilename[PATH_MAX];
|
||||
char motionfilename[PATH_MAX];
|
||||
|
||||
int area_minx[9], area_miny[9], area_maxx[9], area_maxy[9];
|
||||
int areadetect_eventnbr;
|
||||
/* ToDo Determine why we need these...just put it all into prepare? */
|
||||
unsigned long long int timenow, timebefore;
|
||||
|
||||
unsigned int rate_limit;
|
||||
int minimum_frame_time_downcounter;
|
||||
unsigned int get_image; /* Flag used to signal that we capture new image when we run the loop */
|
||||
|
||||
long int required_frame_time, frame_delay;
|
||||
|
||||
long int rolling_average_limit;
|
||||
long int *rolling_average_data;
|
||||
unsigned long int rolling_average;
|
||||
|
||||
int olddiffs; //only need this in here for a printf later...do we need that printf?
|
||||
int smartmask_ratio;
|
||||
int smartmask_count;
|
||||
|
||||
int previous_diffs, previous_location_x, previous_location_y;
|
||||
unsigned long int time_last_frame, time_current_frame;
|
||||
|
||||
unsigned int smartmask_lastrate;
|
||||
|
||||
unsigned int passflag; //only purpose is to flag first frame vs all others.....
|
||||
int rolling_frame;
|
||||
|
||||
struct MHD_Daemon *webcontrol_daemon;
|
||||
struct MHD_Daemon *webstream_daemon;
|
||||
char webcontrol_digest_rand[8];
|
||||
char webstream_digest_rand[8];
|
||||
int camera_id;
|
||||
|
||||
pthread_mutex_t mutex_stream;
|
||||
|
||||
struct stream_data stream_norm; /* Copy of the image to use for web stream*/
|
||||
struct stream_data stream_sub; /* Copy of the image to use for web stream*/
|
||||
struct stream_data stream_motion; /* Copy of the image to use for web stream*/
|
||||
struct stream_data stream_source; /* Copy of the image to use for web stream*/
|
||||
|
||||
struct params_context *webcontrol_headers; /* Headers for webcontrol */
|
||||
struct params_context *stream_headers; /* Headers for stream */
|
||||
|
||||
|
||||
};
|
||||
|
||||
extern pthread_mutex_t global_lock;
|
||||
extern volatile int threads_running;
|
||||
extern FILE *ptr_logfile;
|
||||
|
||||
/* TLS keys below */
|
||||
extern pthread_key_t tls_key_threadnr; /* key for thread number */
|
||||
void motion_remove_pid(void);
|
||||
|
||||
#endif /* _INCLUDE_MOTION_H */
|
||||
#endif /* _INCLUDE_MOTIONPLUS_HPP_ */
|
||||
|
||||
+1757
File diff suppressed because it is too large
Load Diff
+125
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_MOVIE_HPP_
|
||||
#define _INCLUDE_MOVIE_HPP_
|
||||
|
||||
enum TIMELAPSE_TYPE {
|
||||
TIMELAPSE_NONE, /* No timelapse, regular processing */
|
||||
TIMELAPSE_APPEND, /* Use append version of timelapse */
|
||||
TIMELAPSE_NEW /* Use create new file version of timelapse */
|
||||
};
|
||||
|
||||
|
||||
class cls_movie {
|
||||
public:
|
||||
cls_movie(cls_camera *p_cam, std::string pmovie_type);
|
||||
~cls_movie();
|
||||
void start();
|
||||
void stop();
|
||||
int put_image(ctx_image_data *img_data, const struct timespec *ts1);
|
||||
void reset_start_time(const struct timespec *ts1);
|
||||
|
||||
struct timespec cb_st_ts; /* The time set before calling the av functions */
|
||||
struct timespec cb_cr_ts; /* Time during the interrupt to determine duration since start*/
|
||||
int cb_dur; /* Seconds permitted before triggering a interrupt */
|
||||
std::string full_nm;
|
||||
std::string file_nm;
|
||||
std::string file_dir;
|
||||
bool is_running;
|
||||
|
||||
private:
|
||||
cls_camera *cam;
|
||||
|
||||
void free_pkt();
|
||||
void free_nal();
|
||||
void encode_nal();
|
||||
int timelapse_exists(const char *fname);
|
||||
int encode_video();
|
||||
int timelapse_append(AVPacket *pkt);
|
||||
void free_context();
|
||||
int get_oformat();
|
||||
int set_pts(const struct timespec *ts1);
|
||||
int set_quality();
|
||||
int set_codec_preferred();
|
||||
int set_codec();
|
||||
int set_stream();
|
||||
int alloc_video_buffer(AVFrame *frame, int align);
|
||||
int set_picture();
|
||||
int set_outputfile();
|
||||
int flush_codec();
|
||||
int put_frame(const struct timespec *ts1);
|
||||
void put_pix_yuv420(ctx_image_data *img_data);
|
||||
int movie_open();
|
||||
void init_container();
|
||||
void init_vars();
|
||||
|
||||
void passthru_reset();
|
||||
int passthru_pktpts();
|
||||
void passthru_write(int indx);
|
||||
void passthru_minpts();
|
||||
int passthru_put(ctx_image_data *img_data);
|
||||
int passthru_streams_video(AVStream *stream_in);
|
||||
int passthru_streams_audio(AVStream *stream_in);
|
||||
int passthru_streams();
|
||||
int passthru_check();
|
||||
int passthru_open();
|
||||
|
||||
void start_norm();
|
||||
void start_motion();
|
||||
void start_timelapse();
|
||||
void start_extpipe();
|
||||
int extpipe_put();
|
||||
void on_movie_start();
|
||||
void on_movie_end();
|
||||
|
||||
AVFormatContext *oc;
|
||||
AVStream *strm_video;
|
||||
AVStream *strm_audio;
|
||||
AVCodecContext *ctx_codec;
|
||||
myAVCodec *codec;
|
||||
AVPacket *pkt;
|
||||
AVFrame *picture; /* contains default image pointers */
|
||||
AVDictionary *opts;
|
||||
cls_netcam *netcam_data;
|
||||
int width;
|
||||
int height;
|
||||
enum TIMELAPSE_TYPE tlapse;
|
||||
int fps;
|
||||
int64_t last_pts;
|
||||
int64_t base_pts;
|
||||
int64_t pass_audio_base;
|
||||
int64_t pass_video_base;
|
||||
bool test_mode;
|
||||
int gop_cnt;
|
||||
struct timespec start_time;
|
||||
bool high_resolution;
|
||||
bool motion_images;
|
||||
bool passthrough;
|
||||
|
||||
char *nal_info;
|
||||
int nal_info_len;
|
||||
FILE *extpipe_stream;
|
||||
std::string container;
|
||||
std::string preferred_codec;
|
||||
std::string movie_type;
|
||||
|
||||
};
|
||||
|
||||
#endif /* #define _INCLUDE_MOVIE_HPP_ */
|
||||
+2320
-813
File diff suppressed because it is too large
Load Diff
+167
-224
@@ -1,268 +1,211 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* netcam.h *
|
||||
* Headers associated with functions in the netcam.c module.
|
||||
* This code was inspired by the original netcam.c module
|
||||
* written by Jeroen Vreeken and enhanced by several Motion
|
||||
* project contributors, particularly Angel Carpintero and
|
||||
* Christopher Price.
|
||||
* Copyright 2005, William M. Brack
|
||||
*/
|
||||
#ifndef _INCLUDE_NETCAM_H
|
||||
#define _INCLUDE_NETCAM_H
|
||||
|
||||
/* This is a workaround regarding these defines. The config.h file defines
|
||||
* HAVE_STDLIB_H as 1 whereas the jpeglib.h just defines it without a value.
|
||||
* this causes massive warnings/error on mis-matched definitions. We do not
|
||||
* control either of these so we have to suffer through this workaround hack
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
#if (HAVE_STDLIB_H == 1)
|
||||
#undef HAVE_STDLIB_H
|
||||
#define HAVE_STDLIB_H_ORIG 1
|
||||
#endif
|
||||
|
||||
#include <jpeglib.h>
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#ifdef HAVE_STDLIB_H_ORIG
|
||||
#undef HAVE_STDLIB_H
|
||||
#undef HAVE_STDLIB_H_ORIG
|
||||
#define HAVE_STDLIB_H 1
|
||||
#else
|
||||
#undef HAVE_STDLIB_H
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#ifndef _INCLUDE_NETCAM_HPP_
|
||||
#define _INCLUDE_NETCAM_HPP_
|
||||
|
||||
typedef struct netcam_context *netcam_context_ptr;
|
||||
#define NETCAM_BUFFSIZE 4096
|
||||
|
||||
#include "netcam_wget.hpp"
|
||||
#include "netcam_jpeg.hpp"
|
||||
enum NETCAM_STATUS {
|
||||
NETCAM_CONNECTED, /* The camera is currently connected */
|
||||
NETCAM_READINGIMAGE, /* Motion is reading a image from camera */
|
||||
NETCAM_NOTCONNECTED, /* The camera has never connected */
|
||||
NETCAM_RECONNECTING /* Motion is trying to reconnect to camera */
|
||||
};
|
||||
|
||||
#define NETCAM_BUFFSIZE 4096 /* Initial size reserved for a JPEG
|
||||
image. If expansion is required,
|
||||
this value is also used for the
|
||||
amount to increase. */
|
||||
struct ctx_imgsize {
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
/*
|
||||
* Error return codes for netcam routines. The values are "bit
|
||||
* significant". All error returns will return bit 1 set to indicate
|
||||
* these are "netcam errors"; additional bits set will give more detail
|
||||
* as to what kind of error it was.
|
||||
* Bit 0 is reserved for V4L type errors.
|
||||
*
|
||||
*/
|
||||
#define NETCAM_GENERAL_ERROR 0x02 /* binary 000010 */
|
||||
#define NETCAM_NOTHING_NEW_ERROR 0x06 /* binary 000110 */
|
||||
#define NETCAM_JPEG_CONV_ERROR 0x0a /* binary 001010 */
|
||||
#define NETCAM_RESTART_ERROR 0x12 /* binary 010010 */
|
||||
#define NETCAM_FATAL_ERROR -2
|
||||
|
||||
#define NCS_UNSUPPORTED 0 /* streaming is not supported */
|
||||
#define NCS_MULTIPART 1 /* streaming is done via multipart */
|
||||
#define NCS_BLOCK 2 /* streaming is done via MJPG-block */
|
||||
|
||||
/*
|
||||
* struct url_t is used when parsing the user-supplied URL, as well as
|
||||
* when attempting to connect to the netcam.
|
||||
*/
|
||||
struct url_t {
|
||||
char *service;
|
||||
char *userpass;
|
||||
char *host;
|
||||
struct ctx_url {
|
||||
std::string service;
|
||||
std::string userpass;
|
||||
std::string host;
|
||||
int port;
|
||||
char *path;
|
||||
std::string path;
|
||||
};
|
||||
|
||||
/*
|
||||
* We use a special "triple-buffer" technique. There are
|
||||
* three separate buffers (latest, receiving and jpegbuf)
|
||||
* which are each described using a struct netcam_image_buff
|
||||
*/
|
||||
* We use a special "triple-buffer" technique. There are
|
||||
* three separate buffers (latest, receiving and jpegbuf)
|
||||
* which are each described using a struct netcam_image_buff
|
||||
*/
|
||||
typedef struct netcam_image_buff {
|
||||
char *ptr;
|
||||
int content_length;
|
||||
size_t size; /* total allocated size */
|
||||
size_t used; /* bytes already used */
|
||||
struct timeval image_time; /* time this image was received */
|
||||
struct timespec image_time; /* time this image was received */
|
||||
} netcam_buff;
|
||||
typedef netcam_buff *netcam_buff_ptr;
|
||||
|
||||
extern struct netcam_caps { /* netcam capabilities: */
|
||||
unsigned char streaming; /* See the NCS_* defines */
|
||||
unsigned char content_length; /* 0 - unsupported */
|
||||
} caps;
|
||||
struct ctx_packet_item{
|
||||
AVPacket *packet;
|
||||
int64_t idnbr;
|
||||
bool iskey;
|
||||
bool iswritten;
|
||||
};
|
||||
|
||||
struct ctx_filelist_item {
|
||||
std::string fullnm;
|
||||
std::string filenm;
|
||||
std::string displaynm;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct netcam_context contains all the structures and other data
|
||||
* for an individual netcam.
|
||||
*/
|
||||
typedef struct netcam_context {
|
||||
struct context *cnt; /* pointer to parent motion context structure */
|
||||
struct params_context *parameters; /* User specified parameters for the camera */
|
||||
int haveproxy; /* bool for whether there is a proxy */
|
||||
int finish; /* flag to break the camera-
|
||||
handling thread out of it's
|
||||
infinite loop in emergency */
|
||||
class cls_netcam {
|
||||
public:
|
||||
cls_netcam(cls_camera *p_cam, bool p_is_high);
|
||||
~cls_netcam();
|
||||
|
||||
int threadnr; /* motion's thread number for
|
||||
the camera-handling thread
|
||||
(if required). Used for
|
||||
error reporting */
|
||||
cls_camera *cam;
|
||||
bool interrupted; /* Boolean for whether interrupt has been tripped */
|
||||
enum NETCAM_STATUS status; /* Status of whether the camera is connecting, closed, etc*/
|
||||
struct timespec ist_tm; /* The time set before calling the av functions */
|
||||
struct timespec icur_tm; /* Time during the interrupt to determine duration since start*/
|
||||
int idur; /* Seconds permitted before triggering a interrupt */
|
||||
std::string camera_name; /* The name of the camera as provided in the config file */
|
||||
std::string cameratype; /* String specifying Normal or High for use in logging */
|
||||
|
||||
pthread_t thread_id; /* thread i.d. for a camera-handling thread (if required). */
|
||||
pthread_mutex_t mutex; /* mutex used with conditional waits */
|
||||
pthread_mutex_t mutex_transfer; /* mutex used with transferring stream info for pass-through */
|
||||
pthread_mutex_t mutex_pktarray; /* mutex used with the packet array */
|
||||
|
||||
pthread_mutex_t mutex; /* mutex used with conditional waits */
|
||||
AVFormatContext *transfer_format; /* Format context just for transferring to pass-through */
|
||||
ctx_packet_item *pktarray; /* Pointer to array of packets for passthru processing */
|
||||
int pktarray_size; /* The number of packets in array. 1 based */
|
||||
int video_stream_index; /* Stream index associated with video from camera */
|
||||
int audio_stream_index; /* Stream index associated with audio from camera */
|
||||
|
||||
pthread_cond_t exiting; /* signal for exiting thread */
|
||||
bool handler_stop;
|
||||
bool handler_running;
|
||||
pthread_t handler_thread;
|
||||
void handler();
|
||||
|
||||
pthread_cond_t cap_cond; /* pthread condition structure to
|
||||
initiate next capture request (used
|
||||
only with non-streaming cameras */
|
||||
int next(ctx_image_data *img_data);
|
||||
void noimage();
|
||||
void netcam_start();
|
||||
void netcam_stop();
|
||||
|
||||
pthread_cond_t pic_ready; /* pthread condition structure used
|
||||
for synchronisation between the
|
||||
camera handler and the motion main
|
||||
loop, showing new frame is ready */
|
||||
private:
|
||||
AVFormatContext *format_context; /* Main format context for the camera */
|
||||
AVCodecContext *codec_context; /* Codec being sent from the camera */
|
||||
AVStream *strm;
|
||||
AVFrame *frame; /* Reusable frame for images from camera */
|
||||
AVFrame *swsframe_in; /* Used when resizing image sent from camera */
|
||||
AVFrame *swsframe_out; /* Used when resizing image sent from camera */
|
||||
struct SwsContext *swsctx; /* Context for the resizing of the image */
|
||||
AVPacket *packet_recv; /* The packet that is currently being processed */
|
||||
|
||||
int start_capture; /* besides our signalling condition,
|
||||
we also keep a flag to assure the
|
||||
camera-handler will always start
|
||||
a new cycle as soon as possible,
|
||||
even if it's not currently waiting
|
||||
on the condition. */
|
||||
int pktarray_index; /* The index to the most current packet in array */
|
||||
int64_t idnbr; /* A ID number to track the packet vs image */
|
||||
AVDictionary *opts; /* AVOptions when opening the format context */
|
||||
int swsframe_size; /* The size of the image after resizing */
|
||||
|
||||
char *connect_host; /* the host to connect to (may be
|
||||
either the camera host, or
|
||||
possibly a proxy) */
|
||||
enum AVHWDeviceType hw_type;
|
||||
enum AVPixelFormat hw_pix_fmt;
|
||||
AVBufferRef *hw_device_ctx;
|
||||
myAVCodec *decoder;
|
||||
|
||||
int connect_port; /* usually will be 80, but can be
|
||||
specified as something else by
|
||||
the user */
|
||||
netcam_buff_ptr img_recv; /* The image buffer that is currently being processed */
|
||||
netcam_buff_ptr img_latest; /* The most recent image buffer that finished processing */
|
||||
|
||||
int connect_http_10; /* set to TRUE if HTTP 1.0 connection
|
||||
(netcam_keepalive off) */
|
||||
bool high_resolution; /* Boolean for whether this context is the Norm or High */
|
||||
|
||||
int connect_http_11; /* set to TRUE if HTTP 1.1 connection
|
||||
(netcam_keepalive on) */
|
||||
bool first_image; /* Boolean for whether we have captured the first image */
|
||||
bool passthrough; /* Boolean for whether we are doing pass-through processing */
|
||||
|
||||
int connect_keepalive; /* set to TRUE if connection maintained after
|
||||
a request, otherwise FALSE to close down
|
||||
the socket each time (netcam_keealive force) */
|
||||
std::string path; /* The connection string to use for the camera */
|
||||
std::string service; /* String specifying the type of camera http, rtsp, v4l2 */
|
||||
ctx_imgsize imgsize; /* The image size parameters */
|
||||
|
||||
int keepalive_thisconn; /* set to TRUE if cam has sent 'Keep-Alive' in this connection */
|
||||
int capture_rate; /* Frames per second from configuration file */
|
||||
int reconnect_count; /* Count of the times reconnection is tried*/
|
||||
int src_fps; /* The fps provided from source*/
|
||||
std::string decoder_nm; /* User requested decoder */
|
||||
|
||||
int keepalive_timeup; /* set to TRUE if it is time to close netcam's socket,
|
||||
and then re-open it with Keep-Alive set again.
|
||||
Even Keep-Alive netcams need a close/open sometimes. */
|
||||
struct timespec connection_tm; /* Time when camera was connected*/
|
||||
int64_t connection_pts; /* PTS from the connection */
|
||||
int64_t last_pts; /* PTS from the last packet read */
|
||||
int last_stream_index; /* Stream index for last packet */
|
||||
bool pts_adj; /* Bool for whether to use pts for timing */
|
||||
|
||||
char *connect_request; /* contains the complete string
|
||||
required for connection to the
|
||||
camera */
|
||||
struct timespec frame_prev_tm; /* The time set before calling the av functions */
|
||||
struct timespec frame_curr_tm; /* Time during the interrupt to determine duration since start*/
|
||||
|
||||
int sock; /* fd for the camera's socket.
|
||||
Note that this value is also
|
||||
present within the struct
|
||||
rbuf *response. */
|
||||
ctx_params *params; /* parameters for the camera */
|
||||
|
||||
struct timeval timeout; /* The current timeout setting for
|
||||
the socket. */
|
||||
std::string threadname; /* The thread name*/
|
||||
int threadnbr; /* The thread number */
|
||||
int cfg_width;
|
||||
int cfg_height;
|
||||
int cfg_framerate;
|
||||
int cfg_idur;
|
||||
std::string cfg_params;
|
||||
|
||||
struct rbuf *response; /* this structure (defined in the
|
||||
netcam_wget module) contains
|
||||
the context for an HTTP
|
||||
connection. Note that this
|
||||
structure includes a large
|
||||
buffer for the HTTP data */
|
||||
std::vector<ctx_filelist_item> filelist;
|
||||
std::string filedir;
|
||||
int filenbr;
|
||||
|
||||
struct ftp_context *ftp; /* this structure contains the context for FTP connection */
|
||||
struct file_context *file; /* this structure contains the context for FILE connection */
|
||||
void filelist_load();
|
||||
void check_buffsize(netcam_buff_ptr buff, size_t numbytes);
|
||||
char *url_match(regmatch_t m, const char *input);
|
||||
void url_invalid(ctx_url *parse_url);
|
||||
void url_parse(ctx_url *parse_url, std::string text_url);
|
||||
void free_pkt();
|
||||
int check_pixfmt();
|
||||
void pktarray_free();
|
||||
void context_null();
|
||||
void context_close();
|
||||
void pktarray_resize();
|
||||
void pktarray_add();
|
||||
int decode_sw();
|
||||
int decode_vaapi();
|
||||
int decode_cuda();
|
||||
int decode_drm();
|
||||
int decode_video();
|
||||
int decode_packet();
|
||||
void hwdecoders();
|
||||
void decoder_error(int retcd, const char* fnc_nm);
|
||||
int init_vaapi();
|
||||
int init_cuda();
|
||||
int init_drm();
|
||||
int init_swdecoder();
|
||||
int open_codec();
|
||||
int open_sws();
|
||||
int resize();
|
||||
void pkt_ts();
|
||||
int read_image();
|
||||
int ntc();
|
||||
void set_options();
|
||||
void set_path ();
|
||||
void set_parms ();
|
||||
int copy_stream();
|
||||
int open_context();
|
||||
int connect();
|
||||
|
||||
int (*get_image)(netcam_context_ptr);
|
||||
/* Function to fetch the image from
|
||||
the netcam. It is initialised in
|
||||
netcam_setup depending upon whether
|
||||
the picture source is from an http
|
||||
server or from an ftp server */
|
||||
void handler_wait();
|
||||
void handler_reconnect();
|
||||
void handler_startup();
|
||||
void handler_shutdown();
|
||||
|
||||
};
|
||||
|
||||
struct netcam_caps caps; /* Type of camera */
|
||||
char *boundary; /* 'boundary' string when used to separate mjpeg images */
|
||||
size_t boundary_length; /* string length of the boundary string */
|
||||
|
||||
netcam_buff_ptr latest; /* This buffer contains the latest frame received from the camera */
|
||||
netcam_buff_ptr receiving; /* This buffer is used for receiving data from the camera */
|
||||
netcam_buff_ptr jpegbuf; /* This buffer is used for jpeg decompression */
|
||||
|
||||
int imgcnt; /* count for # of received jpegs */
|
||||
int imgcnt_last; /* remember last count to check if a new image arrived */
|
||||
int warning_count; /* simple count of number of warnings since last good frame was received */
|
||||
int error_count; /* simple count of number of errors since last good frame was received */
|
||||
|
||||
unsigned int width; /* info for decompression */
|
||||
unsigned int height;
|
||||
|
||||
int JFIF_marker; /* Debug to know if JFIF was present or not */
|
||||
unsigned int netcam_tolerant_check; /* For network cameras with buggy firmwares */
|
||||
|
||||
struct timeval last_image; /* time the most recent image was received */
|
||||
float av_frame_time; /* "running average" of time between successive frames (microseconds) */
|
||||
|
||||
struct jpeg_error_mgr jerr;
|
||||
jmp_buf setjmp_buffer;
|
||||
|
||||
int jpeg_error; /* flag to show error or warning occurred during decompression*/
|
||||
|
||||
int handler_finished;
|
||||
|
||||
} netcam_context;
|
||||
|
||||
|
||||
int netcam_start(struct context *cnt);
|
||||
int netcam_next(struct context *cnt, struct image_data *img_data);
|
||||
void netcam_cleanup(netcam_context_ptr netcam, int init_retry_flag);
|
||||
void netcam_url_parse(struct url_t *parse_url, const char *text_url);
|
||||
void netcam_url_free(struct url_t *parse_url);
|
||||
ssize_t netcam_recv(netcam_context_ptr netcam, void *buffptr, size_t buffsize);
|
||||
|
||||
/**
|
||||
* Publish new image
|
||||
*
|
||||
* Moves the image in 'receiving' into 'latest' and updates last frame time
|
||||
*/
|
||||
void netcam_image_read_complete(netcam_context_ptr netcam);
|
||||
|
||||
/**
|
||||
* This routine checks whether there is enough room in a buffer to copy
|
||||
* some additional data. If there is not enough room, it will re-allocate
|
||||
* the buffer and adjust it's size.
|
||||
*
|
||||
* Parameters:
|
||||
* buff Pointer to a netcam_image_buffer structure.
|
||||
* numbytes The number of bytes to be copied.
|
||||
*
|
||||
* Returns: Nothing
|
||||
*/
|
||||
void netcam_check_buffsize(netcam_buff_ptr buff, size_t numbytes);
|
||||
|
||||
#endif
|
||||
#endif /* _INCLUDE_NETCAM_HPP_ */
|
||||
|
||||
-1056
File diff suppressed because it is too large
Load Diff
@@ -1,55 +0,0 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* netcam_ftp.h
|
||||
* Headers associated with functions in the netcam_ftp.c module.
|
||||
* Much of the FTP routines was inspired by the nanoftp.c module from
|
||||
* libxml2 (Copyright Daniel Veillard, 2003). The routines have been
|
||||
* modified to fit the needs of the Motion project.
|
||||
* Copyright 2005, William M. Brack
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_NETCAM_FTP_H
|
||||
#define _INCLUDE_NETCAM_FTP_H
|
||||
|
||||
#define FTP_BUF_SIZE 1024
|
||||
|
||||
typedef struct ftp_context {
|
||||
char *path; /* the path within the URL */
|
||||
char *user; /* user string */
|
||||
char *passwd; /* passwd string */
|
||||
struct sockaddr_in ftp_address; /* the socket addr structure */
|
||||
int passive; /* flag show passive/active mode used */
|
||||
int control_file_desc; /* file descriptor for the control socket */
|
||||
int data_file_desc; /* file descriptor for the data socket */
|
||||
int state; /* WRITE / READ / CLOSED */
|
||||
int returnValue; /* the protocol return value */
|
||||
|
||||
/* buffer for data received from the control connection */
|
||||
char control_buffer[FTP_BUF_SIZE + 1];
|
||||
int control_buffer_index;
|
||||
int control_buffer_used;
|
||||
int control_buffer_answer;
|
||||
} ftp_context, *ftp_context_pointer;
|
||||
|
||||
|
||||
/* The public interface */
|
||||
int ftp_close(ftp_context_pointer ctxt);
|
||||
int ftp_connect(netcam_context_ptr netcam);
|
||||
int netcam_setup_ftp(netcam_context_ptr netcam, struct url_t *url);
|
||||
|
||||
#endif
|
||||
-1858
File diff suppressed because it is too large
Load Diff
@@ -1,68 +0,0 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* netcam_http.h
|
||||
* Headers associated with functions in the netcam_http.c module.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_NETCAM_HTTP_H
|
||||
#define _INCLUDE_NETCAM_HTTP_H
|
||||
|
||||
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#define MJPG_MH_MAGIC "MJPG"
|
||||
#define MJPG_MH_MAGIC_SIZE 4
|
||||
|
||||
typedef struct file_context {
|
||||
char *path; /* the path within the URL */
|
||||
int control_file_desc; /* file descriptor for the control socket */
|
||||
time_t last_st_mtime; /* time this image was modified */
|
||||
} tfile_context;
|
||||
|
||||
|
||||
/*
|
||||
* MJPG Chunk header for MJPG streaming.
|
||||
* Little-endian data is read from the network.
|
||||
*/
|
||||
typedef struct {
|
||||
char mh_magic[MJPG_MH_MAGIC_SIZE]; /* must contain the string MJP
|
||||
not null-terminated. */
|
||||
unsigned int mh_framesize; /* Total size of the current
|
||||
frame in bytes (~45kb on WVC200) */
|
||||
unsigned short mh_framewidth; /* Frame width in pixels */
|
||||
unsigned short mh_frameheight; /* Frame height in pixels */
|
||||
unsigned int mh_frameoffset; /* Offset of this chunk relative
|
||||
to the beginning of frame. */
|
||||
unsigned short mh_chunksize; /* The size of the chunk data
|
||||
following this header. */
|
||||
char mh_reserved[30]; /* Unknown data, seems to be
|
||||
constant between all headers */
|
||||
} mjpg_header;
|
||||
|
||||
|
||||
void netcam_disconnect(netcam_context_ptr netcam);
|
||||
int netcam_connect(netcam_context_ptr netcam, int err_flag);
|
||||
int netcam_read_first_header(netcam_context_ptr netcam);
|
||||
int netcam_setup_html(netcam_context_ptr netcam, struct url_t *url);
|
||||
int netcam_setup_mjpg(netcam_context_ptr netcam, struct url_t *url);
|
||||
int netcam_setup_file(netcam_context_ptr netcam, struct url_t *url);
|
||||
int netcam_read_next_header(netcam_context_ptr netcam);
|
||||
|
||||
#endif // _INCLUDE_NETCAM_HTTP_H
|
||||
@@ -1,591 +0,0 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* netcam_jpeg.c
|
||||
*
|
||||
* Module for handling JPEG decompression for network cameras.
|
||||
*
|
||||
* This code was inspired by the original module written by
|
||||
* Jeroen Vreeken and enhanced by several Motion project
|
||||
* contributors, particularly Angel Carpintero and
|
||||
* Christopher Price.
|
||||
*
|
||||
* Copyright 2005, William M. Brack
|
||||
*/
|
||||
#include "motion.hpp"
|
||||
#include "translate.hpp"
|
||||
#include "util.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "rotate.hpp"
|
||||
#include "netcam.hpp"
|
||||
#include "netcam_jpeg.hpp"
|
||||
|
||||
/* This is a workaround regarding these defines. The config.h file defines
|
||||
* HAVE_STDLIB_H as 1 whereas the jpeglib.h just defines it without a value.
|
||||
* this causes massive warnings/error on mis-matched definitions. We do not
|
||||
* control either of these so we have to suffer through this workaround hack
|
||||
*/
|
||||
#if (HAVE_STDLIB_H == 1)
|
||||
#undef HAVE_STDLIB_H
|
||||
#define HAVE_STDLIB_H_ORIG 1
|
||||
#endif
|
||||
|
||||
#include <jpeglib.h>
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#ifdef HAVE_STDLIB_H_ORIG
|
||||
#undef HAVE_STDLIB_H
|
||||
#undef HAVE_STDLIB_H_ORIG
|
||||
#define HAVE_STDLIB_H 1
|
||||
#else
|
||||
#undef HAVE_STDLIB_H
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#include <jerror.h>
|
||||
|
||||
/*
|
||||
* netcam_source_mgr is a locally-defined structure to contain elements
|
||||
* which are not present in the standard libjpeg (the element 'pub' is a
|
||||
* pointer to the standard information).
|
||||
*/
|
||||
typedef struct {
|
||||
struct jpeg_source_mgr pub;
|
||||
char *data;
|
||||
int length;
|
||||
JOCTET *buffer;
|
||||
boolean start_of_file;
|
||||
} netcam_source_mgr;
|
||||
|
||||
typedef netcam_source_mgr *netcam_src_ptr;
|
||||
|
||||
|
||||
/*
|
||||
* Here we declare function prototypes for all the routines involved with
|
||||
* overriding libjpeg functions. The reason these are required is that,
|
||||
* although the standard library handles input and output with stdio,
|
||||
* we are working with "remote" data (from the camera or from a file).
|
||||
*/
|
||||
static void netcam_init_source(j_decompress_ptr);
|
||||
static boolean netcam_fill_input_buffer(j_decompress_ptr);
|
||||
static void netcam_skip_input_data(j_decompress_ptr, long);
|
||||
static void netcam_term_source(j_decompress_ptr);
|
||||
static void netcam_memory_src(j_decompress_ptr, char *, int);
|
||||
static void netcam_error_exit(j_common_ptr);
|
||||
|
||||
static void netcam_init_source(j_decompress_ptr cinfo)
|
||||
{
|
||||
/* Get our "private" structure from the libjpeg structure. */
|
||||
netcam_src_ptr src = (netcam_src_ptr) cinfo->src;
|
||||
/*
|
||||
* Set the 'start_of_file' flag in our private structure
|
||||
* (used by my_fill_input_buffer).
|
||||
*/
|
||||
src->start_of_file = TRUE;
|
||||
}
|
||||
|
||||
static boolean netcam_fill_input_buffer(j_decompress_ptr cinfo)
|
||||
{
|
||||
netcam_src_ptr src = (netcam_src_ptr) cinfo->src;
|
||||
size_t nbytes;
|
||||
|
||||
/*
|
||||
* start_of_file is set any time netcam_init_source has been called
|
||||
* since the last entry to this routine. This would be the normal
|
||||
* path when a new image is to be processed. It is assumed that
|
||||
* this routine will only be called once for the entire image.
|
||||
* If an unexpected call (with start_of_file FALSE) occurs, the
|
||||
* routine calls ERREXIT().
|
||||
*/
|
||||
if (src->start_of_file) {
|
||||
nbytes = src->length;
|
||||
src->buffer = (JOCTET *) src->data;
|
||||
} else {
|
||||
nbytes = 2;
|
||||
MOTION_LOG(DBG, TYPE_NETCAM, NO_ERRNO,_("Not enough data from netcam."));
|
||||
ERREXIT(cinfo, JERR_INPUT_EOF);
|
||||
}
|
||||
|
||||
src->pub.next_input_byte = src->buffer;
|
||||
src->pub.bytes_in_buffer = nbytes;
|
||||
src->start_of_file = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void netcam_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
|
||||
{
|
||||
netcam_src_ptr src = (netcam_src_ptr) cinfo->src;
|
||||
|
||||
if (num_bytes > 0) {
|
||||
while (num_bytes > (long) src->pub.bytes_in_buffer) {
|
||||
num_bytes -= (long) src->pub.bytes_in_buffer;
|
||||
(void) netcam_fill_input_buffer (cinfo);
|
||||
}
|
||||
src->pub.next_input_byte += (size_t) num_bytes;
|
||||
src->pub.bytes_in_buffer -= (size_t) num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
static void netcam_term_source(j_decompress_ptr cinfo)
|
||||
{
|
||||
(void)cinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* netcam_memory_src
|
||||
*
|
||||
* Routine to setup for fetching data from a netcam buffer, used by the
|
||||
* JPEG library decompression routine.
|
||||
*
|
||||
* Parameters:
|
||||
* cinfo pointer to the jpeg decompression object.
|
||||
* data pointer to the image data received from a netcam.
|
||||
* length total size of the image.
|
||||
*
|
||||
* Returns: Nothing
|
||||
*
|
||||
*/
|
||||
static void netcam_memory_src(j_decompress_ptr cinfo, char *data, int length)
|
||||
{
|
||||
netcam_src_ptr src;
|
||||
|
||||
if (cinfo->src == NULL) {
|
||||
cinfo->src = (struct jpeg_source_mgr *)
|
||||
(*cinfo->mem->alloc_small)
|
||||
((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
sizeof (netcam_source_mgr));
|
||||
}
|
||||
|
||||
|
||||
src = (netcam_src_ptr)cinfo->src;
|
||||
src->data = data;
|
||||
src->length = length;
|
||||
src->pub.init_source = netcam_init_source;
|
||||
src->pub.fill_input_buffer = netcam_fill_input_buffer;
|
||||
src->pub.skip_input_data = netcam_skip_input_data;
|
||||
src->pub.resync_to_restart = jpeg_resync_to_restart;
|
||||
src->pub.term_source = netcam_term_source;
|
||||
src->pub.bytes_in_buffer = 0;
|
||||
src->pub.next_input_byte = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* netcam_error_exit
|
||||
*
|
||||
* Routine to override the libjpeg error exit routine so
|
||||
* that we can just throw away the bad frame and continue
|
||||
* with more data from the netcam.
|
||||
*
|
||||
* Parameters
|
||||
*
|
||||
* cinfo pointer to the decompression control structure.
|
||||
*
|
||||
* Returns: does an (ugly) longjmp to get back to netcam_jpeg
|
||||
* code.
|
||||
*
|
||||
*/
|
||||
static void netcam_error_exit(j_common_ptr cinfo)
|
||||
{
|
||||
/* Fetch our pre-stored pointer to the netcam context. */
|
||||
netcam_context_ptr netcam = cinfo->client_data;
|
||||
/* Output the message associated with the error. */
|
||||
(*cinfo->err->output_message)(cinfo);
|
||||
/* Set flag to show the decompression had errors. */
|
||||
netcam->jpeg_error |= 1;
|
||||
/* Need to "cleanup" the aborted decompression. */
|
||||
jpeg_destroy (cinfo);
|
||||
|
||||
MOTION_LOG(DBG, TYPE_NETCAM, NO_ERRNO,_("netcam->jpeg_error %d"), netcam->jpeg_error);
|
||||
|
||||
/* Jump back to wherever we started. */
|
||||
longjmp(netcam->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* netcam_output_message
|
||||
*
|
||||
* Routine to override the libjpeg error message output routine.
|
||||
* We do this so that we can output our module and thread i.d.,
|
||||
* as well as put the message to the motion log.
|
||||
*
|
||||
* Parameters
|
||||
*
|
||||
* cinfo pointer to the decompression control structure.
|
||||
*
|
||||
* Returns Nothing
|
||||
*
|
||||
*/
|
||||
static void netcam_output_message(j_common_ptr cinfo)
|
||||
{
|
||||
char buffer[JMSG_LENGTH_MAX];
|
||||
|
||||
/* Fetch our pre-stored pointer to the netcam context. */
|
||||
netcam_context_ptr netcam = cinfo->client_data;
|
||||
|
||||
/*
|
||||
* While experimenting with a "appro" netcam it was discovered
|
||||
* that the jpeg data produced by the camera caused warning
|
||||
* messages from libjpeg (JWRN_EXTRANEOUS_DATA). The following
|
||||
* code is to assure that specific warning is ignored.
|
||||
*
|
||||
* NOTE: It's likely that we will discover other error message
|
||||
* codes which we want to ignore. In that case, we should have
|
||||
* some sort of table-lookup to decide which messages we really
|
||||
* care about.
|
||||
*/
|
||||
if ((cinfo->err->msg_code != JWRN_EXTRANEOUS_DATA) &&
|
||||
(cinfo->err->msg_code == JWRN_NOT_SEQUENTIAL) && (!netcam->netcam_tolerant_check)) {
|
||||
netcam->jpeg_error |= 2; /* Set flag to show problem */
|
||||
}
|
||||
|
||||
/*
|
||||
* Format the message according to library standards.
|
||||
* Write it out to the motion log.
|
||||
*/
|
||||
(*cinfo->err->format_message)(cinfo, buffer);
|
||||
MOTION_LOG(DBG, TYPE_NETCAM, NO_ERRNO, "%s", buffer);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* netcam_init_jpeg
|
||||
*
|
||||
* Initialises the JPEG library prior to doing a
|
||||
* decompression.
|
||||
*
|
||||
* Parameters:
|
||||
* netcam pointer to netcam_context.
|
||||
* cinfo pointer to JPEG decompression context.
|
||||
*
|
||||
* Returns: Error code.
|
||||
*/
|
||||
static int netcam_init_jpeg(netcam_context_ptr netcam, j_decompress_ptr cinfo)
|
||||
{
|
||||
netcam_buff_ptr buff;
|
||||
|
||||
/*
|
||||
* First we check whether a new image has arrived. If not, we
|
||||
* setup to wait for 1/2 a frame time. This will (hopefully)
|
||||
* help in synchronizing the camera frames with the motion main
|
||||
* loop.
|
||||
*/
|
||||
pthread_mutex_lock(&netcam->mutex);
|
||||
|
||||
if (netcam->imgcnt_last == netcam->imgcnt) { /* Need to wait */
|
||||
struct timespec waittime;
|
||||
struct timeval curtime;
|
||||
int retcode;
|
||||
|
||||
/*
|
||||
* We calculate the delay time (representing the desired frame
|
||||
* rate). This delay time is in *nanoseconds*.
|
||||
* We will wait 0.5 seconds which gives a practical minimum
|
||||
* framerate of 2 which is desired for the motion_loop to
|
||||
* function.
|
||||
*/
|
||||
gettimeofday(&curtime, NULL);
|
||||
curtime.tv_usec += 500000;
|
||||
|
||||
if (curtime.tv_usec > 1000000) {
|
||||
curtime.tv_usec -= 1000000;
|
||||
curtime.tv_sec++;
|
||||
}
|
||||
|
||||
waittime.tv_sec = curtime.tv_sec;
|
||||
waittime.tv_nsec = 1000L * curtime.tv_usec;
|
||||
|
||||
do {
|
||||
retcode = pthread_cond_timedwait(&netcam->pic_ready,
|
||||
&netcam->mutex, &waittime);
|
||||
} while (retcode == EINTR);
|
||||
|
||||
if (retcode) { /* We assume a non-zero reply is ETIMEOUT */
|
||||
pthread_mutex_unlock(&netcam->mutex);
|
||||
return NETCAM_GENERAL_ERROR | NETCAM_NOTHING_NEW_ERROR;
|
||||
}
|
||||
|
||||
MOTION_LOG(DBG, TYPE_NETCAM, NO_ERRNO,_("***new pic delay successful***"));
|
||||
}
|
||||
|
||||
netcam->imgcnt_last = netcam->imgcnt;
|
||||
|
||||
/* Set latest buffer as "current". */
|
||||
buff = netcam->latest;
|
||||
netcam->latest = netcam->jpegbuf;
|
||||
netcam->jpegbuf = buff;
|
||||
pthread_mutex_unlock(&netcam->mutex);
|
||||
|
||||
/* Clear any error flag from previous work. */
|
||||
netcam->jpeg_error = 0;
|
||||
|
||||
buff = netcam->jpegbuf;
|
||||
/*
|
||||
* Prepare for the decompression.
|
||||
* Initialize the JPEG decompression object.
|
||||
*/
|
||||
jpeg_create_decompress(cinfo);
|
||||
|
||||
/* Set up own error exit routine. */
|
||||
cinfo->err = jpeg_std_error(&netcam->jerr);
|
||||
cinfo->client_data = netcam;
|
||||
netcam->jerr.error_exit = netcam_error_exit;
|
||||
netcam->jerr.output_message = netcam_output_message;
|
||||
|
||||
/* Specify the data source as our own routine. */
|
||||
netcam_memory_src(cinfo, buff->ptr, buff->used);
|
||||
|
||||
/* Read file parameters (rejecting tables-only). */
|
||||
jpeg_read_header(cinfo, TRUE);
|
||||
|
||||
/* Override the desired colour space. */
|
||||
if (cinfo->out_color_space != JCS_GRAYSCALE) {
|
||||
cinfo->out_color_space = JCS_YCbCr;
|
||||
}
|
||||
|
||||
/* Start the decompressor. */
|
||||
jpeg_start_decompress(cinfo);
|
||||
|
||||
if (netcam->jpeg_error) {
|
||||
MOTION_LOG(DBG, TYPE_NETCAM, NO_ERRNO,_("jpeg_error %d"), netcam->jpeg_error);
|
||||
}
|
||||
|
||||
return netcam->jpeg_error;
|
||||
}
|
||||
|
||||
/**
|
||||
* netcam_image_conv
|
||||
*
|
||||
* Parameters:
|
||||
* netcam pointer to netcam_context
|
||||
* cinfo pointer to JPEG decompression context
|
||||
* image pointer to buffer of destination image (yuv420)
|
||||
*
|
||||
* Returns : netcam->jpeg_error
|
||||
*/
|
||||
static int netcam_image_conv(netcam_context_ptr netcam, struct jpeg_decompress_struct *cinfo
|
||||
, struct image_data *img_data)
|
||||
{
|
||||
JSAMPARRAY line; /* Array of decomp data lines */
|
||||
unsigned char *wline; /* Will point to line[0] */
|
||||
/* Working variables */
|
||||
int linesize, i;
|
||||
unsigned char *upic, *vpic;
|
||||
unsigned char *pic = img_data->image_norm;
|
||||
unsigned char y; /* Switch for decoding YUV data */
|
||||
unsigned int width, height;
|
||||
|
||||
width = cinfo->output_width;
|
||||
height = cinfo->output_height;
|
||||
|
||||
if (width && ((width != netcam->width) || (height != netcam->height))) {
|
||||
MOTION_LOG(WRN, TYPE_NETCAM, NO_ERRNO
|
||||
,_("JPEG image size %dx%d, JPEG was %dx%d")
|
||||
,netcam->width, netcam->height, width, height);
|
||||
jpeg_destroy_decompress(cinfo);
|
||||
netcam->jpeg_error |= 4;
|
||||
return netcam->jpeg_error;
|
||||
}
|
||||
/* Set the output pointers (these come from YUV411P definition. */
|
||||
upic = pic + width * height;
|
||||
vpic = upic + (width * height) / 4;
|
||||
|
||||
|
||||
/* YCbCr format will give us one byte each for YUV. */
|
||||
linesize = cinfo->output_width * 3;
|
||||
|
||||
/* Allocate space for one line. */
|
||||
line = (cinfo->mem->alloc_sarray)((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
cinfo->output_width * cinfo->output_components, 1);
|
||||
|
||||
wline = line[0];
|
||||
y = 0;
|
||||
|
||||
while (cinfo->output_scanline < height) {
|
||||
jpeg_read_scanlines(cinfo, line, 1);
|
||||
|
||||
if (cinfo->out_color_space == JCS_GRAYSCALE) {
|
||||
|
||||
for (i = 0; i < (int)cinfo->output_width; i++) {
|
||||
pic[i] = wline[i];
|
||||
}
|
||||
pic += cinfo->output_width;
|
||||
|
||||
} else {
|
||||
|
||||
for (i = 0; i < linesize; i += 3) {
|
||||
pic[i / 3] = wline[i];
|
||||
if (i & 1) {
|
||||
upic[(i / 3) / 2] = wline[i + 1];
|
||||
vpic[(i / 3) / 2] = wline[i + 2];
|
||||
}
|
||||
}
|
||||
|
||||
pic += linesize / 3;
|
||||
|
||||
if (y++ & 1) {
|
||||
upic += width / 2;
|
||||
vpic += width / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jpeg_finish_decompress(cinfo);
|
||||
jpeg_destroy_decompress(cinfo);
|
||||
|
||||
rotate_map(netcam->cnt, img_data);
|
||||
|
||||
if (netcam->jpeg_error) {
|
||||
MOTION_LOG(DBG, TYPE_NETCAM, NO_ERRNO,_("jpeg_error %d"), netcam->jpeg_error);
|
||||
}
|
||||
|
||||
return netcam->jpeg_error;
|
||||
}
|
||||
|
||||
/**
|
||||
* netcam_proc_jpeg
|
||||
*
|
||||
* Routine to decode an image received from a netcam into a YUV420P buffer
|
||||
* suitable for processing by motion.
|
||||
*
|
||||
* Parameters:
|
||||
* netcam pointer to the netcam_context structure.
|
||||
* image pointer to a buffer for the returned image.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* 0 Success
|
||||
* non-zero error code from other routines
|
||||
* (e.g. netcam_init_jpeg or netcam_image_conv)
|
||||
* or just NETCAM_GENERAL_ERROR
|
||||
*/
|
||||
int netcam_proc_jpeg(netcam_context_ptr netcam, struct image_data *img_data)
|
||||
{
|
||||
struct jpeg_decompress_struct cinfo; /* Decompression control struct. */
|
||||
int retval = 0; /* Value returned to caller. */
|
||||
int ret; /* Working var. */
|
||||
|
||||
/*
|
||||
* This routine is only called from the main thread.
|
||||
* We need to "protect" the "latest" image while we
|
||||
* decompress it. netcam_init_jpeg uses
|
||||
* netcam->mutex to do this.
|
||||
*/
|
||||
MOTION_LOG(DBG, TYPE_NETCAM, NO_ERRNO
|
||||
,_("processing jpeg image - content length %d"), netcam->latest->content_length);
|
||||
|
||||
ret = netcam_init_jpeg(netcam, &cinfo);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a sanity check on dimensions
|
||||
* If dimensions have changed we throw an
|
||||
* error message that will cause
|
||||
* restart of Motion.
|
||||
*/
|
||||
if (netcam->width) { /* 0 means not yet init'ed */
|
||||
if ((cinfo.output_width != netcam->width) ||
|
||||
(cinfo.output_height != netcam->height)) {
|
||||
retval = NETCAM_RESTART_ERROR;
|
||||
MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO
|
||||
,_("Camera width/height mismatch with JPEG image - "
|
||||
" expected %dx%d, JPEG %dx%d retval %d")
|
||||
,netcam->width, netcam->height
|
||||
,cinfo.output_width, cinfo.output_height, retval);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do the conversion */
|
||||
ret = netcam_image_conv(netcam, &cinfo, img_data);
|
||||
|
||||
if (ret != 0) {
|
||||
retval |= NETCAM_JPEG_CONV_ERROR;
|
||||
MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO
|
||||
,_("ret %d retval %d"), ret, retval);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* netcam_fix_jpeg_header
|
||||
*
|
||||
* Routine to decode an image received from a netcam into a YUV420P buffer
|
||||
* suitable for processing by motion.
|
||||
*
|
||||
* Parameters:
|
||||
* netcam pointer to the netcam_context structure
|
||||
*
|
||||
* Returns: Nothing
|
||||
*
|
||||
*/
|
||||
void netcam_fix_jpeg_header(netcam_context_ptr netcam)
|
||||
{
|
||||
char *ptr_buffer;
|
||||
|
||||
ptr_buffer = memmem(netcam->receiving->ptr, netcam->receiving->used, "\xff\xd8", 2);
|
||||
|
||||
if (ptr_buffer != NULL) {
|
||||
size_t soi_position = 0;
|
||||
|
||||
soi_position = ptr_buffer - netcam->receiving->ptr;
|
||||
|
||||
if (soi_position > 0) {
|
||||
memmove(netcam->receiving->ptr, netcam->receiving->ptr + soi_position,
|
||||
netcam->receiving->used - soi_position);
|
||||
netcam->receiving->used -= soi_position;
|
||||
}
|
||||
|
||||
// if (debug_level > CAMERA_INFO)
|
||||
// motion_log(LOG_INFO, 0, "SOI found , position %d",
|
||||
// __FUNCTION__, soi_position);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* netcam_get_dimensions
|
||||
*
|
||||
* This function gets the height and width of the JPEG image
|
||||
* located in the supplied netcam_image_buffer.
|
||||
*
|
||||
* Parameters
|
||||
*
|
||||
* netcam pointer to the netcam context.
|
||||
*
|
||||
* Returns: Nothing, but fills in width and height into context.
|
||||
*
|
||||
*/
|
||||
void netcam_get_dimensions(netcam_context_ptr netcam)
|
||||
{
|
||||
struct jpeg_decompress_struct cinfo; /* Decompression control struct. */
|
||||
int ret;
|
||||
|
||||
ret = netcam_init_jpeg(netcam, &cinfo);
|
||||
|
||||
netcam->width = cinfo.output_width;
|
||||
netcam->height = cinfo.output_height;
|
||||
netcam->JFIF_marker = cinfo.saw_JFIF_marker;
|
||||
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO, "JFIF_marker %s PRESENT ret %d",
|
||||
netcam->JFIF_marker ? "IS" : "NOT", ret);
|
||||
}
|
||||
@@ -1,391 +0,0 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002
|
||||
* Free Software Foundation, Inc.
|
||||
*
|
||||
* Additional Copyright (C) 2004-2005 Christopher Price,
|
||||
* Angel Carpintero, and other contributing authors.
|
||||
*
|
||||
* Major part of this file is reused code from GNU Wget. It has been
|
||||
* merged and modified for use in the program Motion which is also
|
||||
* released under the terms of the GNU General Public License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "motion.hpp"
|
||||
#include "util.hpp"
|
||||
#include "netcam.hpp"
|
||||
#include "netcam_wget.hpp"
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#define MINVAL(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
/* This file contains the generic routines for work with headers.
|
||||
Currently they are used only by HTTP in http.c, but they can be
|
||||
used by anything that cares about RFC822-style headers.
|
||||
|
||||
Header is defined in RFC2068, as quoted below. Note that this
|
||||
definition is not HTTP-specific -- it is virtually
|
||||
indistinguishable from the one given in RFC822 or RFC1036.
|
||||
|
||||
message-header = field-name ":" [ field-value ] CRLF
|
||||
|
||||
field-name = token
|
||||
field-value = *( field-content | LWS )
|
||||
|
||||
field-content = <the OCTETs making up the field-value
|
||||
and consisting of either *TEXT or combinations
|
||||
of token, tspecials, and quoted-string>
|
||||
|
||||
The public functions are header_get() and header_process(), which
|
||||
see. */
|
||||
|
||||
|
||||
/* Get a header from read-buffer RBUF and return it in *HDR.
|
||||
|
||||
As defined in RFC2068 and elsewhere, a header can be folded into
|
||||
multiple lines if the continuation line begins with a space or
|
||||
horizontal TAB. Also, this function will accept a header ending
|
||||
with just LF instead of CRLF.
|
||||
|
||||
The header may be of arbitrary length; the function will allocate
|
||||
as much memory as necessary for it to fit. It need not contain a
|
||||
`:', thus you can use it to retrieve, say, HTTP status line.
|
||||
|
||||
All trailing whitespace is stripped from the header, and it is
|
||||
zero-terminated.
|
||||
*/
|
||||
int header_get(netcam_context_ptr netcam, char **hdr, enum header_get_flags flags)
|
||||
{
|
||||
int i;
|
||||
int bufsize = 80;
|
||||
|
||||
*hdr = mymalloc(bufsize);
|
||||
|
||||
for (i = 0; 1; i++) {
|
||||
int res;
|
||||
/* #### Use DO_REALLOC? */
|
||||
if (i > bufsize - 1) {
|
||||
*hdr = (char *)myrealloc(*hdr, (bufsize <<= 1), "");
|
||||
}
|
||||
|
||||
res = RBUF_READCHAR (netcam, *hdr + i);
|
||||
|
||||
if (res == 1) {
|
||||
if ((*hdr)[i] == '\n') {
|
||||
if (!((flags & HG_NO_CONTINUATIONS) || i == 0
|
||||
|| (i == 1 && (*hdr)[0] == '\r'))) {
|
||||
char next;
|
||||
/*
|
||||
* If the header is non-empty, we need to check if
|
||||
* it continues on to the other line. We do that by
|
||||
* peeking at the next character.
|
||||
*/
|
||||
res = rbuf_peek(netcam, &next);
|
||||
|
||||
if (res == 0) {
|
||||
(*hdr)[i] = '\0';
|
||||
return HG_EOF;
|
||||
} else if (res == -1) {
|
||||
(*hdr)[i] = '\0';
|
||||
return HG_ERROR;
|
||||
}
|
||||
/* If the next character is HT or SP, just continue. */
|
||||
if (next == '\t' || next == ' ') {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Strip trailing whitespace. (*hdr)[i] is the newline;
|
||||
* decrement I until it points to the last available
|
||||
* whitespace.
|
||||
*/
|
||||
while (i > 0 && isspace((*hdr)[i - 1])) {
|
||||
--i;
|
||||
}
|
||||
|
||||
(*hdr)[i] = '\0';
|
||||
break;
|
||||
}
|
||||
} else if (res == 0) {
|
||||
(*hdr)[i] = '\0';
|
||||
return HG_EOF;
|
||||
} else {
|
||||
(*hdr)[i] = '\0';
|
||||
return HG_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return HG_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* header_process
|
||||
*
|
||||
* Check whether HEADER begins with NAME and, if yes, skip the `:' and
|
||||
* the whitespace, and call PROCFUN with the arguments of HEADER's
|
||||
* contents (after the `:' and space) and ARG. Otherwise, return 0.
|
||||
*/
|
||||
int header_process(const char *header, const char *name
|
||||
, int (*procfun)(const char *, void *), void *arg)
|
||||
{
|
||||
/* Check whether HEADER matches NAME. */
|
||||
while (*name && (tolower (*name) == tolower (*header)))
|
||||
++name, ++header;
|
||||
|
||||
if (*name || *header++ != ':') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
header += skip_lws (header);
|
||||
return ((*procfun) (header, arg));
|
||||
}
|
||||
|
||||
/* Helper functions for use with header_process(). */
|
||||
|
||||
/**
|
||||
* header_extract_number
|
||||
*
|
||||
* Extract a long integer from HEADER and store it to CLOSURE. If an
|
||||
* error is encountered, return 0, else 1.
|
||||
*/
|
||||
int header_extract_number(const char *header, void *closure)
|
||||
{
|
||||
const char *p = header;
|
||||
long result;
|
||||
|
||||
for (result = 0; isdigit (*p); p++) {
|
||||
result = 10 * result + (*p - '0');
|
||||
}
|
||||
|
||||
/* Failure if no number present. */
|
||||
if (p == header) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Skip trailing whitespace. */
|
||||
p += skip_lws (p);
|
||||
|
||||
/* We return the value, even if a format error follows. */
|
||||
*(long *)closure = result;
|
||||
|
||||
/* Indicate failure if trailing garbage is present. */
|
||||
if (*p) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* header_strdup
|
||||
*
|
||||
* Strdup HEADER, and place the pointer to CLOSURE.
|
||||
*/
|
||||
int header_strdup(const char *header, void *closure)
|
||||
{
|
||||
*(char **)closure = mystrdup(header);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* skip_lws
|
||||
* Skip LWS (linear white space), if present. Returns number of
|
||||
* characters to skip.
|
||||
*/
|
||||
int skip_lws(const char *string)
|
||||
{
|
||||
const char *p = string;
|
||||
|
||||
while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') {
|
||||
++p;
|
||||
}
|
||||
|
||||
return p - string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* motion_base64_encode
|
||||
*
|
||||
* Encode the string S of length LENGTH to base64 format and place it
|
||||
* to STORE. STORE will be 0-terminated, and must point to a writable
|
||||
* buffer of at least 1+BASE64_LENGTH(length) bytes.
|
||||
*/
|
||||
void motion_base64_encode(const char *s, char *store, int length)
|
||||
{
|
||||
/* Conversion table. */
|
||||
static const char tbl[64] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', '0', '1', '2', '3',
|
||||
'4', '5', '6', '7', '8', '9', '+', '/'
|
||||
};
|
||||
|
||||
int i;
|
||||
unsigned char *p = (unsigned char *)store;
|
||||
|
||||
/* Transform the 3x8 bits to 4x6 bits, as required by base64. */
|
||||
for (i = 0; i < length; i += 3) {
|
||||
*p++ = tbl[s[0] >> 2];
|
||||
*p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
|
||||
*p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
|
||||
*p++ = tbl[s[2] & 0x3f];
|
||||
s += 3;
|
||||
}
|
||||
|
||||
/* Pad the result if necessary... */
|
||||
if (i == length + 1) {
|
||||
*(p - 1) = '=';
|
||||
} else if (i == length + 2) {
|
||||
*(p - 1) = *(p - 2) = '=';
|
||||
}
|
||||
|
||||
/* ...and zero-terminate it. */
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* strdupdelim
|
||||
*/
|
||||
char *strdupdelim(const char *beg, const char *end)
|
||||
{
|
||||
char *res = mymalloc(end - beg + 1);
|
||||
memcpy (res, beg, end - beg);
|
||||
|
||||
res[end - beg] = '\0';
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* http_process_type
|
||||
*/
|
||||
int http_process_type(const char *hdr, void *arg)
|
||||
{
|
||||
char **result = (char **)arg;
|
||||
/* Locate P on `;' or the terminating zero, whichever comes first. */
|
||||
const char *p = strchr (hdr, ';');
|
||||
|
||||
if (!p) {
|
||||
p = hdr + strlen (hdr);
|
||||
}
|
||||
|
||||
while (p > hdr && isspace (*(p - 1))) {
|
||||
--p;
|
||||
}
|
||||
|
||||
*result = strdupdelim (hdr, p);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* rbuf_initialize
|
||||
*
|
||||
* This is a simple implementation of buffering IO-read functions.
|
||||
*/
|
||||
void rbuf_initialize(netcam_context_ptr netcam)
|
||||
{
|
||||
netcam->response->buffer_pos = netcam->response->buffer;
|
||||
netcam->response->buffer_left = 0;
|
||||
}
|
||||
|
||||
int rbuf_read_bufferful(netcam_context_ptr netcam)
|
||||
{
|
||||
return netcam_recv(netcam, netcam->response->buffer,
|
||||
sizeof (netcam->response->buffer));
|
||||
}
|
||||
|
||||
/**
|
||||
* rbuf_peek
|
||||
*
|
||||
* Like rbuf_readchar(), only don't move the buffer position.
|
||||
*/
|
||||
int rbuf_peek(netcam_context_ptr netcam, char *store)
|
||||
{
|
||||
if (!netcam->response->buffer_left) {
|
||||
int res;
|
||||
rbuf_initialize(netcam);
|
||||
res = netcam_recv (netcam, netcam->response->buffer,
|
||||
sizeof (netcam->response->buffer));
|
||||
|
||||
if (res <= 0) {
|
||||
*store = '\0';
|
||||
return res;
|
||||
}
|
||||
|
||||
netcam->response->buffer_left = res;
|
||||
}
|
||||
|
||||
*store = *netcam->response->buffer_pos;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* rbuf_flush
|
||||
*
|
||||
* Flush RBUF's buffer to WHERE. Flush MAXSIZE bytes at most.
|
||||
* Returns the number of bytes actually copied. If the buffer is
|
||||
* empty, 0 is returned.
|
||||
*/
|
||||
int rbuf_flush(netcam_context_ptr netcam, char *where, int maxsize)
|
||||
{
|
||||
if (!netcam->response->buffer_left) {
|
||||
return 0;
|
||||
} else {
|
||||
int howmuch = MINVAL ((int)netcam->response->buffer_left, maxsize);
|
||||
|
||||
if (where) {
|
||||
memcpy(where, netcam->response->buffer_pos, howmuch);
|
||||
}
|
||||
|
||||
netcam->response->buffer_left -= howmuch;
|
||||
netcam->response->buffer_pos += howmuch;
|
||||
return howmuch;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* http_result_code
|
||||
*
|
||||
* Get the HTTP result code
|
||||
*/
|
||||
int http_result_code(const char *header)
|
||||
{
|
||||
char *cptr;
|
||||
|
||||
/* Assure the header starts out right. */
|
||||
if (strncmp(header, "HTTP", 4)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Find the space following the HTTP/1.x */
|
||||
if ((cptr = strchr(header+4, ' ')) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return atoi(cptr + 1);
|
||||
}
|
||||
|
||||
+536
-723
File diff suppressed because it is too large
Load Diff
+73
-35
@@ -1,39 +1,77 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* picture.h
|
||||
* Headers associated with functions in the picture.c module.
|
||||
* Copyright 2002 by Jeroen Vreeken (pe1rxq@amsat.org)
|
||||
* Portions of this file are Copyright by Lionnel Maugis
|
||||
*/
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
#ifndef _INCLUDE_PICTURE_HPP_
|
||||
#define _INCLUDE_PICTURE_HPP_
|
||||
|
||||
#ifndef _INCLUDE_PICTURE_H_
|
||||
#define _INCLUDE_PICTURE_H_
|
||||
#ifdef HAVE_WEBP
|
||||
#include <webp/encode.h>
|
||||
#include <webp/mux.h>
|
||||
#endif /* HAVE_WEBP */
|
||||
|
||||
void overlay_smartmask(struct context *cnt, unsigned char *out);
|
||||
void overlay_fixed_mask(struct context *cnt, unsigned char *out);
|
||||
void put_fixed_mask(struct context *cnt, const char *file);
|
||||
void overlay_largest_label(struct context *cnt, unsigned char *out);
|
||||
int put_picture_memory(struct context *cnt, unsigned char* dest_image, int image_size
|
||||
, unsigned char *image, int quality, int width, int height);
|
||||
void put_picture(struct context *cnt, char *file, unsigned char *image, int ftype);
|
||||
unsigned char *get_pgm(FILE *picture, int width, int height);
|
||||
void pic_scale_img(int width_src, int height_src, unsigned char *img_src, unsigned char *img_dst);
|
||||
unsigned prepare_exif(unsigned char **exif, const struct context *cnt
|
||||
, const struct timeval *tv_in1, const struct coord *box);
|
||||
class cls_picture {
|
||||
public:
|
||||
cls_picture(cls_camera *p_cam);
|
||||
~cls_picture();
|
||||
|
||||
#endif /* _INCLUDE_PICTURE_H_ */
|
||||
int put_memory(u_char* img_dst
|
||||
, int image_size, u_char *image, int quality, int width, int height);
|
||||
void scale_img(int width_src, int height_src, u_char *img_src, u_char *img_dst);
|
||||
void save_preview();
|
||||
void process_norm();
|
||||
void process_motion();
|
||||
void process_snapshot();
|
||||
void process_preview();
|
||||
|
||||
private:
|
||||
cls_camera *cam;
|
||||
|
||||
std::string full_nm;
|
||||
std::string file_nm;
|
||||
std::string file_dir;
|
||||
|
||||
#ifdef HAVE_WEBP
|
||||
void webp_exif(WebPMux* webp_mux
|
||||
, timespec *ts1, ctx_coord *box);
|
||||
#endif
|
||||
void save_webp(FILE *fp, u_char *image
|
||||
, int width, int height
|
||||
, timespec *ts1, ctx_coord *box);
|
||||
void save_yuv420p(FILE *fp, u_char *image
|
||||
, int width, int height
|
||||
, timespec *ts1, ctx_coord *box);
|
||||
void save_grey(FILE *picture, u_char *image
|
||||
, int width, int height
|
||||
, timespec *ts1, ctx_coord *box);
|
||||
void save_norm( char *file, u_char *image);
|
||||
void save_roi( char *file, u_char *image);
|
||||
void save_ppm(FILE *picture, u_char *image, int width, int height);
|
||||
void pic_write(FILE *picture, u_char *image);
|
||||
u_char *load_pgm(FILE *picture, int width, int height);
|
||||
void write_mask(const char *file);
|
||||
void init_privacy();
|
||||
void init_mask();
|
||||
void init_cfg();
|
||||
void on_picture_save_command(char *fname);
|
||||
void picname(char* fullname, std::string fmtstr
|
||||
, std::string basename, std::string extname);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* _INCLUDE_PICTURE_HPP_ */
|
||||
|
||||
@@ -1,331 +0,0 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PWC_IOCTL_H
|
||||
#define PWC_IOCTL_H
|
||||
|
||||
/* (C) 2001-2004 Nemosoft Unv.
|
||||
(C) 2004-2006 Luc Saillard (luc@saillard.org)
|
||||
|
||||
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
|
||||
driver and thus may have bugs that are not present in the original version.
|
||||
Please send bug reports and support requests to <luc@saillard.org>.
|
||||
The decompression routines have been implemented by reverse-engineering the
|
||||
Nemosoft binary pwcx module. Caveat emptor.
|
||||
|
||||
*/
|
||||
|
||||
/* This is pwc-ioctl.h belonging to PWC 10.0.10
|
||||
It contains structures and defines to communicate from user space
|
||||
directly to the driver.
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes
|
||||
2001/08/03 Alvarado Added ioctl constants to access methods for
|
||||
changing white balance and red/blue gains
|
||||
2002/12/15 G. H. Fernandez-Toribio VIDIOCGREALSIZE
|
||||
2003/12/13 Nemosft Unv. Some modifications to make interfacing to
|
||||
PWCX easier
|
||||
2006/01/01 Luc Saillard Add raw format definition
|
||||
*/
|
||||
|
||||
/* These are private ioctl() commands, specific for the Philips webcams.
|
||||
They contain functions not found in other webcams, and settings not
|
||||
specified in the Video4Linux API.
|
||||
|
||||
The #define names are built up like follows:
|
||||
VIDIOC VIDeo IOCtl prefix
|
||||
PWC Philps WebCam
|
||||
G optional: Get
|
||||
S optional: Set
|
||||
... the function
|
||||
*/
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <linux/types.h>
|
||||
#include <linux/version.h>
|
||||
#endif
|
||||
|
||||
/* Enumeration of image sizes */
|
||||
#define PSZ_SQCIF 0x00
|
||||
#define PSZ_QSIF 0x01
|
||||
#define PSZ_QCIF 0x02
|
||||
#define PSZ_SIF 0x03
|
||||
#define PSZ_CIF 0x04
|
||||
#define PSZ_VGA 0x05
|
||||
#define PSZ_MAX 6
|
||||
|
||||
|
||||
/* The frame rate is encoded in the video_window.flags parameter using
|
||||
the upper 16 bits, since some flags are defined nowadays. The following
|
||||
defines provide a mask and shift to filter out this value.
|
||||
This value can also be passing using the private flag when using v4l2 and
|
||||
VIDIOC_S_FMT ioctl.
|
||||
|
||||
In 'Snapshot' mode the camera freezes its automatic exposure and colour
|
||||
balance controls.
|
||||
*/
|
||||
#define PWC_FPS_SHIFT 16
|
||||
#define PWC_FPS_MASK 0x00FF0000
|
||||
#define PWC_FPS_FRMASK 0x003F0000
|
||||
#define PWC_FPS_SNAPSHOT 0x00400000
|
||||
#define PWC_QLT_MASK 0x03000000
|
||||
#define PWC_QLT_SHIFT 24
|
||||
|
||||
|
||||
/* structure for transferring x & y coordinates */
|
||||
struct pwc_coord
|
||||
{
|
||||
int x, y; /* guess what */
|
||||
int size; /* size, or offset */
|
||||
};
|
||||
|
||||
|
||||
/* Used with VIDIOCPWCPROBE */
|
||||
struct pwc_probe
|
||||
{
|
||||
char name[32];
|
||||
int type;
|
||||
};
|
||||
|
||||
struct pwc_serial
|
||||
{
|
||||
char serial[30]; /* String with serial number. Contains terminating 0 */
|
||||
};
|
||||
|
||||
/* pwc_whitebalance.mode values */
|
||||
#define PWC_WB_INDOOR 0
|
||||
#define PWC_WB_OUTDOOR 1
|
||||
#define PWC_WB_FL 2
|
||||
#define PWC_WB_MANUAL 3
|
||||
#define PWC_WB_AUTO 4
|
||||
|
||||
/* Used with VIDIOCPWC[SG]AWB (Auto White Balance).
|
||||
Set mode to one of the PWC_WB_* values above.
|
||||
*red and *blue are the respective gains of these colour components inside
|
||||
the camera; range 0..65535
|
||||
When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read;
|
||||
otherwise undefined.
|
||||
'read_red' and 'read_blue' are read-only.
|
||||
*/
|
||||
struct pwc_whitebalance
|
||||
{
|
||||
int mode;
|
||||
int manual_red, manual_blue; /* R/W */
|
||||
int read_red, read_blue; /* R/O */
|
||||
};
|
||||
|
||||
/*
|
||||
'control_speed' and 'control_delay' are used in automatic whitebalance mode,
|
||||
and tell the camera how fast it should react to changes in lighting, and
|
||||
with how much delay. Valid values are 0..65535.
|
||||
*/
|
||||
struct pwc_wb_speed
|
||||
{
|
||||
int control_speed;
|
||||
int control_delay;
|
||||
|
||||
};
|
||||
|
||||
/* Used with VIDIOCPWC[SG]LED */
|
||||
struct pwc_leds
|
||||
{
|
||||
int led_on; /* Led on-time; range = 0..25000 */
|
||||
int led_off; /* Led off-time; range = 0..25000 */
|
||||
};
|
||||
|
||||
/* Image size (used with GREALSIZE) */
|
||||
struct pwc_imagesize
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
/* Defines and structures for Motorized Pan & Tilt */
|
||||
#define PWC_MPT_PAN 0x01
|
||||
#define PWC_MPT_TILT 0x02
|
||||
#define PWC_MPT_TIMEOUT 0x04 /* for status */
|
||||
|
||||
/* Set angles; when absolute != 0, the angle is absolute and the
|
||||
driver calculates the relative offset for you. This can only
|
||||
be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
|
||||
absolute angles.
|
||||
*/
|
||||
struct pwc_mpt_angles
|
||||
{
|
||||
int absolute; /* write-only */
|
||||
int pan; /* degrees * 100 */
|
||||
int tilt; /* degress * 100 */
|
||||
};
|
||||
|
||||
/* Range of angles of the camera, both horizontally and vertically.
|
||||
*/
|
||||
struct pwc_mpt_range
|
||||
{
|
||||
int pan_min, pan_max; /* degrees * 100 */
|
||||
int tilt_min, tilt_max;
|
||||
};
|
||||
|
||||
struct pwc_mpt_status
|
||||
{
|
||||
int status;
|
||||
int time_pan;
|
||||
int time_tilt;
|
||||
};
|
||||
|
||||
|
||||
/* This is used for out-of-kernel decompression. With it, you can get
|
||||
all the necessary information to initialize and use the decompressor
|
||||
routines in standalone applications.
|
||||
*/
|
||||
struct pwc_video_command
|
||||
{
|
||||
int type; /* camera type (645, 675, 730, etc.) */
|
||||
int release; /* release number */
|
||||
|
||||
int size; /* one of PSZ_* */
|
||||
int alternate;
|
||||
int command_len; /* length of USB video command */
|
||||
unsigned char command_buf[13]; /* Actual USB video command */
|
||||
int bandlength; /* >0 = compressed */
|
||||
int frame_size; /* Size of one (un)compressed frame */
|
||||
};
|
||||
|
||||
/* Flags for PWCX subroutines. Not all modules honour all flags. */
|
||||
#define PWCX_FLAG_PLANAR 0x0001
|
||||
#define PWCX_FLAG_BAYER 0x0008
|
||||
|
||||
|
||||
/* IOCTL definitions */
|
||||
|
||||
/* Restore user settings */
|
||||
#define VIDIOCPWCRUSER _IO('v', 192)
|
||||
/* Save user settings */
|
||||
#define VIDIOCPWCSUSER _IO('v', 193)
|
||||
/* Restore factory settings */
|
||||
#define VIDIOCPWCFACTORY _IO('v', 194)
|
||||
|
||||
/* You can manipulate the compression factor. A compression preference of 0
|
||||
means use uncompressed modes when available; 1 is low compression, 2 is
|
||||
medium and 3 is high compression preferred. Of course, the higher the
|
||||
compression, the lower the bandwidth used but more chance of artefacts
|
||||
in the image. The driver automatically chooses a higher compression when
|
||||
the preferred mode is not available.
|
||||
*/
|
||||
/* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
|
||||
#define VIDIOCPWCSCQUAL _IOW('v', 195, int)
|
||||
/* Get preferred compression quality */
|
||||
#define VIDIOCPWCGCQUAL _IOR('v', 195, int)
|
||||
|
||||
|
||||
/* Retrieve serial number of camera */
|
||||
#define VIDIOCPWCGSERIAL _IOR('v', 198, struct pwc_serial)
|
||||
|
||||
/* This is a probe function; since so many devices are supported, it
|
||||
becomes difficult to include all the names in programs that want to
|
||||
check for the enhanced Philips stuff. So in stead, try this PROBE;
|
||||
it returns a structure with the original name, and the corresponding
|
||||
Philips type.
|
||||
To use, fill the structure with zeroes, call PROBE and if that succeeds,
|
||||
compare the name with that returned from VIDIOCGCAP; they should be the
|
||||
same. If so, you can be assured it is a Philips (OEM) cam and the type
|
||||
is valid.
|
||||
*/
|
||||
#define VIDIOCPWCPROBE _IOR('v', 199, struct pwc_probe)
|
||||
|
||||
/* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
|
||||
#define VIDIOCPWCSAGC _IOW('v', 200, int)
|
||||
/* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
|
||||
#define VIDIOCPWCGAGC _IOR('v', 200, int)
|
||||
/* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
|
||||
#define VIDIOCPWCSSHUTTER _IOW('v', 201, int)
|
||||
|
||||
/* Color compensation (Auto White Balance) */
|
||||
#define VIDIOCPWCSAWB _IOW('v', 202, struct pwc_whitebalance)
|
||||
#define VIDIOCPWCGAWB _IOR('v', 202, struct pwc_whitebalance)
|
||||
|
||||
/* Auto WB speed */
|
||||
#define VIDIOCPWCSAWBSPEED _IOW('v', 203, struct pwc_wb_speed)
|
||||
#define VIDIOCPWCGAWBSPEED _IOR('v', 203, struct pwc_wb_speed)
|
||||
|
||||
/* LEDs on/off/blink; int range 0..65535 */
|
||||
#define VIDIOCPWCSLED _IOW('v', 205, struct pwc_leds)
|
||||
#define VIDIOCPWCGLED _IOR('v', 205, struct pwc_leds)
|
||||
|
||||
/* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */
|
||||
#define VIDIOCPWCSCONTOUR _IOW('v', 206, int)
|
||||
#define VIDIOCPWCGCONTOUR _IOR('v', 206, int)
|
||||
|
||||
/* Backlight compensation; 0 = off, otherwise on */
|
||||
#define VIDIOCPWCSBACKLIGHT _IOW('v', 207, int)
|
||||
#define VIDIOCPWCGBACKLIGHT _IOR('v', 207, int)
|
||||
|
||||
/* Flickerless mode; = 0 off, otherwise on */
|
||||
#define VIDIOCPWCSFLICKER _IOW('v', 208, int)
|
||||
#define VIDIOCPWCGFLICKER _IOR('v', 208, int)
|
||||
|
||||
/* Dynamic noise reduction; 0 off, 3 = high noise reduction */
|
||||
#define VIDIOCPWCSDYNNOISE _IOW('v', 209, int)
|
||||
#define VIDIOCPWCGDYNNOISE _IOR('v', 209, int)
|
||||
|
||||
/* Real image size as used by the camera; tells you whether or not there's a gray border around the image */
|
||||
#define VIDIOCPWCGREALSIZE _IOR('v', 210, struct pwc_imagesize)
|
||||
|
||||
/* Motorized pan & tilt functions */
|
||||
#define VIDIOCPWCMPTRESET _IOW('v', 211, int)
|
||||
#define VIDIOCPWCMPTGRANGE _IOR('v', 211, struct pwc_mpt_range)
|
||||
#define VIDIOCPWCMPTSANGLE _IOW('v', 212, struct pwc_mpt_angles)
|
||||
#define VIDIOCPWCMPTGANGLE _IOR('v', 212, struct pwc_mpt_angles)
|
||||
#define VIDIOCPWCMPTSTATUS _IOR('v', 213, struct pwc_mpt_status)
|
||||
|
||||
/* Get the USB set-video command; needed for initializing libpwcx */
|
||||
#define VIDIOCPWCGVIDCMD _IOR('v', 215, struct pwc_video_command)
|
||||
struct pwc_table_init_buffer {
|
||||
int len;
|
||||
char *buffer;
|
||||
};
|
||||
#define VIDIOCPWCGVIDTABLE _IOR('v', 216, struct pwc_table_init_buffer)
|
||||
|
||||
/*
|
||||
* This is private command used when communicating with v4l2.
|
||||
* In the future all private ioctl will be remove/replace to
|
||||
* use interface offer by v4l2.
|
||||
*/
|
||||
|
||||
#if (defined(HAVE_V4L2)) && defined(__linux__)
|
||||
|
||||
#define V4L2_CID_PRIVATE_SAVE_USER (V4L2_CID_PRIVATE_BASE + 0)
|
||||
#define V4L2_CID_PRIVATE_RESTORE_USER (V4L2_CID_PRIVATE_BASE + 1)
|
||||
#define V4L2_CID_PRIVATE_RESTORE_FACTORY (V4L2_CID_PRIVATE_BASE + 2)
|
||||
#define V4L2_CID_PRIVATE_COLOUR_MODE (V4L2_CID_PRIVATE_BASE + 3)
|
||||
#define V4L2_CID_PRIVATE_AUTOCONTOUR (V4L2_CID_PRIVATE_BASE + 4)
|
||||
#define V4L2_CID_PRIVATE_CONTOUR (V4L2_CID_PRIVATE_BASE + 5)
|
||||
#define V4L2_CID_PRIVATE_BACKLIGHT (V4L2_CID_PRIVATE_BASE + 6)
|
||||
#define V4L2_CID_PRIVATE_FLICKERLESS (V4L2_CID_PRIVATE_BASE + 7)
|
||||
#define V4L2_CID_PRIVATE_NOISE_REDUCTION (V4L2_CID_PRIVATE_BASE + 8)
|
||||
|
||||
struct pwc_raw_frame {
|
||||
__le16 type; /* type of the webcam */
|
||||
__le16 vbandlength; /* Size of 4lines compressed (used by the decompressor) */
|
||||
__u8 cmd[4]; /* the four byte of the command (in case of nala,
|
||||
only the first 3 bytes is filled) */
|
||||
__u8 rawframe[0]; /* frame_size = H/4*vbandlength */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#endif /* HAVE_V4L2 && __linux__ */
|
||||
|
||||
#endif
|
||||
+120
-263
@@ -1,52 +1,27 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* rotate.c
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Module for handling image rotation.
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Copyright 2004-2005, Per Jonsson (per@pjd.nu)
|
||||
* Motion 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.
|
||||
*
|
||||
* Image rotation is a feature of Motion that can be used when the
|
||||
* camera is mounted upside-down or on the side. The module only
|
||||
* supports rotation in multiples of 90 degrees. Using rotation
|
||||
* increases the Motion CPU usage slightly.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Version history:
|
||||
* v6 (29-Aug-2005) - simplified the code as Motion now requires
|
||||
* that width and height are multiples of 16
|
||||
* v5 (3-Aug-2005) - cleanup in code comments
|
||||
* - better adherence to coding standard
|
||||
* - fix for __bswap_32 macro collision
|
||||
* - fixed bug where initialization would be
|
||||
* incomplete for invalid degrees of rotation
|
||||
* - now uses MOTION_LOG for error reporting
|
||||
* v4 (26-Oct-2004) - new fix for width/height from imgs/conf due to
|
||||
* earlier misinterpretation
|
||||
* v3 (11-Oct-2004) - cleanup of width/height from imgs/conf
|
||||
* v2 (26-Sep-2004) - separation of capture/internal dimensions
|
||||
* - speed optimization, including bswap
|
||||
* v1 (28-Aug-2004) - initial version
|
||||
*/
|
||||
#include "motion.hpp"
|
||||
#include "translate.hpp"
|
||||
#include "util.hpp"
|
||||
#include "camera.hpp"
|
||||
#include "conf.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "rotate.hpp"
|
||||
|
||||
#include <stdint.h>
|
||||
#if defined(__APPLE__)
|
||||
#include <libkern/OSByteOrder.h>
|
||||
@@ -64,24 +39,11 @@
|
||||
#include <byteswap.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* reverse_inplace_quad
|
||||
*
|
||||
* Reverses a block of memory in-place, 4 bytes at a time. This function
|
||||
* requires the uint32_t type, which is 32 bits wide.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* src - the memory block to reverse
|
||||
* size - the size (in bytes) of the memory block
|
||||
*
|
||||
* Returns: nothing
|
||||
*/
|
||||
static void reverse_inplace_quad(unsigned char *src, int size)
|
||||
void cls_rotate::reverse_inplace_quad(u_char *src, int size)
|
||||
{
|
||||
uint32_t *nsrc = (uint32_t *)src; /* first quad */
|
||||
uint32_t *ndst = (uint32_t *)(src + size - 4); /* last quad */
|
||||
register uint32_t tmp;
|
||||
uint32_t tmp;
|
||||
|
||||
while (nsrc < ndst) {
|
||||
tmp = bswap_32(*ndst);
|
||||
@@ -90,10 +52,10 @@ static void reverse_inplace_quad(unsigned char *src, int size)
|
||||
}
|
||||
}
|
||||
|
||||
static void flip_inplace_horizontal(unsigned char *src, int width, int height)
|
||||
void cls_rotate::flip_inplace_horizontal(u_char *src, int width, int height)
|
||||
{
|
||||
uint8_t *nsrc, *ndst;
|
||||
register uint8_t tmp;
|
||||
uint8_t tmp;
|
||||
int l,w;
|
||||
|
||||
for(l=0; l < height/2; l++) {
|
||||
@@ -108,10 +70,10 @@ static void flip_inplace_horizontal(unsigned char *src, int width, int height)
|
||||
|
||||
}
|
||||
|
||||
static void flip_inplace_vertical(unsigned char *src, int width, int height)
|
||||
void cls_rotate::flip_inplace_vertical(u_char *src, int width, int height)
|
||||
{
|
||||
uint8_t *nsrc, *ndst;
|
||||
register uint8_t tmp;
|
||||
uint8_t tmp;
|
||||
int l;
|
||||
|
||||
for(l=0; l < height; l++) {
|
||||
@@ -125,206 +87,38 @@ static void flip_inplace_vertical(unsigned char *src, int width, int height)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* rot90cw
|
||||
*
|
||||
* Performs a 90 degrees clockwise rotation of the memory block pointed to
|
||||
* by src. The rotation is NOT performed in-place; dst must point to a
|
||||
* receiving memory block the same size as src.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* src - pointer to the memory block (image) to rotate clockwise
|
||||
* dst - where to put the rotated memory block
|
||||
* size - the size (in bytes) of the memory blocks (both src and dst)
|
||||
* width - the width of the memory block when seen as an image
|
||||
* height - the height of the memory block when seen as an image
|
||||
*
|
||||
* Returns: nothing
|
||||
*/
|
||||
static void rot90cw(unsigned char *src, register unsigned char *dst
|
||||
,int size, int width, int height)
|
||||
void cls_rotate::rot90cw(u_char *src, u_char *dst, int size, int width, int height)
|
||||
{
|
||||
unsigned char *endp;
|
||||
register unsigned char *base;
|
||||
u_char *endp;
|
||||
u_char *base;
|
||||
int j;
|
||||
|
||||
endp = src + size;
|
||||
for (base = endp - width; base < endp; base++) {
|
||||
src = base;
|
||||
for (j = 0; j < height; j++, src -= width) {
|
||||
for (j = 0; j < height; j++, src -= width)
|
||||
*dst++ = *src;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* rot90ccw
|
||||
*
|
||||
* Performs a 90 degrees counterclockwise rotation of the memory block pointed
|
||||
* to by src. The rotation is not performed in-place; dst must point to a
|
||||
* receiving memory block the same size as src.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* src - pointer to the memory block (image) to rotate counterclockwise
|
||||
* dst - where to put the rotated memory block
|
||||
* size - the size (in bytes) of the memory blocks (both src and dst)
|
||||
* width - the width of the memory block when seen as an image
|
||||
* height - the height of the memory block when seen as an image
|
||||
*
|
||||
* Returns: nothing
|
||||
*/
|
||||
static inline void rot90ccw(unsigned char *src, register unsigned char *dst
|
||||
,int size, int width, int height)
|
||||
void cls_rotate::rot90ccw(u_char *src, u_char *dst, int size, int width, int height)
|
||||
{
|
||||
unsigned char *endp;
|
||||
register unsigned char *base;
|
||||
u_char *endp;
|
||||
u_char *base;
|
||||
int j;
|
||||
|
||||
endp = src + size;
|
||||
dst = dst + size - 1;
|
||||
for (base = endp - width; base < endp; base++) {
|
||||
src = base;
|
||||
for (j = 0; j < height; j++, src -= width) {
|
||||
for (j = 0; j < height; j++, src -= width)
|
||||
*dst-- = *src;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* rotate_init
|
||||
*
|
||||
* Initializes rotation data - allocates memory and determines which function
|
||||
* to use for 180 degrees rotation.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* cnt - the current thread's context structure
|
||||
*
|
||||
* Returns: nothing
|
||||
*/
|
||||
void rotate_init(struct context *cnt)
|
||||
{
|
||||
int size_norm, size_high;
|
||||
|
||||
/* Make sure buffer_norm isn't freed if it hasn't been allocated. */
|
||||
cnt->rotate_data.buffer_norm = NULL;
|
||||
cnt->rotate_data.buffer_high = NULL;
|
||||
|
||||
/*
|
||||
* Assign the value in conf.rotate to rotate_data.degrees. This way,
|
||||
* we have a value that is safe from changes caused by motion-control.
|
||||
*/
|
||||
if ((cnt->conf.rotate % 90) > 0) {
|
||||
MOTION_LOG(WRN, TYPE_ALL, NO_ERRNO
|
||||
,_("Config option \"rotate\" not a multiple of 90: %d")
|
||||
,cnt->conf.rotate);
|
||||
cnt->conf.rotate = 0; /* Disable rotation. */
|
||||
cnt->rotate_data.degrees = 0; /* Force return below. */
|
||||
} else {
|
||||
cnt->rotate_data.degrees = cnt->conf.rotate % 360; /* Range: 0..359 */
|
||||
}
|
||||
|
||||
if (cnt->conf.flip_axis[0]=='h') {
|
||||
cnt->rotate_data.axis = FLIP_TYPE_HORIZONTAL;
|
||||
} else if (cnt->conf.flip_axis[0]=='v') {
|
||||
cnt->rotate_data.axis = FLIP_TYPE_VERTICAL;
|
||||
} else {
|
||||
cnt->rotate_data.axis = FLIP_TYPE_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Upon entrance to this function, imgs.width and imgs.height contain the
|
||||
* capture dimensions (as set in the configuration file, or read from a
|
||||
* netcam source).
|
||||
*
|
||||
* If rotating 90 or 270 degrees, the capture dimensions and output dimensions
|
||||
* are not the same. Capture dimensions will be contained in capture_width_norm and
|
||||
* capture_height_norm in cnt->rotate_data, while output dimensions will be contained
|
||||
* in imgs.width and imgs.height.
|
||||
*/
|
||||
|
||||
/* 1. Transfer capture dimensions into capture_width_norm and capture_height_norm. */
|
||||
cnt->rotate_data.capture_width_norm = cnt->imgs.width;
|
||||
cnt->rotate_data.capture_height_norm = cnt->imgs.height;
|
||||
|
||||
cnt->rotate_data.capture_width_high = cnt->imgs.width_high;
|
||||
cnt->rotate_data.capture_height_high = cnt->imgs.height_high;
|
||||
|
||||
size_norm = cnt->imgs.width * cnt->imgs.height * 3 / 2;
|
||||
size_high = cnt->imgs.width_high * cnt->imgs.height_high * 3 / 2;
|
||||
|
||||
if ((cnt->rotate_data.degrees == 90) || (cnt->rotate_data.degrees == 270)) {
|
||||
/* 2. "Swap" imgs.width and imgs.height. */
|
||||
cnt->imgs.width = cnt->rotate_data.capture_height_norm;
|
||||
cnt->imgs.height = cnt->rotate_data.capture_width_norm;
|
||||
if (size_high > 0 ) {
|
||||
cnt->imgs.width_high = cnt->rotate_data.capture_height_high;
|
||||
cnt->imgs.height_high = cnt->rotate_data.capture_width_high;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're not rotating, let's exit once we have setup the capture dimensions
|
||||
* and output dimensions properly.
|
||||
*/
|
||||
if (cnt->rotate_data.degrees == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate memory if rotating 90 or 270 degrees, because those rotations
|
||||
* cannot be performed in-place (they can, but it would be too slow).
|
||||
*/
|
||||
if ((cnt->rotate_data.degrees == 90) || (cnt->rotate_data.degrees == 270)) {
|
||||
cnt->rotate_data.buffer_norm = mymalloc(size_norm);
|
||||
if (size_high > 0) {
|
||||
cnt->rotate_data.buffer_high = mymalloc(size_high);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* rotate_deinit
|
||||
*
|
||||
* Frees resources previously allocated by rotate_init.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* cnt - the current thread's context structure
|
||||
*
|
||||
* Returns: nothing
|
||||
*/
|
||||
void rotate_deinit(struct context *cnt)
|
||||
{
|
||||
|
||||
if (cnt->rotate_data.buffer_norm) {
|
||||
free(cnt->rotate_data.buffer_norm);
|
||||
}
|
||||
|
||||
if (cnt->rotate_data.buffer_high) {
|
||||
free(cnt->rotate_data.buffer_high);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* rotate_map
|
||||
*
|
||||
* Main entry point for rotation.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* img_data- pointer to the image data to rotate
|
||||
* cnt - the current thread's context structure
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* 0 - success
|
||||
* -1 - failure (shouldn't happen)
|
||||
*/
|
||||
int rotate_map(struct context *cnt, struct image_data *img_data)
|
||||
void cls_rotate::process(ctx_image_data *img_data)
|
||||
{
|
||||
/*
|
||||
* The image format is YUV 4:2:0 planar, which has the pixel
|
||||
@@ -336,38 +130,33 @@ int rotate_map(struct context *cnt, struct image_data *img_data)
|
||||
|
||||
int indx, indx_max;
|
||||
int wh, wh4 = 0, w2 = 0, h2 = 0; /* width * height, width * height / 4 etc. */
|
||||
int size, deg;
|
||||
enum FLIP_TYPE axis;
|
||||
int size;
|
||||
int width, height;
|
||||
unsigned char *img;
|
||||
unsigned char *temp_buff;
|
||||
u_char *img;
|
||||
u_char *temp_buff;
|
||||
|
||||
if (cnt->rotate_data.degrees == 0 && cnt->rotate_data.axis == FLIP_TYPE_NONE) {
|
||||
return 0;
|
||||
if ((degrees == 0) && (axis == FLIP_TYPE_NONE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
indx = 0;
|
||||
indx_max = 0;
|
||||
if ((cnt->rotate_data.capture_width_high != 0) && (cnt->rotate_data.capture_height_high != 0)) {
|
||||
if ((capture_width_high != 0) && (capture_height_high != 0)) {
|
||||
indx_max = 1;
|
||||
} else {
|
||||
indx_max = 0;
|
||||
}
|
||||
|
||||
while (indx <= indx_max) {
|
||||
deg = cnt->rotate_data.degrees;
|
||||
axis = cnt->rotate_data.axis;
|
||||
wh4 = 0;
|
||||
w2 = 0;
|
||||
h2 = 0;
|
||||
if (indx == 0) {
|
||||
if (indx == 0 ) {
|
||||
img = img_data->image_norm;
|
||||
width = cnt->rotate_data.capture_width_norm;
|
||||
height = cnt->rotate_data.capture_height_norm;
|
||||
temp_buff = cnt->rotate_data.buffer_norm;
|
||||
width = capture_width_norm;
|
||||
height = capture_height_norm;
|
||||
temp_buff = buffer_norm;
|
||||
} else {
|
||||
img = img_data->image_high;
|
||||
width = cnt->rotate_data.capture_width_high;
|
||||
height = cnt->rotate_data.capture_height_high;
|
||||
temp_buff = cnt->rotate_data.buffer_high;
|
||||
width = capture_width_high;
|
||||
height = capture_height_high;
|
||||
temp_buff = buffer_high;
|
||||
}
|
||||
/*
|
||||
* Pre-calculate some stuff:
|
||||
@@ -398,12 +187,12 @@ int rotate_map(struct context *cnt, struct image_data *img_data)
|
||||
break;
|
||||
}
|
||||
|
||||
switch (deg) {
|
||||
switch (degrees) {
|
||||
case 90:
|
||||
rot90cw(img, temp_buff, wh, width, height);
|
||||
rot90cw(img + wh, temp_buff + wh, wh4, w2, h2);
|
||||
rot90cw(img + wh + wh4, temp_buff + wh + wh4, wh4, w2, h2);
|
||||
memcpy(img, temp_buff, size);
|
||||
memcpy(img, temp_buff, (uint)size);
|
||||
break;
|
||||
case 180:
|
||||
reverse_inplace_quad(img, wh);
|
||||
@@ -414,15 +203,83 @@ int rotate_map(struct context *cnt, struct image_data *img_data)
|
||||
rot90ccw(img, temp_buff, wh, width, height);
|
||||
rot90ccw(img + wh, temp_buff + wh, wh4, w2, h2);
|
||||
rot90ccw(img + wh + wh4, temp_buff + wh + wh4, wh4, w2, h2);
|
||||
memcpy(img, temp_buff, size);
|
||||
memcpy(img, temp_buff, (uint)size);
|
||||
break;
|
||||
default:
|
||||
/* Invalid */
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
indx++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
cls_rotate::cls_rotate(cls_camera *p_cam)
|
||||
{
|
||||
cam = p_cam;
|
||||
int size_norm, size_high;
|
||||
|
||||
buffer_norm = nullptr;
|
||||
buffer_high = nullptr;
|
||||
|
||||
if ((cam->cfg->rotate % 90) > 0) {
|
||||
MOTPLS_LOG(WRN, TYPE_ALL, NO_ERRNO
|
||||
,_("Config option \"rotate\" not a multiple of 90: %d")
|
||||
,cam->cfg->rotate);
|
||||
cam->cfg->rotate = 0; /* Disable rotation. */
|
||||
degrees = 0; /* Force return below. */
|
||||
} else {
|
||||
degrees = cam->cfg->rotate % 360; /* Range: 0..359 */
|
||||
}
|
||||
|
||||
if (cam->cfg->flip_axis == "horizontal") {
|
||||
axis = FLIP_TYPE_HORIZONTAL;
|
||||
} else if (cam->cfg->flip_axis == "vertical") {
|
||||
axis = FLIP_TYPE_VERTICAL;
|
||||
} else {
|
||||
axis = FLIP_TYPE_NONE;
|
||||
}
|
||||
|
||||
/* At this point, imgs.width and imgs.height contain the capture dimensions.
|
||||
* If rotating 90 or 270 degrees, the output h/w will be swapped.
|
||||
*/
|
||||
|
||||
/* 1. Transfer capture dimensions into capture_width_norm and capture_height_norm. */
|
||||
capture_width_norm = cam->imgs.width;
|
||||
capture_height_norm = cam->imgs.height;
|
||||
|
||||
capture_width_high = cam->imgs.width_high;
|
||||
capture_height_high = cam->imgs.height_high;
|
||||
|
||||
size_norm = cam->imgs.width * cam->imgs.height * 3 / 2;
|
||||
size_high = cam->imgs.width_high * cam->imgs.height_high * 3 / 2;
|
||||
|
||||
/* "Swap" imgs.width and imgs.height. */
|
||||
if ((degrees == 90) || (degrees == 270)) {
|
||||
cam->imgs.width = capture_height_norm;
|
||||
cam->imgs.height = capture_width_norm;
|
||||
if (size_high > 0 ) {
|
||||
cam->imgs.width_high = capture_height_high;
|
||||
cam->imgs.height_high = capture_width_high;
|
||||
}
|
||||
}
|
||||
|
||||
if (degrees == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((degrees == 90) || (degrees == 270)) {
|
||||
buffer_norm =(u_char*) mymalloc((uint)size_norm);
|
||||
if (size_high > 0 ) {
|
||||
buffer_high =(u_char*) mymalloc((uint)size_high);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cls_rotate::~cls_rotate()
|
||||
{
|
||||
myfree(buffer_norm);
|
||||
myfree(buffer_high);
|
||||
|
||||
}
|
||||
|
||||
+50
-70
@@ -1,77 +1,57 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* rotate.h
|
||||
* Headers associated with functions in the rotate.c module.
|
||||
* Copyright 2004-2005, Per Jonsson (per@pjd.nu)
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef _INCLUDE_ROTATE_HPP_
|
||||
#define _INCLUDE_ROTATE_HPP_
|
||||
|
||||
#ifndef _INCLUDE_ROTATE_H
|
||||
#define _INCLUDE_ROTATE_H
|
||||
enum FLIP_TYPE {
|
||||
FLIP_TYPE_NONE,
|
||||
FLIP_TYPE_HORIZONTAL,
|
||||
FLIP_TYPE_VERTICAL
|
||||
};
|
||||
|
||||
/**
|
||||
* rotate_init
|
||||
*
|
||||
* Sets up rotation data by allocating a temporary buffer for 90/270 degrees
|
||||
* rotation, and by determining the right rotate-180-degrees function.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* cnt - current thread's context structure
|
||||
*
|
||||
* Returns: nothing
|
||||
*/
|
||||
void rotate_init(struct context *cnt);
|
||||
class cls_rotate {
|
||||
public:
|
||||
cls_rotate(cls_camera *p_cam);
|
||||
~cls_rotate();
|
||||
|
||||
/**
|
||||
* rotate_deinit
|
||||
*
|
||||
* Frees memory allocated by rotate_init.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* cnt - current thread's context structure
|
||||
*/
|
||||
void rotate_deinit(struct context *cnt);
|
||||
void process(ctx_image_data *img_data);
|
||||
|
||||
/**
|
||||
* rotate_map
|
||||
*
|
||||
* Rotates the image stored in img according to the rotation data
|
||||
* available in cnt. Rotation is performed clockwise. Supports 90,
|
||||
* 180 and 270 degrees rotation. 180 degrees rotation is performed
|
||||
* in-place by simply reversing the image data, which is a very
|
||||
* fast operation. 90 and 270 degrees rotation are performed using
|
||||
* a temporary buffer and a somewhat more complicated algorithm,
|
||||
* which makes them slower.
|
||||
*
|
||||
* Note that to the caller, all rotations will seem as they are
|
||||
* performed in-place.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* img_data - the image data to rotate
|
||||
* cnt - current thread's context structure
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* 0 - success
|
||||
* -1 - failure (rare, shouldn't happen)
|
||||
*/
|
||||
int rotate_map(struct context *cnt, struct image_data *img_data);
|
||||
private:
|
||||
cls_camera *cam;
|
||||
|
||||
#endif
|
||||
u_char *buffer_norm; /* Temp low res buffer for 90 and 270 degrees rotation */
|
||||
u_char *buffer_high; /* Temp high res buffer for 90 and 270 degrees rotation */
|
||||
int degrees; /* Degrees to rotate; */
|
||||
enum FLIP_TYPE axis; /* Rotate image over the Horizontal or Vertical axis. */
|
||||
|
||||
int capture_width_norm; /* Capture width of normal resolution image */
|
||||
int capture_height_norm; /* Capture height of normal resolution image */
|
||||
|
||||
int capture_width_high; /* Capture width of high resolution image */
|
||||
int capture_height_high; /* Capture height of high resolution image */
|
||||
|
||||
void reverse_inplace_quad(u_char *src, int size);
|
||||
void flip_inplace_horizontal(u_char *src, int width, int height);
|
||||
void flip_inplace_vertical(u_char *src, int width, int height);
|
||||
void rot90cw(u_char *src, u_char *dst, int size, int width, int height);
|
||||
void rot90ccw(u_char *src, u_char *dst, int size, int width, int height);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE_ROTATE_HPP_ */
|
||||
|
||||
@@ -0,0 +1,371 @@
|
||||
/*
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "motion.hpp"
|
||||
#include "util.hpp"
|
||||
#include "conf.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "camera.hpp"
|
||||
#include "netcam.hpp"
|
||||
#include "dbse.hpp"
|
||||
#include "schedule.hpp"
|
||||
|
||||
static void *schedule_handler(void *arg)
|
||||
{
|
||||
((cls_schedule *)arg)->handler();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void cls_schedule::schedule_cam(cls_camera *p_cam)
|
||||
{
|
||||
int indx, cur_dy;
|
||||
struct tm c_tm;
|
||||
struct timespec curr_ts;
|
||||
bool stopcam;
|
||||
|
||||
if ((restart == true) ||
|
||||
(handler_stop == true) ||
|
||||
(p_cam == nullptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_cam->schedule.size() != 7) {
|
||||
return;
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &curr_ts);
|
||||
localtime_r(&curr_ts.tv_sec, &c_tm);
|
||||
cur_dy = c_tm.tm_wday;
|
||||
|
||||
stopcam = false;
|
||||
for (indx=0; indx<p_cam->schedule[cur_dy].size(); indx++) {
|
||||
if ((p_cam->schedule[cur_dy][indx].action == "stop") &&
|
||||
(c_tm.tm_hour >= p_cam->schedule[cur_dy][indx].st_hr) &&
|
||||
(c_tm.tm_min >= p_cam->schedule[cur_dy][indx].st_min) &&
|
||||
(c_tm.tm_hour <= p_cam->schedule[cur_dy][indx].en_hr) &&
|
||||
(c_tm.tm_min <= p_cam->schedule[cur_dy][indx].en_min) ) {
|
||||
if (p_cam->schedule[cur_dy][indx].detect) {
|
||||
stopcam = false;
|
||||
} else {
|
||||
stopcam = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((stopcam == true) && (p_cam->handler_stop == false)) {
|
||||
p_cam->event_stop = true;
|
||||
p_cam->restart = false;
|
||||
p_cam->handler_stop = true;
|
||||
p_cam->finish = true;
|
||||
if (p_cam->camera_type == CAMERA_TYPE_NETCAM) {
|
||||
if (p_cam->netcam != nullptr) {
|
||||
p_cam->netcam->idur = 0;
|
||||
}
|
||||
if (p_cam->netcam_high != nullptr) {
|
||||
p_cam->netcam_high->idur = 0;
|
||||
}
|
||||
}
|
||||
p_cam->handler_shutdown();
|
||||
} else if ((stopcam == false) && (p_cam->handler_running == false)) {
|
||||
p_cam->handler_startup();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cls_schedule::cleandir_remove_dir(std::string dirnm)
|
||||
{
|
||||
DIR *dp;
|
||||
dirent *ep;
|
||||
|
||||
if ((restart == true) || (handler_stop == true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
dp = opendir(dirnm.c_str());
|
||||
if (dp != nullptr) {
|
||||
ep = readdir(dp);
|
||||
while(ep != nullptr) {
|
||||
if ((mystrne(ep->d_name,".") &&
|
||||
mystrne(ep->d_name,"..")) ||
|
||||
(restart == true) ||
|
||||
(handler_stop == true)) {
|
||||
closedir(dp);
|
||||
return;
|
||||
}
|
||||
ep = readdir(dp);
|
||||
}
|
||||
closedir(dp);
|
||||
MOTPLS_LOG(DBG, TYPE_ALL, NO_ERRNO
|
||||
, _("Removing empty directory %s"),dirnm.c_str());
|
||||
rmdir(dirnm.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void cls_schedule::cleandir_remove(std::string sql, bool removedir)
|
||||
{
|
||||
vec_files flst;
|
||||
struct stat statbuf;
|
||||
int indx;
|
||||
|
||||
app->dbse->filelist_get(sql, flst);
|
||||
|
||||
for (indx=0;indx<flst.size();indx++) {
|
||||
if (stat(flst[indx].full_nm.c_str(), &statbuf) == 0) {
|
||||
MOTPLS_LOG(DBG, TYPE_ALL, NO_ERRNO
|
||||
, _("Removing %s"),flst[indx].full_nm.c_str());
|
||||
remove(flst[indx].full_nm.c_str());
|
||||
sql = " delete from motion ";
|
||||
sql += " where record_id = ";
|
||||
sql += std::to_string(flst[indx].record_id);
|
||||
app->dbse->exec_sql(sql);
|
||||
}
|
||||
if (removedir == true) {
|
||||
cleandir_remove_dir(flst[indx].file_dir);
|
||||
}
|
||||
if ((restart == true) || (handler_stop == true)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cls_schedule::cleandir_sql(int device_id, std::string &sql, struct timespec ts)
|
||||
{
|
||||
struct tm c_tm;
|
||||
std::string tmp_dtl, tmp_tml;
|
||||
char tmp[50];
|
||||
|
||||
localtime_r(&ts.tv_sec, &c_tm);
|
||||
|
||||
sprintf(tmp, "%04d%02d%02d"
|
||||
,c_tm.tm_year+1900,c_tm.tm_mon+1,c_tm.tm_mday);
|
||||
tmp_dtl = tmp;
|
||||
|
||||
sprintf(tmp,"%02d:%02d",c_tm.tm_hour,c_tm.tm_min);
|
||||
tmp_tml = tmp;
|
||||
|
||||
sql = " select * ";
|
||||
sql += " from motion ";
|
||||
sql += " where ";
|
||||
sql += " device_id = " + std::to_string(device_id);
|
||||
sql += " and ((file_dtl < " + tmp_dtl + ") ";
|
||||
sql += " or ((file_dtl = " + tmp_dtl + ") ";
|
||||
sql += " and (file_tml < '" + tmp_tml + "'))) ";
|
||||
sql += " order by ";
|
||||
sql += " file_dtl, file_tml;";
|
||||
|
||||
}
|
||||
|
||||
void cls_schedule::cleandir_run(cls_camera *p_cam)
|
||||
{
|
||||
struct timespec test_ts;
|
||||
int64_t cdur;
|
||||
std::string sql;
|
||||
|
||||
if ((restart == true) || (handler_stop == true)) {
|
||||
return;
|
||||
}
|
||||
if (p_cam->cleandir->dur_unit == "m") {
|
||||
cdur = p_cam->cleandir->dur_val * (60);
|
||||
} else if (p_cam->cleandir->dur_unit == "h") {
|
||||
cdur = p_cam->cleandir->dur_val * (60 * 60);
|
||||
} else if (p_cam->cleandir->dur_unit == "d") {
|
||||
cdur = p_cam->cleandir->dur_val * (60 * 60 * 24);
|
||||
} else if (p_cam->cleandir->dur_unit == "w") {
|
||||
cdur = p_cam->cleandir->dur_val * (60 * 60 * 24 * 7);
|
||||
} else {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("Invalid clean directory duration units %s")
|
||||
,p_cam->cleandir->dur_unit.c_str());
|
||||
return;
|
||||
}
|
||||
if (cdur <= 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("Invalid clean directory duration %d%s")
|
||||
, p_cam->cleandir->dur_val
|
||||
, p_cam->cleandir->dur_unit.c_str());
|
||||
return;
|
||||
}
|
||||
test_ts = p_cam->cleandir->next_ts;
|
||||
test_ts.tv_sec -= cdur;
|
||||
|
||||
cleandir_sql(p_cam->cfg->device_id, sql, test_ts);
|
||||
cleandir_remove(sql, p_cam->cleandir->removedir);
|
||||
|
||||
}
|
||||
|
||||
void cls_schedule::cleandir_cam(cls_camera *p_cam)
|
||||
{
|
||||
struct tm c_tm;
|
||||
struct timespec curr_ts;
|
||||
|
||||
if ((restart == true) ||
|
||||
(handler_stop == true) ||
|
||||
(p_cam == nullptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_cam->cleandir == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &curr_ts);
|
||||
|
||||
if (curr_ts.tv_sec >= p_cam->cleandir->next_ts.tv_sec) {
|
||||
if (p_cam->cleandir->action == "delete") {
|
||||
cleandir_run(p_cam);
|
||||
} else {
|
||||
util_exec_command(p_cam, p_cam->cleandir->script);
|
||||
/* The dbse_clean function will eliminate any entries for deleted files*/
|
||||
}
|
||||
if (p_cam->cleandir->freq == "hourly") {
|
||||
p_cam->cleandir->next_ts.tv_sec += (60 * 60);
|
||||
} else if (p_cam->cleandir->freq == "daily") {
|
||||
p_cam->cleandir->next_ts.tv_sec += (60 * 60 * 24);
|
||||
} else if (p_cam->cleandir->freq == "weekly") {
|
||||
p_cam->cleandir->next_ts.tv_sec += (60 * 60 * 24 * 7);
|
||||
}
|
||||
localtime_r(&p_cam->cleandir->next_ts.tv_sec, &c_tm);
|
||||
if (p_cam->cleandir->action == "delete") {
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO
|
||||
, _("Cleandir next run:%04d-%02d-%02d %02d:%02d Criteria:%d%s RemoveDir:%s")
|
||||
,c_tm.tm_year+1900,c_tm.tm_mon+1,c_tm.tm_mday
|
||||
,c_tm.tm_hour,c_tm.tm_min
|
||||
,p_cam->cleandir->dur_val
|
||||
,p_cam->cleandir->dur_unit.c_str()
|
||||
,p_cam->cleandir->removedir ? "Y":"N");
|
||||
} else {
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO
|
||||
, _("Clean directory set to run script at %04d-%02d-%02d %02d:%02d")
|
||||
,c_tm.tm_year+1900,c_tm.tm_mon+1,c_tm.tm_mday
|
||||
,c_tm.tm_hour,c_tm.tm_min);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cls_schedule::timing()
|
||||
{
|
||||
int indx;
|
||||
for (indx=0; indx<30; indx++) {
|
||||
if ((restart == true) || (handler_stop == true)) {
|
||||
return;
|
||||
}
|
||||
SLEEP(1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void cls_schedule::handler()
|
||||
{
|
||||
int indx;
|
||||
|
||||
mythreadname_set("sh", 0, "schedule");
|
||||
|
||||
while (handler_stop == false) {
|
||||
for (indx=0; indx<app->cam_cnt; indx++) {
|
||||
schedule_cam(app->cam_list[indx]);
|
||||
}
|
||||
for (indx=0; indx<app->cam_cnt; indx++) {
|
||||
cleandir_cam(app->cam_list[indx]);
|
||||
}
|
||||
timing();
|
||||
}
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Schedule process closed"));
|
||||
handler_running = false;
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
void cls_schedule::handler_startup()
|
||||
{
|
||||
int retcd;
|
||||
pthread_attr_t thread_attr;
|
||||
|
||||
if (handler_running == false) {
|
||||
handler_running = true;
|
||||
handler_stop = false;
|
||||
restart = false;
|
||||
pthread_attr_init(&thread_attr);
|
||||
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
|
||||
retcd = pthread_create(&handler_thread, &thread_attr, &schedule_handler, this);
|
||||
if (retcd != 0) {
|
||||
MOTPLS_LOG(WRN, TYPE_ALL, NO_ERRNO,_("Unable to start schedule thread."));
|
||||
handler_running = false;
|
||||
handler_stop = true;
|
||||
}
|
||||
pthread_attr_destroy(&thread_attr);
|
||||
}
|
||||
}
|
||||
|
||||
void cls_schedule::handler_shutdown()
|
||||
{
|
||||
int waitcnt;
|
||||
|
||||
if (handler_running == true) {
|
||||
handler_stop = true;
|
||||
waitcnt = 0;
|
||||
while ((handler_running == true) && (waitcnt < app->cfg->watchdog_tmo)){
|
||||
SLEEP(1,0)
|
||||
waitcnt++;
|
||||
}
|
||||
if (waitcnt == app->cfg->watchdog_tmo) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("Normal shutdown of schedule thread failed"));
|
||||
if (app->cfg->watchdog_kill > 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
,_("Waiting additional %d seconds (watchdog_kill).")
|
||||
,app->cfg->watchdog_kill);
|
||||
waitcnt = 0;
|
||||
while ((handler_running == true) && (waitcnt < app->cfg->watchdog_kill)){
|
||||
SLEEP(1,0)
|
||||
waitcnt++;
|
||||
}
|
||||
if (waitcnt == app->cfg->watchdog_kill) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("No response to shutdown. Killing it."));
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("Memory leaks will occur."));
|
||||
pthread_kill(handler_thread, SIGVTALRM);
|
||||
}
|
||||
} else {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("watchdog_kill set to terminate application."));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
handler_running = false;
|
||||
watchdog = app->cfg->watchdog_tmo;
|
||||
}
|
||||
}
|
||||
|
||||
cls_schedule::cls_schedule(cls_motapp *p_app)
|
||||
{
|
||||
app = p_app;
|
||||
|
||||
handler_running = false;
|
||||
handler_stop = true;
|
||||
finish = false;
|
||||
watchdog = app->cfg->watchdog_tmo;
|
||||
|
||||
handler_startup();
|
||||
}
|
||||
|
||||
cls_schedule::~cls_schedule()
|
||||
{
|
||||
finish = true;
|
||||
handler_shutdown();
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SCHEDULE_HPP_
|
||||
#define _INCLUDE_SCHEDULE_HPP_
|
||||
|
||||
class cls_schedule {
|
||||
public:
|
||||
cls_schedule(cls_motapp *p_app);
|
||||
~cls_schedule();
|
||||
|
||||
bool handler_stop;
|
||||
bool handler_running;
|
||||
pthread_t handler_thread;
|
||||
void handler();
|
||||
|
||||
bool restart;
|
||||
bool finish;
|
||||
|
||||
private:
|
||||
cls_motapp *app;
|
||||
|
||||
int watchdog;
|
||||
|
||||
void handler_startup();
|
||||
void handler_shutdown();
|
||||
void timing();
|
||||
void cleandir_cam(cls_camera *p_cam);
|
||||
void cleandir_run(cls_camera *p_cam);
|
||||
void cleandir_remove(std::string sql, bool removedir);
|
||||
void cleandir_remove_dir(std::string dirnm);
|
||||
void cleandir_sql(int device_id, std::string &sql, struct timespec ts);
|
||||
void schedule_cam(cls_camera *p_cam);
|
||||
|
||||
};
|
||||
|
||||
#endif /*_INCLUDE_SCHEDULE_HPP_*/
|
||||
+962
@@ -0,0 +1,962 @@
|
||||
/*
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "motion.hpp"
|
||||
#include "util.hpp"
|
||||
#include "conf.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "sound.hpp"
|
||||
|
||||
static void *sound_handler(void *arg)
|
||||
{
|
||||
((cls_sound *)arg)->handler();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void cls_sound::init_values()
|
||||
{
|
||||
#ifdef HAVE_FFTW3
|
||||
snd_info->snd_fftw->bin_max = 0;
|
||||
snd_info->snd_fftw->bin_min = 0;
|
||||
snd_info->snd_fftw->bin_size = 0;
|
||||
snd_info->snd_fftw->ff_in = NULL;
|
||||
snd_info->snd_fftw->ff_out = NULL;
|
||||
snd_info->snd_fftw->ff_plan = NULL;
|
||||
#endif
|
||||
snd_info->sample_rate = 0;
|
||||
snd_info->channels = 0;
|
||||
snd_info->vol_count = 0;
|
||||
snd_info->vol_max = 0;
|
||||
snd_info->vol_min = 9999;
|
||||
snd_info->buffer = NULL;
|
||||
snd_info->buffer_size = 0;
|
||||
snd_info->pulse_server = "";
|
||||
}
|
||||
|
||||
void cls_sound::init_alerts(ctx_snd_alert *tmp_alert)
|
||||
{
|
||||
tmp_alert->alert_id = 0;
|
||||
tmp_alert->alert_nm = "";
|
||||
tmp_alert->freq_high = 10000;
|
||||
tmp_alert->freq_low = 0;
|
||||
tmp_alert->volume_count = 0;
|
||||
tmp_alert->volume_level = 0;
|
||||
tmp_alert->trigger_count = 0;
|
||||
tmp_alert->trigger_threshold = 10;
|
||||
tmp_alert->trigger_duration = 10;
|
||||
clock_gettime(CLOCK_MONOTONIC, &tmp_alert->trigger_time);
|
||||
|
||||
}
|
||||
|
||||
void cls_sound::edit_alerts()
|
||||
{
|
||||
std::list<ctx_snd_alert>::iterator it_a0;
|
||||
std::list<ctx_snd_alert>::iterator it_a1;
|
||||
int indx, id_chk, id_cnt;
|
||||
bool validids;
|
||||
|
||||
validids = true;
|
||||
for (it_a0=snd_info->alerts.begin(); it_a0!=snd_info->alerts.end(); it_a0++) {
|
||||
id_chk = it_a0->alert_id;
|
||||
id_cnt = 0;
|
||||
for (it_a1=snd_info->alerts.begin(); it_a1!=snd_info->alerts.end(); it_a1++) {
|
||||
if (id_chk == it_a1->alert_id) {
|
||||
id_cnt++;
|
||||
}
|
||||
}
|
||||
if (id_cnt > 1) {
|
||||
validids = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (validids == false) {
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, "Sound alert ids must be unique.");
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, "Creating new sound alert ids.");
|
||||
indx = 0;
|
||||
for (it_a0=snd_info->alerts.begin(); it_a0!=snd_info->alerts.end(); it_a0++) {
|
||||
it_a0->alert_id = indx;
|
||||
indx++;
|
||||
}
|
||||
}
|
||||
|
||||
for (it_a0=snd_info->alerts.begin(); it_a0!=snd_info->alerts.end(); it_a0++) {
|
||||
if (it_a0->alert_nm == "") {
|
||||
it_a0->alert_nm = "sound_alert" + std::to_string(it_a0->alert_id);
|
||||
}
|
||||
if (it_a0->volume_level < snd_info->vol_min) {
|
||||
snd_info->vol_min = it_a0->volume_level;
|
||||
}
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO, "Sound Alert Parameters:");
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO, " alert_id: %d",it_a0->alert_id);
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO, " alert_nm %s",it_a0->alert_nm.c_str());
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO, " freq_low: %.4f",it_a0->freq_low);
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO, " freq_high: %.4f",it_a0->freq_high);
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO, " volume_count: %d",it_a0->volume_count);
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO, " volume_level: %d",it_a0->volume_level);
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO, " trigger_threshold: %d",it_a0->trigger_threshold);
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO, " trigger_duration: %d",it_a0->trigger_duration);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cls_sound::load_alerts()
|
||||
{
|
||||
ctx_snd_alert tmp_alert;
|
||||
std::list<std::string> parm_val;
|
||||
std::list<std::string>::iterator it_a;
|
||||
ctx_params *tmp_params;
|
||||
ctx_params_item *itm;
|
||||
int indx;
|
||||
|
||||
cfg->edit_get("snd_alerts", parm_val, PARM_CAT_18);
|
||||
|
||||
tmp_params = new ctx_params;
|
||||
for (it_a=parm_val.begin(); it_a!=parm_val.end(); it_a++) {
|
||||
util_parms_parse(tmp_params,"snd_alerts", it_a->c_str());
|
||||
init_alerts(&tmp_alert);
|
||||
for (indx=0;indx<tmp_params->params_cnt;indx++) {
|
||||
itm = &tmp_params->params_array[indx];
|
||||
if (itm->param_name == "alert_id") {
|
||||
tmp_alert.alert_id = mtoi(itm->param_value);
|
||||
}
|
||||
if (itm->param_name == "alert_nm") {
|
||||
tmp_alert.alert_nm = itm->param_value;
|
||||
}
|
||||
if (itm->param_name == "freq_low") {
|
||||
tmp_alert.freq_low = mtof(itm->param_value);
|
||||
}
|
||||
if (itm->param_name == "freq_high") {
|
||||
tmp_alert.freq_high = mtof(itm->param_value);
|
||||
}
|
||||
if (itm->param_name == "volume_count") {
|
||||
tmp_alert.volume_count = mtoi(itm->param_value);
|
||||
}
|
||||
if (itm->param_name == "volume_level") {
|
||||
tmp_alert.volume_level = mtoi(itm->param_value);
|
||||
}
|
||||
if (itm->param_name == "trigger_threshold") {
|
||||
tmp_alert.trigger_threshold = mtoi(itm->param_value);
|
||||
}
|
||||
if (itm->param_name == "trigger_duration") {
|
||||
tmp_alert.trigger_duration = mtoi(itm->param_value);
|
||||
}
|
||||
}
|
||||
snd_info->alerts.push_back(tmp_alert);
|
||||
}
|
||||
|
||||
mydelete(tmp_params);
|
||||
|
||||
edit_alerts();
|
||||
}
|
||||
|
||||
void cls_sound::load_params()
|
||||
{
|
||||
int indx;
|
||||
ctx_params_item *itm;
|
||||
|
||||
util_parms_parse(snd_info->params,"snd_params", cfg->snd_params);
|
||||
|
||||
util_parms_add_default(snd_info->params,"source","alsa");
|
||||
util_parms_add_default(snd_info->params,"channels","1");
|
||||
util_parms_add_default(snd_info->params,"frames","2048");
|
||||
util_parms_add_default(snd_info->params,"sample_rate","44100");
|
||||
|
||||
for (indx=0;indx<snd_info->params->params_cnt;indx++) {
|
||||
itm = &snd_info->params->params_array[indx];
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, "%s : %s"
|
||||
,itm->param_name.c_str(),itm->param_value.c_str());
|
||||
}
|
||||
|
||||
for (indx=0;indx<snd_info->params->params_cnt;indx++) {
|
||||
itm = &snd_info->params->params_array[indx];
|
||||
if (itm->param_name == "source") {
|
||||
snd_info->source = itm->param_value;
|
||||
}
|
||||
if (itm->param_name == "channels") {
|
||||
snd_info->channels = mtoi(itm->param_value);
|
||||
}
|
||||
if (itm->param_name == "frames") {
|
||||
snd_info->frames = mtoi(itm->param_value);
|
||||
}
|
||||
if (itm->param_name == "sample_rate") {
|
||||
snd_info->sample_rate = mtoi(itm->param_value);
|
||||
}
|
||||
if (itm->param_name == "pulse_server") {
|
||||
snd_info->pulse_server = itm->param_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_ALSA /************ Start ALSA *******************/
|
||||
|
||||
void cls_sound::alsa_list_subdev()
|
||||
{
|
||||
ctx_snd_alsa *alsa = snd_info->snd_alsa;
|
||||
int indx, retcd, cnt;
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Card %i(%s): %s [%s]")
|
||||
, alsa->card_id, alsa->device_nm.c_str()
|
||||
, snd_ctl_card_info_get_id(alsa->card_info)
|
||||
, snd_ctl_card_info_get_name(alsa->card_info));
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _(" Device %i (%s,%d): %s [%s]")
|
||||
, alsa->device_id, alsa->device_nm.c_str()
|
||||
, alsa->device_id
|
||||
, snd_pcm_info_get_id(alsa->pcm_info)
|
||||
, snd_pcm_info_get_name(alsa->pcm_info));
|
||||
|
||||
cnt = (int)snd_pcm_info_get_subdevices_count(alsa->pcm_info);
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _(" Subdevices: %i/%i")
|
||||
, snd_pcm_info_get_subdevices_avail(alsa->pcm_info),cnt);
|
||||
|
||||
for (indx=0; indx<cnt; indx++) {
|
||||
snd_pcm_info_set_subdevice(alsa->pcm_info, (uint)indx);
|
||||
retcd = snd_ctl_pcm_info(alsa->ctl_hdl, alsa->pcm_info);
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("control digital audio playback info (%i): %s")
|
||||
, alsa->card_id, snd_strerror(retcd));
|
||||
} else {
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO
|
||||
, _(" Subdevice #%i: %s"), indx
|
||||
, snd_pcm_info_get_subdevice_name(alsa->pcm_info));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cls_sound::alsa_list_card()
|
||||
{
|
||||
ctx_snd_alsa *alsa = snd_info->snd_alsa;
|
||||
int retcd;
|
||||
|
||||
retcd = snd_ctl_card_info(alsa->ctl_hdl, alsa->card_info);
|
||||
if (retcd < 0) {
|
||||
snd_ctl_close(alsa->ctl_hdl);
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("control hardware info (%i): %s")
|
||||
, alsa->card_id, snd_strerror(retcd));
|
||||
return;
|
||||
}
|
||||
|
||||
alsa->device_id = -1;
|
||||
retcd = snd_ctl_pcm_next_device(alsa->ctl_hdl, &alsa->device_id);
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("snd_ctl_pcm_next_device"));
|
||||
return;
|
||||
}
|
||||
|
||||
while (alsa->device_id >= 0) {
|
||||
snd_pcm_info_set_device(alsa->pcm_info, (uint)alsa->device_id);
|
||||
snd_pcm_info_set_subdevice(alsa->pcm_info, 0);
|
||||
snd_pcm_info_set_stream(alsa->pcm_info, SND_PCM_STREAM_CAPTURE);
|
||||
retcd = snd_ctl_pcm_info(alsa->ctl_hdl, alsa->pcm_info);
|
||||
if (retcd == 0) {
|
||||
alsa_list_subdev();
|
||||
} else if (retcd != -ENOENT){
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("control digital audio info (%i): %s")
|
||||
, alsa->card_id, snd_strerror(retcd));
|
||||
}
|
||||
retcd = snd_ctl_pcm_next_device(alsa->ctl_hdl, &alsa->device_id);
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("snd_ctl_pcm_next_device"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cls_sound::alsa_list()
|
||||
{
|
||||
ctx_snd_alsa *alsa = snd_info->snd_alsa;
|
||||
int retcd;
|
||||
|
||||
if (device_status == STATUS_CLOSED) {
|
||||
return;
|
||||
}
|
||||
|
||||
snd_ctl_card_info_alloca(&alsa->card_info);
|
||||
snd_pcm_info_alloca(&alsa->pcm_info);
|
||||
|
||||
alsa->card_id = -1;
|
||||
retcd = snd_card_next(&alsa->card_id);
|
||||
if ((retcd < 0) || (alsa->card_id == -1)) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("no soundcards found..."));
|
||||
device_status = STATUS_CLOSED;
|
||||
return;
|
||||
}
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Devices"));
|
||||
|
||||
while (alsa->card_id >= 0) {
|
||||
alsa->device_nm="hw:"+std::to_string(alsa->card_id);
|
||||
retcd = snd_ctl_open(&alsa->ctl_hdl, alsa->device_nm.c_str(), 0);
|
||||
if (retcd == 0) {
|
||||
alsa_list_card();
|
||||
snd_ctl_close(alsa->ctl_hdl);
|
||||
} else {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("control open (%i): %s")
|
||||
, alsa->card_id, snd_strerror(retcd));
|
||||
}
|
||||
snd_card_next(&alsa->card_id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cls_sound::alsa_start()
|
||||
{
|
||||
ctx_snd_alsa *alsa = snd_info->snd_alsa;
|
||||
snd_pcm_hw_params_t *hw_params;
|
||||
snd_pcm_uframes_t frames_per;
|
||||
snd_pcm_format_t actl_sndfmt;
|
||||
unsigned int actl_rate, smpl_rate;
|
||||
int retcd;
|
||||
|
||||
frames_per = (uint)snd_info->frames;
|
||||
smpl_rate = (unsigned int)snd_info->sample_rate;
|
||||
|
||||
retcd = snd_pcm_open(&alsa->pcm_dev
|
||||
, cfg->snd_device.c_str(), SND_PCM_STREAM_CAPTURE, 0);
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("error: snd_pcm_open device %s (%s)")
|
||||
, cfg->snd_device.c_str(), snd_strerror (retcd));
|
||||
device_status = STATUS_CLOSED;
|
||||
return;
|
||||
}
|
||||
|
||||
retcd = snd_pcm_hw_params_malloc(&hw_params);
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("error: snd_pcm_hw_params_malloc(%s)")
|
||||
, snd_strerror (retcd));
|
||||
device_status = STATUS_CLOSED;
|
||||
return;
|
||||
}
|
||||
|
||||
retcd = snd_pcm_hw_params_any(alsa->pcm_dev, hw_params);
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("error: snd_pcm_hw_params_any(%s)")
|
||||
, snd_strerror (retcd));
|
||||
device_status = STATUS_CLOSED;
|
||||
return;
|
||||
}
|
||||
|
||||
retcd = snd_pcm_hw_params_set_access(alsa->pcm_dev
|
||||
, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("error: snd_pcm_hw_params_set_access(%s)")
|
||||
, snd_strerror (retcd));
|
||||
device_status = STATUS_CLOSED;
|
||||
return;
|
||||
}
|
||||
|
||||
retcd = snd_pcm_hw_params_set_format(alsa->pcm_dev
|
||||
, hw_params, SND_PCM_FORMAT_S16_LE);
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("error: snd_pcm_hw_params_set_format(%s)")
|
||||
, snd_strerror (retcd));
|
||||
device_status = STATUS_CLOSED;
|
||||
return;
|
||||
}
|
||||
|
||||
retcd = snd_pcm_hw_params_set_rate_near(alsa->pcm_dev
|
||||
, hw_params, &smpl_rate, 0);
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("error: snd_pcm_hw_params_set_rate_near(%s)")
|
||||
, snd_strerror (retcd));
|
||||
device_status = STATUS_CLOSED;
|
||||
return;
|
||||
}
|
||||
|
||||
retcd = snd_pcm_hw_params_set_channels(alsa->pcm_dev
|
||||
, hw_params, (uint)snd_info->channels);
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("error: snd_pcm_hw_params_set_channels(%s)")
|
||||
, snd_strerror (retcd));
|
||||
device_status = STATUS_CLOSED;
|
||||
return;
|
||||
}
|
||||
|
||||
retcd = snd_pcm_hw_params_set_period_size_near(alsa->pcm_dev
|
||||
, hw_params, &frames_per, NULL);
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("error: snd_pcm_hw_params_set_period_size_near(%s)")
|
||||
, snd_strerror (retcd));
|
||||
device_status = STATUS_CLOSED;
|
||||
return;
|
||||
}
|
||||
|
||||
retcd = snd_pcm_hw_params(alsa->pcm_dev, hw_params);
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("error: snd_pcm_hw_params(%s)")
|
||||
, snd_strerror (retcd));
|
||||
device_status = STATUS_CLOSED;
|
||||
return;
|
||||
}
|
||||
|
||||
retcd = snd_pcm_prepare(alsa->pcm_dev);
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("error: snd_pcm_prepare(%s)")
|
||||
, snd_strerror (retcd));
|
||||
device_status = STATUS_CLOSED;
|
||||
return;
|
||||
}
|
||||
|
||||
/* get actual parms selected */
|
||||
retcd = snd_pcm_hw_params_get_format(hw_params, &actl_sndfmt);
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("error: snd_pcm_hw_params_get_format(%s)")
|
||||
, snd_strerror (retcd));
|
||||
device_status = STATUS_CLOSED;
|
||||
return;
|
||||
}
|
||||
|
||||
retcd = snd_pcm_hw_params_get_rate(hw_params, &actl_rate, NULL);
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("error: snd_pcm_hw_params_get_rate(%s)")
|
||||
, snd_strerror (retcd));
|
||||
device_status = STATUS_CLOSED;
|
||||
return;
|
||||
}
|
||||
|
||||
retcd = snd_pcm_hw_params_get_period_size(hw_params, &frames_per, NULL);
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("error: snd_pcm_hw_params_get_period_size(%s)")
|
||||
, snd_strerror (retcd));
|
||||
device_status = STATUS_CLOSED;
|
||||
return;
|
||||
}
|
||||
|
||||
snd_pcm_hw_params_free(hw_params);
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Actual rate %hu"), actl_rate);
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Actual frames per %lu"), frames_per);
|
||||
if (actl_sndfmt <= 5) {
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Sound format 16"));
|
||||
} else if (actl_sndfmt <= 9 ) {
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Sound format 24"));
|
||||
} else {
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Sound format 32"));
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
/** allocate and initialize the sound buffers */
|
||||
/*************************************************************/
|
||||
snd_info->frames = (int)frames_per;
|
||||
snd_info->buffer_size = snd_info->frames * 2;
|
||||
snd_info->buffer = (int16_t*)mymalloc(
|
||||
(uint)snd_info->buffer_size * sizeof(int16_t));
|
||||
memset(snd_info->buffer, 0x00
|
||||
, (uint)snd_info->buffer_size * sizeof(int16_t));
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, "Started.");
|
||||
device_status =STATUS_OPENED;
|
||||
|
||||
}
|
||||
|
||||
void cls_sound::alsa_init()
|
||||
{
|
||||
ctx_snd_alsa *alsa = snd_info->snd_alsa;
|
||||
|
||||
if (snd_info->source != "alsa") {
|
||||
return;
|
||||
}
|
||||
|
||||
alsa->pcm_dev = NULL;
|
||||
alsa->pcm_info = NULL;
|
||||
alsa->card_id = -1;
|
||||
alsa->card_info = NULL;
|
||||
alsa->pcm_dev = NULL;
|
||||
alsa->ctl_hdl = NULL;
|
||||
alsa->card_info = NULL;
|
||||
alsa->card_id = 0;
|
||||
alsa->pcm_info = NULL;
|
||||
alsa->device_nm = "";
|
||||
alsa->device_id = 0;
|
||||
|
||||
alsa_list();
|
||||
alsa_start();
|
||||
}
|
||||
|
||||
void cls_sound::alsa_capture()
|
||||
{
|
||||
ctx_snd_alsa *alsa = snd_info->snd_alsa;
|
||||
long int retcd;
|
||||
|
||||
if (snd_info->source != "alsa") {
|
||||
return;
|
||||
}
|
||||
retcd = snd_pcm_readi(alsa->pcm_dev
|
||||
, snd_info->buffer, (uint)snd_info->frames);
|
||||
if (retcd != snd_info->frames) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("error: read from audio interface failed (%s)")
|
||||
, snd_strerror((int)retcd));
|
||||
device_status = STATUS_CLOSED;
|
||||
}
|
||||
}
|
||||
|
||||
void cls_sound::alsa_cleanup()
|
||||
{
|
||||
if (snd_info->source != "alsa") {
|
||||
return;
|
||||
}
|
||||
if (snd_info->snd_alsa->pcm_dev != NULL) {
|
||||
snd_pcm_close(snd_info->snd_alsa->pcm_dev);
|
||||
snd_config_update_free_global();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /************ End ALSA *******************/
|
||||
|
||||
#ifdef HAVE_PULSE /************ Start PULSE *******************/
|
||||
|
||||
void cls_sound::pulse_init()
|
||||
{
|
||||
pa_sample_spec specs;
|
||||
int errcd;
|
||||
|
||||
if (snd_info->source != "pulse") {
|
||||
return;
|
||||
}
|
||||
|
||||
specs.format = PA_SAMPLE_S16LE;
|
||||
specs.rate = (uint32_t)snd_info->sample_rate;
|
||||
specs.channels = (uint8_t)snd_info->channels;
|
||||
|
||||
snd_info->snd_pulse->dev = NULL;
|
||||
snd_info->snd_pulse->dev = pa_simple_new(
|
||||
(snd_info->pulse_server=="" ? NULL : snd_info->pulse_server.c_str())
|
||||
, "motion", PA_STREAM_RECORD
|
||||
, (cfg->snd_device=="" ? NULL : cfg->snd_device.c_str())
|
||||
, "motion", &specs, NULL, NULL, &errcd);
|
||||
if (snd_info->snd_pulse->dev == NULL) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("Error opening pulse (%s)")
|
||||
, pa_strerror(errcd));
|
||||
device_status = STATUS_CLOSED;
|
||||
return;
|
||||
}
|
||||
snd_info->buffer_size = snd_info->frames * 2;
|
||||
snd_info->buffer = (int16_t*)mymalloc(
|
||||
(uint)snd_info->buffer_size * sizeof(int16_t));
|
||||
memset(snd_info->buffer, 0x00
|
||||
, (uint)snd_info->buffer_size * sizeof(int16_t));
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, "Started.");
|
||||
device_status =STATUS_OPENED;
|
||||
|
||||
}
|
||||
|
||||
void cls_sound::pulse_capture()
|
||||
{
|
||||
ctx_snd_pulse *pulse = snd_info->snd_pulse;
|
||||
int errcd, retcd;
|
||||
|
||||
if (snd_info->source != "pulse") {
|
||||
return;
|
||||
}
|
||||
|
||||
retcd = pa_simple_read(pulse->dev, snd_info->buffer
|
||||
, (uint)snd_info->buffer_size, &errcd);
|
||||
if (retcd < 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("Error capturing PulseAudio (%s)")
|
||||
, pa_strerror(errcd));
|
||||
device_status = STATUS_CLOSED;
|
||||
}
|
||||
}
|
||||
|
||||
void cls_sound::pulse_cleanup()
|
||||
{
|
||||
if (snd_info->source != "pulse") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (snd_info->snd_pulse->dev != NULL) {
|
||||
pa_simple_free(snd_info->snd_pulse->dev);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /************ End PULSE *******************/
|
||||
|
||||
#ifdef HAVE_FFTW3 /************ Start FFTW3 *******************/
|
||||
|
||||
void cls_sound::fftw_open()
|
||||
{
|
||||
ctx_snd_fftw *fftw = snd_info->snd_fftw;
|
||||
int indx;
|
||||
|
||||
if (device_status == STATUS_CLOSED) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO
|
||||
, _("Opening FFTW plan"));
|
||||
|
||||
fftw->ff_in = (double*) fftw_malloc(
|
||||
sizeof(fftw_complex) * (uint)snd_info->frames);
|
||||
fftw->ff_out = (fftw_complex*) fftw_malloc(
|
||||
sizeof(fftw_complex) * (uint)snd_info->frames);
|
||||
fftw->ff_plan = fftw_plan_dft_r2c_1d(
|
||||
snd_info->frames, fftw->ff_in, fftw->ff_out, FFTW_MEASURE);
|
||||
|
||||
for (indx=0; indx<snd_info->frames; indx++) {
|
||||
fftw->ff_in[indx] = 0;
|
||||
}
|
||||
fftw->bin_min = 1;
|
||||
fftw->bin_max = (snd_info->frames / 2);
|
||||
fftw->bin_size = ((float)snd_info->sample_rate / (float)snd_info->frames);
|
||||
|
||||
}
|
||||
|
||||
float cls_sound::HammingWindow(int n1, int N2){
|
||||
return 0.54F - 0.46F * (float)(cos((2 * M_PI * n1)) / (N2 - 1));
|
||||
}
|
||||
|
||||
float cls_sound::HannWindow(int n1, int N2){
|
||||
return 0.5F * (float)(1 - (cos(2 * M_PI * n1 * N2)));
|
||||
}
|
||||
|
||||
void cls_sound::check_alerts()
|
||||
{
|
||||
double freq_value;
|
||||
int indx, chkval, chkcnt;
|
||||
double pMaxIntensity;
|
||||
int pMaxBinIndex;
|
||||
double pRealNbr;
|
||||
double pImaginaryNbr;
|
||||
double pIntensity;
|
||||
bool trigger;
|
||||
std::list<ctx_snd_alert>::iterator it;
|
||||
struct timespec trig_ts;
|
||||
|
||||
for (indx=0;indx <snd_info->frames;indx++){
|
||||
if (cfg->snd_window == "hamming") {
|
||||
snd_info->snd_fftw->ff_in[indx] =
|
||||
snd_info->buffer[indx] * HammingWindow(indx, snd_info->frames);
|
||||
} else if (cfg->snd_window == "hann") {
|
||||
snd_info->snd_fftw->ff_in[indx] =
|
||||
snd_info->buffer[indx] * HannWindow(indx, snd_info->frames);
|
||||
} else {
|
||||
snd_info->snd_fftw->ff_in[indx] = snd_info->buffer[indx];
|
||||
}
|
||||
}
|
||||
|
||||
fftw_execute(snd_info->snd_fftw->ff_plan);
|
||||
|
||||
pMaxIntensity = 0;
|
||||
pMaxBinIndex = 0;
|
||||
|
||||
for (indx = snd_info->snd_fftw->bin_min;
|
||||
indx <= snd_info->snd_fftw->bin_max; indx++) {
|
||||
pRealNbr = snd_info->snd_fftw->ff_out[indx][0];
|
||||
pImaginaryNbr = snd_info->snd_fftw->ff_out[indx][1];
|
||||
pIntensity = pRealNbr * pRealNbr + pImaginaryNbr * pImaginaryNbr;
|
||||
if (pIntensity > pMaxIntensity){
|
||||
pMaxIntensity = pIntensity;
|
||||
pMaxBinIndex = indx;
|
||||
}
|
||||
}
|
||||
|
||||
freq_value = (snd_info->snd_fftw->bin_size * pMaxBinIndex * snd_info->channels);
|
||||
|
||||
if (cfg->snd_show) {
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO
|
||||
, _("Freq: %.4f threshold: %d count: %d maximum: %d")
|
||||
, freq_value, snd_info->vol_min
|
||||
, snd_info->vol_count, snd_info->vol_max);
|
||||
}
|
||||
|
||||
for (it=snd_info->alerts.begin(); it!=snd_info->alerts.end(); it++) {
|
||||
trigger = false;
|
||||
if ((freq_value >= it->freq_low) && (freq_value <= it->freq_high)) {
|
||||
chkcnt = 0;
|
||||
for(indx=0; indx < snd_info->frames; indx++) {
|
||||
chkval = abs((int)snd_info->buffer[indx] / 256);
|
||||
if (chkval >= it->volume_level) {
|
||||
chkcnt++;
|
||||
}
|
||||
}
|
||||
if (chkcnt >= it->volume_count) {
|
||||
trigger = true;
|
||||
}
|
||||
}
|
||||
if (trigger) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &trig_ts);
|
||||
if ((trig_ts.tv_sec - it->trigger_time.tv_sec) > it->trigger_duration) {
|
||||
it->trigger_count = 1;
|
||||
} else {
|
||||
it->trigger_count++;
|
||||
}
|
||||
clock_gettime(CLOCK_MONOTONIC, &it->trigger_time);
|
||||
|
||||
if (it->trigger_count == it->trigger_threshold) {
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO
|
||||
, _("Sound Alert %d-%s : level %d count %d max vol %d")
|
||||
, it->alert_id ,it->alert_nm.c_str()
|
||||
, it->volume_level, chkcnt
|
||||
, snd_info->vol_max);
|
||||
if (cfg->on_sound_alert != "") {
|
||||
snd_info->trig_freq =std::to_string(freq_value);
|
||||
snd_info->trig_nbr = std::to_string(it->alert_id);
|
||||
snd_info->trig_nm = it->alert_nm;
|
||||
util_exec_command(this, cfg->on_sound_alert);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /************ End FFTW3 *******************/
|
||||
|
||||
void cls_sound::capture()
|
||||
{
|
||||
if (device_status == STATUS_CLOSED) {
|
||||
return;
|
||||
}
|
||||
#ifdef HAVE_ALSA
|
||||
alsa_capture();
|
||||
#endif
|
||||
#ifdef HAVE_PULSE
|
||||
pulse_capture();
|
||||
#endif
|
||||
}
|
||||
|
||||
void cls_sound::cleanup()
|
||||
{
|
||||
#ifdef HAVE_ALSA
|
||||
alsa_cleanup();
|
||||
#endif
|
||||
#ifdef HAVE_PULSE
|
||||
pulse_cleanup();
|
||||
#endif
|
||||
#ifdef HAVE_FFTW3
|
||||
fftw_destroy_plan(snd_info->snd_fftw->ff_plan);
|
||||
fftw_free(snd_info->snd_fftw->ff_in);
|
||||
fftw_free(snd_info->snd_fftw->ff_out);
|
||||
#endif
|
||||
if (snd_info->buffer != NULL) {
|
||||
free(snd_info->buffer);
|
||||
snd_info->buffer = NULL;
|
||||
}
|
||||
|
||||
mydelete(snd_info->snd_alsa);
|
||||
mydelete(snd_info->snd_fftw);
|
||||
mydelete(snd_info->snd_pulse);
|
||||
mydelete(snd_info->params);
|
||||
mydelete(snd_info);
|
||||
|
||||
device_status = STATUS_CLOSED;
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, "Stopped.");
|
||||
|
||||
}
|
||||
|
||||
void cls_sound::init()
|
||||
{
|
||||
if ((device_status != STATUS_INIT) && (restart == false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (restart == true) {
|
||||
cleanup();
|
||||
restart = false;
|
||||
}
|
||||
|
||||
cfg->parms_copy(conf_src);
|
||||
|
||||
mythreadname_set("sl",cfg->device_id, cfg->device_name.c_str());
|
||||
|
||||
MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO,_("Initialize sound frequency"));
|
||||
|
||||
snd_info = new ctx_snd_info;
|
||||
snd_info->params = new ctx_params;
|
||||
snd_info->snd_fftw = new ctx_snd_fftw;
|
||||
snd_info->snd_alsa = new ctx_snd_alsa;
|
||||
snd_info->snd_pulse = new ctx_snd_pulse;
|
||||
|
||||
init_values();
|
||||
load_params();
|
||||
load_alerts();
|
||||
|
||||
if ((snd_info->source != "alsa") &&
|
||||
(snd_info->source != "pulse")) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO,_("Invalid sound source."));
|
||||
device_status = STATUS_CLOSED;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ALSA
|
||||
alsa_init();
|
||||
#endif
|
||||
#ifdef HAVE_PULSE
|
||||
pulse_init();
|
||||
#endif
|
||||
#ifdef HAVE_FFTW3
|
||||
fftw_open();
|
||||
#endif
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Detecting"));
|
||||
|
||||
}
|
||||
|
||||
void cls_sound::check_levels()
|
||||
{
|
||||
#ifdef HAVE_FFTW3
|
||||
int indx, chkval;
|
||||
|
||||
if (device_status == STATUS_CLOSED) {
|
||||
return;
|
||||
}
|
||||
|
||||
snd_info->vol_max = 0;
|
||||
snd_info->vol_count = 0;
|
||||
|
||||
for(indx=0; indx < snd_info->frames; indx++) {
|
||||
chkval = abs((int)snd_info->buffer[indx] / 256);
|
||||
if (chkval > snd_info->vol_max) snd_info->vol_max = chkval ;
|
||||
if (chkval > snd_info->vol_min) snd_info->vol_count++;
|
||||
}
|
||||
|
||||
if (snd_info->vol_count > 0) {
|
||||
check_alerts();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void cls_sound::handler()
|
||||
{
|
||||
device_status = STATUS_INIT;
|
||||
|
||||
while (handler_stop == false) {
|
||||
watchdog = cfg->watchdog_tmo;
|
||||
init();
|
||||
capture();
|
||||
check_levels();
|
||||
if (device_status == STATUS_CLOSED) {
|
||||
handler_stop = true;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup();
|
||||
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Sound exiting"));
|
||||
|
||||
handler_running = false;
|
||||
pthread_exit(nullptr);
|
||||
}
|
||||
|
||||
void cls_sound::handler_startup()
|
||||
{
|
||||
int retcd;
|
||||
pthread_attr_t thread_attr;
|
||||
|
||||
#if !defined(HAVE_FFTW3) || (!defined(HAVE_ALSA) && !defined(HAVE_PULSE))
|
||||
MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Required packages not installed"));
|
||||
device_status = STATUS_CLOSED;
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (handler_running == false) {
|
||||
handler_running = true;
|
||||
handler_stop = false;
|
||||
pthread_attr_init(&thread_attr);
|
||||
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
|
||||
retcd = pthread_create(&handler_thread, &thread_attr, &sound_handler, this);
|
||||
if (retcd != 0) {
|
||||
MOTPLS_LOG(WRN, TYPE_ALL, NO_ERRNO,_("Unable to start sound frequency detection loop."));
|
||||
handler_running = false;
|
||||
handler_stop = true;
|
||||
}
|
||||
pthread_attr_destroy(&thread_attr);
|
||||
}
|
||||
}
|
||||
|
||||
void cls_sound::handler_shutdown()
|
||||
{
|
||||
int waitcnt;
|
||||
|
||||
if (handler_running == true) {
|
||||
handler_stop = true;
|
||||
waitcnt = 0;
|
||||
while ((handler_running == true) && (waitcnt < cfg->watchdog_tmo)){
|
||||
SLEEP(1,0)
|
||||
waitcnt++;
|
||||
}
|
||||
if (waitcnt == cfg->watchdog_tmo) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("Normal shutdown of sound frequency detection failed"));
|
||||
if (cfg->watchdog_kill > 0) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
,_("Waiting additional %d seconds (watchdog_kill).")
|
||||
,cfg->watchdog_kill);
|
||||
waitcnt = 0;
|
||||
while ((handler_running == true) && (waitcnt < cfg->watchdog_kill)){
|
||||
SLEEP(1,0)
|
||||
waitcnt++;
|
||||
}
|
||||
if (waitcnt == cfg->watchdog_kill) {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("No response to shutdown. Killing it."));
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("Memory leaks will occur."));
|
||||
pthread_kill(handler_thread, SIGVTALRM);
|
||||
}
|
||||
} else {
|
||||
MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO
|
||||
, _("watchdog_kill set to terminate application."));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
handler_running = false;
|
||||
watchdog = cfg->watchdog_tmo;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cls_sound::cls_sound(cls_motapp *p_app)
|
||||
{
|
||||
app = p_app;
|
||||
handler_running = false;
|
||||
handler_stop = true;
|
||||
restart = false;
|
||||
watchdog = 30;
|
||||
}
|
||||
|
||||
cls_sound::~cls_sound()
|
||||
{
|
||||
mydelete(conf_src);
|
||||
mydelete(cfg);
|
||||
}
|
||||
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOUND_HPP_
|
||||
#define _INCLUDE_SOUND_HPP_
|
||||
|
||||
#ifdef HAVE_ALSA
|
||||
extern "C" {
|
||||
#include <alsa/asoundlib.h>
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PULSE
|
||||
extern "C" {
|
||||
#include <pulse/simple.h>
|
||||
#include <pulse/error.h>
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_FFTW3
|
||||
extern "C" {
|
||||
#include <fftw3.h>
|
||||
}
|
||||
#endif
|
||||
|
||||
struct ctx_snd_alert {
|
||||
int alert_id; /* Id number for the alert*/
|
||||
std::string alert_nm; /* Name of the alert*/
|
||||
int volume_level; /* Volume level required to consider the sample*/
|
||||
int volume_count; /* For each sample, number of times required to exceed volumne level*/
|
||||
double freq_low; /* Lowest frequency for detecting this alert*/
|
||||
double freq_high; /* Highest frequency for detecting this alert*/
|
||||
int trigger_count; /* Count of how many times it has been triggered so far*/
|
||||
int trigger_threshold; /* How many times does it need to be triggered before an event*/
|
||||
timespec trigger_time; /* The last time the trigger was invoked */
|
||||
int trigger_duration; /* Min. duration to trigger a new /event */
|
||||
};
|
||||
|
||||
struct ctx_snd_alsa {
|
||||
#ifdef HAVE_ALSA
|
||||
int device_id;
|
||||
std::string device_nm;
|
||||
snd_pcm_t *pcm_dev;
|
||||
snd_pcm_info_t *pcm_info;
|
||||
int card_id;
|
||||
snd_ctl_card_info_t *card_info;
|
||||
snd_ctl_t *ctl_hdl;
|
||||
#else
|
||||
int dummy;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ctx_snd_pulse {
|
||||
#ifdef HAVE_PULSE
|
||||
pa_simple *dev;
|
||||
#else
|
||||
int dummy;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ctx_snd_fftw {
|
||||
#ifdef HAVE_FFTW3
|
||||
fftw_plan ff_plan;
|
||||
double *ff_in;
|
||||
fftw_complex *ff_out;
|
||||
int bin_max;
|
||||
int bin_min;
|
||||
double bin_size;
|
||||
#else
|
||||
int dummy;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ctx_snd_info {
|
||||
std::string source; /* Source string in ALSA format e.g. hw:1,0*/
|
||||
int sample_rate; /* Sample rate of sound source*/
|
||||
int channels; /* Number of audio channels */
|
||||
std::list<ctx_snd_alert> alerts; /* list of sound alert criteria */
|
||||
int vol_min; /* The minimum volume from alerts*/
|
||||
int vol_max; /* Maximum volume of sample*/
|
||||
int vol_count; /* Number of times volumne exceeded user specified volume level */
|
||||
int16_t *buffer;
|
||||
int buffer_size;
|
||||
int frames;
|
||||
std::string pulse_server;
|
||||
std::string trig_freq;
|
||||
std::string trig_nbr;
|
||||
std::string trig_nm;
|
||||
ctx_params *params; /* Device parameters*/
|
||||
ctx_snd_fftw *snd_fftw; /* fftw for sound*/
|
||||
ctx_snd_alsa *snd_alsa; /* Alsa device for sound*/
|
||||
ctx_snd_pulse *snd_pulse; /* PulseAudio for sound*/
|
||||
};
|
||||
|
||||
class cls_sound {
|
||||
public:
|
||||
cls_sound(cls_motapp *p_app);
|
||||
~cls_sound();
|
||||
|
||||
enum DEVICE_STATUS device_status;
|
||||
|
||||
cls_config *conf_src;
|
||||
cls_config *cfg;
|
||||
std::string device_name;
|
||||
ctx_snd_info *snd_info;
|
||||
int threadnr;
|
||||
bool restart;
|
||||
bool finish;
|
||||
|
||||
bool handler_stop;
|
||||
bool handler_running;
|
||||
pthread_t handler_thread;
|
||||
void handler();
|
||||
void handler_startup();
|
||||
void handler_shutdown();
|
||||
|
||||
private:
|
||||
cls_motapp *app;
|
||||
int watchdog;
|
||||
|
||||
void cleanup();
|
||||
void init_values();
|
||||
void init();
|
||||
void init_alerts(ctx_snd_alert *tmp_alert);
|
||||
void edit_alerts();
|
||||
void load_alerts();
|
||||
void load_params();
|
||||
void capture();
|
||||
void check_levels();
|
||||
|
||||
#ifdef HAVE_ALSA
|
||||
void alsa_list_subdev();
|
||||
void alsa_list_card();
|
||||
void alsa_list();
|
||||
void alsa_start();
|
||||
void alsa_init();
|
||||
void alsa_capture();
|
||||
void alsa_cleanup();
|
||||
#endif
|
||||
#ifdef HAVE_PULSE
|
||||
void pulse_init();
|
||||
void pulse_capture();
|
||||
void pulse_cleanup();
|
||||
#endif
|
||||
#ifdef HAVE_FFTW3
|
||||
void fftw_open();
|
||||
float HammingWindow(int n1, int N2);
|
||||
float HannWindow(int n1, int N2);
|
||||
void check_alerts();
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE_SOUND_HPP_ */
|
||||
-1453
File diff suppressed because it is too large
Load Diff
-211
@@ -1,211 +0,0 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* track.h
|
||||
* Headers associated with functions in the track.c module.
|
||||
* Copyright 2000, Jeroen Vreeken
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_TRACK_H
|
||||
#define _INCLUDE_TRACK_H
|
||||
|
||||
#include "alg.hpp"
|
||||
#include <termios.h>
|
||||
|
||||
struct trackoptions {
|
||||
int dev;
|
||||
/* Config options: */
|
||||
unsigned int type;
|
||||
char *port;
|
||||
unsigned int motorx;
|
||||
unsigned int motory;
|
||||
int maxx;
|
||||
int maxy;
|
||||
int minx;
|
||||
int miny;
|
||||
unsigned int stepsize;
|
||||
unsigned int speed;
|
||||
unsigned int homex;
|
||||
unsigned int homey;
|
||||
unsigned int iomojo_id;
|
||||
unsigned int active; /* This is the track_auto but 'auto' is defined word so use active*/
|
||||
unsigned int motorx_reverse;
|
||||
unsigned int motory_reverse;
|
||||
unsigned int minmaxfound;
|
||||
unsigned int step_angle_x;
|
||||
unsigned int step_angle_y;
|
||||
unsigned int move_wait;
|
||||
/* UVC */
|
||||
int pan_angle; // degrees
|
||||
int tilt_angle; // degrees
|
||||
char *generic_move;
|
||||
};
|
||||
|
||||
extern struct trackoptions track_template;
|
||||
|
||||
unsigned int track_center(struct context *cnt, int dev
|
||||
, unsigned int manual, int xoff, int yoff);
|
||||
unsigned int track_move(struct context *cnt, int dev, struct coord *cent
|
||||
, struct images *imgs, unsigned int manual);
|
||||
|
||||
enum track_action { TRACK_CENTER, TRACK_MOVE };
|
||||
|
||||
/*
|
||||
* Some default values:
|
||||
*/
|
||||
#define TRACK_SPEED 255
|
||||
#define TRACK_STEPSIZE 40
|
||||
|
||||
#define TRACK_TYPE_STEPPER 1
|
||||
#define TRACK_TYPE_IOMOJO 2
|
||||
#define TRACK_TYPE_PWC 3
|
||||
#define TRACK_TYPE_GENERIC 4
|
||||
#define TRACK_TYPE_UVC 5
|
||||
#define TRACK_TYPE_SERVO 6
|
||||
|
||||
/*
|
||||
* Some defines for the Serial stepper motor:
|
||||
*/
|
||||
|
||||
#define STEPPER_BAUDRATE B9600
|
||||
|
||||
#define STEPPER_STATUS_LEFT 1
|
||||
#define STEPPER_STATUS_RIGHT 2
|
||||
#define STEPPER_STATUS_SAFETYL 4
|
||||
#define STEPPER_STATUS_SAFETYR 8
|
||||
|
||||
#define STEPPER_STATUS_UP 1
|
||||
#define STEPPER_STATUS_DOWN 2
|
||||
#define STEPPER_STATUS_SAFETYU 4
|
||||
#define STEPPER_STATUS_SAFETYD 8
|
||||
|
||||
|
||||
|
||||
#define STEPPER_COMMAND_STATUS 0
|
||||
#define STEPPER_COMMAND_LEFT_N 1
|
||||
#define STEPPER_COMMAND_RIGHT_N 2
|
||||
#define STEPPER_COMMAND_LEFT 3
|
||||
#define STEPPER_COMMAND_RIGHT 4
|
||||
#define STEPPER_COMMAND_SWEEP 5
|
||||
#define STEPPER_COMMAND_STOP 6
|
||||
#define STEPPER_COMMAND_SPEED 7
|
||||
|
||||
#define STEPPER_COMMAND_UP_N 1
|
||||
#define STEPPER_COMMAND_DOWN_N 2
|
||||
#define STEPPER_COMMAND_UP 3
|
||||
#define STEPPER_COMMAND_DOWN 4
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Some defines for the Serial servo motor:
|
||||
*/
|
||||
|
||||
/*
|
||||
* Controlling:
|
||||
* Three bytes are sent to the servo - BYTE1=SERVO_COMMAND BYTE2=COMMAND BYTE3=DATA
|
||||
* eg, sending the command 01 02 08 would Command SERVO_COMMAND1 to move LEFT a total of 8 STEPS
|
||||
*
|
||||
* An extra command 0x08 has been added but here is the basic command set.
|
||||
*
|
||||
* 0x00 STATUS - Current status byte will be returned, data byte ignored
|
||||
* 0x01 LEFT_N - Servo will take N Steps to the Left until it reaches the Servos safety limit
|
||||
* 0x02 RIGHT_N - Servo will take N Steps to the Right until it reaches the Servos safety limit
|
||||
* 0x03 LEFT - Servo will move to Left most position, data byte ignored.
|
||||
* 0x04 RIGHT - Servo will move to Right most position, data byte ignored.
|
||||
* 0x05 SWEEP - Servo will sweep between its extremes, data byte ignored.
|
||||
* 0x06 STOP - Servo will Stop, data byte ignored
|
||||
* 0x07 SPEED - Set servos speed between 0 and 255.
|
||||
* 0x08 ABSOLUTE - Set servo to absolute position between 0 and 255
|
||||
* 0x09 POSITION - Get servo to absolute position between 0 and 255
|
||||
* */
|
||||
|
||||
#define SERVO_BAUDRATE B9600
|
||||
|
||||
#define SERVO_COMMAND_STATUS 0
|
||||
#define SERVO_COMMAND_LEFT_N 1
|
||||
#define SERVO_COMMAND_RIGHT_N 2
|
||||
#define SERVO_COMMAND_LEFT 3
|
||||
#define SERVO_COMMAND_RIGHT 4
|
||||
#define SERVO_COMMAND_SWEEP 5
|
||||
#define SERVO_COMMAND_STOP 6
|
||||
#define SERVO_COMMAND_SPEED 7
|
||||
#define SERVO_COMMAND_ABSOLUTE 8
|
||||
#define SERVO_COMMAND_POSITION 9
|
||||
|
||||
|
||||
#define SERVO_COMMAND_UP_N 1
|
||||
#define SERVO_COMMAND_DOWN_N 2
|
||||
#define SERVO_COMMAND_UP 3
|
||||
#define SERVO_COMMAND_DOWN 4
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Some defines for the Iomojo Smilecam:
|
||||
*/
|
||||
|
||||
#define IOMOJO_BAUDRATE B19200
|
||||
|
||||
#define IOMOJO_CHECKPOWER_CMD 0xff
|
||||
#define IOMOJO_CHECKPOWER_RET 'Q'
|
||||
#define IOMOJO_MOVEOFFSET_CMD 0xfe
|
||||
#define IOMOJO_SETSPEED_CMD 0xfd
|
||||
#define IOMOJO_SETSPEED_RET 'P'
|
||||
#define IOMOJO_MOVEHOME 0xf9
|
||||
#define IOMOJO_RESTART 0xf7
|
||||
|
||||
#define IOMOJO_DIRECTION_RIGHT 0x01
|
||||
#define IOMOJO_DIRECTION_LEFT 0x02
|
||||
#define IOMOJO_DIRECTION_DOWN 0x04
|
||||
#define IOMOJO_DIRECTION_UP 0x08
|
||||
|
||||
#ifdef HAVE_V4L2
|
||||
|
||||
/*
|
||||
* Defines for the Logitech QuickCam Orbit/Sphere USB webcam
|
||||
*/
|
||||
|
||||
#define LQOS_VERTICAL_DEGREES 180
|
||||
#define LQOS_HORIZONAL_DEGREES 120
|
||||
|
||||
/*
|
||||
* UVC
|
||||
*/
|
||||
|
||||
#ifndef V4L2_CID_PAN_RELATIVE
|
||||
#define V4L2_CID_PAN_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+4)
|
||||
#endif
|
||||
|
||||
#ifndef V4L2_CID_TILT_RELATIVE
|
||||
#define V4L2_CID_TILT_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+5)
|
||||
#endif
|
||||
|
||||
#ifndef V4L2_CID_PAN_RESET
|
||||
#define V4L2_CID_PAN_RESET (V4L2_CID_CAMERA_CLASS_BASE+6)
|
||||
#endif
|
||||
|
||||
#ifndef V4L2_CID_TILT_RESET
|
||||
#define V4L2_CID_TILT_RESET (V4L2_CID_CAMERA_CLASS_BASE+7)
|
||||
#endif
|
||||
|
||||
#define INCPANTILT 64 // 1 degree
|
||||
|
||||
|
||||
#endif /* HAVE_V4L2 */
|
||||
|
||||
#endif /* _INCLUDE_TRACK_H */
|
||||
+1024
-1090
File diff suppressed because it is too large
Load Diff
+107
-107
@@ -1,125 +1,125 @@
|
||||
/* This file is part of Motion.
|
||||
*
|
||||
* Motion 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.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* util.h
|
||||
* Headers associated with functions in the util.c module.
|
||||
*/
|
||||
* This file is part of Motion.
|
||||
*
|
||||
* Motion 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Motion 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 Motion. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_UTIL_H
|
||||
#define _INCLUDE_UTIL_H
|
||||
#ifndef _INCLUDE_UTIL_HPP_
|
||||
#define _INCLUDE_UTIL_HPP_
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
#define MYFFVER (LIBAVFORMAT_VERSION_MAJOR * 1000)+LIBAVFORMAT_VERSION_MINOR
|
||||
|
||||
#if ( MYFFVER >= 56000)
|
||||
#define MY_PIX_FMT_YUV420P AV_PIX_FMT_YUV420P
|
||||
#define MY_PIX_FMT_YUVJ420P AV_PIX_FMT_YUVJ420P
|
||||
#define MyPixelFormat AVPixelFormat
|
||||
#else //Old ffmpeg pixel formats
|
||||
#define MY_PIX_FMT_YUV420P PIX_FMT_YUV420P
|
||||
#define MY_PIX_FMT_YUVJ420P PIX_FMT_YUVJ420P
|
||||
#define MyPixelFormat PixelFormat
|
||||
#endif //myffver >= 56000
|
||||
#if (LIBAVCODEC_VERSION_MAJOR >= 59)
|
||||
typedef const AVCodec myAVCodec; /* Version independent definition for AVCodec*/
|
||||
#else
|
||||
typedef AVCodec myAVCodec; /* Version independent definition for AVCodec*/
|
||||
#endif
|
||||
|
||||
#if ( MYFFVER > 54006)
|
||||
#define MY_FLAG_READ AVIO_FLAG_READ
|
||||
#define MY_FLAG_WRITE AVIO_FLAG_WRITE
|
||||
#define MY_FLAG_READ_WRITE AVIO_FLAG_READ_WRITE
|
||||
#else //Older versions
|
||||
#define MY_FLAG_READ URL_RDONLY
|
||||
#define MY_FLAG_WRITE URL_WRONLY
|
||||
#define MY_FLAG_READ_WRITE URL_RDWR
|
||||
#endif
|
||||
#if (MYFFVER <= 60016)
|
||||
typedef uint8_t myuint; /* Version independent uint */
|
||||
#else
|
||||
typedef const uint8_t myuint; /* Version independent uint */
|
||||
#endif
|
||||
|
||||
/*********************************************/
|
||||
#if ( MYFFVER >= 56000)
|
||||
#define MY_CODEC_ID_MSMPEG4V2 AV_CODEC_ID_MSMPEG4V2
|
||||
#define MY_CODEC_ID_FLV1 AV_CODEC_ID_FLV1
|
||||
#define MY_CODEC_ID_FFV1 AV_CODEC_ID_FFV1
|
||||
#define MY_CODEC_ID_NONE AV_CODEC_ID_NONE
|
||||
#define MY_CODEC_ID_MPEG2VIDEO AV_CODEC_ID_MPEG2VIDEO
|
||||
#define MY_CODEC_ID_H264 AV_CODEC_ID_H264
|
||||
#define MY_CODEC_ID_HEVC AV_CODEC_ID_HEVC
|
||||
#else
|
||||
#define MY_CODEC_ID_MSMPEG4V2 CODEC_ID_MSMPEG4V2
|
||||
#define MY_CODEC_ID_FLV1 CODEC_ID_FLV1
|
||||
#define MY_CODEC_ID_FFV1 CODEC_ID_FFV1
|
||||
#define MY_CODEC_ID_NONE CODEC_ID_NONE
|
||||
#define MY_CODEC_ID_MPEG2VIDEO CODEC_ID_MPEG2VIDEO
|
||||
#define MY_CODEC_ID_H264 CODEC_ID_H264
|
||||
#define MY_CODEC_ID_HEVC CODEC_ID_H264
|
||||
#endif
|
||||
|
||||
/*********************************************/
|
||||
#if (MYFFVER >= 57000)
|
||||
#define MY_CODEC_FLAG_GLOBAL_HEADER AV_CODEC_FLAG_GLOBAL_HEADER
|
||||
#define MY_CODEC_FLAG_QSCALE AV_CODEC_FLAG_QSCALE
|
||||
#else
|
||||
#define MY_CODEC_FLAG_GLOBAL_HEADER CODEC_FLAG_GLOBAL_HEADER
|
||||
#define MY_CODEC_FLAG_QSCALE CODEC_FLAG_QSCALE
|
||||
#endif
|
||||
#ifdef HAVE_GETTEXT
|
||||
#include <libintl.h>
|
||||
extern int _nl_msg_cat_cntr; /* Required for changing the locale dynamically */
|
||||
#endif
|
||||
|
||||
#if (MYFFVER >= 59000)
|
||||
typedef const AVCodec my_AVCodec; /* Version independent for AVCodec*/
|
||||
#else
|
||||
typedef AVCodec my_AVCodec; /* Version independent for AVCodec*/
|
||||
#endif
|
||||
#define _(STRING) mytranslate_text(STRING, 2)
|
||||
|
||||
AVFrame *my_frame_alloc(void);
|
||||
void my_frame_free(AVFrame *frame);
|
||||
void my_packet_free(AVPacket *pkt);
|
||||
void my_avcodec_close(AVCodecContext *codec_context);
|
||||
int my_image_get_buffer_size(enum MyPixelFormat pix_fmt, int width, int height);
|
||||
int my_image_copy_to_buffer(AVFrame *frame,uint8_t *buffer_ptr,enum MyPixelFormat pix_fmt,int width,int height,int dest_size);
|
||||
int my_image_fill_arrays(AVFrame *frame,uint8_t *buffer_ptr,enum MyPixelFormat pix_fmt,int width,int height);
|
||||
int my_copy_packet(AVPacket *dest_pkt, AVPacket *src_pkt);
|
||||
AVPacket *my_packet_alloc(AVPacket *pkt);
|
||||
|
||||
#endif /* HAVE_FFMPEG */
|
||||
#define SLEEP(seconds, nanoseconds) { \
|
||||
struct timespec ts1; \
|
||||
ts1.tv_sec = seconds; \
|
||||
ts1.tv_nsec = (long)nanoseconds; \
|
||||
while (nanosleep(&ts1, &ts1) == -1); \
|
||||
}
|
||||
#define myfree(x) {if(x!=nullptr) {free(x); x=nullptr;}}
|
||||
#define mydelete(x) {if(x!=nullptr) {delete x; x=nullptr;}}
|
||||
|
||||
#if MHD_VERSION >= 0x00097002
|
||||
typedef enum MHD_Result mymhd_retcd;
|
||||
typedef enum MHD_Result mhdrslt; /* Version independent return result from MHD */
|
||||
#else
|
||||
typedef int mymhd_retcd;
|
||||
typedef int mhdrslt; /* Version independent return result from MHD */
|
||||
#endif
|
||||
|
||||
void *mymalloc(size_t nbytes);
|
||||
void *myrealloc(void *ptr, size_t size, const char *desc);
|
||||
FILE *myfopen(const char *path, const char *mode);
|
||||
int myfclose(FILE *fh);
|
||||
size_t mystrftime(const struct context *cnt, char *s, size_t max, const char *userformat
|
||||
, const struct timeval *tv1, const char *filename, int sqltype);
|
||||
int mycreate_path(const char *path);
|
||||
struct ctx_params_item {
|
||||
std::string param_name; /* The name or description of the ID as requested by user*/
|
||||
std::string param_value; /* The value that the user wants the control set to*/
|
||||
};
|
||||
typedef std::vector<ctx_params_item> vec_params;
|
||||
struct ctx_params {
|
||||
vec_params params_array;
|
||||
int params_cnt;
|
||||
std::string params_desc;
|
||||
};
|
||||
|
||||
char *mystrcpy(char *to, const char *from);
|
||||
char *mystrdup(const char *from);
|
||||
void *mymalloc(size_t nbytes);
|
||||
|
||||
void util_threadname_set(const char *abbr, int threadnbr, const char *threadname);
|
||||
void util_threadname_get(char *threadname);
|
||||
int util_check_passthrough(struct context *cnt);
|
||||
void util_trim(char *parm);
|
||||
void util_parms_free(struct params_context *parameters);
|
||||
void util_parms_parse(struct params_context *parameters, char *confparm, int logmsg);
|
||||
void util_parms_add_default(struct params_context *parameters, const char *parm_nm, const char *parm_vl);
|
||||
void util_parms_add_update(struct params_context *parameters, const char *parm_nm, const char *parm_vl);
|
||||
void util_parms_update(struct params_context *params, struct context *cnt, const char *cfgitm);
|
||||
void *myrealloc(void *ptr, size_t size, const char *desc);
|
||||
int mycreate_path(const char *path);
|
||||
FILE *myfopen(const char *path, const char *mode);
|
||||
int myfclose(FILE *fh);
|
||||
void mystrftime(cls_camera *cam, char *s, size_t mx_sz
|
||||
, const char *usrfmt, const char *fname);
|
||||
void mystrftime(cls_camera *cam, std::string &rslt
|
||||
, std::string usrfmt, std::string fname);
|
||||
void mystrftime(cls_sound *snd, std::string &dst, std::string fmt);
|
||||
void util_exec_command(cls_camera *cam, const char *command, const char *filename);
|
||||
void util_exec_command(cls_sound *snd, std::string cmd);
|
||||
void util_exec_command(cls_camera *cam, std::string cmd);
|
||||
|
||||
int mystrceq(const char *var1, const char *var2);
|
||||
int mystrcne(const char *var1, const char *var2);
|
||||
int mystreq(const char *var1, const char *var2);
|
||||
int mystrne(const char *var1, const char *var2);
|
||||
void mythreadname_set(const char *abbr, int threadnbr, const char *threadname);
|
||||
void mythreadname_get(char *threadname);
|
||||
void mythreadname_get(std::string &threadname);
|
||||
|
||||
#endif
|
||||
char* mytranslate_text(const char *msgid, int setnls);
|
||||
void mytranslate_init(void);
|
||||
|
||||
int mystrceq(const char* var1, const char* var2);
|
||||
int mystrcne(const char* var1, const char* var2);
|
||||
int mystreq(const char* var1, const char* var2);
|
||||
int mystrne(const char* var1, const char* var2);
|
||||
void myltrim(std::string &parm);
|
||||
void myrtrim(std::string &parm);
|
||||
void mytrim(std::string &parm);
|
||||
void myunquote(std::string &parm);
|
||||
|
||||
void myframe_key(AVFrame *frame);
|
||||
void myframe_interlaced(AVFrame *frame);
|
||||
AVPacket *mypacket_alloc(AVPacket *pkt);
|
||||
|
||||
void util_parms_parse(ctx_params *params, std::string parm_desc, std::string confline);
|
||||
void util_parms_add_default(ctx_params *params, std::string parm_nm, std::string parm_vl);
|
||||
void util_parms_add_default(ctx_params *params, std::string parm_nm, int parm_vl);
|
||||
void util_parms_add(ctx_params *params, std::string parm_nm, std::string parm_val);
|
||||
void util_parms_update(ctx_params *params, std::string &confline);
|
||||
|
||||
int mtoi(std::string parm);
|
||||
int mtoi(char *parm);
|
||||
float mtof(char *parm);
|
||||
float mtof(std::string parm);
|
||||
bool mtob(std::string parm);
|
||||
bool mtob(char *parm);
|
||||
long mtol(std::string parm);
|
||||
long mtol(char *parm);
|
||||
std::string mtok(std::string &parm, std::string tok);
|
||||
|
||||
void util_resize(uint8_t *src, int src_w, int src_h
|
||||
, uint8_t *dst, int dst_w, int dst_h);
|
||||
|
||||
#endif /* _INCLUDE_UTIL_HPP_ */
|
||||
|
||||
-1045
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user