mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +00:00
Merging gst-plugins-bad
This commit is contained in:
commit
07ad3439ce
2782 changed files with 1503377 additions and 0 deletions
16
.gitignore
vendored
Normal file
16
.gitignore
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
*~
|
||||||
|
|
||||||
|
Build
|
||||||
|
*.user
|
||||||
|
*.suo
|
||||||
|
*.ipch
|
||||||
|
*.sdf
|
||||||
|
*.opensdf
|
||||||
|
*.DS_Store
|
||||||
|
|
||||||
|
# Meson
|
||||||
|
/build
|
||||||
|
/subprojects
|
||||||
|
|
||||||
|
# hotdoc
|
||||||
|
docs/hotdoc/libs/generated_sitemap.txt
|
1
.gitlab-ci.yml
Normal file
1
.gitlab-ci.yml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
include: "https://gitlab.freedesktop.org/gstreamer/gst-ci/raw/master/gitlab/ci_template.yml"
|
1
.indentignore
Normal file
1
.indentignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ext/sctp/usrsctp/usrsctplib/
|
21
AUTHORS
Normal file
21
AUTHORS
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
Erik Walthinsen <omega@temple-baptist.com>
|
||||||
|
Matt Howell <mhowell@users.sourceforge.net>
|
||||||
|
Brent Bradburn <bbradburn@users.sourceforge.net>
|
||||||
|
Wim Taymans <wim.taymans@chello.be>
|
||||||
|
Richard Boulton <richard@tartarus.org>
|
||||||
|
Zaheer Abbas Merali <zaheerabbas at merali dot org>
|
||||||
|
David I. Lehn <dlehn@users.sourceforge.net>
|
||||||
|
Chris Emerson <chris@tartarus.org>
|
||||||
|
Jens Thiele <karme@unforgettable.com>
|
||||||
|
Thomas Nyberg <thomas@codefactory.se>
|
||||||
|
Bastien Nocera <hadess@hadess.net>
|
||||||
|
Christian Fredrik Kalager Schaller <Uraeus@linuxrising.org>
|
||||||
|
Thomas Vander Stichele <thomas@apestaart.org>
|
||||||
|
Andy Wingo <wingo@pobox.com>
|
||||||
|
Cameron Hutchison <camh@xdna.net>
|
||||||
|
David Schleef <ds@schleef.org>
|
||||||
|
Benjamin Otte <in7y118@public.uni-hamburg.de>
|
||||||
|
Ronald Bultje <rbultje@ronald.bitfreak.net>
|
||||||
|
Julien MOUTTE <julien@moutte.net>
|
||||||
|
Jan Schmidt <thaytan@mad.scientist.com>
|
||||||
|
Arwed v. Merkatz <v.merkatz@gmx.net>
|
502
COPYING
Normal file
502
COPYING
Normal file
|
@ -0,0 +1,502 @@
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 2.1, February 1999
|
||||||
|
|
||||||
|
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
[This is the first released version of the Lesser GPL. It also counts
|
||||||
|
as the successor of the GNU Library Public License, version 2, hence
|
||||||
|
the version number 2.1.]
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
Licenses are intended to guarantee your freedom to share and change
|
||||||
|
free software--to make sure the software is free for all its users.
|
||||||
|
|
||||||
|
This license, the Lesser General Public License, applies to some
|
||||||
|
specially designated software packages--typically libraries--of the
|
||||||
|
Free Software Foundation and other authors who decide to use it. You
|
||||||
|
can use it too, but we suggest you first think carefully about whether
|
||||||
|
this license or the ordinary General Public License is the better
|
||||||
|
strategy to use in any particular case, based on the explanations below.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom of use,
|
||||||
|
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 this service if you wish); that you receive source code or can get
|
||||||
|
it if you want it; that you can change the software and use pieces of
|
||||||
|
it in new free programs; and that you are informed that you can do
|
||||||
|
these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
distributors to deny you these rights or to ask you to surrender these
|
||||||
|
rights. These restrictions translate to certain responsibilities for
|
||||||
|
you if you distribute copies of the library or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of the library, whether gratis
|
||||||
|
or for a fee, you must give the recipients all the rights that we gave
|
||||||
|
you. You must make sure that they, too, receive or can get the source
|
||||||
|
code. If you link other code with the library, you must provide
|
||||||
|
complete object files to the recipients, so that they can relink them
|
||||||
|
with the library after making changes to the library and recompiling
|
||||||
|
it. And you must show them these terms so they know their rights.
|
||||||
|
|
||||||
|
We protect your rights with a two-step method: (1) we copyright the
|
||||||
|
library, and (2) we offer you this license, which gives you legal
|
||||||
|
permission to copy, distribute and/or modify the library.
|
||||||
|
|
||||||
|
To protect each distributor, we want to make it very clear that
|
||||||
|
there is no warranty for the free library. Also, if the library is
|
||||||
|
modified by someone else and passed on, the recipients should know
|
||||||
|
that what they have is not the original version, so that the original
|
||||||
|
author's reputation will not be affected by problems that might be
|
||||||
|
introduced by others.
|
||||||
|
|
||||||
|
Finally, software patents pose a constant threat to the existence of
|
||||||
|
any free program. We wish to make sure that a company cannot
|
||||||
|
effectively restrict the users of a free program by obtaining a
|
||||||
|
restrictive license from a patent holder. Therefore, we insist that
|
||||||
|
any patent license obtained for a version of the library must be
|
||||||
|
consistent with the full freedom of use specified in this license.
|
||||||
|
|
||||||
|
Most GNU software, including some libraries, is covered by the
|
||||||
|
ordinary GNU General Public License. This license, the GNU Lesser
|
||||||
|
General Public License, applies to certain designated libraries, and
|
||||||
|
is quite different from the ordinary General Public License. We use
|
||||||
|
this license for certain libraries in order to permit linking those
|
||||||
|
libraries into non-free programs.
|
||||||
|
|
||||||
|
When a program is linked with a library, whether statically or using
|
||||||
|
a shared library, the combination of the two is legally speaking a
|
||||||
|
combined work, a derivative of the original library. The ordinary
|
||||||
|
General Public License therefore permits such linking only if the
|
||||||
|
entire combination fits its criteria of freedom. The Lesser General
|
||||||
|
Public License permits more lax criteria for linking other code with
|
||||||
|
the library.
|
||||||
|
|
||||||
|
We call this license the "Lesser" General Public License because it
|
||||||
|
does Less to protect the user's freedom than the ordinary General
|
||||||
|
Public License. It also provides other free software developers Less
|
||||||
|
of an advantage over competing non-free programs. These disadvantages
|
||||||
|
are the reason we use the ordinary General Public License for many
|
||||||
|
libraries. However, the Lesser license provides advantages in certain
|
||||||
|
special circumstances.
|
||||||
|
|
||||||
|
For example, on rare occasions, there may be a special need to
|
||||||
|
encourage the widest possible use of a certain library, so that it becomes
|
||||||
|
a de-facto standard. To achieve this, non-free programs must be
|
||||||
|
allowed to use the library. A more frequent case is that a free
|
||||||
|
library does the same job as widely used non-free libraries. In this
|
||||||
|
case, there is little to gain by limiting the free library to free
|
||||||
|
software only, so we use the Lesser General Public License.
|
||||||
|
|
||||||
|
In other cases, permission to use a particular library in non-free
|
||||||
|
programs enables a greater number of people to use a large body of
|
||||||
|
free software. For example, permission to use the GNU C Library in
|
||||||
|
non-free programs enables many more people to use the whole GNU
|
||||||
|
operating system, as well as its variant, the GNU/Linux operating
|
||||||
|
system.
|
||||||
|
|
||||||
|
Although the Lesser General Public License is Less protective of the
|
||||||
|
users' freedom, it does ensure that the user of a program that is
|
||||||
|
linked with the Library has the freedom and the wherewithal to run
|
||||||
|
that program using a modified version of the Library.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow. Pay close attention to the difference between a
|
||||||
|
"work based on the library" and a "work that uses the library". The
|
||||||
|
former contains code derived from the library, whereas the latter must
|
||||||
|
be combined with the library in order to run.
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License Agreement applies to any software library or other
|
||||||
|
program which contains a notice placed by the copyright holder or
|
||||||
|
other authorized party saying it may be distributed under the terms of
|
||||||
|
this Lesser General Public License (also called "this License").
|
||||||
|
Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
A "library" means a collection of software functions and/or data
|
||||||
|
prepared so as to be conveniently linked with application programs
|
||||||
|
(which use some of those functions and data) to form executables.
|
||||||
|
|
||||||
|
The "Library", below, refers to any such software library or work
|
||||||
|
which has been distributed under these terms. A "work based on the
|
||||||
|
Library" means either the Library or any derivative work under
|
||||||
|
copyright law: that is to say, a work containing the Library or a
|
||||||
|
portion of it, either verbatim or with modifications and/or translated
|
||||||
|
straightforwardly into another language. (Hereinafter, translation is
|
||||||
|
included without limitation in the term "modification".)
|
||||||
|
|
||||||
|
"Source code" for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For a library, complete source code means
|
||||||
|
all the source code for all modules it contains, plus any associated
|
||||||
|
interface definition files, plus the scripts used to control compilation
|
||||||
|
and installation of the library.
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running a program using the Library is not restricted, and output from
|
||||||
|
such a program is covered only if its contents constitute a work based
|
||||||
|
on the Library (independent of the use of the Library in a tool for
|
||||||
|
writing it). Whether that is true depends on what the Library does
|
||||||
|
and what the program that uses the Library does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Library's
|
||||||
|
complete source code as you receive it, in any medium, provided that
|
||||||
|
you conspicuously and appropriately publish on each copy an
|
||||||
|
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||||
|
all the notices that refer to this License and to the absence of any
|
||||||
|
warranty; and distribute a copy of this License along with the
|
||||||
|
Library.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy,
|
||||||
|
and you may at your option offer warranty protection in exchange for a
|
||||||
|
fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Library or any portion
|
||||||
|
of it, thus forming a work based on the Library, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The modified work must itself be a software library.
|
||||||
|
|
||||||
|
b) You must cause the files modified to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
c) You must cause the whole of the work to be licensed at no
|
||||||
|
charge to all third parties under the terms of this License.
|
||||||
|
|
||||||
|
d) If a facility in the modified Library refers to a function or a
|
||||||
|
table of data to be supplied by an application program that uses
|
||||||
|
the facility, other than as an argument passed when the facility
|
||||||
|
is invoked, then you must make a good faith effort to ensure that,
|
||||||
|
in the event an application does not supply such function or
|
||||||
|
table, the facility still operates, and performs whatever part of
|
||||||
|
its purpose remains meaningful.
|
||||||
|
|
||||||
|
(For example, a function in a library to compute square roots has
|
||||||
|
a purpose that is entirely well-defined independent of the
|
||||||
|
application. Therefore, Subsection 2d requires that any
|
||||||
|
application-supplied function or table used by this function must
|
||||||
|
be optional: if the application does not supply it, the square
|
||||||
|
root function must still compute square roots.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Library,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Library, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote
|
||||||
|
it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Library.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Library
|
||||||
|
with the Library (or with a work based on the Library) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||||
|
License instead of this License to a given copy of the Library. To do
|
||||||
|
this, you must alter all the notices that refer to this License, so
|
||||||
|
that they refer to the ordinary GNU General Public License, version 2,
|
||||||
|
instead of to this License. (If a newer version than version 2 of the
|
||||||
|
ordinary GNU General Public License has appeared, then you can specify
|
||||||
|
that version instead if you wish.) Do not make any other change in
|
||||||
|
these notices.
|
||||||
|
|
||||||
|
Once this change is made in a given copy, it is irreversible for
|
||||||
|
that copy, so the ordinary GNU General Public License applies to all
|
||||||
|
subsequent copies and derivative works made from that copy.
|
||||||
|
|
||||||
|
This option is useful when you wish to copy part of the code of
|
||||||
|
the Library into a program that is not a library.
|
||||||
|
|
||||||
|
4. You may copy and distribute the Library (or a portion or
|
||||||
|
derivative of it, under Section 2) in object code or executable form
|
||||||
|
under the terms of Sections 1 and 2 above provided that you accompany
|
||||||
|
it with the complete corresponding machine-readable source code, which
|
||||||
|
must be distributed under the terms of Sections 1 and 2 above on a
|
||||||
|
medium customarily used for software interchange.
|
||||||
|
|
||||||
|
If distribution of object code is made by offering access to copy
|
||||||
|
from a designated place, then offering equivalent access to copy the
|
||||||
|
source code from the same place satisfies the requirement to
|
||||||
|
distribute the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
5. A program that contains no derivative of any portion of the
|
||||||
|
Library, but is designed to work with the Library by being compiled or
|
||||||
|
linked with it, is called a "work that uses the Library". Such a
|
||||||
|
work, in isolation, is not a derivative work of the Library, and
|
||||||
|
therefore falls outside the scope of this License.
|
||||||
|
|
||||||
|
However, linking a "work that uses the Library" with the Library
|
||||||
|
creates an executable that is a derivative of the Library (because it
|
||||||
|
contains portions of the Library), rather than a "work that uses the
|
||||||
|
library". The executable is therefore covered by this License.
|
||||||
|
Section 6 states terms for distribution of such executables.
|
||||||
|
|
||||||
|
When a "work that uses the Library" uses material from a header file
|
||||||
|
that is part of the Library, the object code for the work may be a
|
||||||
|
derivative work of the Library even though the source code is not.
|
||||||
|
Whether this is true is especially significant if the work can be
|
||||||
|
linked without the Library, or if the work is itself a library. The
|
||||||
|
threshold for this to be true is not precisely defined by law.
|
||||||
|
|
||||||
|
If such an object file uses only numerical parameters, data
|
||||||
|
structure layouts and accessors, and small macros and small inline
|
||||||
|
functions (ten lines or less in length), then the use of the object
|
||||||
|
file is unrestricted, regardless of whether it is legally a derivative
|
||||||
|
work. (Executables containing this object code plus portions of the
|
||||||
|
Library will still fall under Section 6.)
|
||||||
|
|
||||||
|
Otherwise, if the work is a derivative of the Library, you may
|
||||||
|
distribute the object code for the work under the terms of Section 6.
|
||||||
|
Any executables containing that work also fall under Section 6,
|
||||||
|
whether or not they are linked directly with the Library itself.
|
||||||
|
|
||||||
|
6. As an exception to the Sections above, you may also combine or
|
||||||
|
link a "work that uses the Library" with the Library to produce a
|
||||||
|
work containing portions of the Library, and distribute that work
|
||||||
|
under terms of your choice, provided that the terms permit
|
||||||
|
modification of the work for the customer's own use and reverse
|
||||||
|
engineering for debugging such modifications.
|
||||||
|
|
||||||
|
You must give prominent notice with each copy of the work that the
|
||||||
|
Library is used in it and that the Library and its use are covered by
|
||||||
|
this License. You must supply a copy of this License. If the work
|
||||||
|
during execution displays copyright notices, you must include the
|
||||||
|
copyright notice for the Library among them, as well as a reference
|
||||||
|
directing the user to the copy of this License. Also, you must do one
|
||||||
|
of these things:
|
||||||
|
|
||||||
|
a) Accompany the work with the complete corresponding
|
||||||
|
machine-readable source code for the Library including whatever
|
||||||
|
changes were used in the work (which must be distributed under
|
||||||
|
Sections 1 and 2 above); and, if the work is an executable linked
|
||||||
|
with the Library, with the complete machine-readable "work that
|
||||||
|
uses the Library", as object code and/or source code, so that the
|
||||||
|
user can modify the Library and then relink to produce a modified
|
||||||
|
executable containing the modified Library. (It is understood
|
||||||
|
that the user who changes the contents of definitions files in the
|
||||||
|
Library will not necessarily be able to recompile the application
|
||||||
|
to use the modified definitions.)
|
||||||
|
|
||||||
|
b) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (1) uses at run time a
|
||||||
|
copy of the library already present on the user's computer system,
|
||||||
|
rather than copying library functions into the executable, and (2)
|
||||||
|
will operate properly with a modified version of the library, if
|
||||||
|
the user installs one, as long as the modified version is
|
||||||
|
interface-compatible with the version that the work was made with.
|
||||||
|
|
||||||
|
c) Accompany the work with a written offer, valid for at
|
||||||
|
least three years, to give the same user the materials
|
||||||
|
specified in Subsection 6a, above, for a charge no more
|
||||||
|
than the cost of performing this distribution.
|
||||||
|
|
||||||
|
d) If distribution of the work is made by offering access to copy
|
||||||
|
from a designated place, offer equivalent access to copy the above
|
||||||
|
specified materials from the same place.
|
||||||
|
|
||||||
|
e) Verify that the user has already received a copy of these
|
||||||
|
materials or that you have already sent this user a copy.
|
||||||
|
|
||||||
|
For an executable, the required form of the "work that uses the
|
||||||
|
Library" must include any data and utility programs needed for
|
||||||
|
reproducing the executable from it. However, as a special exception,
|
||||||
|
the materials to be distributed need not include anything that is
|
||||||
|
normally distributed (in either source or binary form) with the major
|
||||||
|
components (compiler, kernel, and so on) of the operating system on
|
||||||
|
which the executable runs, unless that component itself accompanies
|
||||||
|
the executable.
|
||||||
|
|
||||||
|
It may happen that this requirement contradicts the license
|
||||||
|
restrictions of other proprietary libraries that do not normally
|
||||||
|
accompany the operating system. Such a contradiction means you cannot
|
||||||
|
use both them and the Library together in an executable that you
|
||||||
|
distribute.
|
||||||
|
|
||||||
|
7. You may place library facilities that are a work based on the
|
||||||
|
Library side-by-side in a single library together with other library
|
||||||
|
facilities not covered by this License, and distribute such a combined
|
||||||
|
library, provided that the separate distribution of the work based on
|
||||||
|
the Library and of the other library facilities is otherwise
|
||||||
|
permitted, and provided that you do these two things:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work
|
||||||
|
based on the Library, uncombined with any other library
|
||||||
|
facilities. This must be distributed under the terms of the
|
||||||
|
Sections above.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library of the fact
|
||||||
|
that part of it is a work based on the Library, and explaining
|
||||||
|
where to find the accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
8. You may not copy, modify, sublicense, link with, or distribute
|
||||||
|
the Library except as expressly provided under this License. Any
|
||||||
|
attempt otherwise to copy, modify, sublicense, link with, or
|
||||||
|
distribute the Library is void, and will automatically terminate your
|
||||||
|
rights under this License. However, parties who have received copies,
|
||||||
|
or rights, from you under this License will not have their licenses
|
||||||
|
terminated so long as such parties remain in full compliance.
|
||||||
|
|
||||||
|
9. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Library or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Library (or any work based on the
|
||||||
|
Library), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Library or works based on it.
|
||||||
|
|
||||||
|
10. Each time you redistribute the Library (or any work based on the
|
||||||
|
Library), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute, link with or modify the Library
|
||||||
|
subject to these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties with
|
||||||
|
this License.
|
||||||
|
|
||||||
|
11. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
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
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Library at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Library by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Library.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under any
|
||||||
|
particular circumstance, the balance of the section is intended to apply,
|
||||||
|
and the section as a whole is intended to apply in other circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
12. If the distribution and/or use of the Library is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Library under this License may add
|
||||||
|
an explicit geographical distribution limitation excluding those countries,
|
||||||
|
so that distribution is permitted only in or among countries not thus
|
||||||
|
excluded. In such case, this License incorporates the limitation as if
|
||||||
|
written in the body of this License.
|
||||||
|
|
||||||
|
13. The Free Software Foundation may publish revised and/or new
|
||||||
|
versions of the Lesser 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 Library
|
||||||
|
specifies a version number of this License which applies to it and
|
||||||
|
"any later version", you have the option of following the terms and
|
||||||
|
conditions either of that version or of any later version published by
|
||||||
|
the Free Software Foundation. If the Library does not specify a
|
||||||
|
license version number, you may choose any version ever published by
|
||||||
|
the Free Software Foundation.
|
||||||
|
|
||||||
|
14. If you wish to incorporate parts of the Library into other free
|
||||||
|
programs whose distribution conditions are incompatible with these,
|
||||||
|
write to the author to ask for permission. For software which is
|
||||||
|
copyrighted by the Free Software Foundation, write to the Free
|
||||||
|
Software Foundation; we sometimes make exceptions for this. Our
|
||||||
|
decision will be guided by the two goals of preserving the free status
|
||||||
|
of all derivatives of our free software and of promoting the sharing
|
||||||
|
and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||||
|
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||||
|
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||||
|
OTHER PARTIES PROVIDE THE LIBRARY "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
|
||||||
|
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||||
|
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||||
|
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||||
|
AND/OR REDISTRIBUTE THE LIBRARY 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
|
||||||
|
LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||||
|
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Libraries
|
||||||
|
|
||||||
|
If you develop a new library, and you want it to be of the greatest
|
||||||
|
possible use to the public, we recommend making it free software that
|
||||||
|
everyone can redistribute and change. You can do so by permitting
|
||||||
|
redistribution under these terms (or, alternatively, under the terms of the
|
||||||
|
ordinary General Public License).
|
||||||
|
|
||||||
|
To apply these terms, attach the following notices to the library. It is
|
||||||
|
safest to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least the
|
||||||
|
"copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the library's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||||
|
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1990
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
That's all there is to it!
|
12
MAINTAINERS
Normal file
12
MAINTAINERS
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
GStreamer is currently maintained by the consensus of a number
|
||||||
|
of people, including, but not limited to:
|
||||||
|
|
||||||
|
Jan Schmidt <thaytan@noraisin.net>
|
||||||
|
Wim Taymans <wim.taymans@gmail.com>
|
||||||
|
David Schleef <ds@schleef.org>
|
||||||
|
Tim-Philipp Müller <tim centricular net>
|
||||||
|
Sebastian Dröge <slomo@coaxion.net>
|
||||||
|
|
||||||
|
Maintainer-related issues should be addressed to:
|
||||||
|
|
||||||
|
gstreamer-devel@lists.freedesktop.org
|
299
NEWS
Normal file
299
NEWS
Normal file
|
@ -0,0 +1,299 @@
|
||||||
|
GStreamer 1.20 Release Notes
|
||||||
|
|
||||||
|
GStreamer 1.20 has not been released yet. It is scheduled for release
|
||||||
|
around October/November 2021.
|
||||||
|
|
||||||
|
1.19.x is the unstable development version that is being developed in
|
||||||
|
the git main branch and which will eventually result in 1.20, and 1.19.2
|
||||||
|
is the current development release in that series
|
||||||
|
|
||||||
|
It is expected that feature freeze will be in early October 2021,
|
||||||
|
followed by one or two 1.19.9x pre-releases and the new 1.20 stable
|
||||||
|
release around October/November 2021.
|
||||||
|
|
||||||
|
1.20 will be backwards-compatible to the stable 1.18, 1.16, 1.14, 1.12,
|
||||||
|
1.10, 1.8, 1.6,, 1.4, 1.2 and 1.0 release series.
|
||||||
|
|
||||||
|
See https://gstreamer.freedesktop.org/releases/1.20/ for the latest
|
||||||
|
version of this document.
|
||||||
|
|
||||||
|
Last updated: Wednesday 22 September 2021, 18:00 UTC (log)
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
The GStreamer team is proud to announce a new major feature release in
|
||||||
|
the stable 1.x API series of your favourite cross-platform multimedia
|
||||||
|
framework!
|
||||||
|
|
||||||
|
As always, this release is again packed with many new features, bug
|
||||||
|
fixes and other improvements.
|
||||||
|
|
||||||
|
Highlights
|
||||||
|
|
||||||
|
- this section will be completed in due course
|
||||||
|
|
||||||
|
Major new features and changes
|
||||||
|
|
||||||
|
Noteworthy new features and API
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
New elements
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
New element features and additions
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
Plugin and library moves
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
- There were no plugin moves or library moves in this cycle.
|
||||||
|
|
||||||
|
Plugin removals
|
||||||
|
|
||||||
|
The following elements or plugins have been removed:
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
Miscellaneous API additions
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
Miscellaneous performance, latency and memory optimisations
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
Miscellaneous other changes and enhancements
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
Tracing framework and debugging improvements
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
Tools
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
GStreamer RTSP server
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
GStreamer VAAPI
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
GStreamer OMX
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
GStreamer Editing Services and NLE
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
GStreamer validate
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
GStreamer Python Bindings
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
GStreamer C# Bindings
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
GStreamer Rust Bindings and Rust Plugins
|
||||||
|
|
||||||
|
The GStreamer Rust bindings are released separately with a different
|
||||||
|
release cadence that’s tied to gtk-rs, but the latest release has
|
||||||
|
already been updated for the upcoming new GStreamer 1.20 API.
|
||||||
|
|
||||||
|
gst-plugins-rs, the module containing GStreamer plugins written in Rust,
|
||||||
|
has also seen lots of activity with many new elements and plugins.
|
||||||
|
|
||||||
|
What follows is a list of elements and plugins available in
|
||||||
|
gst-plugins-rs, so people don’t miss out on all those potentially useful
|
||||||
|
elements that have no C equivalent.
|
||||||
|
|
||||||
|
- FIXME: add new elements
|
||||||
|
|
||||||
|
Rust audio plugins
|
||||||
|
|
||||||
|
- audiornnoise: New element for audio denoising which implements the
|
||||||
|
noise removal algorithm of the Xiph RNNoise library, in Rust
|
||||||
|
- rsaudioecho: Port of the audioecho element from gst-plugins-good
|
||||||
|
rsaudioloudnorm: Live audio loudness normalization element based on
|
||||||
|
the FFmpeg af_loudnorm filter
|
||||||
|
- claxondec: FLAC lossless audio codec decoder element based on the
|
||||||
|
pure-Rust claxon implementation
|
||||||
|
- csoundfilter: Audio filter that can use any filter defined via the
|
||||||
|
Csound audio programming language
|
||||||
|
- lewtondec: Vorbis audio decoder element based on the pure-Rust
|
||||||
|
lewton implementation
|
||||||
|
|
||||||
|
Rust video plugins
|
||||||
|
|
||||||
|
- cdgdec/cdgparse: Decoder and parser for the CD+G video codec based
|
||||||
|
on a pure-Rust CD+G implementation, used for example by karaoke CDs
|
||||||
|
- cea608overlay: CEA-608 Closed Captions overlay element
|
||||||
|
- cea608tott: CEA-608 Closed Captions to timed-text (e.g. VTT or SRT
|
||||||
|
subtitles) converter
|
||||||
|
- tttocea608: CEA-608 Closed Captions from timed-text converter
|
||||||
|
- mccenc/mccparse: MacCaption Closed Caption format encoder and parser
|
||||||
|
- sccenc/sccparse: Scenarist Closed Caption format encoder and parser
|
||||||
|
- dav1dec: AV1 video decoder based on the dav1d decoder implementation
|
||||||
|
by the VLC project
|
||||||
|
- rav1enc: AV1 video encoder based on the fast and pure-Rust rav1e
|
||||||
|
encoder implementation
|
||||||
|
- rsflvdemux: Alternative to the flvdemux FLV demuxer element from
|
||||||
|
gst-plugins-good, not feature-equivalent yet
|
||||||
|
- rsgifenc/rspngenc: GIF/PNG encoder elements based on the pure-Rust
|
||||||
|
implementations by the image-rs project
|
||||||
|
|
||||||
|
Rust text plugins
|
||||||
|
|
||||||
|
- textwrap: Element for line-wrapping timed text (e.g. subtitles) for
|
||||||
|
better screen-fitting, including hyphenation support for some
|
||||||
|
languages
|
||||||
|
|
||||||
|
Rust network plugins
|
||||||
|
|
||||||
|
- reqwesthttpsrc: HTTP(S) source element based on the Rust
|
||||||
|
reqwest/hyper HTTP implementations and almost feature-equivalent
|
||||||
|
with the main GStreamer HTTP source souphttpsrc
|
||||||
|
- s3src/s3sink: Source/sink element for the Amazon S3 cloud storage
|
||||||
|
- awstranscriber: Live audio to timed text transcription element using
|
||||||
|
the Amazon AWS Transcribe API
|
||||||
|
|
||||||
|
Generic Rust plugins
|
||||||
|
|
||||||
|
- sodiumencrypter/sodiumdecrypter: Encryption/decryption element based
|
||||||
|
on libsodium/NaCl
|
||||||
|
- togglerecord: Recording element that allows to pause/resume
|
||||||
|
recordings easily and considers keyframe boundaries
|
||||||
|
- fallbackswitch/fallbacksrc: Elements for handling potentially
|
||||||
|
failing (network) sources, restarting them on errors/timeout and
|
||||||
|
showing a fallback stream instead
|
||||||
|
- threadshare: Set of elements that provide alternatives for various
|
||||||
|
existing GStreamer elements but allow to share the streaming threads
|
||||||
|
between each other to reduce the number of threads
|
||||||
|
- rsfilesrc/rsfilesink: File source/sink elements as replacements for
|
||||||
|
the existing filesrc/filesink elements
|
||||||
|
|
||||||
|
Build and Dependencies
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
gst-build
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
Cerbero
|
||||||
|
|
||||||
|
Cerbero is a meta build system used to build GStreamer plus dependencies
|
||||||
|
on platforms where dependencies are not readily available, such as
|
||||||
|
Windows, Android, iOS and macOS.
|
||||||
|
|
||||||
|
General improvements
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
macOS / iOS
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
Windows
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
Windows MSI installer
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
Linux
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
Android
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
Platform-specific changes and improvements
|
||||||
|
|
||||||
|
Android
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
macOS and iOS
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
Windows
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
Linux
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
Documentation improvements
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
Possibly Breaking Changes
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
- MPEG-TS SCTE-35 API changes (FIXME: flesh out)
|
||||||
|
- gst_parse_launch() and friends now error out on non-existing
|
||||||
|
properties on top-level bins where they would silently fail and
|
||||||
|
ignore those before.
|
||||||
|
|
||||||
|
Known Issues
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
- There are a couple of known WebRTC-related regressions/blockers:
|
||||||
|
|
||||||
|
- webrtc: DTLS setup with Chrome is broken
|
||||||
|
- webrtcbin: First keyframe is usually lost
|
||||||
|
|
||||||
|
Contributors
|
||||||
|
|
||||||
|
- this section will be filled in in due course
|
||||||
|
|
||||||
|
… and many others who have contributed bug reports, translations, sent
|
||||||
|
suggestions or helped testing.
|
||||||
|
|
||||||
|
Stable 1.20 branch
|
||||||
|
|
||||||
|
After the 1.20.0 release there will be several 1.20.x bug-fix releases
|
||||||
|
which will contain bug fixes which have been deemed suitable for a
|
||||||
|
stable branch, but no new features or intrusive changes will be added to
|
||||||
|
a bug-fix release usually. The 1.20.x bug-fix releases will be made from
|
||||||
|
the git 1.20 branch, which will be a stable branch.
|
||||||
|
|
||||||
|
1.20.0
|
||||||
|
|
||||||
|
1.20.0 is scheduled to be released around October/November 2021.
|
||||||
|
|
||||||
|
Schedule for 1.22
|
||||||
|
|
||||||
|
Our next major feature release will be 1.22, and 1.21 will be the
|
||||||
|
unstable development version leading up to the stable 1.22 release. The
|
||||||
|
development of 1.21/1.22 will happen in the git main branch.
|
||||||
|
|
||||||
|
The plan for the 1.22 development cycle is yet to be confirmed.
|
||||||
|
|
||||||
|
1.22 will be backwards-compatible to the stable 1.20, 1.18, 1.16, 1.14,
|
||||||
|
1.12, 1.10, 1.8, 1.6, 1.4, 1.2 and 1.0 release series.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
|
These release notes have been prepared by Tim-Philipp Müller with
|
||||||
|
contributions from …
|
||||||
|
|
||||||
|
License: CC BY-SA 4.0
|
252
README
Normal file
252
README
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
GStreamer 1.19.x development series
|
||||||
|
|
||||||
|
WHAT IT IS
|
||||||
|
----------
|
||||||
|
|
||||||
|
This is GStreamer, a framework for streaming media.
|
||||||
|
|
||||||
|
WHERE TO START
|
||||||
|
--------------
|
||||||
|
|
||||||
|
We have a website at
|
||||||
|
|
||||||
|
https://gstreamer.freedesktop.org
|
||||||
|
|
||||||
|
Our documentation, including tutorials, API reference and FAQ can be found at
|
||||||
|
|
||||||
|
https://gstreamer.freedesktop.org/documentation/
|
||||||
|
|
||||||
|
You can subscribe to our mailing lists:
|
||||||
|
|
||||||
|
https://lists.freedesktop.org/mailman/listinfo/gstreamer-announce
|
||||||
|
|
||||||
|
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
|
||||||
|
|
||||||
|
We track bugs, feature requests and merge requests (patches) in GitLab at
|
||||||
|
|
||||||
|
https://gitlab.freedesktop.org/gstreamer/
|
||||||
|
|
||||||
|
You can join us on IRC - #gstreamer on irc.freenode.org
|
||||||
|
|
||||||
|
GStreamer 1.0 series
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Starring
|
||||||
|
|
||||||
|
GSTREAMER
|
||||||
|
|
||||||
|
The core around which all other modules revolve. Base functionality and
|
||||||
|
libraries, some essential elements, documentation, and testing.
|
||||||
|
|
||||||
|
BASE
|
||||||
|
|
||||||
|
A well-groomed and well-maintained collection of GStreamer plug-ins and
|
||||||
|
elements, spanning the range of possible types of elements one would want
|
||||||
|
to write for GStreamer.
|
||||||
|
|
||||||
|
And introducing, for the first time ever, on the development screen ...
|
||||||
|
|
||||||
|
THE GOOD
|
||||||
|
|
||||||
|
--- "Such ingratitude. After all the times I've saved your life."
|
||||||
|
|
||||||
|
A collection of plug-ins you'd want to have right next to you on the
|
||||||
|
battlefield. Shooting sharp and making no mistakes, these plug-ins have it
|
||||||
|
all: good looks, good code, and good licensing. Documented and dressed up
|
||||||
|
in tests. If you're looking for a role model to base your own plug-in on,
|
||||||
|
here it is.
|
||||||
|
|
||||||
|
If you find a plot hole or a badly lip-synced line of code in them,
|
||||||
|
let us know - it is a matter of honour for us to ensure Blondie doesn't look
|
||||||
|
like he's been walking 100 miles through the desert without water.
|
||||||
|
|
||||||
|
THE UGLY
|
||||||
|
|
||||||
|
--- "When you have to shoot, shoot. Don't talk."
|
||||||
|
|
||||||
|
There are times when the world needs a color between black and white.
|
||||||
|
Quality code to match the good's, but two-timing, backstabbing and ready to
|
||||||
|
sell your freedom down the river. These plug-ins might have a patent noose
|
||||||
|
around their neck, or a lock-up license, or any other problem that makes you
|
||||||
|
think twice about shipping them.
|
||||||
|
|
||||||
|
We don't call them ugly because we like them less. Does a mother love her
|
||||||
|
son less because he's not as pretty as the other ones ? No - she commends
|
||||||
|
him on his great personality. These plug-ins are the life of the party.
|
||||||
|
And we'll still step in and set them straight if you report any unacceptable
|
||||||
|
behaviour - because there are two kinds of people in the world, my friend:
|
||||||
|
those with a rope around their neck and the people who do the cutting.
|
||||||
|
|
||||||
|
THE BAD
|
||||||
|
|
||||||
|
--- "That an accusation?"
|
||||||
|
|
||||||
|
No perfectly groomed moustache or any amount of fine clothing is going to
|
||||||
|
cover up the truth - these plug-ins are Bad with a capital B.
|
||||||
|
They look fine on the outside, and might even appear to get the job done, but
|
||||||
|
at the end of the day they're a black sheep. Without a golden-haired angel
|
||||||
|
to watch over them, they'll probably land in an unmarked grave at the final
|
||||||
|
showdown.
|
||||||
|
|
||||||
|
Don't bug us about their quality - exercise your Free Software rights,
|
||||||
|
patch up the offender and send us the patch on the fastest steed you can
|
||||||
|
steal from the Confederates. Because you see, in this world, there's two
|
||||||
|
kinds of people, my friend: those with loaded guns and those who dig.
|
||||||
|
You dig.
|
||||||
|
|
||||||
|
The Lowdown
|
||||||
|
-----------
|
||||||
|
|
||||||
|
--- "I've never seen so many plug-ins wasted so badly."
|
||||||
|
|
||||||
|
GStreamer Plug-ins has grown so big that it's hard to separate the wheat from
|
||||||
|
the chaff. Also, distributors have brought up issues about the legal status
|
||||||
|
of some of the plug-ins we ship. To remedy this, we've divided the previous
|
||||||
|
set of available plug-ins into four modules:
|
||||||
|
|
||||||
|
- gst-plugins-base: a small and fixed set of plug-ins, covering a wide range
|
||||||
|
of possible types of elements; these are continuously kept up-to-date
|
||||||
|
with any core changes during the development series.
|
||||||
|
|
||||||
|
- We believe distributors can safely ship these plug-ins.
|
||||||
|
- People writing elements should base their code on these elements.
|
||||||
|
- These elements come with examples, documentation, and regression tests.
|
||||||
|
|
||||||
|
- gst-plugins-good: a set of plug-ins that we consider to have good quality
|
||||||
|
code, correct functionality, our preferred license (LGPL for the plug-in
|
||||||
|
code, LGPL or LGPL-compatible for the supporting library).
|
||||||
|
|
||||||
|
- We believe distributors can safely ship these plug-ins.
|
||||||
|
- People writing elements should base their code on these elements.
|
||||||
|
|
||||||
|
- gst-plugins-ugly: a set of plug-ins that have good quality and correct
|
||||||
|
functionality, but distributing them might pose problems. The license
|
||||||
|
on either the plug-ins or the supporting libraries might not be how we'd
|
||||||
|
like. The code might be widely known to present patent problems.
|
||||||
|
|
||||||
|
- Distributors should check if they want/can ship these plug-ins.
|
||||||
|
- People writing elements should base their code on these elements.
|
||||||
|
|
||||||
|
- gst-plugins-bad: a set of plug-ins that aren't up to par compared to the
|
||||||
|
rest. They might be close to being good quality, but they're missing
|
||||||
|
something - be it a good code review, some documentation, a set of tests,
|
||||||
|
a real live maintainer, or some actual wide use.
|
||||||
|
If the blanks are filled in they might be upgraded to become part of
|
||||||
|
either gst-plugins-good or gst-plugins-ugly, depending on the other factors.
|
||||||
|
|
||||||
|
- If the plug-ins break, you can't complain - instead, you can fix the
|
||||||
|
problem and send us a patch, or bribe someone into fixing them for you.
|
||||||
|
- New contributors can start here for things to work on.
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
---------
|
||||||
|
|
||||||
|
- Linux is of course fully supported
|
||||||
|
- FreeBSD is reported to work; other BSDs should work too; same for Solaris
|
||||||
|
- MacOS works, binary 1.x packages can be built using the cerbero build tool
|
||||||
|
- Windows works; binary 1.x packages can be built using the cerbero build tool
|
||||||
|
- MSys/MinGW builds
|
||||||
|
- Microsoft Visual Studio builds are also available and supported
|
||||||
|
- Android works, binary 1.x packages can be built using the cerbero build tool
|
||||||
|
- iOS works
|
||||||
|
|
||||||
|
INSTALLING FROM PACKAGES
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
You should always prefer installing from packages first. GStreamer is
|
||||||
|
well-maintained for a number of distributions, including Fedora, Debian,
|
||||||
|
Ubuntu, Mandrake, Arch Linux, Gentoo, ...
|
||||||
|
|
||||||
|
Only in cases where you:
|
||||||
|
|
||||||
|
- want to hack on GStreamer
|
||||||
|
- want to verify that a bug has been fixed
|
||||||
|
- do not have a sane distribution
|
||||||
|
|
||||||
|
should you choose to build from source tarballs or git.
|
||||||
|
|
||||||
|
Find more information about the various packages at
|
||||||
|
|
||||||
|
https://gstreamer.freedesktop.org/download/
|
||||||
|
|
||||||
|
COMPILING FROM SOURCE TARBALLS
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
- again, make sure that you really need to install from source!
|
||||||
|
If GStreamer is one of your first projects ever that you build from source,
|
||||||
|
consider taking on an easier project.
|
||||||
|
|
||||||
|
- you need a recent version of Meson installed, see
|
||||||
|
|
||||||
|
http://mesonbuild.com/Getting-meson.html
|
||||||
|
|
||||||
|
and
|
||||||
|
|
||||||
|
https://gitlab.freedesktop.org/gstreamer/gst-build/blob/master/README.md
|
||||||
|
|
||||||
|
- run
|
||||||
|
|
||||||
|
meson build
|
||||||
|
ninja -C build
|
||||||
|
|
||||||
|
to build GStreamer.
|
||||||
|
|
||||||
|
- if you want to install it (not required, but what you usually want to do), run
|
||||||
|
|
||||||
|
ninja -C build install
|
||||||
|
|
||||||
|
- try out a simple test:
|
||||||
|
gst-launch-1.0 -v fakesrc num_buffers=5 ! fakesink
|
||||||
|
(If you didn't install GStreamer, run `./build/tools/gst-launch-1.0`)
|
||||||
|
|
||||||
|
If it outputs a bunch of messages from fakesrc and fakesink, everything is
|
||||||
|
ok.
|
||||||
|
|
||||||
|
If it did not work, keep in mind that you might need to adjust the
|
||||||
|
PATH and/or LD_LIBRARY_PATH environment variables to make the system
|
||||||
|
find GStreamer in the prefix where you installed (by default that is /usr/local).
|
||||||
|
|
||||||
|
- After this, you're ready to install gst-plugins, which will provide the
|
||||||
|
functionality you're probably looking for by now, so go on and read
|
||||||
|
that README.
|
||||||
|
|
||||||
|
COMPILING FROM GIT
|
||||||
|
------------------
|
||||||
|
|
||||||
|
You can build an uninstalled GStreamer from git for development or testing
|
||||||
|
purposes without affecting your system installation.
|
||||||
|
|
||||||
|
Get started with:
|
||||||
|
|
||||||
|
git clone https://gitlab.freedesktop.org/gstreamer/gst-build
|
||||||
|
meson build
|
||||||
|
ninja -C build
|
||||||
|
ninja -C build uninstalled
|
||||||
|
|
||||||
|
For more information, see the `gst-build` module and its documentation:
|
||||||
|
|
||||||
|
https://gitlab.freedesktop.org/gstreamer/gst-build/blob/master/README.md
|
||||||
|
|
||||||
|
|
||||||
|
PLUG-IN DEPENDENCIES AND LICENSES
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
GStreamer is developed under the terms of the LGPL (see COPYING file for
|
||||||
|
details). Some of our plug-ins however rely on libraries which are available
|
||||||
|
under other licenses. This means that if you are distributing an application
|
||||||
|
which has a non-GPL compatible license (for instance a closed-source
|
||||||
|
application) with GStreamer, you have to make sure not to distribute GPL-linked
|
||||||
|
plug-ins.
|
||||||
|
|
||||||
|
When using GPL-linked plug-ins, GStreamer is for all practical reasons
|
||||||
|
under the GPL itself.
|
||||||
|
|
||||||
|
HISTORY
|
||||||
|
-------
|
||||||
|
|
||||||
|
The fundamental design comes from the video pipeline at Oregon Graduate
|
||||||
|
Institute, as well as some ideas from DirectMedia. It's based on plug-ins that
|
||||||
|
will provide the various codec and other functionality. The interface
|
||||||
|
hopefully is generic enough for various companies (ahem, Apple) to release
|
||||||
|
binary codecs for Linux, until such time as they get a clue and release the
|
||||||
|
source.
|
174
README.static-linking
Normal file
174
README.static-linking
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
=================================
|
||||||
|
GStreamer Static Linking README
|
||||||
|
=================================
|
||||||
|
|
||||||
|
DRAFT, April 2013
|
||||||
|
|
||||||
|
|
||||||
|
I. INTRODUCTION
|
||||||
|
|
||||||
|
It is possible to link GStreamer libraries, plugins and applications
|
||||||
|
statically, both in case of free/libre/open-source software applications
|
||||||
|
and proprietary applications. On some platforms static linking may even
|
||||||
|
be required.
|
||||||
|
|
||||||
|
However, distributing statically linked binaries using GStreamer usually
|
||||||
|
requires additional effort to stay compliant with the GNU LGPL v2.1 license.
|
||||||
|
|
||||||
|
The purpose of this document is to draw attention to this fact, and to
|
||||||
|
summarise in layman's terms what we believe is required from anyone
|
||||||
|
distributing statically linked GStreamer binaries. Most of this also
|
||||||
|
applies to dynamically linked GStreamer binaries.
|
||||||
|
|
||||||
|
|
||||||
|
II. DISCLAIMER
|
||||||
|
|
||||||
|
This document is not legal advice, nor is it comprehensive. It may use
|
||||||
|
words in ways that do not match the definition or use in the license
|
||||||
|
text. It may even be outright wrong. Read the license text for all the
|
||||||
|
details, it is the only legally binding document in this respect.
|
||||||
|
|
||||||
|
This document is primarily concerned with the implications for the
|
||||||
|
distribution of binaries based on LGPL-licensed software as imposed by
|
||||||
|
the LGPL license, but there may be other restrictions to the distribution
|
||||||
|
of such binaries, such as terms and conditions of distribution channels
|
||||||
|
(e.g. "app stores").
|
||||||
|
|
||||||
|
|
||||||
|
III. THE SPIRIT OF THE LGPL LICENSE
|
||||||
|
|
||||||
|
The GNU LGPL v2.1 license allows use of such-licensed software by
|
||||||
|
proprietary applications, but still aims to ensure that at least the
|
||||||
|
LGPL-licensed software parts remain free under all circumstances. This
|
||||||
|
means any changes to LGPL-licensed source code must be documented and
|
||||||
|
be made available on request to those who received binaries of the
|
||||||
|
software. It also means that it must be possible to make changes to the
|
||||||
|
LGPL-licensed software parts and make the application use those, as far
|
||||||
|
as that is possible. And that recipients of an application using
|
||||||
|
LGPL-licensed software are made aware of their rights according to the
|
||||||
|
LGPL license.
|
||||||
|
|
||||||
|
In an environment where GStreamer libraries and plugins are used as
|
||||||
|
dynamically-loaded shared objects (DLL/.so/.dyn files), this is usually
|
||||||
|
not a big problem, because it is fairly easy to compile a modified version
|
||||||
|
of the GStreamer libraries or LGPL plugins, and the application will/should
|
||||||
|
just pick up and use the modified version automatically. All that is needed
|
||||||
|
is for the original, LGPL-licensed source code and source code modifications
|
||||||
|
to be made available, and for a way to build the libraries or plugins for
|
||||||
|
the platform required (usually that will be using the build system scripts
|
||||||
|
that come with GStreamer, and using the typical build environment on the
|
||||||
|
system in question, but where that is not the case the needed build scripts
|
||||||
|
and/or tools would need to be provided as well).
|
||||||
|
|
||||||
|
|
||||||
|
IV. THINGS YOU NEED TO DO
|
||||||
|
|
||||||
|
* You must tell users of your application that you are using LGPL-licensed
|
||||||
|
software, which LGPL-licensed software exactly, and you must provide them
|
||||||
|
with a copy of the license so they know their rights under the LGPL.
|
||||||
|
|
||||||
|
* You must provide (on request) all the source code and all the changes
|
||||||
|
or additions you have made to the LGPL-licensed software you are using.
|
||||||
|
|
||||||
|
For GStreamer code we would recommend that the changes be provided either
|
||||||
|
in form of a branch in a git repository, or as a set of "git format-patch"-
|
||||||
|
style patches against a GStreamer release or a snapshot of a GStreamer git
|
||||||
|
repository. The patches should ideally say what was changed and why it
|
||||||
|
was changed, and there should ideally be separate patches for independent
|
||||||
|
changes.
|
||||||
|
|
||||||
|
* You must provide a way for users of your application to make changes to
|
||||||
|
the LGPL-licensed parts of the code, and re-create a full application
|
||||||
|
binary with the changes (using the standard toolchain and tools of the
|
||||||
|
target platform; if you are using a custom toolchain or custom tools
|
||||||
|
you must provide these and document how to use them to create a new
|
||||||
|
application binary).
|
||||||
|
|
||||||
|
Note that this of course does not mean that the user is allowed to
|
||||||
|
re-distribute the changed application. Nor does it mean that you have
|
||||||
|
to provide your proprietary source code - it is sufficient to provide a
|
||||||
|
ready-made compiled object file that can be relinked into an application
|
||||||
|
binary with the re-compiled LGPL components.
|
||||||
|
|
||||||
|
|
||||||
|
V. THINGS TO LOOK OUT FOR
|
||||||
|
|
||||||
|
While most GStreamer plugins and the libraries they depend on are licensed
|
||||||
|
under the LGPL or even more permissive licenses, that is not the case for
|
||||||
|
all plugins and libraries used, esp. those in the gst-plugins-ugly or
|
||||||
|
some of those in the gst-plugins-bad set of plugins.
|
||||||
|
|
||||||
|
When statically linking proprietary code, care must be taken not to
|
||||||
|
statically link plugins or libraries that are licensed under less permissive
|
||||||
|
terms than the LGPL, such as e.g. GPL-licensed libraries.
|
||||||
|
|
||||||
|
|
||||||
|
VI. SPECIAL CONSIDERATIONS FOR SPECIFIC USE-CASES
|
||||||
|
|
||||||
|
|
||||||
|
1. Proprietary GStreamer/GLib-based Application On iOS
|
||||||
|
|
||||||
|
Let's assume an individual or a company wants to distribute a proprietary
|
||||||
|
iOS application that is built on top of GStreamer and GLib through
|
||||||
|
Apple's App Store. At the time of writing the Apple iPhone developer
|
||||||
|
agreement didn’t allow the bundling of shared libraries, so distributing
|
||||||
|
a proprietary iOS application with shared libraries is only possible using
|
||||||
|
distribution mechanisms outside of the App Store and/or only to jailbroken
|
||||||
|
devices, a prospect that may not appeal to our individual or company. So the
|
||||||
|
only alternative then is to link everything statically, which means the
|
||||||
|
obligations mentioned above come into play.
|
||||||
|
|
||||||
|
|
||||||
|
2. Example: Jabber on iOS
|
||||||
|
|
||||||
|
Tandberg (now Cisco) created a Jabber application for iOS, based on GStreamer.
|
||||||
|
On request they provided an LGPL compliance bundle in form of a zip file, with
|
||||||
|
roughly the following contents:
|
||||||
|
|
||||||
|
buildapp.sh
|
||||||
|
readme.txt
|
||||||
|
Jabber/Jabber-Info.plist
|
||||||
|
Jabber/libip.a [236MB binary with proprietary code]
|
||||||
|
Jabber/main.mm
|
||||||
|
Jabber/xcconfig/Application.xcconfig
|
||||||
|
Jabber/xcconfig/Debug.xcconfig
|
||||||
|
Jabber/xcconfig/Release.xcconfig
|
||||||
|
Jabber/xcconfig/Shared.xcconfig
|
||||||
|
Jabber/Resources/*.lproj/Localizable.strings
|
||||||
|
Jabber/Resources/{Images,Audio,Sounds,IB,Message Styles,Emoticons,Fonts}/*
|
||||||
|
Jabber/Resources/*
|
||||||
|
Jabber.xcodeproj/project.pbxproj
|
||||||
|
Jabber.xcodeproj/project.xcworkspace/contents.xcworkspacedata
|
||||||
|
opensource/build/config.site
|
||||||
|
opensource/build/m4/movi.m4
|
||||||
|
opensource/build/scripts/clean-deps.sh
|
||||||
|
opensource/build/scripts/fixup-makefile.sh
|
||||||
|
opensource/build/scripts/MoviMaker.py
|
||||||
|
opensource/build.sh
|
||||||
|
opensource/env.sh
|
||||||
|
opensource/Makefile
|
||||||
|
opensource/external/glib/*
|
||||||
|
opensource/external/gstreamer/{gstreamer,gst-plugins-*}/*
|
||||||
|
opensource/external/openssl/*
|
||||||
|
opensource/external/proxy-libintl/*
|
||||||
|
opensource/toolchain/darwin-x86/bin/{misc autotoools,m4,glib-mkenums,glib-genmarshal,libtool,pkg-config,etc.}
|
||||||
|
opensource/toolchain/darwin-x86/share/{aclocal,aclocal-1.11,autoconf,automake-1.11,libtool}/*
|
||||||
|
opensource/toolchain/darwin-x86/share/Config.pm
|
||||||
|
opensource/toolchain/darwin-x86/share/Config.pm.movi.in
|
||||||
|
patches/glib/glib.patch
|
||||||
|
patches/gst-plugins-bad/gst-plugins-bad.patch
|
||||||
|
patches/gst-plugins-base/gst-plugins-base.patch
|
||||||
|
patches/gst-plugins-good/gst-plugins-good.patch
|
||||||
|
patches/gstreamer/gstreamer.patch
|
||||||
|
patches/openssl/openssl.patch
|
||||||
|
|
||||||
|
readme.txt starts with "This Readme file describes how to build the Cisco
|
||||||
|
Jabber for iPad application. You need to install Xcode, but the final package
|
||||||
|
is built by running buildapp.sh." and describes how to build project,
|
||||||
|
prerequisites, the procedure in detail, and a "How to Include Provisioning
|
||||||
|
Profile Manually / Alternate Code Signing Instructions" section.
|
||||||
|
|
||||||
|
|
||||||
|
3. Random Links Which May Be Of Interest
|
||||||
|
|
||||||
|
[0] http://multinc.com/2009/08/24/compatibility-between-the-iphone-app-store-and-the-lgpl/
|
96
RELEASE
Normal file
96
RELEASE
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
This is GStreamer gst-plugins-bad 1.19.2.
|
||||||
|
|
||||||
|
GStreamer 1.19 is the development branch leading up to the next major
|
||||||
|
stable version which will be 1.20.
|
||||||
|
|
||||||
|
The 1.19 development series adds new features on top of the 1.18 series and is
|
||||||
|
part of the API and ABI-stable 1.x release series of the GStreamer multimedia
|
||||||
|
framework.
|
||||||
|
|
||||||
|
Full release notes will one day be found at:
|
||||||
|
|
||||||
|
https://gstreamer.freedesktop.org/releases/1.20/
|
||||||
|
|
||||||
|
Binaries for Android, iOS, Mac OS X and Windows will usually be provided
|
||||||
|
shortly after the release.
|
||||||
|
|
||||||
|
This module will not be very useful by itself and should be used in conjunction
|
||||||
|
with other GStreamer modules for a complete multimedia experience.
|
||||||
|
|
||||||
|
- gstreamer: provides the core GStreamer libraries and some generic plugins
|
||||||
|
|
||||||
|
- gst-plugins-base: a basic set of well-supported plugins and additional
|
||||||
|
media-specific GStreamer helper libraries for audio,
|
||||||
|
video, rtsp, rtp, tags, OpenGL, etc.
|
||||||
|
|
||||||
|
- gst-plugins-good: a set of well-supported plugins under our preferred
|
||||||
|
license
|
||||||
|
|
||||||
|
- gst-plugins-ugly: a set of well-supported plugins which might pose
|
||||||
|
problems for distributors
|
||||||
|
|
||||||
|
- gst-plugins-bad: a set of plugins of varying quality that have not made
|
||||||
|
their way into one of core/base/good/ugly yet, for one
|
||||||
|
reason or another. Many of these are are production quality
|
||||||
|
elements, but may still be missing documentation or unit
|
||||||
|
tests; others haven't passed the rigorous quality testing
|
||||||
|
we expect yet.
|
||||||
|
|
||||||
|
- gst-libav: a set of codecs plugins based on the ffmpeg library. This is
|
||||||
|
where you can find audio and video decoders and encoders
|
||||||
|
for a wide variety of formats including H.264, AAC, etc.
|
||||||
|
|
||||||
|
- gstreamer-vaapi: hardware-accelerated video decoding and encoding using
|
||||||
|
VA-API on Linux. Primarily for Intel graphics hardware.
|
||||||
|
|
||||||
|
- gst-omx: hardware-accelerated video decoding and encoding, primarily for
|
||||||
|
embedded Linux systems that provide an OpenMax
|
||||||
|
implementation layer such as the Raspberry Pi.
|
||||||
|
|
||||||
|
- gst-rtsp-server: library to serve files or streaming pipelines via RTSP
|
||||||
|
|
||||||
|
- gst-editing-services: library an plugins for non-linear editing
|
||||||
|
|
||||||
|
==== Download ====
|
||||||
|
|
||||||
|
You can find source releases of gstreamer in the download
|
||||||
|
directory: https://gstreamer.freedesktop.org/src/gstreamer/
|
||||||
|
|
||||||
|
The git repository and details how to clone it can be found at
|
||||||
|
https://gitlab.freedesktop.org/gstreamer/
|
||||||
|
|
||||||
|
==== Homepage ====
|
||||||
|
|
||||||
|
The project's website is https://gstreamer.freedesktop.org/
|
||||||
|
|
||||||
|
==== Support and Bugs ====
|
||||||
|
|
||||||
|
We have recently moved from GNOME Bugzilla to GitLab on freedesktop.org
|
||||||
|
for bug reports and feature requests:
|
||||||
|
|
||||||
|
https://gitlab.freedesktop.org/gstreamer
|
||||||
|
|
||||||
|
Please submit patches via GitLab as well, in form of Merge Requests. See
|
||||||
|
|
||||||
|
https://gstreamer.freedesktop.org/documentation/contribute/
|
||||||
|
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
For help and support, please subscribe to and send questions to the
|
||||||
|
gstreamer-devel mailing list (see below for details).
|
||||||
|
|
||||||
|
There is also a #gstreamer IRC channel on the Freenode IRC network.
|
||||||
|
|
||||||
|
==== Developers ====
|
||||||
|
|
||||||
|
GStreamer source code repositories can be found on GitLab on freedesktop.org:
|
||||||
|
|
||||||
|
https://gitlab.freedesktop.org/gstreamer
|
||||||
|
|
||||||
|
and can also be cloned from there and this is also where you can submit
|
||||||
|
Merge Requests or file issues for bugs or feature requests.
|
||||||
|
|
||||||
|
Interested developers of the core library, plugins, and applications should
|
||||||
|
subscribe to the gstreamer-devel list:
|
||||||
|
|
||||||
|
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
|
65
REQUIREMENTS
Normal file
65
REQUIREMENTS
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
GStreamer uses a *large* array of tools and libraries, most of which are
|
||||||
|
optional. We have attempted to make sure that any code that depends on
|
||||||
|
optional libraries doesn't get built unless you have those libraries. If
|
||||||
|
you find this not to be the case, please, let us know by filing a bug
|
||||||
|
report at http://bugzilla.gnome.org/.
|
||||||
|
|
||||||
|
|
||||||
|
Required tools:
|
||||||
|
===============
|
||||||
|
|
||||||
|
An extra set of tools is required if you wish to build GStreamer out of
|
||||||
|
CVS (using autogen.sh):
|
||||||
|
|
||||||
|
autoconf 2.52 or better
|
||||||
|
automake 1.5
|
||||||
|
gettext 0.11.5
|
||||||
|
libtool v1.4 or better
|
||||||
|
pkgconfig 0.9.0 or better (http://www.freedesktop.org/software/pkgconfig/)
|
||||||
|
|
||||||
|
Required libraries:
|
||||||
|
===================
|
||||||
|
|
||||||
|
The core GStreamer libraries. See the gstreamer/ module in GStreamer cvs, or
|
||||||
|
the version that corresponds to this plugin release.
|
||||||
|
|
||||||
|
Optional libraries:
|
||||||
|
===================
|
||||||
|
|
||||||
|
This file lists supporting libraries for which gst-plugins contains plugins,
|
||||||
|
as well as their minimum version. You can find the corresponding plugins in
|
||||||
|
ext/(library)
|
||||||
|
|
||||||
|
libdvdread (for the dvdsrc)
|
||||||
|
http://dvdnav.mplayerhq.hu/
|
||||||
|
(optional: libcss for encrypted DVDs)
|
||||||
|
libdvdnav (for the dvdnavsrc)
|
||||||
|
http://dvdnav.mplayerhq.hu/
|
||||||
|
(optional: libcss for encrypted DVDs)
|
||||||
|
>= 0.1.9
|
||||||
|
libgsm (for the gsm plugin)
|
||||||
|
http://kbs.cs.tu-berlin.de/~jutta/toast.html
|
||||||
|
sdl (for the sdl sink)
|
||||||
|
http://www.libsdl.org
|
||||||
|
dtsdec (for DTS audio decoding)
|
||||||
|
http://www.videolan.org/libdca.html
|
||||||
|
musepack (for musepack audio codec/format)
|
||||||
|
(http://www.musepack.net/)
|
||||||
|
nas (for the NAS sound server sink)
|
||||||
|
(http://radscan.com/nas.html)
|
||||||
|
libmms (for MMS protocol support)
|
||||||
|
(http://www.sf.net/projects/libmms)
|
||||||
|
libamrnb (for AMR-NB support)
|
||||||
|
(http://www.penguin.cz/~utx/amr)
|
||||||
|
libamrwb (for AMR-WB support)
|
||||||
|
(http://www.penguin.cz/~utx/amr)
|
||||||
|
libkate (for Kate support)
|
||||||
|
(http://libkate.googlecode.com/)
|
||||||
|
librtmp (for RTMP support)
|
||||||
|
(http://rtmpdump.mplayerhq.hu/)
|
||||||
|
|
||||||
|
Optional (debian) packages:
|
||||||
|
===========================
|
||||||
|
|
||||||
|
gtk-doc-tools 1.6 -- needed to build documentation
|
||||||
|
python-xml -- needed to build plugin documentation
|
23
data/meson.build
Normal file
23
data/meson.build
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
encoding_targetsdir = join_paths(get_option('datadir'),
|
||||||
|
'gstreamer-' + api_version, 'encoding-profiles')
|
||||||
|
|
||||||
|
encoding_targets = [
|
||||||
|
['file-extension', ['targets/file-extension/ogv.gep',
|
||||||
|
'targets/file-extension/oga.gep',
|
||||||
|
'targets/file-extension/mkv.gep',
|
||||||
|
'targets/file-extension/mp3.gep',
|
||||||
|
'targets/file-extension/webm.gep',
|
||||||
|
'targets/file-extension/flv.gep',
|
||||||
|
'targets/file-extension/mp4.gep',
|
||||||
|
'targets/file-extension/ts.gep',
|
||||||
|
'targets/file-extension/avi.gep',],
|
||||||
|
],
|
||||||
|
['online-services', ['targets/online-service/youtube.gep',]],
|
||||||
|
['device', ['targets/device/dvd.gep',]],
|
||||||
|
]
|
||||||
|
|
||||||
|
foreach path_targets : encoding_targets
|
||||||
|
dir = join_paths(encoding_targetsdir, path_targets.get(0))
|
||||||
|
etargets = path_targets.get(1)
|
||||||
|
install_data(sources: etargets, install_dir: dir)
|
||||||
|
endforeach
|
24
data/targets/device/dvd.gep
Normal file
24
data/targets/device/dvd.gep
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
[GStreamer Encoding Target]
|
||||||
|
name=dvd
|
||||||
|
category=device
|
||||||
|
description=Encoding target suitable for DVDs
|
||||||
|
|
||||||
|
[profile-dvd]
|
||||||
|
name=dvd
|
||||||
|
type=container
|
||||||
|
description[c]=This is an encoding profile usable for DVDs
|
||||||
|
format=video/mpeg, mpegversion=(int)2, systemstream=(boolean)true
|
||||||
|
|
||||||
|
[streamprofile-dvd-0]
|
||||||
|
parent=dvd
|
||||||
|
type=video
|
||||||
|
format=video/mpeg, mpegversion=(int)2, systemstream=(boolean)false
|
||||||
|
presence=0
|
||||||
|
pass=0
|
||||||
|
variableframerate=false
|
||||||
|
|
||||||
|
[streamprofile-dvd-1]
|
||||||
|
parent=dvd
|
||||||
|
type=audio
|
||||||
|
format=audio/mpeg, mpegversion=(int)1, layer=(int)2
|
||||||
|
presence=0
|
21
data/targets/file-extension/avi.gep
Normal file
21
data/targets/file-extension/avi.gep
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
[GStreamer Encoding Target]
|
||||||
|
name=avi
|
||||||
|
category=file-extension
|
||||||
|
description=Default target for files with a .avi extension
|
||||||
|
|
||||||
|
[profile-default]
|
||||||
|
name=default
|
||||||
|
type=container
|
||||||
|
description=Default profile for files with a .avi extension.
|
||||||
|
format=video/x-msvideo
|
||||||
|
|
||||||
|
[streamprofile-default-0]
|
||||||
|
parent=default
|
||||||
|
type=audio
|
||||||
|
format=audio/mpeg, mpegversion=(int)1, mpegaudioversion=(int)1, layer=(int)3
|
||||||
|
|
||||||
|
[streamprofile-default-1]
|
||||||
|
parent=default
|
||||||
|
type=video
|
||||||
|
format=video/mpeg, mpegversion=(int)4
|
||||||
|
|
32
data/targets/file-extension/flv.gep
Normal file
32
data/targets/file-extension/flv.gep
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
[GStreamer Encoding Target]
|
||||||
|
name=flv
|
||||||
|
category=file-extension
|
||||||
|
description=Default target for files with a .flv extension
|
||||||
|
|
||||||
|
[profile-default]
|
||||||
|
name=default
|
||||||
|
type=container
|
||||||
|
description=Default profile for files with a .flv extension.
|
||||||
|
format=video/x-flv
|
||||||
|
|
||||||
|
[streamprofile-default-0]
|
||||||
|
parent=default
|
||||||
|
type=audio
|
||||||
|
format=audio/mpeg,mpegversion=4
|
||||||
|
|
||||||
|
[streamprofile-default-1]
|
||||||
|
parent=default
|
||||||
|
type=audio
|
||||||
|
format=audio/mpeg, mpegversion=(int)1, mpegaudioversion=(int)1, layer=(int)3
|
||||||
|
|
||||||
|
[streamprofile-default-2]
|
||||||
|
parent=default
|
||||||
|
type=video
|
||||||
|
format=video/x-h264
|
||||||
|
preset=Profile YouTube
|
||||||
|
pass=0
|
||||||
|
|
||||||
|
[streamprofile-default-3]
|
||||||
|
parent=default
|
||||||
|
type=video
|
||||||
|
format=video/x-h264
|
28
data/targets/file-extension/mkv.gep
Normal file
28
data/targets/file-extension/mkv.gep
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
[GStreamer Encoding Target]
|
||||||
|
name=mkv;matroska;
|
||||||
|
category=file-extension
|
||||||
|
description=Default target for files with a .mkv extension
|
||||||
|
|
||||||
|
[profile-default]
|
||||||
|
name=default
|
||||||
|
description=Default profile for files with a .mkv extension. Audio stream can be either opus (default) or vorbis depending on what is available on the system. Video stream will be either in vp8 (default) or vp9.
|
||||||
|
type=container
|
||||||
|
format=video/x-matroska
|
||||||
|
|
||||||
|
[streamprofile-default-0]
|
||||||
|
parent=default
|
||||||
|
type=audio
|
||||||
|
format=audio/x-vorbis;audio/x-opus
|
||||||
|
|
||||||
|
[streamprofile-default-1]
|
||||||
|
parent=default
|
||||||
|
type=video
|
||||||
|
format=video/x-h264
|
||||||
|
preset=Quality Normal
|
||||||
|
pass=0
|
||||||
|
|
||||||
|
[streamprofile-default-2]
|
||||||
|
parent=default
|
||||||
|
type=video
|
||||||
|
format=video/x-h264
|
||||||
|
pass=0
|
15
data/targets/file-extension/mp3.gep
Normal file
15
data/targets/file-extension/mp3.gep
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[GStreamer Encoding Target]
|
||||||
|
name=mp3
|
||||||
|
category=file-extension
|
||||||
|
description=Default target for files with a .mp3 extension
|
||||||
|
|
||||||
|
[profile-default]
|
||||||
|
name=default
|
||||||
|
type=container
|
||||||
|
description=Default profile for files with a .mp3 extension.
|
||||||
|
format=application/x-id3
|
||||||
|
|
||||||
|
[streamprofile-default-0]
|
||||||
|
parent=default
|
||||||
|
type=audio
|
||||||
|
format=audio/mpeg, mpegversion=(int)1, mpegaudioversion=(int)1, layer=(int)3
|
34
data/targets/file-extension/mp4.gep
Normal file
34
data/targets/file-extension/mp4.gep
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
[GStreamer Encoding Target]
|
||||||
|
name=mp4;mov
|
||||||
|
category=file-extension
|
||||||
|
description=Default target for files with a .mp4 and .mov extension
|
||||||
|
|
||||||
|
[profile-default]
|
||||||
|
name=default
|
||||||
|
type=container
|
||||||
|
description=Default profile for files with a .mp4 extension. Suitable for uploading to youtube.
|
||||||
|
format=video/quicktime
|
||||||
|
preset=Profile YouTube
|
||||||
|
|
||||||
|
[streamprofile-default-0]
|
||||||
|
parent=default
|
||||||
|
type=audio
|
||||||
|
format=audio/mpeg,mpegversion=4,base-profile=lc,rate={48000,96000},channels=2;audio/mpeg,mpegversion=4,base-profile=lc,rate={48000,96000}
|
||||||
|
restriction=audio/x-raw,channels=6,channel-mask=0x3f;audio/x-raw,channels=2
|
||||||
|
|
||||||
|
[streamprofile-default-1]
|
||||||
|
parent=default
|
||||||
|
type=video
|
||||||
|
format=video/x-h264
|
||||||
|
preset=Profile YouTube
|
||||||
|
pass=0
|
||||||
|
|
||||||
|
[streamprofile-default-2]
|
||||||
|
parent=default
|
||||||
|
type=audio
|
||||||
|
format=audio/mpeg,mpegversion=4
|
||||||
|
|
||||||
|
[streamprofile-default-3]
|
||||||
|
parent=default
|
||||||
|
type=video
|
||||||
|
format=video/x-h264
|
15
data/targets/file-extension/oga.gep
Normal file
15
data/targets/file-extension/oga.gep
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[GStreamer Encoding Target]
|
||||||
|
name=oga
|
||||||
|
category=file-extension
|
||||||
|
description=Default target for files with a .ogg and friends extension
|
||||||
|
|
||||||
|
[profile-default]
|
||||||
|
name=default
|
||||||
|
description=Default target for files with a .ogg and friends extension
|
||||||
|
type=container
|
||||||
|
format=audio/ogg
|
||||||
|
|
||||||
|
[streamprofile-default-0]
|
||||||
|
parent=default
|
||||||
|
type=audio
|
||||||
|
format=audio/x-vorbis;audio/x-opus
|
25
data/targets/file-extension/ogv.gep
Normal file
25
data/targets/file-extension/ogv.gep
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
[GStreamer Encoding Target]
|
||||||
|
name=ogv;ogg
|
||||||
|
category=file-extension
|
||||||
|
description=Default target for files with a .ogg and friends extension
|
||||||
|
|
||||||
|
[profile-default]
|
||||||
|
name=default
|
||||||
|
description=Default target for files with a .ogg and friends extension
|
||||||
|
type=container
|
||||||
|
format=application/ogg
|
||||||
|
|
||||||
|
[streamprofile-default-0]
|
||||||
|
parent=default
|
||||||
|
type=audio
|
||||||
|
format=audio/x-vorbis;audio/x-opus
|
||||||
|
|
||||||
|
[streamprofile-default-1]
|
||||||
|
parent=default
|
||||||
|
type=video
|
||||||
|
format=video/x-theora
|
||||||
|
|
||||||
|
[streamprofile-default-2]
|
||||||
|
parent=default
|
||||||
|
type=video
|
||||||
|
format=video/x-vp8
|
33
data/targets/file-extension/ts.gep
Normal file
33
data/targets/file-extension/ts.gep
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
[GStreamer Encoding Target]
|
||||||
|
name=ts
|
||||||
|
category=file-extension
|
||||||
|
description=Default target for files with a .ts extension
|
||||||
|
|
||||||
|
[profile-default]
|
||||||
|
name=default
|
||||||
|
type=container
|
||||||
|
description=Default profile for files with a .ts extension. Suitable for streamming.
|
||||||
|
format=video/mpegts,systemstream=true,packetsize=188
|
||||||
|
|
||||||
|
[streamprofile-default-0]
|
||||||
|
parent=default
|
||||||
|
type=audio
|
||||||
|
format=audio/mpeg,mpegversion=4,base-profile=lc,rate={48000,96000},channels=2;audio/mpeg,mpegversion=4,base-profile=lc,rate={48000,96000}
|
||||||
|
restriction=audio/x-raw,channels=6,channel-mask=0x3f;audio/x-raw,channels=2
|
||||||
|
|
||||||
|
[streamprofile-default-1]
|
||||||
|
parent=default
|
||||||
|
type=video
|
||||||
|
format=video/x-h264
|
||||||
|
preset=Profile YouTube
|
||||||
|
pass=0
|
||||||
|
|
||||||
|
[streamprofile-default-2]
|
||||||
|
parent=default
|
||||||
|
type=audio
|
||||||
|
format=audio/mpeg,mpegversion=4
|
||||||
|
|
||||||
|
[streamprofile-default-3]
|
||||||
|
parent=default
|
||||||
|
type=video
|
||||||
|
format=video/x-h264
|
21
data/targets/file-extension/webm.gep
Normal file
21
data/targets/file-extension/webm.gep
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
[GStreamer Encoding Target]
|
||||||
|
name=webm
|
||||||
|
category=file-extension
|
||||||
|
description=Default target for files with a .webm extension
|
||||||
|
|
||||||
|
[profile-default]
|
||||||
|
name=default
|
||||||
|
description=Default profile for files with a .webm extension. Audio stream can be either vorbis (default) or opus depending on what is available on the system. Video stream will be either in vp8 (default) or vp9.
|
||||||
|
type=container
|
||||||
|
format=video/webm
|
||||||
|
|
||||||
|
[streamprofile-default-0]
|
||||||
|
parent=default
|
||||||
|
type=audio
|
||||||
|
format=audio/x-vorbis;audio/x-opus
|
||||||
|
|
||||||
|
[streamprofile-default-1]
|
||||||
|
parent=default
|
||||||
|
type=video
|
||||||
|
format=video/x-vp8;video/x-vp9
|
||||||
|
pass=0
|
24
data/targets/online-service/youtube.gep
Normal file
24
data/targets/online-service/youtube.gep
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
[GStreamer Encoding Target]
|
||||||
|
name=youtube;yt
|
||||||
|
category=online-service
|
||||||
|
description=Recommended encoding settings for YouTube
|
||||||
|
|
||||||
|
[profile-default]
|
||||||
|
name=default
|
||||||
|
type=container
|
||||||
|
description=Youtube recommended profile with automatic audio setting
|
||||||
|
format=video/quicktime
|
||||||
|
preset=Profile YouTube
|
||||||
|
|
||||||
|
[streamprofile-default-0]
|
||||||
|
parent=default
|
||||||
|
type=audio
|
||||||
|
format=audio/mpeg,mpegversion=4,base-profile=lc
|
||||||
|
restriction=audio/x-raw,channels=6,rate={48000,96000};audio/x-raw,channels=2,rate={48000,96000}
|
||||||
|
|
||||||
|
[streamprofile-default-1]
|
||||||
|
parent=default
|
||||||
|
type=video
|
||||||
|
format=video/x-h264,profile=high
|
||||||
|
preset=Profile YouTube
|
||||||
|
pass=0
|
1
docs/gst_api_version.in
Normal file
1
docs/gst_api_version.in
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@GST_API_VERSION@
|
5
docs/index.md
Normal file
5
docs/index.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
short-description: GStreamer Bad Plugins API reference.
|
||||||
|
...
|
||||||
|
|
||||||
|
# GStreamer Bad Plugins
|
1
docs/libs/adaptivedemux/index.md
Normal file
1
docs/libs/adaptivedemux/index.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# Adaptive Demux library
|
1
docs/libs/adaptivedemux/sitemap.txt
Normal file
1
docs/libs/adaptivedemux/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
c-index
|
6
docs/libs/audio/index.md
Normal file
6
docs/libs/audio/index.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# Bad Audio library
|
||||||
|
|
||||||
|
This library should be linked to by getting cflags and libs from
|
||||||
|
gstreamer-bad-audio{{ gst_api_version.md }}.pc
|
||||||
|
|
||||||
|
> NOTE: This library API is considered *unstable*
|
1
docs/libs/audio/sitemap.txt
Normal file
1
docs/libs/audio/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
gi-index
|
3
docs/libs/base/index.md
Normal file
3
docs/libs/base/index.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Base classes from -bad
|
||||||
|
|
||||||
|
> NOTE: This library API is considered *unstable*
|
1
docs/libs/base/sitemap.txt
Normal file
1
docs/libs/base/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
gi-index
|
7
docs/libs/basecamerabinsrc/index.md
Normal file
7
docs/libs/basecamerabinsrc/index.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# BaseCamerabinSrc Library
|
||||||
|
|
||||||
|
This library should be linked to by getting cflags and libs from
|
||||||
|
gstreamer-plugins-bad-{{ gst_api_version.md }}.pc and adding
|
||||||
|
-lgstbasecamerabinsrc-{{ gst_api_version.md }} to the library flags.
|
||||||
|
|
||||||
|
> NOTE: This library API is considered *unstable*
|
1
docs/libs/basecamerabinsrc/sitemap.txt
Normal file
1
docs/libs/basecamerabinsrc/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
gi-index
|
7
docs/libs/codecparsers/index.md
Normal file
7
docs/libs/codecparsers/index.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# Bitstream parsing Library
|
||||||
|
|
||||||
|
This library should be linked to by getting cflags and libs from
|
||||||
|
gstreamer-plugins-bad-{{ gst_api_version.md }}.pc and adding
|
||||||
|
-lgstcodeparsers-{{ gst_api_version.md }} to the library flags.
|
||||||
|
|
||||||
|
> NOTE: This library API is considered *unstable*
|
1
docs/libs/codecparsers/sitemap.txt
Normal file
1
docs/libs/codecparsers/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
c-index
|
3
docs/libs/codecs/index.md
Normal file
3
docs/libs/codecs/index.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# GstCodecs
|
||||||
|
|
||||||
|
> NOTE: This library API is considered *unstable*
|
1
docs/libs/codecs/sitemap.txt
Normal file
1
docs/libs/codecs/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
gi-index
|
7
docs/libs/insertbin/index.md
Normal file
7
docs/libs/insertbin/index.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
short-description: A library that contains a bin to insertally link filter-like elements.
|
||||||
|
...
|
||||||
|
|
||||||
|
# GstInsertBin
|
||||||
|
|
||||||
|
> NOTE: This library API is considered *unstable*
|
1
docs/libs/insertbin/sitemap.txt
Normal file
1
docs/libs/insertbin/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
gi-index
|
104
docs/libs/mpegts/index.md
Normal file
104
docs/libs/mpegts/index.md
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
# MPEG-TS helper library
|
||||||
|
|
||||||
|
This library should be linked to by getting cflags and libs from
|
||||||
|
gstreamer-plugins-bad-{{ gst_api_version.md }}.pc and adding
|
||||||
|
-lgstmpegts-{{ gst_api_version.md }} to the library flags.
|
||||||
|
|
||||||
|
> NOTE: This library API is considered *unstable*
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
The MPEG-TS helper library provides a collection of definitions, object,
|
||||||
|
enumerations and functions to assist with dealing with the base *MPEG 2
|
||||||
|
Transport Stream* (MPEG-TS) format (as defined by `ISO/IEC 13818-1` and `ITU-T
|
||||||
|
H.222.0`) and its derivates (`DVB`, `ATSC`, `SCTE`, `ARIB`, `Blu-ray`, `AVCHD`,
|
||||||
|
...).
|
||||||
|
|
||||||
|
|
||||||
|
This library provides helpers for dealing with:
|
||||||
|
|
||||||
|
* The various Section Information (SI) and Program-Specific Information (SI),
|
||||||
|
handled with the [GstMpegtsSection](GstMpegtsSection) object and related
|
||||||
|
functions.
|
||||||
|
|
||||||
|
* The various descriptors present in SI/PSI, handled with the
|
||||||
|
[GstMpegtsDescriptor](GstMpegtsDescriptor) object and related functions.
|
||||||
|
|
||||||
|
|
||||||
|
This library does not cover:
|
||||||
|
|
||||||
|
* Parsing MPEG-TS packets (PSI or PES) and extracting the sections. One can use
|
||||||
|
an existing demuxer/parser element for this, or parse the packets
|
||||||
|
themselves.
|
||||||
|
|
||||||
|
* Generate and multiplex MPEG-TS packets and sections. One can use an existing
|
||||||
|
muxer element for this.
|
||||||
|
|
||||||
|
Applications, or external elements, can interact with the existing MPEG-TS
|
||||||
|
elements via [messages](gst_message_new_mpegts_section) (to receive sections) or
|
||||||
|
[events](gst_mpegts_section_send_event) (to send sections).
|
||||||
|
|
||||||
|
## Specification and References
|
||||||
|
|
||||||
|
As much as possible, the information contained in this library is based on the
|
||||||
|
official Specification and/or References listed below:
|
||||||
|
|
||||||
|
### `MPEG-TS`
|
||||||
|
|
||||||
|
This is the base specification from which all variants are derived. It covers
|
||||||
|
the basic sections (for program signalling) and descriptors. All variants must
|
||||||
|
abide by this specification.
|
||||||
|
|
||||||
|
* `ISO/IEC 13818-1` and `ITU-T H.222.0`: *"Information technology – Generic
|
||||||
|
coding of moving pictures and associated audio information: Systems"*. The two
|
||||||
|
specifications are identical, the ITU one is more easily available (*nudge*).
|
||||||
|
|
||||||
|
### `SMPTE-RA` : *SMPTE Registration Authority*
|
||||||
|
The official registration authority for MPEG-TS. This is used for the base
|
||||||
|
[Registration Descriptor](gst_mpegts_descriptor_parse_registration) which
|
||||||
|
allows to unambiguously identify a stream when it is not specified in a standard
|
||||||
|
(yet).
|
||||||
|
|
||||||
|
* <http://smpte-ra.org/>
|
||||||
|
|
||||||
|
### `DVB` : *Digital Video Broadcasting*
|
||||||
|
|
||||||
|
This standards body covers the variant of MPEG-TS used in Europe, Oceania, and
|
||||||
|
most of Asia and Africa. The standards are actually published by the `ETSI`
|
||||||
|
(European Telecommunications Standards Institute).
|
||||||
|
|
||||||
|
* `ETSI EN 300 468`: *"Digital Video Broadcasting (DVB); Specification for
|
||||||
|
Service Information (SI) in DVB systems"*. Covers all the sections and
|
||||||
|
descriptors used in DVB variants.
|
||||||
|
* `ETSI EN 101 154`: *"Digital Video Broadcasting (DVB);Specification for the
|
||||||
|
use of Video and Audio Coding in Broadcast and Broadband
|
||||||
|
Applications"*. Provides more details about signalling/sectios for audio/video
|
||||||
|
codecs.
|
||||||
|
|
||||||
|
### `ATSC` : *Advanced Television Systems Committee*
|
||||||
|
|
||||||
|
This set of standards covers the variants of MPEG-TS used in North America.
|
||||||
|
* `ATSC A/53-3` : *"ATSC Digital Television Standard, Part 3 – Service Multiplex
|
||||||
|
and Transport Subsystem Characteristics"*. How ATSC extends the base MPEG-TS.
|
||||||
|
* `ATSC A/65` : *"ATSC Standard:Program and System Information Protocol for
|
||||||
|
Terrestrial Broadcast and Cable"*. Covers all sections and descriptors used in
|
||||||
|
ATSC 1.0 variants.
|
||||||
|
* `ATSC A/90` : *"ATSC Data Broadcast Standard"*. Extensions for data transfer
|
||||||
|
(i.e. DSM-CC).
|
||||||
|
* `ATSC A/107` : *"ATSC 2.0 Standard"*. Adds a few more descriptors.
|
||||||
|
* `ATSC Code Points Registry` : The list of stream types, decriptor types,
|
||||||
|
etc... used by ATSC standards.
|
||||||
|
|
||||||
|
### `SCTE` : *Society of Cable Telecommunications Engineers*
|
||||||
|
|
||||||
|
This set of standards evolved in parallel with ATSC in North-America. Most of it
|
||||||
|
has been merged into ATSC and other standards since.
|
||||||
|
|
||||||
|
* `ANSI/SCTE 35` : *"Digital Program Insertion Cueing Message for Cable"*
|
||||||
|
|
||||||
|
### `DSM-CC` : "Digital Storage Media - Command & Control"
|
||||||
|
|
||||||
|
This ISO standard is the base for asynchronously carrying "files" over mpeg-ts.
|
||||||
|
|
||||||
|
* `ISO/IEC 13818-6` : *"Information technology — Generic coding of moving
|
||||||
|
pictures and associated audio information — Part 6: Extensions for DSM-CC"*.
|
1
docs/libs/mpegts/sitemap.txt
Normal file
1
docs/libs/mpegts/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
gi-index
|
7
docs/libs/opencv/index.md
Normal file
7
docs/libs/opencv/index.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# Opencv Library
|
||||||
|
|
||||||
|
This library should be linked to by getting cflags and libs from
|
||||||
|
gstreamer-plugins-bad-{{ gst_api_version.md }}.pc and adding
|
||||||
|
-lgstopencv-{{ gst_api_version.md }} to the library flags.
|
||||||
|
|
||||||
|
> NOTE: This library API is considered *unstable*
|
1
docs/libs/opencv/sitemap.txt
Normal file
1
docs/libs/opencv/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
c-index
|
3
docs/libs/play/index.md
Normal file
3
docs/libs/play/index.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Play Library
|
||||||
|
|
||||||
|
> NOTE: This library API is considered *unstable*
|
1
docs/libs/play/sitemap.txt
Normal file
1
docs/libs/play/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
gi-index
|
3
docs/libs/player/index.md
Normal file
3
docs/libs/player/index.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Player Library
|
||||||
|
|
||||||
|
> NOTE: This library API is considered *unstable*
|
1
docs/libs/player/sitemap.txt
Normal file
1
docs/libs/player/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
gi-index
|
3
docs/libs/tools/index.md
Normal file
3
docs/libs/tools/index.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Useful elements
|
||||||
|
|
||||||
|
> NOTE: This library API is considered *unstable*
|
1
docs/libs/tools/sitemap.txt
Normal file
1
docs/libs/tools/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
gi-index
|
8
docs/libs/transcoder/index.md
Normal file
8
docs/libs/transcoder/index.md
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# GstTranscoder
|
||||||
|
|
||||||
|
High level API to transcode streams
|
||||||
|
|
||||||
|
This library should be linked to by getting cflags and libs from
|
||||||
|
gstreamer-transcoder-{{ gst_api_version.md }}
|
||||||
|
|
||||||
|
> NOTE: This library API is considered *unstable*
|
1
docs/libs/transcoder/sitemap.txt
Normal file
1
docs/libs/transcoder/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
gi-index
|
3
docs/libs/video/index.md
Normal file
3
docs/libs/video/index.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Video helpers and baseclasses
|
||||||
|
|
||||||
|
> NOTE: This library API is considered *unstable*
|
1
docs/libs/video/sitemap.txt
Normal file
1
docs/libs/video/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
gi-index
|
6
docs/libs/vulkan-wayland/index.md
Normal file
6
docs/libs/vulkan-wayland/index.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# Vulkan Wayland Library
|
||||||
|
|
||||||
|
This library should be linked to by getting cflags and libs from
|
||||||
|
gstreamer-vulkan-wayland-{{ gst_api_version.md }}
|
||||||
|
|
||||||
|
> NOTE: This library API is considered *unstable*
|
1
docs/libs/vulkan-wayland/sitemap.txt
Normal file
1
docs/libs/vulkan-wayland/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
gi-index
|
6
docs/libs/vulkan-xcb/index.md
Normal file
6
docs/libs/vulkan-xcb/index.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# Vulkan XCB Library
|
||||||
|
|
||||||
|
This library should be linked to by getting cflags and libs from
|
||||||
|
gstreamer-vulkan-{{ gst_api_version.md }}
|
||||||
|
|
||||||
|
> NOTE: This library API is considered *unstable*
|
1
docs/libs/vulkan-xcb/sitemap.txt
Normal file
1
docs/libs/vulkan-xcb/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
gi-index
|
6
docs/libs/vulkan/index.md
Normal file
6
docs/libs/vulkan/index.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# Vulkan Library
|
||||||
|
|
||||||
|
This library should be linked to by getting cflags and libs from
|
||||||
|
gstreamer-vulkan-{{ gst_api_version.md }}
|
||||||
|
|
||||||
|
> NOTE: This library API is considered *unstable*
|
1
docs/libs/vulkan/sitemap.txt
Normal file
1
docs/libs/vulkan/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
gi-index
|
6
docs/libs/webrtc/index.md
Normal file
6
docs/libs/webrtc/index.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# WebRTC Library
|
||||||
|
|
||||||
|
This library should be linked to by getting cflags and libs from
|
||||||
|
gstreamer-webrtc-{{ gst_api_version.md }}
|
||||||
|
|
||||||
|
> NOTE: This library API is considered *unstable*
|
1
docs/libs/webrtc/sitemap.txt
Normal file
1
docs/libs/webrtc/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
gi-index
|
245
docs/meson.build
Normal file
245
docs/meson.build
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
build_hotdoc = false
|
||||||
|
|
||||||
|
if meson.is_cross_build()
|
||||||
|
if get_option('doc').enabled()
|
||||||
|
error('Documentation enabled but building the doc while cross building is not supported yet.')
|
||||||
|
endif
|
||||||
|
|
||||||
|
message('Documentation not built as building it while cross building is not supported yet.')
|
||||||
|
subdir_done()
|
||||||
|
endif
|
||||||
|
|
||||||
|
required_hotdoc_extensions = ['gi-extension', 'c-extension', 'gst-extension']
|
||||||
|
if gst_dep.type_name() == 'internal'
|
||||||
|
gst_proj = subproject('gstreamer')
|
||||||
|
plugins_cache_generator = gst_proj.get_variable('plugins_cache_generator')
|
||||||
|
else
|
||||||
|
plugins_cache_generator = find_program(join_paths(gst_dep.get_pkgconfig_variable('libexecdir'), 'gstreamer-' + api_version, 'gst-plugins-doc-cache-generator'),
|
||||||
|
required: false)
|
||||||
|
endif
|
||||||
|
|
||||||
|
plugins_cache = join_paths(meson.current_source_dir(), 'plugins', 'gst_plugins_cache.json')
|
||||||
|
|
||||||
|
if plugins.length() == 0
|
||||||
|
message('All bad plugins have been disabled')
|
||||||
|
elif plugins_cache_generator.found()
|
||||||
|
plugins_doc_dep = custom_target('bad-plugins-doc-cache',
|
||||||
|
command: [plugins_cache_generator, plugins_cache, '@OUTPUT@', '@INPUT@'],
|
||||||
|
input: plugins,
|
||||||
|
output: 'gst_plugins_cache.json',
|
||||||
|
build_always_stale: true,
|
||||||
|
)
|
||||||
|
else
|
||||||
|
warning('GStreamer plugin inspector for documentation not found, can\'t update the cache')
|
||||||
|
endif
|
||||||
|
|
||||||
|
hotdoc_p = find_program('hotdoc', required: get_option('doc'))
|
||||||
|
if not hotdoc_p.found()
|
||||||
|
message('Hotdoc not found, not building the documentation')
|
||||||
|
subdir_done()
|
||||||
|
endif
|
||||||
|
|
||||||
|
hotdoc_req = '>= 0.11.0'
|
||||||
|
hotdoc_version = run_command(hotdoc_p, '--version').stdout()
|
||||||
|
if not hotdoc_version.version_compare(hotdoc_req)
|
||||||
|
if get_option('doc').enabled()
|
||||||
|
error('Hotdoc version @0@ not found, got @1@'.format(hotdoc_req, hotdoc_version))
|
||||||
|
else
|
||||||
|
message('Hotdoc version @0@ not found, got @1@'.format(hotdoc_req, hotdoc_version))
|
||||||
|
subdir_done()
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
hotdoc = import('hotdoc')
|
||||||
|
foreach extension: required_hotdoc_extensions
|
||||||
|
if not hotdoc.has_extensions(extension)
|
||||||
|
if get_option('doc').enabled()
|
||||||
|
error('Documentation enabled but @0@ missing'.format(extension))
|
||||||
|
endif
|
||||||
|
|
||||||
|
message('@0@ extensions not found, not building documentation requiring it'.format(extension))
|
||||||
|
endif
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
if not build_gir
|
||||||
|
if get_option('doc').enabled()
|
||||||
|
error('Documentation enabled but introspection not built.')
|
||||||
|
endif
|
||||||
|
|
||||||
|
message('Introspection not built, won\'t build documentation requiring it')
|
||||||
|
subdir_done()
|
||||||
|
endif
|
||||||
|
|
||||||
|
build_hotdoc = true
|
||||||
|
|
||||||
|
docconf = configuration_data()
|
||||||
|
docconf.set('GST_API_VERSION', api_version)
|
||||||
|
|
||||||
|
configure_file(input : 'gst_api_version.in',
|
||||||
|
output : 'gst_api_version.md',
|
||||||
|
configuration : docconf)
|
||||||
|
|
||||||
|
root_rel = '..'
|
||||||
|
excludes = []
|
||||||
|
foreach f: [
|
||||||
|
'gst/frei0r/frei0r.h',
|
||||||
|
'gst/mxf/mxful.c',
|
||||||
|
'gst-libs/gst/*/*-private.h',
|
||||||
|
'gst-libs/gst/codecparsers/nalutils.h',
|
||||||
|
'ext/closedcaption/bcd.h',
|
||||||
|
'ext/closedcaption/bit_slicer.[ch]',
|
||||||
|
'ext/closedcaption/decoder.[ch]',
|
||||||
|
'ext/closedcaption/macros.h',
|
||||||
|
'ext/closedcaption/misc.h',
|
||||||
|
'ext/closedcaption/raw_decoder.[ch]',
|
||||||
|
'ext/closedcaption/sampling_par.[ch]',
|
||||||
|
'ext/closedcaption/sliced.[ch]',
|
||||||
|
'ext/*/*.h',
|
||||||
|
'sys/*/*.h',
|
||||||
|
'gst/*/*.h',
|
||||||
|
'gst-libs/gst/*/*-prelude.h',
|
||||||
|
'gst-libs/gst/vulkan/vulkan_fwd.h'
|
||||||
|
]
|
||||||
|
excludes += [join_paths(meson.current_source_dir(), root_rel, f)]
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
libs = []
|
||||||
|
if build_gir
|
||||||
|
libs = [
|
||||||
|
{'name': 'mpegts', 'gir': mpegts_gir, 'lib': gstmpegts_dep},
|
||||||
|
{'name': 'play', 'gir': play_gir, 'lib': gstplay_dep},
|
||||||
|
{'name': 'player', 'gir': player_gir, 'lib': gstplayer_dep},
|
||||||
|
{'name': 'insertbin', 'gir': insertbin_gir, 'lib': gstinsertbin_dep},
|
||||||
|
{'name': 'codecparsers', 'lib': gstcodecparsers_dep},
|
||||||
|
{'name': 'adaptivedemux', 'lib': gstadaptivedemux_dep},
|
||||||
|
{'name': 'basecamerabinsrc', 'gir': basecamerabin_gir, 'lib': gstbasecamerabin_dep},
|
||||||
|
{'name': 'webrtc', 'gir': webrtc_gir, 'lib': gstwebrtc_dep, 'suffix': 'lib'},
|
||||||
|
{'name': 'audio', 'gir': audio_gir, 'lib': gstbadaudio_dep, 'prefix': 'bad-'},
|
||||||
|
{'name': 'transcoder', 'gir': transcoder_gir, 'lib': gst_transcoder_dep},
|
||||||
|
{'name': 'codecs', 'gir': codecs_gir, 'lib': gstcodecs_dep},
|
||||||
|
]
|
||||||
|
|
||||||
|
if gstopencv_dep.found()
|
||||||
|
libs += [
|
||||||
|
{'name': 'opencv', 'lib': gstopencv_dep, 'c_source_patterns': ['*.h', '*.cpp'], 'extra_c_flags': ['-x c++']},
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
|
||||||
|
if gstvulkan_dep.found()
|
||||||
|
libs += [
|
||||||
|
{'name': 'vulkan', 'gir': vulkan_gir, 'lib': gstvulkan_dep, 'suffix': 'lib'},
|
||||||
|
]
|
||||||
|
if enabled_vulkan_winsys.contains('xcb')
|
||||||
|
libs += [
|
||||||
|
{'name': 'vulkan-xcb', 'gir': vulkan_xcb_gir, 'lib': gstvulkanxcb_dep, 'extra_sources' : [
|
||||||
|
join_paths(root_rel, 'gst-libs/gst/vulkan/xcb/gstvkdisplay_xcb.[ch]'),
|
||||||
|
]},
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
if enabled_vulkan_winsys.contains('wayland')
|
||||||
|
libs += [
|
||||||
|
{'name': 'vulkan-wayland', 'gir': vulkan_wayland_gir, 'lib': gstvulkanwayland_dep, 'extra_sources' : [
|
||||||
|
join_paths(root_rel, 'gst-libs/gst/vulkan/wayland/gstvkdisplay_wayland.[ch]'),
|
||||||
|
]},
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
has_gi_extension = hotdoc.has_extensions('gi-extension')
|
||||||
|
has_c_extension = hotdoc.has_extensions('c-extension')
|
||||||
|
libs_doc = []
|
||||||
|
foreach lib_def: libs
|
||||||
|
name = lib_def['name']
|
||||||
|
lib = lib_def['lib']
|
||||||
|
extra_sources = lib_def.get('extra_sources', [])
|
||||||
|
|
||||||
|
c_source_patterns = lib_def.get('c_source_patterns', ['*.[hc]'])
|
||||||
|
c_sources = []
|
||||||
|
foreach pattern: c_source_patterns
|
||||||
|
c_sources += join_paths(root_rel, 'gst-libs/gst', name, pattern)
|
||||||
|
endforeach
|
||||||
|
c_sources += extra_sources
|
||||||
|
|
||||||
|
if lib_def.has_key('gir')
|
||||||
|
if has_gi_extension
|
||||||
|
gir = lib_def['gir']
|
||||||
|
prefix = lib_def.get('prefix', '')
|
||||||
|
suffix = lib_def.get('suffix', '')
|
||||||
|
libs_doc += [hotdoc.generate_doc(prefix + name + suffix,
|
||||||
|
project_version: api_version,
|
||||||
|
gi_c_sources: c_sources,
|
||||||
|
gi_sources: gir[0].full_path(),
|
||||||
|
gi_c_source_filters: excludes,
|
||||||
|
sitemap: join_paths('libs', name, 'sitemap.txt'),
|
||||||
|
index: join_paths('libs/', name, 'index.md'),
|
||||||
|
gi_index: join_paths('libs/', name, 'index.md'),
|
||||||
|
gi_smart_index: true,
|
||||||
|
gi_order_generated_subpages: true,
|
||||||
|
dependencies: [lib, gir],
|
||||||
|
c_flags: '-DGST_USE_UNSTABLE_API',
|
||||||
|
install: false,
|
||||||
|
)]
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
if has_c_extension
|
||||||
|
libs_doc += [hotdoc.generate_doc('gst-plugins-bad-' + name,
|
||||||
|
sitemap: join_paths('libs', name, 'sitemap.txt'),
|
||||||
|
index: join_paths('libs', name, 'index.md'),
|
||||||
|
project_version: api_version,
|
||||||
|
c_sources: c_sources,
|
||||||
|
c_source_filters: excludes,
|
||||||
|
c_index: join_paths('libs', name, 'index.md'),
|
||||||
|
c_smart_index: true,
|
||||||
|
c_order_generated_subpages: true,
|
||||||
|
extra_c_flags: ['-DGST_USE_UNSTABLE_API'] + lib_def.get('extra_c_flags', []),
|
||||||
|
dependencies: lib,
|
||||||
|
install: false,
|
||||||
|
)]
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
list_plugin_res = run_command(python3, '-c',
|
||||||
|
'''
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
|
||||||
|
with open("@0@") as f:
|
||||||
|
print(':'.join(json.load(f).keys()), end='')
|
||||||
|
'''.format(plugins_cache))
|
||||||
|
|
||||||
|
assert(list_plugin_res.returncode() == 0,
|
||||||
|
'Could not list plugins from @0@'.format(plugins_cache))
|
||||||
|
|
||||||
|
plugins_doc = []
|
||||||
|
foreach plugin_name: list_plugin_res.stdout().split(':')
|
||||||
|
plugins_doc += [hotdoc.generate_doc(plugin_name,
|
||||||
|
project_version: api_version,
|
||||||
|
sitemap: 'plugins/sitemap.txt',
|
||||||
|
index: 'plugins/index.md',
|
||||||
|
c_flags: '-DGST_USE_UNSTABLE_API',
|
||||||
|
gst_index: 'plugins/index.md',
|
||||||
|
gst_smart_index: true,
|
||||||
|
gst_c_sources: [
|
||||||
|
join_paths(root_rel, 'sys/*/*.[ch]'),
|
||||||
|
join_paths(root_rel, 'sys/*/*.cpp'),
|
||||||
|
join_paths(root_rel, 'sys/*/*.cc'),
|
||||||
|
join_paths(root_rel, 'sys/*/*.hh'),
|
||||||
|
join_paths(root_rel, 'ext/*/*.[ch]'),
|
||||||
|
join_paths(root_rel, 'ext/*/*.cpp'),
|
||||||
|
join_paths(root_rel, 'ext/*/*.cc'),
|
||||||
|
join_paths(root_rel, 'ext/*/*.hh'),
|
||||||
|
join_paths(root_rel, 'gst/*/*.[ch]'),
|
||||||
|
join_paths(root_rel, 'gst/rtmp2/*/*.[ch]'),
|
||||||
|
],
|
||||||
|
dependencies: [gst_dep, plugins],
|
||||||
|
install: false,
|
||||||
|
disable_incremental_build: true,
|
||||||
|
gst_cache_file: plugins_cache,
|
||||||
|
gst_c_source_filters: excludes,
|
||||||
|
gst_order_generated_subpages: true,
|
||||||
|
gst_plugin_name: plugin_name,
|
||||||
|
include_paths: join_paths(meson.current_source_dir(), '..'),
|
||||||
|
)]
|
||||||
|
endforeach
|
230318
docs/plugins/gst_plugins_cache.json
Normal file
230318
docs/plugins/gst_plugins_cache.json
Normal file
File diff suppressed because one or more lines are too long
0
docs/plugins/index.md
Normal file
0
docs/plugins/index.md
Normal file
85
docs/plugins/inspect/plugin-rist.xml
Normal file
85
docs/plugins/inspect/plugin-rist.xml
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
<plugin>
|
||||||
|
<name>rist</name>
|
||||||
|
<description>Source and Sink for RIST TR-06-1 streaming specification</description>
|
||||||
|
<filename>../../gst/rist/.libs/libgstrist.so</filename>
|
||||||
|
<basename>libgstrist.so</basename>
|
||||||
|
<version>1.15.2.1</version>
|
||||||
|
<license>LGPL</license>
|
||||||
|
<source>gst-plugins-bad</source>
|
||||||
|
<package>GStreamer Bad Plug-ins git</package>
|
||||||
|
<origin>Unknown package origin</origin>
|
||||||
|
<elements>
|
||||||
|
<element>
|
||||||
|
<name>ristrtxreceive</name>
|
||||||
|
<longname>RIST Retransmission receiver</longname>
|
||||||
|
<class>Codec</class>
|
||||||
|
<description>Receive retransmitted RIST packets according to VSF TR-06-1</description>
|
||||||
|
<author>Nicolas Dufresne <nicolas.dufresne@collabora.com></author>
|
||||||
|
<pads>
|
||||||
|
<caps>
|
||||||
|
<name>sink</name>
|
||||||
|
<direction>sink</direction>
|
||||||
|
<presence>always</presence>
|
||||||
|
<details>application/x-rtp</details>
|
||||||
|
</caps>
|
||||||
|
<caps>
|
||||||
|
<name>src</name>
|
||||||
|
<direction>source</direction>
|
||||||
|
<presence>always</presence>
|
||||||
|
<details>application/x-rtp</details>
|
||||||
|
</caps>
|
||||||
|
</pads>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<name>ristrtxsend</name>
|
||||||
|
<longname>RIST Retransmission Sender</longname>
|
||||||
|
<class>Codec</class>
|
||||||
|
<description>Retransmit RTP packets when needed, according to VSF TR-06-1</description>
|
||||||
|
<author>Nicolas Dufresne <nicolas.dufresne@collabora.com></author>
|
||||||
|
<pads>
|
||||||
|
<caps>
|
||||||
|
<name>sink</name>
|
||||||
|
<direction>sink</direction>
|
||||||
|
<presence>always</presence>
|
||||||
|
<details>application/x-rtp, clock-rate=(int)[ 1, 2147483647 ]</details>
|
||||||
|
</caps>
|
||||||
|
<caps>
|
||||||
|
<name>src</name>
|
||||||
|
<direction>source</direction>
|
||||||
|
<presence>always</presence>
|
||||||
|
<details>application/x-rtp</details>
|
||||||
|
</caps>
|
||||||
|
</pads>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<name>ristsink</name>
|
||||||
|
<longname>RIST Sink</longname>
|
||||||
|
<class>Source/Network</class>
|
||||||
|
<description>Sink that implements RIST TR-06-1 streaming specification</description>
|
||||||
|
<author>Nicolas Dufresne <nicolas.dufresne@collabora.com</author>
|
||||||
|
<pads>
|
||||||
|
<caps>
|
||||||
|
<name>sink</name>
|
||||||
|
<direction>sink</direction>
|
||||||
|
<presence>always</presence>
|
||||||
|
<details>application/x-rtp</details>
|
||||||
|
</caps>
|
||||||
|
</pads>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<name>ristsrc</name>
|
||||||
|
<longname>RIST Source</longname>
|
||||||
|
<class>Source/Network</class>
|
||||||
|
<description>Source that implements RIST TR-06-1 streaming specification</description>
|
||||||
|
<author>Nicolas Dufresne <nicolas.dufresne@collabora.com</author>
|
||||||
|
<pads>
|
||||||
|
<caps>
|
||||||
|
<name>src</name>
|
||||||
|
<direction>source</direction>
|
||||||
|
<presence>always</presence>
|
||||||
|
<details>application/x-rtp</details>
|
||||||
|
</caps>
|
||||||
|
</pads>
|
||||||
|
</element>
|
||||||
|
</elements>
|
||||||
|
</plugin>
|
55
docs/plugins/inspect/plugin-sctp.xml
Normal file
55
docs/plugins/inspect/plugin-sctp.xml
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
<plugin>
|
||||||
|
<name>sctp</name>
|
||||||
|
<description>SCTP encoder/decoder plugin</description>
|
||||||
|
<filename>../../ext/sctp/.libs/libgstsctp.so</filename>
|
||||||
|
<basename>libgstsctp.so</basename>
|
||||||
|
<version>1.17.0.1</version>
|
||||||
|
<license>BSD</license>
|
||||||
|
<source>gst-plugins-bad</source>
|
||||||
|
<package>GStreamer Bad Plug-ins git</package>
|
||||||
|
<origin>Unknown package origin</origin>
|
||||||
|
<elements>
|
||||||
|
<element>
|
||||||
|
<name>sctpdec</name>
|
||||||
|
<longname>SCTP Decoder</longname>
|
||||||
|
<class>Decoder/Network/SCTP</class>
|
||||||
|
<description>Decodes packets with SCTP</description>
|
||||||
|
<author>George Kiagiadakis <george.kiagiadakis@collabora.com></author>
|
||||||
|
<pads>
|
||||||
|
<caps>
|
||||||
|
<name>sink</name>
|
||||||
|
<direction>sink</direction>
|
||||||
|
<presence>always</presence>
|
||||||
|
<details>application/x-sctp</details>
|
||||||
|
</caps>
|
||||||
|
<caps>
|
||||||
|
<name>src_%u</name>
|
||||||
|
<direction>source</direction>
|
||||||
|
<presence>sometimes</presence>
|
||||||
|
<details>ANY</details>
|
||||||
|
</caps>
|
||||||
|
</pads>
|
||||||
|
</element>
|
||||||
|
<element>
|
||||||
|
<name>sctpenc</name>
|
||||||
|
<longname>SCTP Encoder</longname>
|
||||||
|
<class>Encoder/Network/SCTP</class>
|
||||||
|
<description>Encodes packets with SCTP</description>
|
||||||
|
<author>George Kiagiadakis <george.kiagiadakis@collabora.com></author>
|
||||||
|
<pads>
|
||||||
|
<caps>
|
||||||
|
<name>sink_%u</name>
|
||||||
|
<direction>sink</direction>
|
||||||
|
<presence>request</presence>
|
||||||
|
<details>ANY</details>
|
||||||
|
</caps>
|
||||||
|
<caps>
|
||||||
|
<name>src</name>
|
||||||
|
<direction>source</direction>
|
||||||
|
<presence>always</presence>
|
||||||
|
<details>application/x-sctp</details>
|
||||||
|
</caps>
|
||||||
|
</pads>
|
||||||
|
</element>
|
||||||
|
</elements>
|
||||||
|
</plugin>
|
1
docs/plugins/sitemap.txt
Normal file
1
docs/plugins/sitemap.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
gst-index
|
17760
docs/random/ChangeLog-0.8
Normal file
17760
docs/random/ChangeLog-0.8
Normal file
File diff suppressed because it is too large
Load diff
18
docs/random/LICENSE
Normal file
18
docs/random/LICENSE
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
27
docs/random/PORTED_09
Normal file
27
docs/random/PORTED_09
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
When porting a plugin start with 0.8 CVS head, not the old code in this module. There are many bugfixes which have gone into 0.8 which you want to keep.
|
||||||
|
|
||||||
|
List of ported plugins (update when you commit a ported plugin):
|
||||||
|
libmms (alima)
|
||||||
|
wavpack (alima)
|
||||||
|
musepack (alima)
|
||||||
|
ivorbis (alima)
|
||||||
|
gsmdec (alima)
|
||||||
|
sdl (alima)
|
||||||
|
speed (fcarvalho)
|
||||||
|
gsmenc (fcarvalho)
|
||||||
|
faac (fcarvalho)
|
||||||
|
wavenc (fcarvalho)
|
||||||
|
effectv (wim)
|
||||||
|
mad (wim)
|
||||||
|
videofilter (wim)
|
||||||
|
aalib (wim)
|
||||||
|
libcaca (zeeshan)
|
||||||
|
law (wim)
|
||||||
|
shout2 (zaheer) - not fully tested
|
||||||
|
esdsink (arwed)
|
||||||
|
|
||||||
|
osssink is partially done in the threaded branch (wim)
|
||||||
|
|
||||||
|
- Remember that some plugins are already ported and now in the gst-plugins-base module.
|
||||||
|
|
||||||
|
When you have ported a plugin remember to copy the relevant parts from configure.ac.orig into configure.ac and re-enable it in the Makefile.am files.
|
3
docs/sitemap.txt
Normal file
3
docs/sitemap.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
index.md
|
||||||
|
gst-plugins-bad-plugins-doc.json
|
||||||
|
gst-plugins-bad-libs-doc.json
|
54
ext/aes/gstaes.c
Normal file
54
ext/aes/gstaes.c
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* GStreamer gstreamer-aes
|
||||||
|
*
|
||||||
|
* Copyright, 2021 Nice, Contact: Rabindra Harlalka <Rabindra.Harlalka@nice.com>
|
||||||
|
*
|
||||||
|
* gstaes.c
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "gstaesdec.h"
|
||||||
|
#include "gstaesenc.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:plugin-aes
|
||||||
|
*
|
||||||
|
* AES encryption and decryption
|
||||||
|
*
|
||||||
|
* See also: @aesenc, @aesdec
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
plugin_init (GstPlugin * plugin)
|
||||||
|
{
|
||||||
|
gboolean success = GST_ELEMENT_REGISTER (aesenc, plugin);
|
||||||
|
success = GST_ELEMENT_REGISTER (aesdec, plugin) || success;
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||||
|
GST_VERSION_MINOR,
|
||||||
|
aes,
|
||||||
|
"AES encryption/decryption plugin",
|
||||||
|
plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
|
625
ext/aes/gstaesdec.c
Normal file
625
ext/aes/gstaesdec.c
Normal file
|
@ -0,0 +1,625 @@
|
||||||
|
/*
|
||||||
|
* GStreamer gstreamer-aesdec
|
||||||
|
*
|
||||||
|
* Copyright, LCC (C) 2015 RidgeRun, LCC <carsten.behling@ridgerun.com>
|
||||||
|
* Copyright, LCC (C) 2016 RidgeRun, LCC <jose.jimenez@ridgerun.com>
|
||||||
|
* Copyright (C) 2020 Nice, Contact: Rabindra Harlalka <Rabindra.Harlalka@nice.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the
|
||||||
|
* GNU Lesser General Public License Version 2.1 (the "LGPL"), in
|
||||||
|
* which case the following provisions apply instead of the ones
|
||||||
|
* mentioned above:
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1335, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:element-aesdec
|
||||||
|
*
|
||||||
|
* AES decryption
|
||||||
|
*
|
||||||
|
* ## Example
|
||||||
|
*
|
||||||
|
* |[
|
||||||
|
* echo "This is an AES crypto test ... " > plain.txt && \
|
||||||
|
* gst-launch-1.0 filesrc location=plain.txt ! \
|
||||||
|
* aesenc key=1f9423681beb9a79215820f6bda73d0f iv=e9aa8e834d8d70b7e0d254ff670dd718 ! \
|
||||||
|
* aesdec key=1f9423681beb9a79215820f6bda73d0f iv=e9aa8e834d8d70b7e0d254ff670dd718 ! \
|
||||||
|
* filesink location=dec.txt && \
|
||||||
|
* cat dec.txt
|
||||||
|
*
|
||||||
|
* ]|
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/base/gstbasetransform.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "gstaeshelper.h"
|
||||||
|
#include "gstaesdec.h"
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (gst_aes_dec_debug);
|
||||||
|
#define GST_CAT_DEFAULT gst_aes_dec_debug
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (GstAesDec, gst_aes_dec, GST_TYPE_BASE_TRANSFORM,
|
||||||
|
GST_DEBUG_CATEGORY_INIT (gst_aes_dec_debug, "aesdec", 0,
|
||||||
|
"aesdec AES decryption element")
|
||||||
|
);
|
||||||
|
GST_ELEMENT_REGISTER_DEFINE (aesdec, "aesdec", GST_RANK_PRIMARY,
|
||||||
|
GST_TYPE_AES_DEC);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
GST_PAD_SINK,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("ANY")
|
||||||
|
);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
|
GST_PAD_SRC,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("ANY")
|
||||||
|
);
|
||||||
|
|
||||||
|
static void gst_aes_dec_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec);
|
||||||
|
static void gst_aes_dec_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec);
|
||||||
|
|
||||||
|
static GstFlowReturn gst_aes_dec_transform (GstBaseTransform * base,
|
||||||
|
GstBuffer * inbuf, GstBuffer * outbuf);
|
||||||
|
static GstFlowReturn gst_aes_dec_prepare_output_buffer (GstBaseTransform * base,
|
||||||
|
GstBuffer * inbuf, GstBuffer ** outbuf);
|
||||||
|
static gboolean
|
||||||
|
gst_aes_dec_sink_event (GstBaseTransform * base, GstEvent * event);
|
||||||
|
|
||||||
|
static gboolean gst_aes_dec_start (GstBaseTransform * base);
|
||||||
|
static gboolean gst_aes_dec_stop (GstBaseTransform * base);
|
||||||
|
|
||||||
|
/* aes_dec helper functions */
|
||||||
|
static gboolean gst_aes_dec_openssl_init (GstAesDec * filter);
|
||||||
|
static gboolean gst_aes_dec_init_cipher (GstAesDec * filter);
|
||||||
|
static void gst_aes_dec_finalize (GObject * object);
|
||||||
|
|
||||||
|
/* GObject vmethod implementations */
|
||||||
|
|
||||||
|
/* initialize class */
|
||||||
|
static void
|
||||||
|
gst_aes_dec_class_init (GstAesDecClass * klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class;
|
||||||
|
GstElementClass *gstelement_class;
|
||||||
|
|
||||||
|
gobject_class = (GObjectClass *) klass;
|
||||||
|
gstelement_class = (GstElementClass *) klass;
|
||||||
|
|
||||||
|
gobject_class->set_property = gst_aes_dec_set_property;
|
||||||
|
gobject_class->get_property = gst_aes_dec_get_property;
|
||||||
|
gobject_class->finalize = gst_aes_dec_finalize;
|
||||||
|
|
||||||
|
gst_type_mark_as_plugin_api (GST_TYPE_AES_CIPHER, 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstAesDec:cipher
|
||||||
|
*
|
||||||
|
* AES cipher mode (key length and mode)
|
||||||
|
* Currently, 128 and 256 bit keys are supported,
|
||||||
|
* in "cipher block chaining" (CBC) mode
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_CIPHER,
|
||||||
|
g_param_spec_enum ("cipher",
|
||||||
|
"Cipher",
|
||||||
|
"cipher mode",
|
||||||
|
GST_TYPE_AES_CIPHER, GST_AES_DEFAULT_CIPHER_MODE,
|
||||||
|
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||||
|
GST_PARAM_MUTABLE_READY)));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstAesDec:serialize-iv
|
||||||
|
*
|
||||||
|
* If true, read initialization vector from first 16 bytes of first buffer
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_SERIALIZE_IV,
|
||||||
|
g_param_spec_boolean ("serialize-iv", "Serialize IV",
|
||||||
|
"Read initialization vector from first 16 bytes of first buffer",
|
||||||
|
GST_AES_DEFAULT_SERIALIZE_IV,
|
||||||
|
G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstAesDec:per-buffer-padding
|
||||||
|
*
|
||||||
|
* If true, each buffer will be padded using PKCS7 padding
|
||||||
|
* If false, only the final buffer in the stream will be padded
|
||||||
|
* (by OpenSSL) using PKCS7
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_PER_BUFFER_PADDING,
|
||||||
|
g_param_spec_boolean ("per-buffer-padding", "Per buffer padding",
|
||||||
|
"If true, pad each buffer using PKCS7 padding scheme. Otherwise, only"
|
||||||
|
"pad final buffer",
|
||||||
|
GST_AES_PER_BUFFER_PADDING_DEFAULT,
|
||||||
|
G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstAesDec:key
|
||||||
|
*
|
||||||
|
* AES encryption key (hexadecimal)
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_KEY,
|
||||||
|
g_param_spec_string ("key", "Key",
|
||||||
|
"AES encryption key (in hexadecimal). Length (in bytes) must be equivalent to "
|
||||||
|
"the number of bits in the key length : "
|
||||||
|
"16 bytes for AES 128 and 32 bytes for AES 256",
|
||||||
|
(gchar *) GST_AES_DEFAULT_KEY,
|
||||||
|
G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY));
|
||||||
|
/**
|
||||||
|
* GstAesDec:iv
|
||||||
|
*
|
||||||
|
* AES encryption initialization vector (hexadecimal)
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_IV,
|
||||||
|
g_param_spec_string ("iv", "Iv",
|
||||||
|
"AES encryption initialization vector (in hexadecimal). "
|
||||||
|
"Length must equal AES block length (16 bytes)",
|
||||||
|
(gchar *) GST_AES_DEFAULT_IV,
|
||||||
|
G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY));
|
||||||
|
|
||||||
|
gst_element_class_set_details_simple (gstelement_class,
|
||||||
|
"aesdec",
|
||||||
|
"Generic/Filter",
|
||||||
|
"AES buffer decryption",
|
||||||
|
"Rabindra Harlalka <Rabindra.Harlalka@nice.com>");
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&src_template));
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&sink_template));
|
||||||
|
|
||||||
|
GST_BASE_TRANSFORM_CLASS (klass)->transform =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_aes_dec_transform);
|
||||||
|
GST_BASE_TRANSFORM_CLASS (klass)->prepare_output_buffer =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_aes_dec_prepare_output_buffer);
|
||||||
|
GST_BASE_TRANSFORM_CLASS (klass)->start =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_aes_dec_start);
|
||||||
|
GST_BASE_TRANSFORM_CLASS (klass)->sink_event =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_aes_dec_sink_event);
|
||||||
|
GST_BASE_TRANSFORM_CLASS (klass)->stop = GST_DEBUG_FUNCPTR (gst_aes_dec_stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize element
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
gst_aes_dec_init (GstAesDec * filter)
|
||||||
|
{
|
||||||
|
GST_INFO_OBJECT (filter, "Initializing plugin");
|
||||||
|
filter->cipher = GST_AES_DEFAULT_CIPHER_MODE;
|
||||||
|
filter->awaiting_first_buffer = TRUE;
|
||||||
|
filter->per_buffer_padding = GST_AES_PER_BUFFER_PADDING_DEFAULT;
|
||||||
|
g_mutex_init (&filter->decoder_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_aes_dec_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
GstAesDec *filter = GST_AES_DEC (object);
|
||||||
|
|
||||||
|
g_mutex_clear (&filter->decoder_lock);
|
||||||
|
G_OBJECT_CLASS (gst_aes_dec_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_aes_dec_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstAesDec *filter = GST_AES_DEC (object);
|
||||||
|
|
||||||
|
g_mutex_lock (&filter->decoder_lock);
|
||||||
|
/* no property may be set after first output buffer is prepared */
|
||||||
|
if (filter->locked_properties) {
|
||||||
|
GST_WARNING_OBJECT (filter,
|
||||||
|
"Properties cannot be set once buffers begin flowing in element. Ignored");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_CIPHER:
|
||||||
|
filter->cipher = g_value_get_enum (value);
|
||||||
|
filter->evp_cipher =
|
||||||
|
EVP_get_cipherbyname (gst_aes_cipher_enum_to_string (filter->cipher));
|
||||||
|
GST_DEBUG_OBJECT (filter, "cipher: %s",
|
||||||
|
gst_aes_cipher_enum_to_string (filter->cipher));
|
||||||
|
break;
|
||||||
|
case PROP_SERIALIZE_IV:
|
||||||
|
filter->serialize_iv = g_value_get_boolean (value);
|
||||||
|
GST_DEBUG_OBJECT (filter, "serialize iv: %s",
|
||||||
|
filter->serialize_iv ? "TRUE" : "FALSE");
|
||||||
|
break;
|
||||||
|
case PROP_PER_BUFFER_PADDING:
|
||||||
|
filter->per_buffer_padding = g_value_get_boolean (value);
|
||||||
|
GST_DEBUG_OBJECT (filter, "Per buffer padding: %s",
|
||||||
|
filter->per_buffer_padding ? "TRUE" : "FALSE");
|
||||||
|
break;
|
||||||
|
case PROP_KEY:
|
||||||
|
{
|
||||||
|
guint hex_len = gst_aes_hexstring2bytearray (GST_ELEMENT (filter),
|
||||||
|
g_value_get_string (value), filter->key);
|
||||||
|
|
||||||
|
if (!hex_len) {
|
||||||
|
GST_ERROR_OBJECT (filter, "invalid key");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
GST_DEBUG_OBJECT (filter, "key: %s", g_value_get_string (value));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PROP_IV:
|
||||||
|
{
|
||||||
|
gchar iv_string[2 * GST_AES_BLOCK_SIZE + 1];
|
||||||
|
guint hex_len = gst_aes_hexstring2bytearray (GST_ELEMENT (filter),
|
||||||
|
g_value_get_string (value), filter->iv);
|
||||||
|
|
||||||
|
if (hex_len != GST_AES_BLOCK_SIZE) {
|
||||||
|
GST_ERROR_OBJECT (filter, "invalid initialization vector");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
GST_DEBUG_OBJECT (filter, "iv: %s",
|
||||||
|
gst_aes_bytearray2hexstring (filter->iv, iv_string,
|
||||||
|
GST_AES_BLOCK_SIZE));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
g_mutex_unlock (&filter->decoder_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_aes_dec_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstAesDec *filter = GST_AES_DEC (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_CIPHER:
|
||||||
|
g_value_set_enum (value, filter->cipher);
|
||||||
|
break;
|
||||||
|
case PROP_SERIALIZE_IV:
|
||||||
|
g_value_set_boolean (value, filter->serialize_iv);
|
||||||
|
break;
|
||||||
|
case PROP_PER_BUFFER_PADDING:
|
||||||
|
g_value_set_boolean (value, filter->per_buffer_padding);
|
||||||
|
break;
|
||||||
|
case PROP_KEY:
|
||||||
|
g_value_set_string (value, (gchar *) filter->key);
|
||||||
|
break;
|
||||||
|
case PROP_IV:
|
||||||
|
g_value_set_string (value, (gchar *) filter->iv);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_aes_dec_sink_event (GstBaseTransform * base, GstEvent * event)
|
||||||
|
{
|
||||||
|
GstAesDec *filter = GST_AES_DEC (base);
|
||||||
|
|
||||||
|
g_mutex_lock (&filter->decoder_lock);
|
||||||
|
|
||||||
|
if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
|
||||||
|
GST_DEBUG_OBJECT (filter, "Received EOS on sink pad");
|
||||||
|
if (!filter->per_buffer_padding && !filter->awaiting_first_buffer) {
|
||||||
|
GstBuffer *outbuf = NULL;
|
||||||
|
gint len;
|
||||||
|
GstMapInfo outmap;
|
||||||
|
|
||||||
|
outbuf = gst_buffer_new_allocate (NULL, EVP_MAX_BLOCK_LENGTH, NULL);
|
||||||
|
if (outbuf == NULL) {
|
||||||
|
GST_DEBUG_OBJECT (filter,
|
||||||
|
"Failed to allocate a new buffer of length %d",
|
||||||
|
EVP_MAX_BLOCK_LENGTH);
|
||||||
|
goto buffer_fail;
|
||||||
|
}
|
||||||
|
if (!gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE)) {
|
||||||
|
GST_DEBUG_OBJECT (filter,
|
||||||
|
"gst_buffer_map on outbuf failed for final buffer.");
|
||||||
|
gst_buffer_unref (outbuf);
|
||||||
|
goto buffer_fail;
|
||||||
|
}
|
||||||
|
if (1 != EVP_CipherFinal_ex (filter->evp_ctx, outmap.data, &len)) {
|
||||||
|
GST_DEBUG_OBJECT (filter, "Could not finalize openssl encryption");
|
||||||
|
gst_buffer_unmap (outbuf, &outmap);
|
||||||
|
gst_buffer_unref (outbuf);
|
||||||
|
goto cipher_fail;
|
||||||
|
}
|
||||||
|
if (len == 0) {
|
||||||
|
GST_DEBUG_OBJECT (filter, "Not pushing final buffer as length is 0");
|
||||||
|
gst_buffer_unmap (outbuf, &outmap);
|
||||||
|
gst_buffer_unref (outbuf);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
GST_DEBUG_OBJECT (filter, "Pushing final buffer of length: %d", len);
|
||||||
|
gst_buffer_unmap (outbuf, &outmap);
|
||||||
|
gst_buffer_set_size (outbuf, len);
|
||||||
|
if (gst_pad_push (base->srcpad, outbuf) != GST_FLOW_OK) {
|
||||||
|
GST_DEBUG_OBJECT (filter, "Failed to push the final buffer");
|
||||||
|
goto push_fail;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (filter,
|
||||||
|
"Not pushing final buffer as we didn't have any input");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
g_mutex_unlock (&filter->decoder_lock);
|
||||||
|
|
||||||
|
return GST_BASE_TRANSFORM_CLASS (gst_aes_dec_parent_class)->sink_event (base,
|
||||||
|
event);
|
||||||
|
|
||||||
|
/* ERROR */
|
||||||
|
buffer_fail:
|
||||||
|
GST_ELEMENT_ERROR (filter, RESOURCE, FAILED, (NULL),
|
||||||
|
("Failed to allocate or map buffer for writing"));
|
||||||
|
g_mutex_unlock (&filter->decoder_lock);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
cipher_fail:
|
||||||
|
GST_ELEMENT_ERROR (filter, STREAM, FAILED, ("Cipher finalization failed."),
|
||||||
|
("Error while finalizing the stream"));
|
||||||
|
g_mutex_unlock (&filter->decoder_lock);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
push_fail:
|
||||||
|
GST_ELEMENT_ERROR (filter, CORE, PAD, (NULL),
|
||||||
|
("Failed to push the final buffer"));
|
||||||
|
g_mutex_unlock (&filter->decoder_lock);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GstBaseTransform vmethod implementations */
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_aes_dec_transform (GstBaseTransform * base,
|
||||||
|
GstBuffer * inbuf, GstBuffer * outbuf)
|
||||||
|
{
|
||||||
|
GstAesDec *filter = GST_AES_DEC (base);
|
||||||
|
GstFlowReturn ret = GST_FLOW_ERROR;
|
||||||
|
GstMapInfo inmap, outmap;
|
||||||
|
guchar *ciphertext;
|
||||||
|
gint ciphertext_len;
|
||||||
|
guchar *plaintext;
|
||||||
|
gint plaintext_len;
|
||||||
|
guint padding = 0;
|
||||||
|
|
||||||
|
if (!gst_buffer_map (inbuf, &inmap, GST_MAP_READ)) {
|
||||||
|
GST_ELEMENT_ERROR (filter, RESOURCE, FAILED, (NULL),
|
||||||
|
("Failed to map buffer for reading"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (!gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE)) {
|
||||||
|
gst_buffer_unmap (inbuf, &inmap);
|
||||||
|
GST_ELEMENT_ERROR (filter, RESOURCE, FAILED, (NULL),
|
||||||
|
("Failed to map buffer for writing"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
/* DECRYPTING */
|
||||||
|
ciphertext = inmap.data;
|
||||||
|
ciphertext_len = gst_buffer_get_size (inbuf);
|
||||||
|
if (filter->awaiting_first_buffer) {
|
||||||
|
if (filter->serialize_iv) {
|
||||||
|
gchar iv_string[2 * GST_AES_BLOCK_SIZE + 1];
|
||||||
|
|
||||||
|
if (ciphertext_len < GST_AES_BLOCK_SIZE) {
|
||||||
|
GST_ELEMENT_ERROR (filter, RESOURCE, FAILED, (NULL),
|
||||||
|
("Cipher text too short"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy (filter->iv, ciphertext, GST_AES_BLOCK_SIZE);
|
||||||
|
GST_DEBUG_OBJECT (filter, "read serialized iv: %s",
|
||||||
|
gst_aes_bytearray2hexstring (filter->iv, iv_string,
|
||||||
|
GST_AES_BLOCK_SIZE));
|
||||||
|
ciphertext += GST_AES_BLOCK_SIZE;
|
||||||
|
ciphertext_len -= GST_AES_BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
if (!gst_aes_dec_init_cipher (filter)) {
|
||||||
|
GST_ELEMENT_ERROR (filter, RESOURCE, FAILED, (NULL),
|
||||||
|
("Failed to initialize cipher"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
plaintext = outmap.data;
|
||||||
|
|
||||||
|
if (!EVP_CipherUpdate (filter->evp_ctx, plaintext,
|
||||||
|
&plaintext_len, ciphertext, ciphertext_len)) {
|
||||||
|
GST_ELEMENT_ERROR (filter, STREAM, FAILED, ("Cipher update failed."),
|
||||||
|
("Error while updating openssl cipher"));
|
||||||
|
goto cleanup;
|
||||||
|
} else {
|
||||||
|
if (filter->per_buffer_padding) {
|
||||||
|
gint k;
|
||||||
|
|
||||||
|
/* sanity check on padding value */
|
||||||
|
padding = plaintext[plaintext_len - 1];
|
||||||
|
if (padding == 0 || padding > GST_AES_BLOCK_SIZE) {
|
||||||
|
GST_ELEMENT_ERROR (filter, STREAM, FAILED, ("Corrupt cipher text."),
|
||||||
|
("Illegal PKCS7 padding value %d", padding));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
for (k = 1; k < padding; ++k) {
|
||||||
|
if (plaintext[plaintext_len - 1 - k] != padding) {
|
||||||
|
GST_ELEMENT_ERROR (filter, STREAM, FAILED, ("Corrupt cipher text."),
|
||||||
|
("PKCS7 padding values must all be equal"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* remove padding (final block padding) */
|
||||||
|
plaintext_len -= padding;
|
||||||
|
}
|
||||||
|
if (plaintext_len > 2 * GST_AES_BLOCK_SIZE)
|
||||||
|
GST_MEMDUMP ("First 32 bytes of plain text", plaintext,
|
||||||
|
2 * GST_AES_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
gst_buffer_unmap (inbuf, &inmap);
|
||||||
|
gst_buffer_unmap (outbuf, &outmap);
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (filter,
|
||||||
|
"Ciphertext len: %d, Plaintext len: %d, Padding: %d",
|
||||||
|
ciphertext_len, plaintext_len, padding);
|
||||||
|
gst_buffer_set_size (outbuf, plaintext_len);
|
||||||
|
ret = GST_FLOW_OK;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
filter->awaiting_first_buffer = FALSE;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_aes_dec_prepare_output_buffer (GstBaseTransform * base,
|
||||||
|
GstBuffer * inbuf, GstBuffer ** outbuf)
|
||||||
|
{
|
||||||
|
GstAesDec *filter = GST_AES_DEC (base);
|
||||||
|
GstBaseTransformClass *bclass = GST_BASE_TRANSFORM_GET_CLASS (base);
|
||||||
|
guint out_size;
|
||||||
|
|
||||||
|
g_mutex_lock (&filter->decoder_lock);
|
||||||
|
filter->locked_properties = TRUE;
|
||||||
|
/* we need extra space at end of output buffer
|
||||||
|
* when we let OpenSSL handle PKCS7 padding */
|
||||||
|
out_size = (gint) gst_buffer_get_size (inbuf) +
|
||||||
|
(!filter->per_buffer_padding ? GST_AES_BLOCK_SIZE : 0);
|
||||||
|
|
||||||
|
/* Since serialized IV is stripped from first buffer,
|
||||||
|
* reduce output buffer size by GST_AES_BLOCK_SIZE in this case */
|
||||||
|
if (filter->serialize_iv && filter->awaiting_first_buffer) {
|
||||||
|
g_assert (gst_buffer_get_size (inbuf) > GST_AES_BLOCK_SIZE);
|
||||||
|
out_size -= GST_AES_BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
g_mutex_unlock (&filter->decoder_lock);
|
||||||
|
|
||||||
|
*outbuf = gst_buffer_new_allocate (NULL, out_size, NULL);
|
||||||
|
GST_LOG_OBJECT (filter,
|
||||||
|
"Input buffer size %d,\nAllocating output buffer size: %d",
|
||||||
|
(gint) gst_buffer_get_size (inbuf), out_size);
|
||||||
|
bclass->copy_metadata (base, inbuf, *outbuf);
|
||||||
|
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_aes_dec_start (GstBaseTransform * base)
|
||||||
|
{
|
||||||
|
GstAesDec *filter = GST_AES_DEC (base);
|
||||||
|
|
||||||
|
GST_INFO_OBJECT (filter, "Starting");
|
||||||
|
if (!gst_aes_dec_openssl_init (filter)) {
|
||||||
|
GST_ERROR_OBJECT (filter, "OpenSSL initialization failed");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!filter->serialize_iv) {
|
||||||
|
if (!gst_aes_dec_init_cipher (filter))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
GST_INFO_OBJECT (filter, "Start successful");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_aes_dec_init_cipher (GstAesDec * filter)
|
||||||
|
{
|
||||||
|
if (!EVP_CipherInit_ex (filter->evp_ctx, filter->evp_cipher, NULL,
|
||||||
|
filter->key, filter->iv, FALSE)) {
|
||||||
|
GST_ERROR_OBJECT (filter, "Could not initialize openssl cipher");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (filter->per_buffer_padding) {
|
||||||
|
if (!EVP_CIPHER_CTX_set_padding (filter->evp_ctx, 0)) {
|
||||||
|
GST_ERROR_OBJECT (filter, "Could not set padding");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_aes_dec_stop (GstBaseTransform * base)
|
||||||
|
{
|
||||||
|
GstAesDec *filter = GST_AES_DEC (base);
|
||||||
|
|
||||||
|
GST_INFO_OBJECT (filter, "Stopping");
|
||||||
|
EVP_CIPHER_CTX_free (filter->evp_ctx);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AesDec helper functions */
|
||||||
|
static gboolean
|
||||||
|
gst_aes_dec_openssl_init (GstAesDec * filter)
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (filter, "Initializing with %s",
|
||||||
|
OpenSSL_version (OPENSSL_VERSION));
|
||||||
|
|
||||||
|
filter->evp_cipher =
|
||||||
|
EVP_get_cipherbyname (gst_aes_cipher_enum_to_string (filter->cipher));
|
||||||
|
if (!filter->evp_cipher) {
|
||||||
|
GST_ERROR_OBJECT (filter, "Could not get cipher by name from openssl");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!(filter->evp_ctx = EVP_CIPHER_CTX_new ()))
|
||||||
|
return FALSE;
|
||||||
|
GST_LOG_OBJECT (filter, "Initialization successful");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
90
ext/aes/gstaesdec.h
Normal file
90
ext/aes/gstaesdec.h
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* GStreamer gstreamer-aesdec
|
||||||
|
*
|
||||||
|
* Copyright, LCC (C) 2015 RidgeRun, LCC <carsten.behling@ridgerun.com>
|
||||||
|
* Copyright, 2020 Nice, Contact: Rabindra Harlalka <Rabindra.Harlalka@nice.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the
|
||||||
|
* GNU Lesser General Public License Version 2.1 (the "LGPL"), in
|
||||||
|
* which case the following provisions apply instead of the ones
|
||||||
|
* mentioned above:
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1335, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GST_AES_DEC_H__
|
||||||
|
#define __GST_AES_DEC_H__
|
||||||
|
|
||||||
|
#include "gstaeshelper.h"
|
||||||
|
#include <gst/base/gstbasetransform.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GST_TYPE_AES_DEC (gst_aes_dec_get_type())
|
||||||
|
G_DECLARE_FINAL_TYPE (GstAesDec, gst_aes_dec, GST, AES_DEC, GstBaseTransform)
|
||||||
|
#define GST_AES_DEC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AES_DEC,GstAesDec))
|
||||||
|
#define GST_AES_DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_AES_DEC,GstAesDecClass))
|
||||||
|
#define GST_AES_DEC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GST_TYPE_AES_DEC,GstAesDecClass))
|
||||||
|
#define GST_IS_AES_DEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AES_DEC))
|
||||||
|
#define GST_IS_AES_DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_AES_DEC))
|
||||||
|
|
||||||
|
struct _GstAesDec
|
||||||
|
{
|
||||||
|
GstBaseTransform element;
|
||||||
|
|
||||||
|
/* Properties */
|
||||||
|
GstAesCipher cipher;
|
||||||
|
guchar key[EVP_MAX_KEY_LENGTH];
|
||||||
|
guchar iv[GST_AES_BLOCK_SIZE];
|
||||||
|
gboolean serialize_iv;
|
||||||
|
gboolean per_buffer_padding;
|
||||||
|
|
||||||
|
/* Element variables */
|
||||||
|
const EVP_CIPHER *evp_cipher;
|
||||||
|
EVP_CIPHER_CTX *evp_ctx;
|
||||||
|
gboolean awaiting_first_buffer;
|
||||||
|
GMutex decoder_lock;
|
||||||
|
/* if TRUE, then properties cannot be changed */
|
||||||
|
gboolean locked_properties;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstAesDecClass
|
||||||
|
{
|
||||||
|
GstBaseTransformClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GST_ELEMENT_REGISTER_DECLARE (aesdec)
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
#endif /* __GST_AES_DEC_H__ */
|
594
ext/aes/gstaesenc.c
Normal file
594
ext/aes/gstaesenc.c
Normal file
|
@ -0,0 +1,594 @@
|
||||||
|
/*
|
||||||
|
* GStreamer gstreamer-aesenc
|
||||||
|
*
|
||||||
|
* Copyright, LCC (C) 2015 RidgeRun, LCC <carsten.behling@ridgerun.com>
|
||||||
|
* Copyright, LCC (C) 2016 RidgeRun, LCC <jose.jimenez@ridgerun.com>
|
||||||
|
* Copyright (C) 2020 Nice, Contact: Rabindra Harlalka <Rabindra.Harlalka@nice.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the
|
||||||
|
* GNU Lesser General Public License Version 2.1 (the "LGPL"), in
|
||||||
|
* which case the following provisions apply instead of the ones
|
||||||
|
* mentioned above:
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1335, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:element-aesenc
|
||||||
|
*
|
||||||
|
* AES encryption
|
||||||
|
*
|
||||||
|
* ## Example
|
||||||
|
*
|
||||||
|
* |[
|
||||||
|
* echo "This is an AES crypto test ... " > plain.txt && \
|
||||||
|
* gst-launch-1.0 filesrc location=plain.txt ! \
|
||||||
|
* aesenc key=1f9423681beb9a79215820f6bda73d0f iv=e9aa8e834d8d70b7e0d254ff670dd718 ! \
|
||||||
|
* aesdec key=1f9423681beb9a79215820f6bda73d0f iv=e9aa8e834d8d70b7e0d254ff670dd718 ! \
|
||||||
|
* filesink location=dec.txt && \
|
||||||
|
* cat dec.txt
|
||||||
|
*
|
||||||
|
* ]|
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/base/gstbasetransform.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "gstaeshelper.h"
|
||||||
|
#include "gstaesenc.h"
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (gst_aes_enc_debug);
|
||||||
|
#define GST_CAT_DEFAULT gst_aes_enc_debug
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (GstAesEnc, gst_aes_enc, GST_TYPE_BASE_TRANSFORM,
|
||||||
|
GST_DEBUG_CATEGORY_INIT (gst_aes_enc_debug, "aesenc", 0,
|
||||||
|
"aesenc AES encryption element")
|
||||||
|
);
|
||||||
|
GST_ELEMENT_REGISTER_DEFINE (aesenc, "aesenc", GST_RANK_PRIMARY,
|
||||||
|
GST_TYPE_AES_ENC);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
GST_PAD_SINK,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("ANY")
|
||||||
|
);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
|
GST_PAD_SRC,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("ANY")
|
||||||
|
);
|
||||||
|
|
||||||
|
static void gst_aes_enc_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec);
|
||||||
|
static void gst_aes_enc_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec);
|
||||||
|
|
||||||
|
static GstFlowReturn gst_aes_enc_transform (GstBaseTransform * base,
|
||||||
|
GstBuffer * inbuf, GstBuffer * outbuf);
|
||||||
|
static GstFlowReturn gst_aes_enc_prepare_output_buffer (GstBaseTransform * base,
|
||||||
|
GstBuffer * inbuf, GstBuffer ** outbuf);
|
||||||
|
|
||||||
|
static gboolean gst_aes_enc_start (GstBaseTransform * base);
|
||||||
|
static gboolean gst_aes_enc_stop (GstBaseTransform * base);
|
||||||
|
static gboolean
|
||||||
|
gst_aes_enc_sink_event (GstBaseTransform * base, GstEvent * event);
|
||||||
|
|
||||||
|
/* aes_enc helper functions */
|
||||||
|
static gboolean gst_aes_enc_openssl_init (GstAesEnc * filter);
|
||||||
|
static void gst_aes_enc_finalize (GObject * object);
|
||||||
|
|
||||||
|
/* GObject vmethod implementations */
|
||||||
|
|
||||||
|
/* initialize class */
|
||||||
|
static void
|
||||||
|
gst_aes_enc_class_init (GstAesEncClass * klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class;
|
||||||
|
GstElementClass *gstelement_class;
|
||||||
|
|
||||||
|
gobject_class = (GObjectClass *) klass;
|
||||||
|
gstelement_class = (GstElementClass *) klass;
|
||||||
|
|
||||||
|
gobject_class->set_property = gst_aes_enc_set_property;
|
||||||
|
gobject_class->get_property = gst_aes_enc_get_property;
|
||||||
|
gobject_class->finalize = gst_aes_enc_finalize;
|
||||||
|
|
||||||
|
gst_type_mark_as_plugin_api (GST_TYPE_AES_CIPHER, 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstAesEnc:cipher
|
||||||
|
*
|
||||||
|
* AES cipher mode (key length and mode)
|
||||||
|
* Currently, 128 and 256 bit keys are supported,
|
||||||
|
* in "cipher block chaining" (CBC) mode
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_CIPHER,
|
||||||
|
g_param_spec_enum ("cipher",
|
||||||
|
"Cipher",
|
||||||
|
"cipher mode",
|
||||||
|
GST_TYPE_AES_CIPHER, GST_AES_DEFAULT_CIPHER_MODE,
|
||||||
|
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||||
|
GST_PARAM_MUTABLE_READY)));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstAesEnc:serialize-iv
|
||||||
|
*
|
||||||
|
* If true, store initialization vector in first 16 bytes of first buffer
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_SERIALIZE_IV,
|
||||||
|
g_param_spec_boolean ("serialize-iv", "Serialize IV",
|
||||||
|
"Store initialization vector in first 16 bytes of first buffer",
|
||||||
|
GST_AES_DEFAULT_SERIALIZE_IV,
|
||||||
|
G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstAesEnc:per-buffer-padding
|
||||||
|
*
|
||||||
|
* If true, each buffer will be padded using PKCS7 padding
|
||||||
|
* If false, only the final buffer in the stream will be padded
|
||||||
|
* (by OpenSSL) using PKCS7
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_PER_BUFFER_PADDING,
|
||||||
|
g_param_spec_boolean ("per-buffer-padding", "Per buffer padding",
|
||||||
|
"If true, pad each buffer using PKCS7 padding scheme. Otherwise, only"
|
||||||
|
"pad final buffer",
|
||||||
|
GST_AES_PER_BUFFER_PADDING_DEFAULT,
|
||||||
|
G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstAesEnc:key
|
||||||
|
*
|
||||||
|
* AES encryption key (hexadecimal)
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_KEY,
|
||||||
|
g_param_spec_string ("key", "Key",
|
||||||
|
"AES encryption key (in hexadecimal). Length (in bytes) must be equivalent to "
|
||||||
|
"the number of bits in the key length : "
|
||||||
|
"16 bytes for AES 128 and 32 bytes for AES 256",
|
||||||
|
(gchar *) GST_AES_DEFAULT_KEY,
|
||||||
|
G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstAesEnc:iv
|
||||||
|
*
|
||||||
|
* AES encryption initialization vector (hexadecimal)
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_IV,
|
||||||
|
g_param_spec_string ("iv", "Iv",
|
||||||
|
"AES encryption initialization vector (in hexadecimal). "
|
||||||
|
"Length must equal AES block length (16 bytes)",
|
||||||
|
(gchar *) GST_AES_DEFAULT_IV,
|
||||||
|
G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY));
|
||||||
|
|
||||||
|
gst_element_class_set_details_simple (gstelement_class,
|
||||||
|
"aesenc",
|
||||||
|
"Generic/Filter",
|
||||||
|
"AES buffer encryption",
|
||||||
|
"Rabindra Harlalka <Rabindra.Harlalka@nice.com>");
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&src_template));
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&sink_template));
|
||||||
|
|
||||||
|
GST_BASE_TRANSFORM_CLASS (klass)->transform =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_aes_enc_transform);
|
||||||
|
GST_BASE_TRANSFORM_CLASS (klass)->prepare_output_buffer =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_aes_enc_prepare_output_buffer);
|
||||||
|
GST_BASE_TRANSFORM_CLASS (klass)->start =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_aes_enc_start);
|
||||||
|
GST_BASE_TRANSFORM_CLASS (klass)->sink_event =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_aes_enc_sink_event);
|
||||||
|
GST_BASE_TRANSFORM_CLASS (klass)->stop = GST_DEBUG_FUNCPTR (gst_aes_enc_stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize element
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
gst_aes_enc_init (GstAesEnc * filter)
|
||||||
|
{
|
||||||
|
GST_INFO_OBJECT (filter, "Initializing plugin");
|
||||||
|
filter->cipher = GST_AES_DEFAULT_CIPHER_MODE;
|
||||||
|
filter->awaiting_first_buffer = TRUE;
|
||||||
|
filter->per_buffer_padding = GST_AES_PER_BUFFER_PADDING_DEFAULT;
|
||||||
|
g_mutex_init (&filter->encoder_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_aes_enc_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
GstAesEnc *filter = GST_AES_ENC (object);
|
||||||
|
|
||||||
|
g_mutex_clear (&filter->encoder_lock);
|
||||||
|
G_OBJECT_CLASS (gst_aes_enc_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_aes_enc_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstAesEnc *filter = GST_AES_ENC (object);
|
||||||
|
|
||||||
|
g_mutex_lock (&filter->encoder_lock);
|
||||||
|
/* no property may be set after first output buffer is prepared */
|
||||||
|
if (filter->locked_properties) {
|
||||||
|
GST_WARNING_OBJECT (filter,
|
||||||
|
"Properties cannot be set once buffers begin flowing in element. Ignored");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_CIPHER:
|
||||||
|
filter->cipher = g_value_get_enum (value);
|
||||||
|
filter->evp_cipher =
|
||||||
|
EVP_get_cipherbyname (gst_aes_cipher_enum_to_string (filter->cipher));
|
||||||
|
GST_DEBUG_OBJECT (filter, "cipher: %s",
|
||||||
|
gst_aes_cipher_enum_to_string (filter->cipher));
|
||||||
|
break;
|
||||||
|
case PROP_SERIALIZE_IV:
|
||||||
|
filter->serialize_iv = g_value_get_boolean (value);
|
||||||
|
GST_DEBUG_OBJECT (filter, "serialize iv: %s",
|
||||||
|
filter->serialize_iv ? "TRUE" : "FALSE");
|
||||||
|
break;
|
||||||
|
case PROP_PER_BUFFER_PADDING:
|
||||||
|
filter->per_buffer_padding = g_value_get_boolean (value);
|
||||||
|
GST_DEBUG_OBJECT (filter, "Per buffer padding: %s",
|
||||||
|
filter->per_buffer_padding ? "TRUE" : "FALSE");
|
||||||
|
break;
|
||||||
|
case PROP_KEY:
|
||||||
|
{
|
||||||
|
guint hex_len = gst_aes_hexstring2bytearray (GST_ELEMENT (filter),
|
||||||
|
g_value_get_string (value), filter->key);
|
||||||
|
|
||||||
|
if (!hex_len) {
|
||||||
|
GST_ERROR_OBJECT (filter, "invalid key");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
GST_DEBUG_OBJECT (filter, "key: %s", g_value_get_string (value));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PROP_IV:
|
||||||
|
{
|
||||||
|
gchar iv_string[2 * GST_AES_BLOCK_SIZE + 1];
|
||||||
|
guint hex_len = gst_aes_hexstring2bytearray (GST_ELEMENT (filter),
|
||||||
|
g_value_get_string (value), filter->iv);
|
||||||
|
|
||||||
|
if (hex_len != GST_AES_BLOCK_SIZE) {
|
||||||
|
GST_ERROR_OBJECT (filter, "invalid initialization vector");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
GST_DEBUG_OBJECT (filter, "iv: %s",
|
||||||
|
gst_aes_bytearray2hexstring (filter->iv, iv_string,
|
||||||
|
GST_AES_BLOCK_SIZE));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
g_mutex_unlock (&filter->encoder_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_aes_enc_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstAesEnc *filter = GST_AES_ENC (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_CIPHER:
|
||||||
|
g_value_set_enum (value, filter->cipher);
|
||||||
|
break;
|
||||||
|
case PROP_SERIALIZE_IV:
|
||||||
|
g_value_set_boolean (value, filter->serialize_iv);
|
||||||
|
break;
|
||||||
|
case PROP_PER_BUFFER_PADDING:
|
||||||
|
g_value_set_boolean (value, filter->per_buffer_padding);
|
||||||
|
break;
|
||||||
|
case PROP_KEY:
|
||||||
|
g_value_set_string (value, (gchar *) filter->key);
|
||||||
|
break;
|
||||||
|
case PROP_IV:
|
||||||
|
g_value_set_string (value, (gchar *) filter->iv);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_aes_enc_sink_event (GstBaseTransform * base, GstEvent * event)
|
||||||
|
{
|
||||||
|
GstAesEnc *filter = GST_AES_ENC (base);
|
||||||
|
g_mutex_lock (&filter->encoder_lock);
|
||||||
|
|
||||||
|
if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
|
||||||
|
GST_DEBUG_OBJECT (filter, "Received EOS on sink pad");
|
||||||
|
if (!filter->per_buffer_padding && !filter->awaiting_first_buffer) {
|
||||||
|
gint len;
|
||||||
|
GstBuffer *outbuf;
|
||||||
|
GstMapInfo outmap;
|
||||||
|
|
||||||
|
outbuf = gst_buffer_new_allocate (NULL, EVP_MAX_BLOCK_LENGTH, NULL);
|
||||||
|
if (outbuf == NULL) {
|
||||||
|
GST_DEBUG_OBJECT (filter,
|
||||||
|
"Failed to allocate a new buffer of length %d",
|
||||||
|
EVP_MAX_BLOCK_LENGTH);
|
||||||
|
goto buffer_fail;
|
||||||
|
}
|
||||||
|
if (!gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE)) {
|
||||||
|
GST_DEBUG_OBJECT (filter,
|
||||||
|
"gst_buffer_map on outbuf failed for final buffer.");
|
||||||
|
gst_buffer_unref (outbuf);
|
||||||
|
goto buffer_fail;
|
||||||
|
}
|
||||||
|
if (1 != EVP_CipherFinal_ex (filter->evp_ctx, outmap.data, &len)) {
|
||||||
|
GST_DEBUG_OBJECT (filter, "Could not finalize openssl encryption");
|
||||||
|
gst_buffer_unmap (outbuf, &outmap);
|
||||||
|
gst_buffer_unref (outbuf);
|
||||||
|
goto cipher_fail;
|
||||||
|
}
|
||||||
|
if (len == 0) {
|
||||||
|
GST_DEBUG_OBJECT (filter, "Not pushing final buffer as length is 0");
|
||||||
|
gst_buffer_unmap (outbuf, &outmap);
|
||||||
|
gst_buffer_unref (outbuf);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
GST_DEBUG_OBJECT (filter, "Pushing final buffer of length: %d", len);
|
||||||
|
gst_buffer_unmap (outbuf, &outmap);
|
||||||
|
gst_buffer_set_size (outbuf, len);
|
||||||
|
if (gst_pad_push (base->srcpad, outbuf) != GST_FLOW_OK) {
|
||||||
|
GST_DEBUG_OBJECT (filter, "Failed to push the final buffer");
|
||||||
|
goto push_fail;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (filter,
|
||||||
|
"Not pushing final buffer as we didn't have any input");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
g_mutex_unlock (&filter->encoder_lock);
|
||||||
|
|
||||||
|
return GST_BASE_TRANSFORM_CLASS (gst_aes_enc_parent_class)->sink_event (base,
|
||||||
|
event);
|
||||||
|
|
||||||
|
/* ERROR */
|
||||||
|
buffer_fail:
|
||||||
|
GST_ELEMENT_ERROR (filter, RESOURCE, FAILED, (NULL),
|
||||||
|
("Failed to allocate or map buffer for writing"));
|
||||||
|
g_mutex_unlock (&filter->encoder_lock);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
cipher_fail:
|
||||||
|
GST_ELEMENT_ERROR (filter, STREAM, FAILED, ("Cipher finalization failed."),
|
||||||
|
("Error while finalizing the stream"));
|
||||||
|
g_mutex_unlock (&filter->encoder_lock);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
push_fail:
|
||||||
|
GST_ELEMENT_ERROR (filter, CORE, PAD, (NULL),
|
||||||
|
("Failed to push the final buffer"));
|
||||||
|
g_mutex_unlock (&filter->encoder_lock);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GstBaseTransform vmethod implementations */
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_aes_enc_transform (GstBaseTransform * base,
|
||||||
|
GstBuffer * inbuf, GstBuffer * outbuf)
|
||||||
|
{
|
||||||
|
GstAesEnc *filter = GST_AES_ENC (base);
|
||||||
|
GstFlowReturn ret = GST_FLOW_ERROR;
|
||||||
|
GstMapInfo inmap, outmap;
|
||||||
|
guchar *plaintext;
|
||||||
|
gint plaintext_len;
|
||||||
|
guchar *ciphertext;
|
||||||
|
gint ciphertext_len;
|
||||||
|
gint out_len;
|
||||||
|
|
||||||
|
if (!gst_buffer_map (inbuf, &inmap, GST_MAP_READ)) {
|
||||||
|
GST_ELEMENT_ERROR (filter, RESOURCE, FAILED, (NULL),
|
||||||
|
("Failed to map buffer for reading"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (!gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE)) {
|
||||||
|
gst_buffer_unmap (inbuf, &inmap);
|
||||||
|
GST_ELEMENT_ERROR (filter, RESOURCE, FAILED, (NULL),
|
||||||
|
("Failed to map buffer for writing"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ENCRYPTING */
|
||||||
|
plaintext = inmap.data;
|
||||||
|
plaintext_len = inmap.size;
|
||||||
|
if (filter->padding)
|
||||||
|
plaintext_len += filter->padding - GST_AES_BLOCK_SIZE;
|
||||||
|
ciphertext = outmap.data;
|
||||||
|
if (filter->awaiting_first_buffer) {
|
||||||
|
if (!EVP_CipherInit_ex (filter->evp_ctx, filter->evp_cipher, NULL,
|
||||||
|
filter->key, filter->iv, TRUE)) {
|
||||||
|
GST_ERROR_OBJECT (filter, "Could not initialize openssl cipher");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (filter->serialize_iv) {
|
||||||
|
memcpy (ciphertext, filter->iv, GST_AES_BLOCK_SIZE);
|
||||||
|
ciphertext += GST_AES_BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* encrypt unpadded buffer */
|
||||||
|
if (!EVP_CipherUpdate (filter->evp_ctx, ciphertext,
|
||||||
|
&ciphertext_len, plaintext, plaintext_len)) {
|
||||||
|
GST_ELEMENT_ERROR (filter, STREAM, FAILED, ("Cipher update failed."),
|
||||||
|
("Error while updating openssl cipher"));
|
||||||
|
goto cleanup;
|
||||||
|
} else if (filter->padding) {
|
||||||
|
gint temp;
|
||||||
|
guint k;
|
||||||
|
|
||||||
|
/* PKCS7 padding */
|
||||||
|
memset (filter->padded_block, filter->padding, GST_AES_BLOCK_SIZE);
|
||||||
|
for (k = 0; k < GST_AES_BLOCK_SIZE - filter->padding; ++k)
|
||||||
|
filter->padded_block[k] = plaintext[plaintext_len + k];
|
||||||
|
|
||||||
|
/* encrypt padding buffer */
|
||||||
|
if (!EVP_CipherUpdate (filter->evp_ctx,
|
||||||
|
ciphertext + ciphertext_len, &temp,
|
||||||
|
filter->padded_block, GST_AES_BLOCK_SIZE)) {
|
||||||
|
GST_ELEMENT_ERROR (filter, STREAM, FAILED, ("Cipher update failed."),
|
||||||
|
("Error while updating openssl cipher"));
|
||||||
|
goto cleanup;
|
||||||
|
} else {
|
||||||
|
g_assert (temp == GST_AES_BLOCK_SIZE);
|
||||||
|
ciphertext_len += GST_AES_BLOCK_SIZE;
|
||||||
|
plaintext_len += GST_AES_BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gst_buffer_unmap (inbuf, &inmap);
|
||||||
|
gst_buffer_unmap (outbuf, &outmap);
|
||||||
|
|
||||||
|
out_len = ciphertext_len + (filter->serialize_iv ? GST_AES_BLOCK_SIZE : 0);
|
||||||
|
gst_buffer_set_size (outbuf, out_len);
|
||||||
|
GST_LOG_OBJECT (filter,
|
||||||
|
"plaintext len: %d, ciphertext len: %d, padding: %d, output buffer length: %d",
|
||||||
|
plaintext_len, ciphertext_len, filter->padding, out_len);
|
||||||
|
ret = GST_FLOW_OK;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
filter->awaiting_first_buffer = FALSE;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_aes_enc_prepare_output_buffer (GstBaseTransform * base,
|
||||||
|
GstBuffer * inbuf, GstBuffer ** outbuf)
|
||||||
|
{
|
||||||
|
GstAesEnc *filter = GST_AES_ENC (base);
|
||||||
|
GstBaseTransformClass *bclass = GST_BASE_TRANSFORM_GET_CLASS (base);
|
||||||
|
guint out_size = (guint) gst_buffer_get_size (inbuf);
|
||||||
|
|
||||||
|
g_mutex_lock (&filter->encoder_lock);
|
||||||
|
filter->locked_properties = TRUE;
|
||||||
|
if (filter->per_buffer_padding) {
|
||||||
|
/* pad to multiple of GST_AES_BLOCK_SIZE */
|
||||||
|
filter->padding =
|
||||||
|
GST_AES_BLOCK_SIZE - (out_size & (GST_AES_BLOCK_SIZE - 1));
|
||||||
|
out_size += filter->padding;
|
||||||
|
} else {
|
||||||
|
/* we need extra space at end of output buffer
|
||||||
|
* when we let OpenSSL handle PKCS7 padding */
|
||||||
|
out_size += GST_AES_BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add room for serialized IV at beginning of first output buffer */
|
||||||
|
if (filter->serialize_iv && filter->awaiting_first_buffer)
|
||||||
|
out_size += GST_AES_BLOCK_SIZE;
|
||||||
|
g_mutex_unlock (&filter->encoder_lock);
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (filter,
|
||||||
|
"Input buffer size %d, output buffer size: %d. padding : %d",
|
||||||
|
(guint) gst_buffer_get_size (inbuf), out_size, filter->padding);
|
||||||
|
*outbuf = gst_buffer_new_allocate (NULL, out_size, NULL);
|
||||||
|
bclass->copy_metadata (base, inbuf, *outbuf);
|
||||||
|
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_aes_enc_start (GstBaseTransform * base)
|
||||||
|
{
|
||||||
|
GstAesEnc *filter = GST_AES_ENC (base);
|
||||||
|
|
||||||
|
GST_INFO_OBJECT (filter, "Starting");
|
||||||
|
if (!gst_aes_enc_openssl_init (filter)) {
|
||||||
|
GST_ERROR_OBJECT (filter, "OpenSSL initialization failed");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_INFO_OBJECT (filter, "Start successful");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_aes_enc_stop (GstBaseTransform * base)
|
||||||
|
{
|
||||||
|
GstAesEnc *filter = GST_AES_ENC (base);
|
||||||
|
|
||||||
|
GST_INFO_OBJECT (filter, "Stopping");
|
||||||
|
EVP_CIPHER_CTX_free (filter->evp_ctx);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AesEnc helper functions */
|
||||||
|
static gboolean
|
||||||
|
gst_aes_enc_openssl_init (GstAesEnc * filter)
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (filter, "Initializing with %s",
|
||||||
|
OpenSSL_version (OPENSSL_VERSION));
|
||||||
|
|
||||||
|
filter->evp_cipher =
|
||||||
|
EVP_get_cipherbyname (gst_aes_cipher_enum_to_string (filter->cipher));
|
||||||
|
if (!filter->evp_cipher) {
|
||||||
|
GST_ERROR_OBJECT (filter, "Could not get cipher by name from openssl");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!(filter->evp_ctx = EVP_CIPHER_CTX_new ()))
|
||||||
|
return FALSE;
|
||||||
|
GST_LOG_OBJECT (filter, "Initialization successful");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
92
ext/aes/gstaesenc.h
Normal file
92
ext/aes/gstaesenc.h
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* GStreamer gstreamer-aesenc
|
||||||
|
*
|
||||||
|
* Copyright, LCC (C) 2015 RidgeRun, LCC <carsten.behling@ridgerun.com>
|
||||||
|
* Copyright, 2020 Nice, Contact: Rabindra Harlalka <Rabindra.Harlalka@nice.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the
|
||||||
|
* GNU Lesser General Public License Version 2.1 (the "LGPL"), in
|
||||||
|
* which case the following provisions apply instead of the ones
|
||||||
|
* mentioned above:
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1335, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GST_AES_ENC_H__
|
||||||
|
#define __GST_AES_ENC_H__
|
||||||
|
|
||||||
|
#include "gstaeshelper.h"
|
||||||
|
#include <gst/base/gstbasetransform.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GST_TYPE_AES_ENC (gst_aes_enc_get_type())
|
||||||
|
G_DECLARE_FINAL_TYPE (GstAesEnc, gst_aes_enc, GST, AES_ENC, GstBaseTransform)
|
||||||
|
#define GST_AES_ENC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AES_ENC,GstAesEnc))
|
||||||
|
#define GST_AES_ENC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_AES_ENC,GstAesEncClass))
|
||||||
|
#define GST_AES_ENC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GST_TYPE_AES_ENC,GstAesEncClass))
|
||||||
|
#define GST_IS_AES_ENC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AES_ENC))
|
||||||
|
#define GST_IS_AES_ENC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_AES_ENC))
|
||||||
|
|
||||||
|
struct _GstAesEnc
|
||||||
|
{
|
||||||
|
GstBaseTransform element;
|
||||||
|
|
||||||
|
/* Properties */
|
||||||
|
GstAesCipher cipher;
|
||||||
|
guchar key[EVP_MAX_KEY_LENGTH];
|
||||||
|
guchar iv[GST_AES_BLOCK_SIZE];
|
||||||
|
gboolean serialize_iv;
|
||||||
|
gboolean per_buffer_padding;
|
||||||
|
|
||||||
|
/* Element variables */
|
||||||
|
const EVP_CIPHER *evp_cipher;
|
||||||
|
EVP_CIPHER_CTX *evp_ctx;
|
||||||
|
guchar padding;
|
||||||
|
guchar padded_block[GST_AES_BLOCK_SIZE];
|
||||||
|
gboolean awaiting_first_buffer;
|
||||||
|
GMutex encoder_lock;
|
||||||
|
/* if TRUE, then properties cannot be changed */
|
||||||
|
gboolean locked_properties;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstAesEncClass
|
||||||
|
{
|
||||||
|
GstBaseTransformClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GST_ELEMENT_REGISTER_DECLARE (aesenc)
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
#endif /* __GST_AES_ENC_H__ */
|
187
ext/aes/gstaeshelper.c
Normal file
187
ext/aes/gstaeshelper.c
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
/*
|
||||||
|
* GStreamer gstreamer-aeshelper
|
||||||
|
*
|
||||||
|
* Copyright, LCC (C) 2015 RidgeRun, LCC <carsten.behling@ridgerun.com>
|
||||||
|
* Copyright, LCC (C) 2016 RidgeRun, LCC <jose.jimenez@ridgerun.com>
|
||||||
|
* Copyright (C) 2020 Nice, Contact: Rabindra Harlalka <Rabindra.Harlalka@nice.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the
|
||||||
|
* GNU Lesser General Public License Version 2.1 (the "LGPL"), in
|
||||||
|
* which case the following provisions apply instead of the ones
|
||||||
|
* mentioned above:
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1335, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "gstaeshelper.h"
|
||||||
|
|
||||||
|
GType
|
||||||
|
gst_aes_cipher_get_type (void)
|
||||||
|
{
|
||||||
|
static GType aes_cipher_type = 0;
|
||||||
|
|
||||||
|
if (g_once_init_enter (&aes_cipher_type)) {
|
||||||
|
static GEnumValue aes_cipher_types[] = {
|
||||||
|
{GST_AES_CIPHER_128_CBC, "AES 128 bit cipher key using CBC method",
|
||||||
|
"aes-128-cbc"},
|
||||||
|
{GST_AES_CIPHER_256_CBC,
|
||||||
|
"AES 256 bit cipher key using CBC method",
|
||||||
|
"aes-256-cbc"},
|
||||||
|
{0, NULL, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
GType temp = g_enum_register_static ("GstAesCipher",
|
||||||
|
aes_cipher_types);
|
||||||
|
|
||||||
|
g_once_init_leave (&aes_cipher_type, temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return aes_cipher_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gchar *
|
||||||
|
gst_aes_cipher_enum_to_string (GstAesCipher cipher)
|
||||||
|
{
|
||||||
|
switch (cipher) {
|
||||||
|
case GST_AES_CIPHER_128_CBC:
|
||||||
|
return "aes-128-cbc";
|
||||||
|
break;
|
||||||
|
case GST_AES_CIPHER_256_CBC:
|
||||||
|
return "aes-256-cbc";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gchar
|
||||||
|
gst_aes_nibble_to_hex (gchar in)
|
||||||
|
{
|
||||||
|
return in < 10 ? in + 48 : in + 55;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gst_aes_bytearray2hexstring
|
||||||
|
*
|
||||||
|
* convert array of bytes to hex string
|
||||||
|
*
|
||||||
|
* @param in input byte array
|
||||||
|
* @param out allocated hex string for output
|
||||||
|
* @param len length of input byte array
|
||||||
|
*
|
||||||
|
* @return output hex string
|
||||||
|
*/
|
||||||
|
gchar *
|
||||||
|
gst_aes_bytearray2hexstring (const guchar * in, gchar * const out,
|
||||||
|
const gushort len)
|
||||||
|
{
|
||||||
|
gushort i;
|
||||||
|
gchar high;
|
||||||
|
gchar low;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
high = (in[i] & 0xF0) >> 4;
|
||||||
|
low = in[i] & 0x0F;
|
||||||
|
out[i * 2] = gst_aes_nibble_to_hex (high);
|
||||||
|
out[i * 2 + 1] = gst_aes_nibble_to_hex (low);
|
||||||
|
}
|
||||||
|
out[len * 2] = 0; /* null terminate */
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gst_aes_hexstring2bytearray
|
||||||
|
*
|
||||||
|
* convert hex string to array of bytes
|
||||||
|
*
|
||||||
|
* @param filter calling element
|
||||||
|
* @param in input hex string
|
||||||
|
* @param allocated byte array for output
|
||||||
|
*
|
||||||
|
* @return output byte array
|
||||||
|
*/
|
||||||
|
guint
|
||||||
|
gst_aes_hexstring2bytearray (GstElement * filter, const gchar * in,
|
||||||
|
guchar * out)
|
||||||
|
{
|
||||||
|
gchar byte_val;
|
||||||
|
guint hex_count = 0;
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (filter, "Converting hex string to number");
|
||||||
|
|
||||||
|
g_return_val_if_fail (in && out, 0);
|
||||||
|
|
||||||
|
while (*in != 0) {
|
||||||
|
/* Compute fist half-byte */
|
||||||
|
if (*in >= 'A' && *in <= 'F') {
|
||||||
|
byte_val = (*in - 55) << 4;
|
||||||
|
} else if (*in >= 'a' && *in <= 'f') {
|
||||||
|
byte_val = (*in - 87) << 4;
|
||||||
|
} else if (*in >= '0' && *in <= '9') {
|
||||||
|
byte_val = (*in - 48) << 4;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
in++;
|
||||||
|
if (*in == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Compute second half-byte */
|
||||||
|
if (*in >= 'A' && *in <= 'F') {
|
||||||
|
*out = (*in - 55) + byte_val;
|
||||||
|
} else if (*in >= 'a' && *in <= 'f') {
|
||||||
|
*out = (*in - 87) + byte_val;
|
||||||
|
} else if (*in >= '0' && *in <= '9') {
|
||||||
|
*out = (*in - 48) + byte_val;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (filter, "ch: %c%c, hex: 0x%x", *(in - 1), *in, *out);
|
||||||
|
in++;
|
||||||
|
out++;
|
||||||
|
if (!in || !out)
|
||||||
|
return 0;
|
||||||
|
hex_count++;
|
||||||
|
}
|
||||||
|
GST_LOG_OBJECT (filter, "Hex string conversion successful");
|
||||||
|
|
||||||
|
return hex_count;
|
||||||
|
}
|
104
ext/aes/gstaeshelper.h
Normal file
104
ext/aes/gstaeshelper.h
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* GStreamer gstreamer-aeshelper
|
||||||
|
*
|
||||||
|
* Copyright, LCC (C) 2015 RidgeRun, LCC <carsten.behling@ridgerun.com>
|
||||||
|
* Copyright, 2020 Nice, Contact: Rabindra Harlalka <Rabindra.Harlalka@nice.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the
|
||||||
|
* GNU Lesser General Public License Version 2.1 (the "LGPL"), in
|
||||||
|
* which case the following provisions apply instead of the ones
|
||||||
|
* mentioned above:
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1335, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GST_AES_HELPER_H__
|
||||||
|
#define __GST_AES_HELPER_H__
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <openssl/conf.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstAesCipher:
|
||||||
|
* @GST_AES_CIPHER_128_CBC: AES cipher with 128 bit key using CBC
|
||||||
|
* @GST_AES_CIPHER_256_CBC: AES cipher with 256 bit key using CBC
|
||||||
|
*
|
||||||
|
* Type of AES cipher to use
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GST_AES_CIPHER_128_CBC,
|
||||||
|
GST_AES_CIPHER_256_CBC
|
||||||
|
} GstAesCipher;
|
||||||
|
|
||||||
|
#define GST_AES_DEFAULT_SERIALIZE_IV FALSE
|
||||||
|
#define GST_AES_DEFAULT_KEY ""
|
||||||
|
#define GST_AES_DEFAULT_IV ""
|
||||||
|
#define GST_AES_DEFAULT_CIPHER_MODE GST_AES_CIPHER_128_CBC
|
||||||
|
#define GST_AES_PER_BUFFER_PADDING_DEFAULT TRUE
|
||||||
|
#define GST_AES_BLOCK_SIZE 16
|
||||||
|
/* only 128 or 256 bit key length is supported */
|
||||||
|
#define GST_AES_MAX_KEY_SIZE 32
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_CIPHER,
|
||||||
|
PROP_SERIALIZE_IV,
|
||||||
|
PROP_KEY,
|
||||||
|
PROP_IV,
|
||||||
|
PROP_PER_BUFFER_PADDING
|
||||||
|
};
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
GType gst_aes_cipher_get_type (void);
|
||||||
|
#define GST_TYPE_AES_CIPHER (gst_aes_cipher_get_type ())
|
||||||
|
const gchar* gst_aes_cipher_enum_to_string (GstAesCipher cipher);
|
||||||
|
|
||||||
|
gchar
|
||||||
|
gst_aes_nibble_to_hex (gchar in);
|
||||||
|
gchar *
|
||||||
|
gst_aes_bytearray2hexstring (const guchar * in, gchar * const out,
|
||||||
|
const gushort len);
|
||||||
|
guint
|
||||||
|
gst_aes_hexstring2bytearray (GstElement * filter, const gchar * in,
|
||||||
|
guchar * out);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
#endif /* __GST_AES_HELPER_H__ */
|
28
ext/aes/meson.build
Normal file
28
ext/aes/meson.build
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
aes_sources = [
|
||||||
|
'gstaes.c',
|
||||||
|
'gstaeshelper.c',
|
||||||
|
'gstaesenc.c',
|
||||||
|
'gstaesdec.c',
|
||||||
|
]
|
||||||
|
|
||||||
|
aes_cargs = []
|
||||||
|
aes_dep = dependency('openssl', required : get_option('aes'))
|
||||||
|
if aes_dep.found()
|
||||||
|
aes_cargs += ['-DHAVE_OPENSSL']
|
||||||
|
else
|
||||||
|
subdir_done()
|
||||||
|
endif
|
||||||
|
|
||||||
|
gstaes = library('gstaes',
|
||||||
|
aes_sources,
|
||||||
|
c_args : gst_plugins_bad_args + aes_cargs,
|
||||||
|
link_args : noseh_link_args,
|
||||||
|
include_directories : [configinc],
|
||||||
|
dependencies : [gstpbutils_dep, gstvideo_dep,
|
||||||
|
aes_dep, gio_dep, libm],
|
||||||
|
install : true,
|
||||||
|
install_dir : plugins_install_dir,
|
||||||
|
)
|
||||||
|
pkgconfig.generate(gstaes, install_dir : plugins_pkgconfig_install_dir)
|
||||||
|
plugins += [gstaes]
|
||||||
|
aes_dep = declare_dependency(include_directories : include_directories('.'))
|
44
ext/aom/gstaom.c
Normal file
44
ext/aom/gstaom.c
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <2017> Sean DuBois <sean@siobud.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
#include "gstaom.h"
|
||||||
|
#include "gstav1enc.h"
|
||||||
|
#include "gstav1dec.h"
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
plugin_init (GstPlugin * plugin)
|
||||||
|
{
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
|
ret |= GST_ELEMENT_REGISTER (av1enc, plugin);
|
||||||
|
ret |= GST_ELEMENT_REGISTER (av1dec, plugin);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||||
|
GST_VERSION_MINOR,
|
||||||
|
aom,
|
||||||
|
"AOM plugin library",
|
||||||
|
plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
|
24
ext/aom/gstaom.h
Normal file
24
ext/aom/gstaom.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <2017> Sean DuBois <sean@siobud.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GST_AOM_H__
|
||||||
|
#define __GST_AOM_H__
|
||||||
|
|
||||||
|
#endif /* __GST_AOM_H__ */
|
485
ext/aom/gstav1dec.c
Normal file
485
ext/aom/gstav1dec.c
Normal file
|
@ -0,0 +1,485 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <2017> Sean DuBois <sean@siobud.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* SECTION:element-av1dec
|
||||||
|
*
|
||||||
|
* AV1 Decoder.
|
||||||
|
*
|
||||||
|
* ## Example launch line
|
||||||
|
*
|
||||||
|
* |[
|
||||||
|
* gst-launch-1.0 -v filesrc location=videotestsrc.webm ! matroskademux ! av1dec ! videoconvert ! videoscale ! autovideosink
|
||||||
|
* ]|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "gstav1dec.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static GstStaticPadTemplate gst_av1_dec_sink_pad_template =
|
||||||
|
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
GST_PAD_SINK,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("video/x-av1")
|
||||||
|
);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate gst_av1_dec_src_pad_template =
|
||||||
|
GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
|
GST_PAD_SRC,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ I420, YV12, Y42B, Y444"
|
||||||
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||||
|
", I420_10LE, I420_12LE, I422_10LE, I422_12LE, Y444_10LE, Y444_12LE"
|
||||||
|
#else
|
||||||
|
", I420_10BE, I420_12BE, I422_10BE, I422_12BE, Y444_10BE, Y444_12BE"
|
||||||
|
#endif
|
||||||
|
" }"))
|
||||||
|
);
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (av1_dec_debug);
|
||||||
|
#define GST_CAT_DEFAULT av1_dec_debug
|
||||||
|
|
||||||
|
#define GST_VIDEO_FORMAT_WITH_ENDIAN(fmt,endian) GST_VIDEO_FORMAT_##fmt##endian
|
||||||
|
|
||||||
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||||
|
#define AOM_FMT_TO_GST(fmt) GST_VIDEO_FORMAT_WITH_ENDIAN(fmt,LE)
|
||||||
|
#else
|
||||||
|
#define AOM_FMT_TO_GST(fmt) GST_VIDEO_FORMAT_WITH_ENDIAN(fmt,BE)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void gst_av1_dec_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec);
|
||||||
|
static void gst_av1_dec_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec);
|
||||||
|
|
||||||
|
static gboolean gst_av1_dec_start (GstVideoDecoder * dec);
|
||||||
|
static gboolean gst_av1_dec_stop (GstVideoDecoder * dec);
|
||||||
|
static gboolean gst_av1_dec_set_format (GstVideoDecoder * dec,
|
||||||
|
GstVideoCodecState * state);
|
||||||
|
static gboolean gst_av1_dec_flush (GstVideoDecoder * dec);
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_av1_dec_handle_frame (GstVideoDecoder * decoder,
|
||||||
|
GstVideoCodecFrame * frame);
|
||||||
|
|
||||||
|
static void gst_av1_dec_image_to_buffer (GstAV1Dec * dec,
|
||||||
|
const aom_image_t * img, GstBuffer * buffer);
|
||||||
|
static GstFlowReturn gst_av1_dec_open_codec (GstAV1Dec * av1dec,
|
||||||
|
GstVideoCodecFrame * frame);
|
||||||
|
static gboolean gst_av1_dec_get_valid_format (GstAV1Dec * dec,
|
||||||
|
const aom_image_t * img, GstVideoFormat * fmt);
|
||||||
|
|
||||||
|
#define gst_av1_dec_parent_class parent_class
|
||||||
|
G_DEFINE_TYPE (GstAV1Dec, gst_av1_dec, GST_TYPE_VIDEO_DECODER);
|
||||||
|
GST_ELEMENT_REGISTER_DEFINE (av1dec, "av1dec", GST_RANK_PRIMARY,
|
||||||
|
GST_TYPE_AV1_DEC);
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_av1_dec_class_init (GstAV1DecClass * klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class;
|
||||||
|
GstElementClass *element_class;
|
||||||
|
GstVideoDecoderClass *vdec_class;
|
||||||
|
|
||||||
|
gobject_class = (GObjectClass *) klass;
|
||||||
|
element_class = (GstElementClass *) klass;
|
||||||
|
vdec_class = (GstVideoDecoderClass *) klass;
|
||||||
|
|
||||||
|
|
||||||
|
parent_class = g_type_class_peek_parent (klass);
|
||||||
|
|
||||||
|
gobject_class->set_property = gst_av1_dec_set_property;
|
||||||
|
gobject_class->get_property = gst_av1_dec_get_property;
|
||||||
|
|
||||||
|
gst_element_class_add_static_pad_template (element_class,
|
||||||
|
&gst_av1_dec_src_pad_template);
|
||||||
|
gst_element_class_add_static_pad_template (element_class,
|
||||||
|
&gst_av1_dec_sink_pad_template);
|
||||||
|
gst_element_class_set_static_metadata (element_class, "AV1 Decoder",
|
||||||
|
"Codec/Decoder/Video", "Decode AV1 video streams",
|
||||||
|
"Sean DuBois <sean@siobud.com>");
|
||||||
|
|
||||||
|
vdec_class->start = GST_DEBUG_FUNCPTR (gst_av1_dec_start);
|
||||||
|
vdec_class->stop = GST_DEBUG_FUNCPTR (gst_av1_dec_stop);
|
||||||
|
vdec_class->flush = GST_DEBUG_FUNCPTR (gst_av1_dec_flush);
|
||||||
|
|
||||||
|
vdec_class->set_format = GST_DEBUG_FUNCPTR (gst_av1_dec_set_format);
|
||||||
|
vdec_class->handle_frame = GST_DEBUG_FUNCPTR (gst_av1_dec_handle_frame);
|
||||||
|
|
||||||
|
klass->codec_algo = &aom_codec_av1_dx_algo;
|
||||||
|
GST_DEBUG_CATEGORY_INIT (av1_dec_debug, "av1dec", 0, "AV1 decoding element");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_av1_dec_init (GstAV1Dec * av1dec)
|
||||||
|
{
|
||||||
|
GstVideoDecoder *dec = (GstVideoDecoder *) av1dec;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (dec, "gst_av1_dec_init");
|
||||||
|
gst_video_decoder_set_packetized (dec, TRUE);
|
||||||
|
gst_video_decoder_set_needs_format (dec, TRUE);
|
||||||
|
gst_video_decoder_set_use_default_pad_acceptcaps (dec, TRUE);
|
||||||
|
GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_DECODER_SINK_PAD (dec));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_av1_dec_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
switch (prop_id) {
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_av1_dec_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
|
GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
switch (prop_id) {
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_av1_dec_start (GstVideoDecoder * dec)
|
||||||
|
{
|
||||||
|
GstAV1Dec *av1dec = GST_AV1_DEC_CAST (dec);
|
||||||
|
|
||||||
|
av1dec->decoder_inited = FALSE;
|
||||||
|
av1dec->output_state = NULL;
|
||||||
|
av1dec->input_state = NULL;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_av1_dec_stop (GstVideoDecoder * dec)
|
||||||
|
{
|
||||||
|
GstAV1Dec *av1dec = GST_AV1_DEC_CAST (dec);
|
||||||
|
|
||||||
|
if (av1dec->output_state) {
|
||||||
|
gst_video_codec_state_unref (av1dec->output_state);
|
||||||
|
av1dec->output_state = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (av1dec->input_state) {
|
||||||
|
gst_video_codec_state_unref (av1dec->input_state);
|
||||||
|
av1dec->input_state = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (av1dec->decoder_inited) {
|
||||||
|
aom_codec_destroy (&av1dec->decoder);
|
||||||
|
}
|
||||||
|
av1dec->decoder_inited = FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_av1_dec_set_format (GstVideoDecoder * dec, GstVideoCodecState * state)
|
||||||
|
{
|
||||||
|
GstAV1Dec *av1dec = GST_AV1_DEC_CAST (dec);
|
||||||
|
|
||||||
|
if (av1dec->decoder_inited) {
|
||||||
|
aom_codec_destroy (&av1dec->decoder);
|
||||||
|
}
|
||||||
|
av1dec->decoder_inited = FALSE;
|
||||||
|
|
||||||
|
if (av1dec->output_state) {
|
||||||
|
gst_video_codec_state_unref (av1dec->output_state);
|
||||||
|
av1dec->output_state = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (av1dec->input_state) {
|
||||||
|
gst_video_codec_state_unref (av1dec->input_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
av1dec->input_state = gst_video_codec_state_ref (state);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_av1_dec_flush (GstVideoDecoder * dec)
|
||||||
|
{
|
||||||
|
GstAV1Dec *av1dec = GST_AV1_DEC_CAST (dec);
|
||||||
|
|
||||||
|
if (av1dec->output_state) {
|
||||||
|
gst_video_codec_state_unref (av1dec->output_state);
|
||||||
|
av1dec->output_state = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (av1dec->decoder_inited) {
|
||||||
|
aom_codec_destroy (&av1dec->decoder);
|
||||||
|
}
|
||||||
|
av1dec->decoder_inited = FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_av1_dec_open_codec (GstAV1Dec * av1dec, GstVideoCodecFrame * frame)
|
||||||
|
{
|
||||||
|
aom_codec_err_t status;
|
||||||
|
GstAV1DecClass *av1class = GST_AV1_DEC_GET_CLASS (av1dec);
|
||||||
|
|
||||||
|
status = aom_codec_dec_init (&av1dec->decoder, av1class->codec_algo, NULL, 0);
|
||||||
|
if (status != AOM_CODEC_OK) {
|
||||||
|
GST_ELEMENT_ERROR (av1dec, LIBRARY, INIT,
|
||||||
|
("Failed to initialize AOM decoder"), ("%s", ""));
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
av1dec->decoder_inited = TRUE;
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_av1_dec_handle_resolution_change (GstAV1Dec * av1dec, aom_image_t * img,
|
||||||
|
GstVideoFormat fmt)
|
||||||
|
{
|
||||||
|
if (!av1dec->output_state ||
|
||||||
|
av1dec->output_state->info.finfo->format != fmt ||
|
||||||
|
av1dec->output_state->info.width != img->d_w ||
|
||||||
|
av1dec->output_state->info.height != img->d_h) {
|
||||||
|
|
||||||
|
if (av1dec->output_state)
|
||||||
|
gst_video_codec_state_unref (av1dec->output_state);
|
||||||
|
|
||||||
|
av1dec->output_state =
|
||||||
|
gst_video_decoder_set_output_state (GST_VIDEO_DECODER (av1dec),
|
||||||
|
fmt, img->d_w, img->d_h, av1dec->input_state);
|
||||||
|
gst_video_decoder_negotiate (GST_VIDEO_DECODER (av1dec));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_av1_dec_image_to_buffer (GstAV1Dec * dec, const aom_image_t * img,
|
||||||
|
GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
int deststride, srcstride, height, width, line, comp, y;
|
||||||
|
guint8 *dest, *src;
|
||||||
|
GstVideoFrame frame;
|
||||||
|
GstVideoInfo *info = &dec->output_state->info;
|
||||||
|
|
||||||
|
if (!gst_video_frame_map (&frame, info, buffer, GST_MAP_WRITE)) {
|
||||||
|
GST_ERROR_OBJECT (dec, "Could not map video buffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (comp = 0; comp < 3; comp++) {
|
||||||
|
dest = GST_VIDEO_FRAME_COMP_DATA (&frame, comp);
|
||||||
|
src = img->planes[comp];
|
||||||
|
width =
|
||||||
|
GST_VIDEO_FRAME_COMP_WIDTH (&frame,
|
||||||
|
comp) * GST_VIDEO_FRAME_COMP_PSTRIDE (&frame, comp);
|
||||||
|
height = GST_VIDEO_FRAME_COMP_HEIGHT (&frame, comp);
|
||||||
|
deststride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, comp);
|
||||||
|
srcstride = img->stride[comp];
|
||||||
|
|
||||||
|
if ((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) && img->bit_depth == 8) {
|
||||||
|
GST_TRACE_OBJECT (dec,
|
||||||
|
"HIGHBITDEPTH image with 8 bit_depth. Comp %d: %d != %d, copying "
|
||||||
|
"line by line.", comp, srcstride, deststride);
|
||||||
|
for (line = 0; line < height; line++) {
|
||||||
|
for (y = 0; y < width; y++) {
|
||||||
|
dest[y] = src[y * 2];
|
||||||
|
}
|
||||||
|
dest += deststride;
|
||||||
|
src += srcstride;
|
||||||
|
}
|
||||||
|
} else if (srcstride == deststride) {
|
||||||
|
GST_TRACE_OBJECT (dec, "Stride matches. Comp %d: %d, copying full plane",
|
||||||
|
comp, srcstride);
|
||||||
|
memcpy (dest, src, srcstride * height);
|
||||||
|
} else {
|
||||||
|
GST_TRACE_OBJECT (dec, "Stride mismatch. Comp %d: %d != %d, copying "
|
||||||
|
"line by line.", comp, srcstride, deststride);
|
||||||
|
for (line = 0; line < height; line++) {
|
||||||
|
memcpy (dest, src, width);
|
||||||
|
dest += deststride;
|
||||||
|
src += srcstride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_video_frame_unmap (&frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_av1_dec_get_valid_format (GstAV1Dec * dec, const aom_image_t * img,
|
||||||
|
GstVideoFormat * fmt)
|
||||||
|
{
|
||||||
|
switch (img->fmt) {
|
||||||
|
case AOM_IMG_FMT_I420:
|
||||||
|
case AOM_IMG_FMT_I42016:
|
||||||
|
if (img->bit_depth == 8) {
|
||||||
|
*fmt = img->monochrome ? GST_VIDEO_FORMAT_GRAY8 : GST_VIDEO_FORMAT_I420;
|
||||||
|
return TRUE;
|
||||||
|
} else if (img->bit_depth == 10) {
|
||||||
|
*fmt = AOM_FMT_TO_GST (I420_10);
|
||||||
|
return TRUE;
|
||||||
|
} else if (img->bit_depth == 12) {
|
||||||
|
*fmt = AOM_FMT_TO_GST (I420_12);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_FIXME_OBJECT (dec,
|
||||||
|
"Please add a 4:2:0 planar %u bit depth frame format",
|
||||||
|
img->bit_depth);
|
||||||
|
GST_ELEMENT_WARNING (dec, STREAM, NOT_IMPLEMENTED, (NULL),
|
||||||
|
("Unsupported frame format - 4:2:0 planar %u bit depth",
|
||||||
|
img->bit_depth));
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
case AOM_IMG_FMT_I422:
|
||||||
|
case AOM_IMG_FMT_I42216:
|
||||||
|
if (img->bit_depth == 8) {
|
||||||
|
*fmt = GST_VIDEO_FORMAT_Y42B;
|
||||||
|
return TRUE;
|
||||||
|
} else if (img->bit_depth == 10) {
|
||||||
|
*fmt = AOM_FMT_TO_GST (I422_10);
|
||||||
|
return TRUE;
|
||||||
|
} else if (img->bit_depth == 12) {
|
||||||
|
*fmt = AOM_FMT_TO_GST (I422_12);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
GST_FIXME_OBJECT (dec,
|
||||||
|
"Please add a 4:2:2 planar %u bit depth frame format",
|
||||||
|
img->bit_depth);
|
||||||
|
GST_ELEMENT_WARNING (dec, STREAM, NOT_IMPLEMENTED, (NULL),
|
||||||
|
("Unsupported frame format - 4:2:2 planar %u bit depth",
|
||||||
|
img->bit_depth));
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
case AOM_IMG_FMT_I444:
|
||||||
|
case AOM_IMG_FMT_I44416:
|
||||||
|
if (img->bit_depth == 8) {
|
||||||
|
*fmt = GST_VIDEO_FORMAT_Y444;
|
||||||
|
return TRUE;
|
||||||
|
} else if (img->bit_depth == 10) {
|
||||||
|
*fmt = AOM_FMT_TO_GST (Y444_10);
|
||||||
|
return TRUE;
|
||||||
|
} else if (img->bit_depth == 12) {
|
||||||
|
*fmt = AOM_FMT_TO_GST (Y444_12);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
GST_FIXME_OBJECT (dec,
|
||||||
|
"Please add a 4:4:4 planar %u bit depth frame format",
|
||||||
|
img->bit_depth);
|
||||||
|
GST_ELEMENT_WARNING (dec, STREAM, NOT_IMPLEMENTED, (NULL),
|
||||||
|
("Unsupported frame format - 4:4:4 planar %u bit depth",
|
||||||
|
img->bit_depth));
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
case AOM_IMG_FMT_YV12:
|
||||||
|
*fmt = GST_VIDEO_FORMAT_YV12;
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_av1_dec_handle_frame (GstVideoDecoder * dec, GstVideoCodecFrame * frame)
|
||||||
|
{
|
||||||
|
GstAV1Dec *av1dec = GST_AV1_DEC_CAST (dec);
|
||||||
|
GstFlowReturn ret;
|
||||||
|
GstMapInfo minfo;
|
||||||
|
aom_codec_err_t status;
|
||||||
|
aom_image_t *img;
|
||||||
|
aom_codec_iter_t iter = NULL;
|
||||||
|
GstVideoFormat fmt;
|
||||||
|
|
||||||
|
if (!av1dec->decoder_inited) {
|
||||||
|
ret = gst_av1_dec_open_codec (av1dec, frame);
|
||||||
|
if (ret == GST_FLOW_CUSTOM_SUCCESS_1) {
|
||||||
|
gst_video_decoder_drop_frame (dec, frame);
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
} else if (ret != GST_FLOW_OK) {
|
||||||
|
gst_video_codec_frame_unref (frame);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gst_buffer_map (frame->input_buffer, &minfo, GST_MAP_READ)) {
|
||||||
|
GST_ERROR_OBJECT (dec, "Failed to map input buffer");
|
||||||
|
gst_video_codec_frame_unref (frame);
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = aom_codec_decode (&av1dec->decoder, minfo.data, minfo.size, NULL);
|
||||||
|
|
||||||
|
gst_buffer_unmap (frame->input_buffer, &minfo);
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
GST_ELEMENT_ERROR (av1dec, LIBRARY, INIT,
|
||||||
|
("Failed to decode frame"), ("%s", ""));
|
||||||
|
gst_video_codec_frame_unref (frame);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
img = aom_codec_get_frame (&av1dec->decoder, &iter);
|
||||||
|
if (img) {
|
||||||
|
if (gst_av1_dec_get_valid_format (av1dec, img, &fmt) == FALSE) {
|
||||||
|
aom_img_free (img);
|
||||||
|
GST_ELEMENT_ERROR (dec, LIBRARY, ENCODE,
|
||||||
|
("Failed to decode frame"), ("Unsupported color format %d",
|
||||||
|
img->fmt));
|
||||||
|
gst_video_codec_frame_unref (frame);
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_av1_dec_handle_resolution_change (av1dec, img, fmt);
|
||||||
|
|
||||||
|
ret = gst_video_decoder_allocate_output_frame (dec, frame);
|
||||||
|
if (ret == GST_FLOW_OK) {
|
||||||
|
gst_av1_dec_image_to_buffer (av1dec, img, frame->output_buffer);
|
||||||
|
ret = gst_video_decoder_finish_frame (dec, frame);
|
||||||
|
} else {
|
||||||
|
gst_video_decoder_drop_frame (dec, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
aom_img_free (img);
|
||||||
|
while ((img = aom_codec_get_frame (&av1dec->decoder, &iter))) {
|
||||||
|
GST_WARNING_OBJECT (dec, "Multiple decoded frames... dropping");
|
||||||
|
aom_img_free (img);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GST_VIDEO_CODEC_FRAME_SET_DECODE_ONLY (frame);
|
||||||
|
gst_video_decoder_finish_frame (dec, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
74
ext/aom/gstav1dec.h
Normal file
74
ext/aom/gstav1dec.h
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <2017> Sean DuBois <sean@siobud.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GST_AV1_DEC_H__
|
||||||
|
#define __GST_AV1_DEC_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/video/gstvideodecoder.h>
|
||||||
|
|
||||||
|
#include <aom/aomdx.h>
|
||||||
|
#include <aom/aom_decoder.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
#define GST_TYPE_AV1_DEC \
|
||||||
|
(gst_av1_dec_get_type())
|
||||||
|
#define GST_AV1_DEC(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AV1_DEC,GstAV1Dec))
|
||||||
|
#define GST_AV1_DEC_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AV1_DEC,GstAV1DecClass))
|
||||||
|
#define GST_IS_AV1_DEC(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AV1_DEC))
|
||||||
|
#define GST_IS_AV1_DEC_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AV1_DEC))
|
||||||
|
#define GST_AV1_DEC_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AV1_DEC, GstAV1DecClass))
|
||||||
|
#define GST_AV1_DEC_CAST(obj) \
|
||||||
|
((GstAV1Dec *) (obj))
|
||||||
|
|
||||||
|
typedef struct _GstAV1Dec GstAV1Dec;
|
||||||
|
typedef struct _GstAV1DecClass GstAV1DecClass;
|
||||||
|
|
||||||
|
struct _GstAV1Dec
|
||||||
|
{
|
||||||
|
GstVideoDecoder base_video_decoder;
|
||||||
|
|
||||||
|
gboolean decoder_inited;
|
||||||
|
|
||||||
|
aom_codec_ctx_t decoder;
|
||||||
|
|
||||||
|
GstVideoCodecState *input_state;
|
||||||
|
GstVideoCodecState *output_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstAV1DecClass
|
||||||
|
{
|
||||||
|
GstVideoDecoderClass parent_class;
|
||||||
|
/*supported aom algo*/
|
||||||
|
aom_codec_iface_t* codec_algo;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_av1_dec_get_type (void);
|
||||||
|
|
||||||
|
GST_ELEMENT_REGISTER_DECLARE (av1dec);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
#endif /* __GST_AV1_DEC_H__ */
|
1111
ext/aom/gstav1enc.c
Normal file
1111
ext/aom/gstav1enc.c
Normal file
File diff suppressed because it is too large
Load diff
141
ext/aom/gstav1enc.h
Normal file
141
ext/aom/gstav1enc.h
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <2017> Sean DuBois <sean@siobud.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GST_AV1_ENC_H__
|
||||||
|
#define __GST_AV1_ENC_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/video/video.h>
|
||||||
|
#include <gst/video/gstvideoencoder.h>
|
||||||
|
|
||||||
|
#include <aom/aom_codec.h>
|
||||||
|
#include <aom/aom_encoder.h>
|
||||||
|
#include <aom/aomcx.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
#define GST_TYPE_AV1_ENC \
|
||||||
|
(gst_av1_enc_get_type())
|
||||||
|
#define GST_AV1_ENC(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AV1_ENC,GstAV1Enc))
|
||||||
|
#define GST_AV1_ENC_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AV1_ENC,GstAV1EncClass))
|
||||||
|
#define GST_IS_AV1_ENC(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AV1_ENC))
|
||||||
|
#define GST_IS_AV1_ENC_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AV1_ENC))
|
||||||
|
#define GST_AV1_ENC_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AV1_ENC, GstAV1EncClass))
|
||||||
|
#define GST_AV1_ENC_CAST(obj) \
|
||||||
|
((GstAV1Enc *) (obj))
|
||||||
|
|
||||||
|
typedef struct _GstAV1Enc GstAV1Enc;
|
||||||
|
typedef struct _GstAV1EncClass GstAV1EncClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstAV1EncResizeMode:
|
||||||
|
* @GST_AV1_ENC_RESIZE_NONE: No frame resizing allowed
|
||||||
|
* @GST_AV1_ENC_RESIZE_FIXED: All frames are coded at the specified scale
|
||||||
|
* @GST_AV1_ENC_RESIZE_RANDOM: All frames are coded at a random scale
|
||||||
|
*
|
||||||
|
* Frame resize mode
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GST_AV1_ENC_RESIZE_NONE = 0,
|
||||||
|
GST_AV1_ENC_RESIZE_FIXED = 1,
|
||||||
|
GST_AV1_ENC_RESIZE_RANDOM = 2,
|
||||||
|
GST_AV1_ENC_RESIZE_MODES
|
||||||
|
} GstAV1EncResizeMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstAV1EncSuperresMode
|
||||||
|
* @GST_AV1_ENC_SUPERRES_NONE: No frame superres allowed
|
||||||
|
* @GST_AV1_ENC_SUPERRES_FIXED: All frames are coded at the specified scale and
|
||||||
|
* super-resolved
|
||||||
|
* @GST_AV1_ENC_SUPERRES_QTHRESH: Superres scale for a frame is determined based
|
||||||
|
* on q_index
|
||||||
|
*
|
||||||
|
* Frame super-resolution mode
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GST_AV1_ENC_SUPERRES_NONE = 0,
|
||||||
|
GST_AV1_ENC_SUPERRES_FIXED = 1,
|
||||||
|
GST_AV1_ENC_SUPERRES_RANDOM = 2,
|
||||||
|
GST_AV1_ENC_SUPERRES_QTHRESH = 3,
|
||||||
|
GST_AV1_ENC_SUPERRES_MODES
|
||||||
|
} GstAV1EncSuperresMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstAV1EncEndUsageMode
|
||||||
|
* @GST_AV1_ENC_END_USAGE_VBR: Variable Bit Rate Mode
|
||||||
|
* @GST_AV1_ENC_END_USAGE_CBR: Constant Bit Rate Mode
|
||||||
|
* @GST_AV1_ENC_END_USAGE_CQ: Constrained Quality Mode
|
||||||
|
* @GST_AV1_ENC_END_USAGE_Q: Constant Quality Mode
|
||||||
|
*
|
||||||
|
* Rate control algorithm to use
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GST_AV1_ENC_END_USAGE_VBR = 0,
|
||||||
|
GST_AV1_ENC_END_USAGE_CBR = 1,
|
||||||
|
GST_AV1_ENC_END_USAGE_CQ = 2,
|
||||||
|
GST_AV1_ENC_END_USAGE_Q = 3,
|
||||||
|
GST_AV1_ENC_END_USAGE_MODES
|
||||||
|
} GstAV1EncEndUsageMode;
|
||||||
|
|
||||||
|
struct _GstAV1Enc
|
||||||
|
{
|
||||||
|
GstVideoEncoder base_video_encoder;
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
guint keyframe_dist;
|
||||||
|
gint cpu_used;
|
||||||
|
gint threads;
|
||||||
|
gboolean row_mt;
|
||||||
|
guint tile_columns;
|
||||||
|
guint tile_rows;
|
||||||
|
|
||||||
|
/* state */
|
||||||
|
gboolean encoder_inited;
|
||||||
|
GstVideoCodecState *input_state;
|
||||||
|
aom_codec_enc_cfg_t aom_cfg;
|
||||||
|
aom_codec_ctx_t encoder;
|
||||||
|
aom_img_fmt_t format;
|
||||||
|
GMutex encoder_lock;
|
||||||
|
|
||||||
|
gboolean target_bitrate_set;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstAV1EncClass
|
||||||
|
{
|
||||||
|
GstVideoEncoderClass parent_class;
|
||||||
|
/*supported aom algo*/
|
||||||
|
aom_codec_iface_t *codec_algo;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_av1_enc_get_type (void);
|
||||||
|
|
||||||
|
GST_ELEMENT_REGISTER_DECLARE (av1enc);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
#endif /* __GST_AV1_ENC_H__ */
|
77
ext/aom/gstav1utils.c
Normal file
77
ext/aom/gstav1utils.c
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/* AV1
|
||||||
|
* Copyright (C) 2018 Wonchul Lee <chul0812@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "gstav1utils.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
enum aom_img_fmt aom_format;
|
||||||
|
GstVideoFormat gst_format;
|
||||||
|
} AomImageFormat;
|
||||||
|
|
||||||
|
static const AomImageFormat img_formats[] = {
|
||||||
|
{AOM_IMG_FMT_YV12, GST_VIDEO_FORMAT_YV12},
|
||||||
|
{AOM_IMG_FMT_I420, GST_VIDEO_FORMAT_I420},
|
||||||
|
{AOM_IMG_FMT_I422, GST_VIDEO_FORMAT_Y42B},
|
||||||
|
{AOM_IMG_FMT_I444, GST_VIDEO_FORMAT_Y444},
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gst_av1_get_error_name (aom_codec_err_t status)
|
||||||
|
{
|
||||||
|
switch (status) {
|
||||||
|
case AOM_CODEC_OK:
|
||||||
|
return "OK";
|
||||||
|
case AOM_CODEC_ERROR:
|
||||||
|
return "error";
|
||||||
|
case AOM_CODEC_MEM_ERROR:
|
||||||
|
return "mem error";
|
||||||
|
case AOM_CODEC_ABI_MISMATCH:
|
||||||
|
return "abi mismatch";
|
||||||
|
case AOM_CODEC_INCAPABLE:
|
||||||
|
return "incapable";
|
||||||
|
case AOM_CODEC_UNSUP_BITSTREAM:
|
||||||
|
return "unsupported bitstream";
|
||||||
|
case AOM_CODEC_UNSUP_FEATURE:
|
||||||
|
return "unsupported feature";
|
||||||
|
case AOM_CODEC_CORRUPT_FRAME:
|
||||||
|
return "corrupt frame";
|
||||||
|
case AOM_CODEC_INVALID_PARAM:
|
||||||
|
return "invalid parameter";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
gst_video_format_to_av1_img_format (GstVideoFormat format)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (img_formats); i++)
|
||||||
|
if (img_formats[i].gst_format == format)
|
||||||
|
return img_formats[i].aom_format;
|
||||||
|
|
||||||
|
GST_WARNING ("av1 img format not found");
|
||||||
|
return -1;
|
||||||
|
}
|
30
ext/aom/gstav1utils.h
Normal file
30
ext/aom/gstav1utils.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/* AV1
|
||||||
|
* Copyright (C) 2018 Wonchul Lee <chul0812@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/video/video.h>
|
||||||
|
#include <aom/aom_codec.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
const char *gst_av1_get_error_name (aom_codec_err_t status);
|
||||||
|
gint gst_video_format_to_av1_img_format (GstVideoFormat format);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
13
ext/aom/meson.build
Normal file
13
ext/aom/meson.build
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
aom_dep = dependency('aom', required: get_option('aom'))
|
||||||
|
if aom_dep.found()
|
||||||
|
gstaom = library('gstaom',
|
||||||
|
['gstaom.c', 'gstav1enc.c', 'gstav1dec.c', 'gstav1utils.c'],
|
||||||
|
c_args : gst_plugins_bad_args,
|
||||||
|
include_directories : [configinc],
|
||||||
|
dependencies : [gstpbutils_dep, gstvideo_dep, aom_dep],
|
||||||
|
install : true,
|
||||||
|
install_dir : plugins_install_dir,
|
||||||
|
)
|
||||||
|
pkgconfig.generate(gstaom, install_dir : plugins_pkgconfig_install_dir)
|
||||||
|
plugins += [gstaom]
|
||||||
|
endif
|
1890
ext/assrender/gstassrender.c
Normal file
1890
ext/assrender/gstassrender.c
Normal file
File diff suppressed because it is too large
Load diff
101
ext/assrender/gstassrender.h
Normal file
101
ext/assrender/gstassrender.h
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008 Benjamin Schmitz <vortex@wolpzone.de>
|
||||||
|
* Copyright (c) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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 Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public License
|
||||||
|
* along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GST_ASS_RENDER_H__
|
||||||
|
#define __GST_ASS_RENDER_H__
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/video/video.h>
|
||||||
|
#include <gst/video/video-overlay-composition.h>
|
||||||
|
|
||||||
|
#include <ass/ass.h>
|
||||||
|
#include <ass/ass_types.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#if !defined(LIBASS_VERSION) || LIBASS_VERSION < 0x00907010
|
||||||
|
#define ASS_Library ass_library_t
|
||||||
|
#define ASS_Renderer ass_renderer_t
|
||||||
|
#define ASS_Track ass_track_t
|
||||||
|
#define ASS_Image ass_image_t
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define GST_TYPE_ASS_RENDER (gst_ass_render_get_type())
|
||||||
|
#define GST_ASS_RENDER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ASS_RENDER,GstAssRender))
|
||||||
|
#define GST_ASS_RENDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ASS_RENDER,GstAssRenderClass))
|
||||||
|
#define GST_ASS_RENDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||||
|
GST_TYPE_ASS_RENDER, GstAssRenderClass))
|
||||||
|
#define GST_IS_ASS_RENDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ASS_RENDER))
|
||||||
|
#define GST_IS_ASS_RENDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ASS_RENDER))
|
||||||
|
|
||||||
|
typedef struct _GstAssRender GstAssRender;
|
||||||
|
typedef struct _GstAssRenderClass GstAssRenderClass;
|
||||||
|
|
||||||
|
struct _GstAssRender
|
||||||
|
{
|
||||||
|
GstElement element;
|
||||||
|
|
||||||
|
GstPad *video_sinkpad, *text_sinkpad, *srcpad;
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
gboolean enable, embeddedfonts;
|
||||||
|
gboolean wait_text;
|
||||||
|
|
||||||
|
/* <private> */
|
||||||
|
GMutex lock;
|
||||||
|
GCond cond;
|
||||||
|
|
||||||
|
GstSegment video_segment;
|
||||||
|
gboolean video_flushing;
|
||||||
|
gboolean video_eos;
|
||||||
|
|
||||||
|
GstVideoInfo info;
|
||||||
|
|
||||||
|
GSList *subtitle_pending;
|
||||||
|
gboolean subtitle_flushing;
|
||||||
|
gboolean subtitle_eos;
|
||||||
|
GstSegment subtitle_segment;
|
||||||
|
|
||||||
|
GMutex ass_mutex;
|
||||||
|
ASS_Library *ass_library;
|
||||||
|
ASS_Renderer *ass_renderer;
|
||||||
|
ASS_Track *ass_track;
|
||||||
|
gint ass_frame_width, ass_frame_height;
|
||||||
|
|
||||||
|
gboolean renderer_init_ok, track_init_ok;
|
||||||
|
gboolean need_process;
|
||||||
|
|
||||||
|
/* overlay stuff */
|
||||||
|
GstVideoOverlayComposition *composition;
|
||||||
|
guint window_width, window_height;
|
||||||
|
gboolean attach_compo_to_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstAssRenderClass
|
||||||
|
{
|
||||||
|
GstElementClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_ass_render_get_type (void);
|
||||||
|
|
||||||
|
GST_ELEMENT_REGISTER_DECLARE (assrender);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
14
ext/assrender/meson.build
Normal file
14
ext/assrender/meson.build
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
ass_dep = dependency('libass', version : '>= 0.10.2', required : get_option('assrender'))
|
||||||
|
if ass_dep.found()
|
||||||
|
gstassrender = library('gstassrender',
|
||||||
|
'gstassrender.c',
|
||||||
|
c_args : gst_plugins_bad_args,
|
||||||
|
link_args : noseh_link_args,
|
||||||
|
include_directories : [configinc],
|
||||||
|
dependencies : [gstvideo_dep, ass_dep],
|
||||||
|
install : true,
|
||||||
|
install_dir : plugins_install_dir,
|
||||||
|
)
|
||||||
|
pkgconfig.generate(gstassrender, install_dir : plugins_pkgconfig_install_dir)
|
||||||
|
plugins += [gstassrender]
|
||||||
|
endif
|
268
ext/avtp/gstavtp.c
Normal file
268
ext/avtp/gstavtp.c
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
/*
|
||||||
|
* GStreamer AVTP Plugin
|
||||||
|
* Copyright (C) 2019 Intel Corporation
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* plugin-avtp:
|
||||||
|
*
|
||||||
|
* ## Audio Video Transport Protocol (AVTP) Plugin
|
||||||
|
*
|
||||||
|
* The AVTP plugin implements typical Talker and Listener functionalities that
|
||||||
|
* can be leveraged by GStreamer-based applications in order to implement TSN
|
||||||
|
* audio/video applications.
|
||||||
|
*
|
||||||
|
* ### Dependencies
|
||||||
|
*
|
||||||
|
* The plugin uses libavtp to handle AVTP packetization. Libavtp source code can
|
||||||
|
* be found in https://github.com/AVnu/libavtp as well as instructions to build
|
||||||
|
* and install it.
|
||||||
|
*
|
||||||
|
* If libavtp isn't detected by configure, the plugin isn't built.
|
||||||
|
*
|
||||||
|
* ### The application/x-avtp mime type
|
||||||
|
*
|
||||||
|
* For valid AVTPDUs encapsulated in GstBuffers, we use the caps with mime type
|
||||||
|
* application/x-avtp.
|
||||||
|
*
|
||||||
|
* AVTP mime type is pretty simple and has no fields.
|
||||||
|
*
|
||||||
|
* ### gPTP Setup
|
||||||
|
*
|
||||||
|
* The Linuxptp project provides the ptp4l daemon, which synchronizes the PTP
|
||||||
|
* clock from NIC, and the pmc tool which communicates with ptp4l to get/set
|
||||||
|
* some runtime settings. The project also provides the phc2sys daemon which
|
||||||
|
* synchronizes the PTP clock and system clock.
|
||||||
|
*
|
||||||
|
* The AVTP plugin requires system clock is synchronized with PTP clock and
|
||||||
|
* TAI offset is properly set in the kernel. ptp4l and phc2sys can be set up
|
||||||
|
* in many different ways, below we provide an example that fullfils the plugin
|
||||||
|
* requirements. For further information check ptp4l(8) and phc2sys(8).
|
||||||
|
*
|
||||||
|
* In the following instructions, replace $IFNAME by your PTP capable NIC
|
||||||
|
* interface. The gPTP.cfg file mentioned below can be found in /usr/share/
|
||||||
|
* doc/linuxptp/ (depending on your distro).
|
||||||
|
*
|
||||||
|
* Synchronize PTP clock with PTP time:
|
||||||
|
*
|
||||||
|
* $ ptp4l -f gPTP.cfg -i $IFNAME
|
||||||
|
*
|
||||||
|
* Enable TAI offset to be automatically set by phc2sys:
|
||||||
|
*
|
||||||
|
* $ pmc -u -t 1 -b 0 'SET GRANDMASTER_SETTINGS_NP \
|
||||||
|
* clockClass 248 clockAccuracy 0xfe \
|
||||||
|
* offsetScaledLogVariance 0xffff \
|
||||||
|
* currentUtcOffset 37 leap61 0 leap59 0 \
|
||||||
|
* currentUtcOffsetValid 1 ptpTimescale 1 \
|
||||||
|
* timeTraceable 1 frequencyTraceable 0 timeSource 0xa0'
|
||||||
|
*
|
||||||
|
* Synchronize system clock with PTP clock:
|
||||||
|
*
|
||||||
|
* $ phc2sys -f gPTP.cfg -s $IFNAME -c CLOCK_REALTIME -w
|
||||||
|
*
|
||||||
|
* The commands above should be run on both AVTP Talker and Listener hosts.
|
||||||
|
*
|
||||||
|
* With clocks properly synchronized, applications using the AVTP plugin
|
||||||
|
* should use GstSytemClock with GST_CLOCK_TYPE_REALTIME as the pipeline
|
||||||
|
* clock.
|
||||||
|
*
|
||||||
|
* ### Clock Reference Format (CRF)
|
||||||
|
*
|
||||||
|
* Even though the systems are synchronized by PTP, it is possible that
|
||||||
|
* different talkers can send media streams which are out of phase or the
|
||||||
|
* frequencies do not exactly match. This is partcularly important when there
|
||||||
|
* is a single listener processing data from multiple talkers. The systems in
|
||||||
|
* this scenario can benefit if a common clock is distributed among the
|
||||||
|
* systems.
|
||||||
|
*
|
||||||
|
* This can be achieved by using the avtpcrfsync element which implements CRF
|
||||||
|
* as described in Chapter 10 of IEEE 1722-2016. avtpcrfcheck can also be used
|
||||||
|
* to validate that the adjustment conforms to the criteria specified in the
|
||||||
|
* spec. For further details, look at the documentation for the respective
|
||||||
|
* elements.
|
||||||
|
*
|
||||||
|
* ### Traffic Control Setup
|
||||||
|
*
|
||||||
|
* FQTSS (Forwarding and Queuing Enhancements for Time-Sensitive Streams) can be
|
||||||
|
* enabled on Linux with the help of the mqprio and cbs qdiscs provided by the
|
||||||
|
* Linux Traffic Control. Below we provide an example to configure those qdiscs
|
||||||
|
* in order to transmit a CVF H.264 stream 1280x720@30fps. For further
|
||||||
|
* information on how to configure these qdiscs check tc-mqprio(8) and
|
||||||
|
* tc-cbs(8) man pages.
|
||||||
|
*
|
||||||
|
* On the host that will run as AVTP Talker (pipeline that generates the video
|
||||||
|
* stream), run the following commands:
|
||||||
|
*
|
||||||
|
* Configure mpqrio qdisc (replace $MQPRIO_HANDLE_ID by an unused handle ID):
|
||||||
|
*
|
||||||
|
* $ tc qdisc add dev $IFNAME parent root handle $MQPRIO_HANDLE_ID mqprio \
|
||||||
|
* num_tc 3 map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 \
|
||||||
|
* queues 1@0 1@1 2@2 hw 0
|
||||||
|
*
|
||||||
|
* Configure cbs qdisc (replace $CBS_HANDLE_ID by an unused handle ID):
|
||||||
|
*
|
||||||
|
* $ tc qdisc replace dev $IFNAME parent $MQPRIO_HANDLE_ID:1 \
|
||||||
|
* handle $CBS_HANDLE_ID cbs idleslope 27756 sendslope -972244 \
|
||||||
|
* hicredit 42 locredit -1499 offload 1
|
||||||
|
*
|
||||||
|
* Also, the plugin implements a transmission scheduling mechanism that relies
|
||||||
|
* on ETF qdisc so make sure it is properly configured in your system. It could
|
||||||
|
* be configured in many ways, below follows an example.
|
||||||
|
*
|
||||||
|
* $ tc qdisc add dev $IFNAME parent $CBS_HANDLE_ID:1 etf \
|
||||||
|
* clockid CLOCK_TAI delta 500000 offload
|
||||||
|
*
|
||||||
|
* No Traffic Control configuration is required at the host running as AVTP
|
||||||
|
* Listener.
|
||||||
|
*
|
||||||
|
* ### Capabilities
|
||||||
|
*
|
||||||
|
* The `avtpsink` and `avtpsrc` elements open `AF_PACKET` sockets, which require
|
||||||
|
* `CAP_NET_RAW` capability. Also, `avtpsink` needs `CAP_NET_ADMIN` to use ETF.
|
||||||
|
* Therefore, applications must have those capabilities in order to successfully
|
||||||
|
* use these elements. For instance, one can use:
|
||||||
|
*
|
||||||
|
* $ sudo setcap cap_net_raw,cap_net_admin+ep <application>
|
||||||
|
*
|
||||||
|
* Applications can drop these capabilities after the sockets are open, after
|
||||||
|
* `avtpsrc` or `avtpsink` elements transition to PAUSED state. See setcap(8)
|
||||||
|
* man page for more information.
|
||||||
|
*
|
||||||
|
* ### Elements configuration
|
||||||
|
*
|
||||||
|
* Each element has its own configuration properties, with some being common
|
||||||
|
* to several elements. Basic properties are:
|
||||||
|
*
|
||||||
|
* * streamid (avtpaafpay, avtpcvfpay, avtpaafdepay, avtpcvfdepay,
|
||||||
|
* avtpcrfsync, avtpcrfcheck): Stream ID associated with the stream.
|
||||||
|
*
|
||||||
|
* * ifname (avtpsink, avtpsrc, avtpcrfsync, avtpcrfcheck): Network interface
|
||||||
|
* used to send/receive AVTP packets.
|
||||||
|
*
|
||||||
|
* * dst-macaddr (avtpsink, avtpsrc): Destination MAC address for the stream.
|
||||||
|
*
|
||||||
|
* * priority (avtpsink): Priority used by the plugin to transmit AVTP
|
||||||
|
* traffic.
|
||||||
|
*
|
||||||
|
* * mtt (avtpaafpay, avtpcvfpay): Maximum Transit Time, in nanoseconds, as
|
||||||
|
* defined in AVTP spec.
|
||||||
|
*
|
||||||
|
* * tu (avtpaafpay, avtpcvfpay): Maximum Time Uncertainty, in nanoseconds, as
|
||||||
|
* defined in AVTP spec.
|
||||||
|
*
|
||||||
|
* * processing-deadline (avtpaafpay, avtpcvfpay, avtpsink): Maximum amount of
|
||||||
|
* time, in nanoseconds, that the pipeline is expected to process any
|
||||||
|
* buffer. This value should be in sync between the one used on the
|
||||||
|
* payloader and the sink, as this time is also taken into consideration to
|
||||||
|
* define the correct presentation time of the packets on the AVTP listener
|
||||||
|
* side. It should be as low as possible (zero if possible).
|
||||||
|
*
|
||||||
|
* * timestamp-mode (avtpaafpay): AAF timestamping mode, as defined in AVTP spec.
|
||||||
|
*
|
||||||
|
* * mtu (avtpcvfpay): Maximum Transmit Unit of the underlying network, used
|
||||||
|
* to determine when to fragment a CVF packet and how big it should be.
|
||||||
|
*
|
||||||
|
* Check each element documentation for more details.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* ### Running a sample pipeline
|
||||||
|
*
|
||||||
|
* The following pipelines uses debugutilsbad "clockselect" element to force
|
||||||
|
* the pipeline clock to be GstPtpClock. A real application would
|
||||||
|
* programmatically define GstPtpClock as the pipeline clock (see next section).
|
||||||
|
* It is also assumes that `gst-launch-1.0` has CAP_NET_RAW and CAP_NET_ADMIN
|
||||||
|
* capabilities.
|
||||||
|
*
|
||||||
|
* On the AVTP talker, the following pipeline can be used to generate an H.264
|
||||||
|
* stream to be sent via network using AVTP:
|
||||||
|
*
|
||||||
|
* $ gst-launch-1.0 clockselect. \( clockid=ptp \
|
||||||
|
* videotestsrc is-live=true ! clockoverlay ! x264enc ! \
|
||||||
|
* avtpcvfpay processing-deadline=20000000 ! \
|
||||||
|
* avtpcrfsync ifname=$IFNAME ! avtpsink ifname=$IFNAME \)
|
||||||
|
*
|
||||||
|
* On the AVTP listener host, the following pipeline can be used to get the
|
||||||
|
* AVTP stream, depacketize it and show it on the screen:
|
||||||
|
*
|
||||||
|
* $ gst-launch-1.0 clockselect. \( clockid=ptp avtpsrc ifname=$IFNAME ! \
|
||||||
|
* avtpcrfcheck ifname=$IFNAME ! avtpcvfdepay ! \
|
||||||
|
* vaapih264dec ! videoconvert ! clockoverlay halignment=right ! \
|
||||||
|
* queue ! autovideosink \)
|
||||||
|
*
|
||||||
|
* ### Pipeline clock
|
||||||
|
*
|
||||||
|
* The AVTP plugin elements require that the pipeline clock is in sync with
|
||||||
|
* the network PTP clock. As GStreamer has a GstPtpClock, using it should be
|
||||||
|
* the simplest way of achieving that.
|
||||||
|
*
|
||||||
|
* However, as there's no way of forcing a clock to a pipeline using
|
||||||
|
* gst-launch-1.0 application, even for quick tests, it's necessary to have
|
||||||
|
* an application. One can refer to GStreamer "hello world" application,
|
||||||
|
* remembering to set the pipeline clock to GstPtpClock before putting the
|
||||||
|
* pipeline on "PLAYING" state. Some code like:
|
||||||
|
*
|
||||||
|
* GstClock *clk = gst_ptp_clock_new("ptp-clock", 0);
|
||||||
|
* gst_clock_wait_for_sync(clk, GST_CLOCK_TIME_NONE);
|
||||||
|
* gst_pipeline_use_clock (GST_PIPELINE (pipeline), clk);
|
||||||
|
*
|
||||||
|
* Would do the trick.
|
||||||
|
*
|
||||||
|
* ### Disclaimer
|
||||||
|
*
|
||||||
|
* It's out of scope for the AVTP plugin to verify how it is invoked, should
|
||||||
|
* a malicious software do it for Denial of Service attempts, or other
|
||||||
|
* compromises attempts.
|
||||||
|
*
|
||||||
|
* Since: 1.18
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
#include "gstavtpaafdepay.h"
|
||||||
|
#include "gstavtpaafpay.h"
|
||||||
|
#include "gstavtpcvfdepay.h"
|
||||||
|
#include "gstavtpcvfpay.h"
|
||||||
|
#include "gstavtpsink.h"
|
||||||
|
#include "gstavtpsrc.h"
|
||||||
|
#include "gstavtpcrfsync.h"
|
||||||
|
#include "gstavtpcrfcheck.h"
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
plugin_init (GstPlugin * plugin)
|
||||||
|
{
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
|
ret |= GST_ELEMENT_REGISTER (avtpaafpay, plugin);
|
||||||
|
ret |= GST_ELEMENT_REGISTER (avtpaafdepay, plugin);
|
||||||
|
ret |= GST_ELEMENT_REGISTER (avtpsink, plugin);
|
||||||
|
ret |= GST_ELEMENT_REGISTER (avtpsrc, plugin);
|
||||||
|
ret |= GST_ELEMENT_REGISTER (avtpcvfpay, plugin);
|
||||||
|
ret |= GST_ELEMENT_REGISTER (avtpcvfdepay, plugin);
|
||||||
|
ret |= GST_ELEMENT_REGISTER (avtpcrfsync, plugin);
|
||||||
|
ret |= GST_ELEMENT_REGISTER (avtpcrfcheck, plugin);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
|
||||||
|
avtp, "Audio/Video Transport Protocol (AVTP) plugin",
|
||||||
|
plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
|
321
ext/avtp/gstavtpaafdepay.c
Normal file
321
ext/avtp/gstavtpaafdepay.c
Normal file
|
@ -0,0 +1,321 @@
|
||||||
|
/*
|
||||||
|
* GStreamer AVTP Plugin
|
||||||
|
* Copyright (C) 2019 Intel Corporation
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:element-avtpaafdepay
|
||||||
|
* @see_also: avtpaafpay
|
||||||
|
*
|
||||||
|
* Extract raw audio from AVTPDUs according to IEEE 1722-2016. For detailed
|
||||||
|
* information see https://standards.ieee.org/standard/1722-2016.html.
|
||||||
|
*
|
||||||
|
* <refsect2>
|
||||||
|
* <title>Example pipeline</title>
|
||||||
|
* |[
|
||||||
|
* gst-launch-1.0 avtpsrc ! avtpaafdepay ! autoaudiosink
|
||||||
|
* ]| This example pipeline will depayload AVTPDUs. Refer to the avtpaafpay
|
||||||
|
* example to create the AVTP stream.
|
||||||
|
* </refsect2>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avtp.h>
|
||||||
|
#include <avtp_aaf.h>
|
||||||
|
#include <gst/audio/audio-format.h>
|
||||||
|
|
||||||
|
#include "gstavtpaafdepay.h"
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (avtpaafdepay_debug);
|
||||||
|
#define GST_CAT_DEFAULT (avtpaafdepay_debug)
|
||||||
|
|
||||||
|
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
|
GST_PAD_SRC,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("audio/x-raw, "
|
||||||
|
"format = (string) { S16BE, S24BE, S32BE, F32BE }, "
|
||||||
|
"rate = (int) { 8000, 16000, 24000, 32000, 44100, 48000, 88200, 96000, 176400, 192000 }, "
|
||||||
|
"channels = " GST_AUDIO_CHANNELS_RANGE ", "
|
||||||
|
"layout = (string) interleaved")
|
||||||
|
);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GstAvtpAafDepay, gst_avtp_aaf_depay,
|
||||||
|
GST_TYPE_AVTP_BASE_DEPAYLOAD);
|
||||||
|
GST_ELEMENT_REGISTER_DEFINE (avtpaafdepay, "avtpaafdepay", GST_RANK_NONE,
|
||||||
|
GST_TYPE_AVTP_AAF_DEPAY);
|
||||||
|
|
||||||
|
static GstFlowReturn gst_avtp_aaf_depay_chain (GstPad * pad, GstObject * parent,
|
||||||
|
GstBuffer * buffer);
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_avtp_aaf_depay_class_init (GstAvtpAafDepayClass * klass)
|
||||||
|
{
|
||||||
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||||
|
GstAvtpBaseDepayloadClass *avtpbasedepayload_class =
|
||||||
|
GST_AVTP_BASE_DEPAYLOAD_CLASS (klass);
|
||||||
|
|
||||||
|
gst_element_class_add_static_pad_template (element_class, &src_template);
|
||||||
|
|
||||||
|
gst_element_class_set_static_metadata (element_class,
|
||||||
|
"AVTP Audio Format (AAF) depayloader",
|
||||||
|
"Codec/Depayloader/Network/AVTP",
|
||||||
|
"Extracts raw audio from AAF AVTPDUs",
|
||||||
|
"Andre Guedes <andre.guedes@intel.com>");
|
||||||
|
|
||||||
|
avtpbasedepayload_class->chain = GST_DEBUG_FUNCPTR (gst_avtp_aaf_depay_chain);
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_INIT (avtpaafdepay_debug, "avtpaafdepay", 0,
|
||||||
|
"AAF AVTP Depayloader");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_avtp_aaf_depay_init (GstAvtpAafDepay * avtpaafdepay)
|
||||||
|
{
|
||||||
|
avtpaafdepay->channels = 0;
|
||||||
|
avtpaafdepay->depth = 0;
|
||||||
|
avtpaafdepay->rate = 0;
|
||||||
|
avtpaafdepay->format = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar *
|
||||||
|
avtp_to_gst_format (int avtp_format)
|
||||||
|
{
|
||||||
|
GstAudioFormat gst_format;
|
||||||
|
|
||||||
|
switch (avtp_format) {
|
||||||
|
case AVTP_AAF_FORMAT_INT_16BIT:
|
||||||
|
gst_format = GST_AUDIO_FORMAT_S16BE;
|
||||||
|
break;
|
||||||
|
case AVTP_AAF_FORMAT_INT_24BIT:
|
||||||
|
gst_format = GST_AUDIO_FORMAT_S24BE;
|
||||||
|
break;
|
||||||
|
case AVTP_AAF_FORMAT_INT_32BIT:
|
||||||
|
gst_format = GST_AUDIO_FORMAT_S32BE;
|
||||||
|
break;
|
||||||
|
case AVTP_AAF_FORMAT_FLOAT_32BIT:
|
||||||
|
gst_format = GST_AUDIO_FORMAT_F32BE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gst_format = GST_AUDIO_FORMAT_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return gst_audio_format_to_string (gst_format);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
avtp_to_gst_rate (int rate)
|
||||||
|
{
|
||||||
|
switch (rate) {
|
||||||
|
case AVTP_AAF_PCM_NSR_8KHZ:
|
||||||
|
return 8000;
|
||||||
|
case AVTP_AAF_PCM_NSR_16KHZ:
|
||||||
|
return 16000;
|
||||||
|
case AVTP_AAF_PCM_NSR_24KHZ:
|
||||||
|
return 24000;
|
||||||
|
case AVTP_AAF_PCM_NSR_32KHZ:
|
||||||
|
return 32000;
|
||||||
|
case AVTP_AAF_PCM_NSR_44_1KHZ:
|
||||||
|
return 44100;
|
||||||
|
case AVTP_AAF_PCM_NSR_48KHZ:
|
||||||
|
return 48000;
|
||||||
|
case AVTP_AAF_PCM_NSR_88_2KHZ:
|
||||||
|
return 88200;
|
||||||
|
case AVTP_AAF_PCM_NSR_96KHZ:
|
||||||
|
return 96000;
|
||||||
|
case AVTP_AAF_PCM_NSR_176_4KHZ:
|
||||||
|
return 176400;
|
||||||
|
case AVTP_AAF_PCM_NSR_192KHZ:
|
||||||
|
return 192000;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_avtp_aaf_depay_push_caps_event (GstAvtpAafDepay * avtpaafdepay,
|
||||||
|
gint rate, gint depth, gint format, gint channels)
|
||||||
|
{
|
||||||
|
GstCaps *caps;
|
||||||
|
GstEvent *event;
|
||||||
|
GstAvtpBaseDepayload *avtpbasedepayload =
|
||||||
|
GST_AVTP_BASE_DEPAYLOAD (avtpaafdepay);
|
||||||
|
|
||||||
|
caps = gst_caps_new_simple ("audio/x-raw",
|
||||||
|
"format", G_TYPE_STRING, avtp_to_gst_format (format),
|
||||||
|
"rate", G_TYPE_INT, avtp_to_gst_rate (rate),
|
||||||
|
"channels", G_TYPE_INT, channels,
|
||||||
|
"layout", G_TYPE_STRING, "interleaved", NULL);
|
||||||
|
|
||||||
|
event = gst_event_new_caps (caps);
|
||||||
|
|
||||||
|
if (!gst_pad_push_event (avtpbasedepayload->srcpad, event)) {
|
||||||
|
GST_ERROR_OBJECT (avtpaafdepay, "Failed to push CAPS event");
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (avtpaafdepay, "CAPS event pushed %" GST_PTR_FORMAT, caps);
|
||||||
|
|
||||||
|
avtpaafdepay->rate = rate;
|
||||||
|
avtpaafdepay->depth = depth;
|
||||||
|
avtpaafdepay->format = format;
|
||||||
|
avtpaafdepay->channels = channels;
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_avtp_aaf_depay_are_audio_features_valid (GstAvtpAafDepay * avtpaafdepay,
|
||||||
|
guint64 rate, guint64 depth, guint64 format, guint64 channels)
|
||||||
|
{
|
||||||
|
if (G_UNLIKELY (rate != avtpaafdepay->rate)) {
|
||||||
|
GST_INFO_OBJECT (avtpaafdepay, "Rate doesn't match, disarding buffer");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (G_UNLIKELY (depth != avtpaafdepay->depth)) {
|
||||||
|
GST_INFO_OBJECT (avtpaafdepay, "Bit depth doesn't match, disarding buffer");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (G_UNLIKELY (format != avtpaafdepay->format)) {
|
||||||
|
GST_INFO_OBJECT (avtpaafdepay,
|
||||||
|
"Sample format doesn't match, disarding buffer");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (G_UNLIKELY (channels != avtpaafdepay->channels)) {
|
||||||
|
GST_INFO_OBJECT (avtpaafdepay,
|
||||||
|
"Number of channels doesn't match, disarding buffer");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_avtp_aaf_depay_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
GstMapInfo info;
|
||||||
|
guint32 subtype, version;
|
||||||
|
GstClockTime ptime;
|
||||||
|
GstBuffer *subbuffer;
|
||||||
|
struct avtp_stream_pdu *pdu;
|
||||||
|
guint64 channels, depth, rate, format, tstamp, seqnum, streamid,
|
||||||
|
streamid_valid, data_len;
|
||||||
|
GstAvtpBaseDepayload *avtpbasedepayload = GST_AVTP_BASE_DEPAYLOAD (parent);
|
||||||
|
GstAvtpAafDepay *avtpaafdepay = GST_AVTP_AAF_DEPAY (avtpbasedepayload);
|
||||||
|
|
||||||
|
if (!gst_buffer_map (buffer, &info, GST_MAP_READ)) {
|
||||||
|
GST_ELEMENT_ERROR (avtpaafdepay, RESOURCE, READ, ("Failed to map memory"),
|
||||||
|
(NULL));
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.size < sizeof (struct avtp_stream_pdu)) {
|
||||||
|
GST_DEBUG_OBJECT (avtpaafdepay, "Malformed AVTPDU, discarding it");
|
||||||
|
gst_buffer_unmap (buffer, &info);
|
||||||
|
goto discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
pdu = (struct avtp_stream_pdu *) info.data;
|
||||||
|
res = avtp_aaf_pdu_get (pdu, AVTP_AAF_FIELD_NSR, &rate);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_aaf_pdu_get (pdu, AVTP_AAF_FIELD_FORMAT, &format);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_aaf_pdu_get (pdu, AVTP_AAF_FIELD_SEQ_NUM, &seqnum);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_aaf_pdu_get (pdu, AVTP_AAF_FIELD_BIT_DEPTH, &depth);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_aaf_pdu_get (pdu, AVTP_AAF_FIELD_TIMESTAMP, &tstamp);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_aaf_pdu_get (pdu, AVTP_AAF_FIELD_SV, &streamid_valid);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_aaf_pdu_get (pdu, AVTP_AAF_FIELD_STREAM_ID, &streamid);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_aaf_pdu_get (pdu, AVTP_AAF_FIELD_CHAN_PER_FRAME, &channels);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_aaf_pdu_get (pdu, AVTP_AAF_FIELD_STREAM_DATA_LEN, &data_len);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_pdu_get ((struct avtp_common_pdu *) pdu, AVTP_FIELD_SUBTYPE,
|
||||||
|
&subtype);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_pdu_get ((struct avtp_common_pdu *) pdu, AVTP_FIELD_VERSION,
|
||||||
|
&version);
|
||||||
|
g_assert (res == 0);
|
||||||
|
|
||||||
|
gst_buffer_unmap (buffer, &info);
|
||||||
|
|
||||||
|
if (subtype != AVTP_SUBTYPE_AAF) {
|
||||||
|
GST_DEBUG_OBJECT (avtpaafdepay, "Subtype doesn't match, discarding buffer");
|
||||||
|
goto discard;
|
||||||
|
}
|
||||||
|
if (version != 0) {
|
||||||
|
GST_DEBUG_OBJECT (avtpaafdepay, "Version doesn't match, discarding buffer");
|
||||||
|
goto discard;
|
||||||
|
}
|
||||||
|
if (streamid_valid != 1 || streamid != avtpbasedepayload->streamid) {
|
||||||
|
GST_DEBUG_OBJECT (avtpaafdepay, "Invalid StreamID, discarding buffer");
|
||||||
|
goto discard;
|
||||||
|
}
|
||||||
|
if (gst_buffer_get_size (buffer) < sizeof (*pdu) + data_len) {
|
||||||
|
GST_DEBUG_OBJECT (avtpaafdepay, "Incomplete AVTPDU, discarding buffer");
|
||||||
|
goto discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!gst_pad_has_current_caps (avtpbasedepayload->srcpad))) {
|
||||||
|
if (!gst_avtp_aaf_depay_push_caps_event (avtpaafdepay, rate, depth, format,
|
||||||
|
channels)) {
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
|
}
|
||||||
|
if (!gst_avtp_base_depayload_push_segment_event (avtpbasedepayload, tstamp)) {
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
avtpbasedepayload->seqnum = seqnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!gst_avtp_aaf_depay_are_audio_features_valid (avtpaafdepay,
|
||||||
|
rate, depth, format, channels)))
|
||||||
|
goto discard;
|
||||||
|
|
||||||
|
if (seqnum != avtpbasedepayload->seqnum) {
|
||||||
|
GST_INFO_OBJECT (avtpaafdepay, "Sequence number mismatch: expected %u"
|
||||||
|
" received %" G_GUINT64_FORMAT, avtpbasedepayload->seqnum, seqnum);
|
||||||
|
avtpbasedepayload->seqnum = seqnum;
|
||||||
|
}
|
||||||
|
avtpbasedepayload->seqnum++;
|
||||||
|
|
||||||
|
ptime = gst_avtp_base_depayload_tstamp_to_ptime (avtpbasedepayload, tstamp,
|
||||||
|
avtpbasedepayload->prev_ptime);
|
||||||
|
|
||||||
|
subbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL,
|
||||||
|
sizeof (struct avtp_stream_pdu), data_len);
|
||||||
|
GST_BUFFER_PTS (subbuffer) = ptime;
|
||||||
|
GST_BUFFER_DTS (subbuffer) = ptime;
|
||||||
|
|
||||||
|
avtpbasedepayload->prev_ptime = ptime;
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
return gst_pad_push (avtpbasedepayload->srcpad, subbuffer);
|
||||||
|
|
||||||
|
discard:
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
65
ext/avtp/gstavtpaafdepay.h
Normal file
65
ext/avtp/gstavtpaafdepay.h
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* GStreamer AVTP Plugin
|
||||||
|
* Copyright (C) 2019 Intel Corporation
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GST_AVTP_AAF_DEPAY_H__
|
||||||
|
#define __GST_AVTP_AAF_DEPAY_H__
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
#include "gstavtpbasedepayload.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GST_TYPE_AVTP_AAF_DEPAY (gst_avtp_aaf_depay_get_type())
|
||||||
|
#define GST_AVTP_AAF_DEPAY(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AVTP_AAF_DEPAY,GstAvtpAafDepay))
|
||||||
|
#define GST_AVTP_AAF_DEPAY_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AVTP_AAF_DEPAY,GstAvtpAafDepayClass))
|
||||||
|
#define GST_IS_AVTP_AAF_DEPAY(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AVTP_AAF_DEPAY))
|
||||||
|
#define GST_IS_AVTP_AAF_DEPAY_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AVTP_AAF_DEPAY))
|
||||||
|
|
||||||
|
typedef struct _GstAvtpAafDepay GstAvtpAafDepay;
|
||||||
|
typedef struct _GstAvtpAafDepayClass GstAvtpAafDepayClass;
|
||||||
|
|
||||||
|
struct _GstAvtpAafDepay
|
||||||
|
{
|
||||||
|
GstAvtpBaseDepayload depayload;
|
||||||
|
|
||||||
|
gint channels;
|
||||||
|
gint depth;
|
||||||
|
gint rate;
|
||||||
|
gint format;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstAvtpAafDepayClass
|
||||||
|
{
|
||||||
|
GstAvtpBaseDepayloadClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_avtp_aaf_depay_get_type (void);
|
||||||
|
|
||||||
|
GST_ELEMENT_REGISTER_DECLARE (avtpaafdepay);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GST_AVTP_AAF_DEPAY_H__ */
|
395
ext/avtp/gstavtpaafpay.c
Normal file
395
ext/avtp/gstavtpaafpay.c
Normal file
|
@ -0,0 +1,395 @@
|
||||||
|
/*
|
||||||
|
* GStreamer AVTP Plugin
|
||||||
|
* Copyright (C) 2019 Intel Corporation
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:element-avtpaafpay
|
||||||
|
* @see_also: avtpaafdepay
|
||||||
|
*
|
||||||
|
* Payload raw audio into AVTPDUs according to IEEE 1722-2016. For detailed
|
||||||
|
* information see https://standards.ieee.org/standard/1722-2016.html.
|
||||||
|
*
|
||||||
|
* <refsect2>
|
||||||
|
* <title>Example pipeline</title>
|
||||||
|
* |[
|
||||||
|
* gst-launch-1.0 audiotestsrc ! audioconvert ! avtpaafpay ! avtpsink
|
||||||
|
* ]| This example pipeline will payload raw audio. Refer to the avtpaafdepay
|
||||||
|
* example to depayload and play the AVTP stream.
|
||||||
|
* </refsect2>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avtp.h>
|
||||||
|
#include <avtp_aaf.h>
|
||||||
|
#include <gst/audio/audio-format.h>
|
||||||
|
|
||||||
|
#include "gstavtpaafpay.h"
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (avtpaafpay_debug);
|
||||||
|
#define GST_CAT_DEFAULT (avtpaafpay_debug)
|
||||||
|
|
||||||
|
#define DEFAULT_TIMESTAMP_MODE GST_AVTP_AAF_TIMESTAMP_MODE_NORMAL
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_TIMESTAMP_MODE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
GST_PAD_SINK,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("audio/x-raw, "
|
||||||
|
"format = (string) { S16BE, S24BE, S32BE, F32BE }, "
|
||||||
|
"rate = (int) { 8000, 16000, 24000, 32000, 44100, 48000, 88200, 96000, 176400, 192000 }, "
|
||||||
|
"channels = " GST_AUDIO_CHANNELS_RANGE ", "
|
||||||
|
"layout = (string) interleaved")
|
||||||
|
);
|
||||||
|
|
||||||
|
#define GST_TYPE_AVTP_AAF_TIMESTAMP_MODE (gst_avtp_aaf_timestamp_mode_get_type())
|
||||||
|
static GType
|
||||||
|
gst_avtp_aaf_timestamp_mode_get_type (void)
|
||||||
|
{
|
||||||
|
static const GEnumValue timestamp_mode_types[] = {
|
||||||
|
{GST_AVTP_AAF_TIMESTAMP_MODE_NORMAL, "Normal timestamping mode", "normal"},
|
||||||
|
{GST_AVTP_AAF_TIMESTAMP_MODE_SPARSE, "Sparse timestamping mode", "sparse"},
|
||||||
|
{0, NULL, NULL},
|
||||||
|
};
|
||||||
|
static gsize id = 0;
|
||||||
|
|
||||||
|
if (g_once_init_enter (&id)) {
|
||||||
|
GType new_type;
|
||||||
|
|
||||||
|
new_type =
|
||||||
|
g_enum_register_static ("GstAvtpAafTimestampMode",
|
||||||
|
timestamp_mode_types);
|
||||||
|
|
||||||
|
g_once_init_leave (&id, (gsize) new_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (GType) id;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define gst_avtp_aaf_pay_parent_class parent_class
|
||||||
|
G_DEFINE_TYPE (GstAvtpAafPay, gst_avtp_aaf_pay, GST_TYPE_AVTP_BASE_PAYLOAD);
|
||||||
|
GST_ELEMENT_REGISTER_DEFINE (avtpaafpay, "avtpaafpay", GST_RANK_NONE,
|
||||||
|
GST_TYPE_AVTP_AAF_PAY);
|
||||||
|
|
||||||
|
static void gst_avtp_aaf_pay_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec);
|
||||||
|
static void gst_avtp_aaf_pay_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec);
|
||||||
|
|
||||||
|
static GstStateChangeReturn gst_avtp_aaf_pay_change_state (GstElement * element,
|
||||||
|
GstStateChange transition);
|
||||||
|
|
||||||
|
static GstFlowReturn gst_avtp_aaf_pay_chain (GstPad * pad, GstObject * parent,
|
||||||
|
GstBuffer * buffer);
|
||||||
|
static gboolean gst_avtp_aaf_pay_sink_event (GstPad * pad, GstObject * parent,
|
||||||
|
GstEvent * event);
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_avtp_aaf_pay_class_init (GstAvtpAafPayClass * klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||||
|
GstAvtpBasePayloadClass *avtpbasepayload_class =
|
||||||
|
GST_AVTP_BASE_PAYLOAD_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->set_property = gst_avtp_aaf_pay_set_property;
|
||||||
|
object_class->get_property = gst_avtp_aaf_pay_get_property;
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class, PROP_TIMESTAMP_MODE,
|
||||||
|
g_param_spec_enum ("timestamp-mode", "Timestamping Mode",
|
||||||
|
"AAF timestamping mode", GST_TYPE_AVTP_AAF_TIMESTAMP_MODE,
|
||||||
|
DEFAULT_TIMESTAMP_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||||
|
GST_PARAM_MUTABLE_PAUSED));
|
||||||
|
|
||||||
|
element_class->change_state =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_avtp_aaf_pay_change_state);
|
||||||
|
|
||||||
|
gst_element_class_add_static_pad_template (element_class, &sink_template);
|
||||||
|
|
||||||
|
gst_element_class_set_static_metadata (element_class,
|
||||||
|
"AVTP Audio Format (AAF) payloader",
|
||||||
|
"Codec/Payloader/Network/AVTP",
|
||||||
|
"Payload-encode Raw audio into AAF AVTPDU (IEEE 1722)",
|
||||||
|
"Andre Guedes <andre.guedes@intel.com>");
|
||||||
|
|
||||||
|
avtpbasepayload_class->chain = GST_DEBUG_FUNCPTR (gst_avtp_aaf_pay_chain);
|
||||||
|
avtpbasepayload_class->sink_event =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_avtp_aaf_pay_sink_event);
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_INIT (avtpaafpay_debug, "avtpaafpay", 0,
|
||||||
|
"AAF AVTP Payloader");
|
||||||
|
|
||||||
|
gst_type_mark_as_plugin_api (GST_TYPE_AVTP_AAF_TIMESTAMP_MODE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_avtp_aaf_pay_init (GstAvtpAafPay * avtpaafpay)
|
||||||
|
{
|
||||||
|
avtpaafpay->timestamp_mode = DEFAULT_TIMESTAMP_MODE;
|
||||||
|
|
||||||
|
avtpaafpay->header = NULL;
|
||||||
|
avtpaafpay->channels = 0;
|
||||||
|
avtpaafpay->depth = 0;
|
||||||
|
avtpaafpay->rate = 0;
|
||||||
|
avtpaafpay->format = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_avtp_aaf_pay_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstAvtpAafPay *avtpaafpay = GST_AVTP_AAF_PAY (object);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (avtpaafpay, "prop_id %u", prop_id);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_TIMESTAMP_MODE:
|
||||||
|
avtpaafpay->timestamp_mode = g_value_get_enum (value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_avtp_aaf_pay_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstAvtpAafPay *avtpaafpay = GST_AVTP_AAF_PAY (object);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (avtpaafpay, "prop_id %u", prop_id);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_TIMESTAMP_MODE:
|
||||||
|
g_value_set_enum (value, avtpaafpay->timestamp_mode);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstStateChangeReturn
|
||||||
|
gst_avtp_aaf_pay_change_state (GstElement * element, GstStateChange transition)
|
||||||
|
{
|
||||||
|
GstStateChangeReturn ret;
|
||||||
|
GstAvtpAafPay *avtpaafpay = GST_AVTP_AAF_PAY (element);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (avtpaafpay, "transition %d", transition);
|
||||||
|
|
||||||
|
switch (transition) {
|
||||||
|
case GST_STATE_CHANGE_NULL_TO_READY:{
|
||||||
|
GstMemory *mem;
|
||||||
|
|
||||||
|
mem = gst_allocator_alloc (NULL, sizeof (struct avtp_stream_pdu), NULL);
|
||||||
|
if (!mem) {
|
||||||
|
GST_ERROR_OBJECT (avtpaafpay, "Failed to allocate GstMemory");
|
||||||
|
return GST_STATE_CHANGE_FAILURE;
|
||||||
|
}
|
||||||
|
avtpaafpay->header = mem;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GST_STATE_CHANGE_READY_TO_PAUSED:{
|
||||||
|
int res;
|
||||||
|
GstMapInfo info;
|
||||||
|
struct avtp_stream_pdu *pdu;
|
||||||
|
GstMemory *mem = avtpaafpay->header;
|
||||||
|
GstAvtpBasePayload *avtpbasepayload = GST_AVTP_BASE_PAYLOAD (element);
|
||||||
|
|
||||||
|
if (!gst_memory_map (mem, &info, GST_MAP_WRITE)) {
|
||||||
|
GST_ERROR_OBJECT (avtpaafpay, "Failed to map GstMemory");
|
||||||
|
return GST_STATE_CHANGE_FAILURE;
|
||||||
|
}
|
||||||
|
pdu = (struct avtp_stream_pdu *) info.data;
|
||||||
|
res = avtp_aaf_pdu_init (pdu);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_MR, 0);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_TV, 1);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_TU, 0);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_STREAM_ID,
|
||||||
|
avtpbasepayload->streamid);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res =
|
||||||
|
avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_SP, avtpaafpay->timestamp_mode);
|
||||||
|
g_assert (res == 0);
|
||||||
|
gst_memory_unmap (mem, &info);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||||
|
if (ret == GST_STATE_CHANGE_FAILURE) {
|
||||||
|
GST_ERROR_OBJECT (avtpaafpay, "Parent failed to handle state transition");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (transition) {
|
||||||
|
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||||
|
gst_memory_unref (avtpaafpay->header);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_avtp_aaf_pay_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
GstMemory *mem;
|
||||||
|
GstMapInfo info;
|
||||||
|
gsize data_len;
|
||||||
|
GstClockTime ptime;
|
||||||
|
struct avtp_stream_pdu *pdu;
|
||||||
|
GstAvtpAafPay *avtpaafpay = GST_AVTP_AAF_PAY (parent);
|
||||||
|
GstAvtpBasePayload *avtpbasepayload = GST_AVTP_BASE_PAYLOAD (parent);
|
||||||
|
|
||||||
|
ptime = gst_avtp_base_payload_calc_ptime (avtpbasepayload, buffer);
|
||||||
|
data_len = gst_buffer_get_size (buffer);
|
||||||
|
|
||||||
|
mem = gst_memory_copy (avtpaafpay->header, 0, -1);
|
||||||
|
if (!gst_memory_map (mem, &info, GST_MAP_WRITE)) {
|
||||||
|
GST_ELEMENT_ERROR (avtpaafpay, RESOURCE, WRITE, ("Failed to map memory"),
|
||||||
|
(NULL));
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
pdu = (struct avtp_stream_pdu *) info.data;
|
||||||
|
res = avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_TIMESTAMP, ptime);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_NSR, avtpaafpay->rate);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_FORMAT, avtpaafpay->format);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_BIT_DEPTH, avtpaafpay->depth);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_STREAM_DATA_LEN, data_len);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_CHAN_PER_FRAME,
|
||||||
|
avtpaafpay->channels);
|
||||||
|
g_assert (res == 0);
|
||||||
|
res = avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_SEQ_NUM,
|
||||||
|
avtpbasepayload->seqnum++);
|
||||||
|
g_assert (res == 0);
|
||||||
|
gst_memory_unmap (mem, &info);
|
||||||
|
|
||||||
|
gst_buffer_prepend_memory (buffer, mem);
|
||||||
|
return gst_pad_push (avtpbasepayload->srcpad, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
gst_to_avtp_rate (gint rate)
|
||||||
|
{
|
||||||
|
switch (rate) {
|
||||||
|
case 8000:
|
||||||
|
return AVTP_AAF_PCM_NSR_8KHZ;
|
||||||
|
case 16000:
|
||||||
|
return AVTP_AAF_PCM_NSR_16KHZ;
|
||||||
|
case 24000:
|
||||||
|
return AVTP_AAF_PCM_NSR_24KHZ;
|
||||||
|
case 32000:
|
||||||
|
return AVTP_AAF_PCM_NSR_32KHZ;
|
||||||
|
case 44100:
|
||||||
|
return AVTP_AAF_PCM_NSR_44_1KHZ;
|
||||||
|
case 48000:
|
||||||
|
return AVTP_AAF_PCM_NSR_48KHZ;
|
||||||
|
case 88200:
|
||||||
|
return AVTP_AAF_PCM_NSR_88_2KHZ;
|
||||||
|
case 96000:
|
||||||
|
return AVTP_AAF_PCM_NSR_96KHZ;
|
||||||
|
case 176400:
|
||||||
|
return AVTP_AAF_PCM_NSR_176_4KHZ;
|
||||||
|
case 192000:
|
||||||
|
return AVTP_AAF_PCM_NSR_192KHZ;
|
||||||
|
default:
|
||||||
|
return AVTP_AAF_PCM_NSR_USER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
gst_to_avtp_format (GstAudioFormat format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case GST_AUDIO_FORMAT_S16BE:
|
||||||
|
return AVTP_AAF_FORMAT_INT_16BIT;
|
||||||
|
case GST_AUDIO_FORMAT_S24BE:
|
||||||
|
return AVTP_AAF_FORMAT_INT_24BIT;
|
||||||
|
case GST_AUDIO_FORMAT_S32BE:
|
||||||
|
return AVTP_AAF_FORMAT_INT_32BIT;
|
||||||
|
case GST_AUDIO_FORMAT_F32BE:
|
||||||
|
return AVTP_AAF_FORMAT_FLOAT_32BIT;
|
||||||
|
default:
|
||||||
|
return AVTP_AAF_FORMAT_USER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_avtp_aaf_pay_new_caps (GstAvtpAafPay * avtpaafpay, GstCaps * caps)
|
||||||
|
{
|
||||||
|
GstAudioInfo info;
|
||||||
|
|
||||||
|
gst_audio_info_init (&info);
|
||||||
|
if (!gst_audio_info_from_caps (&info, caps)) {
|
||||||
|
GST_ERROR_OBJECT (avtpaafpay, "Failed to get info from caps");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
avtpaafpay->channels = info.channels;
|
||||||
|
avtpaafpay->depth = info.finfo->depth;
|
||||||
|
avtpaafpay->rate = gst_to_avtp_rate (info.rate);
|
||||||
|
avtpaafpay->format = gst_to_avtp_format (info.finfo->format);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (avtpaafpay, "channels %d, depth %d, rate %d, format %s",
|
||||||
|
info.channels, info.finfo->depth, info.rate,
|
||||||
|
gst_audio_format_to_string (info.finfo->format));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_avtp_aaf_pay_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||||
|
{
|
||||||
|
GstCaps *caps;
|
||||||
|
GstAvtpAafPay *avtpaafpay = GST_AVTP_AAF_PAY (parent);
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (avtpaafpay, "event %s", GST_EVENT_TYPE_NAME (event));
|
||||||
|
|
||||||
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_CAPS:
|
||||||
|
gst_event_parse_caps (event, &caps);
|
||||||
|
ret = gst_avtp_aaf_pay_new_caps (avtpaafpay, caps);
|
||||||
|
gst_event_unref (event);
|
||||||
|
return ret;
|
||||||
|
default:
|
||||||
|
return GST_AVTP_BASE_PAYLOAD_CLASS (parent_class)->sink_event (pad,
|
||||||
|
parent, event);
|
||||||
|
}
|
||||||
|
}
|
74
ext/avtp/gstavtpaafpay.h
Normal file
74
ext/avtp/gstavtpaafpay.h
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* GStreamer AVTP Plugin
|
||||||
|
* Copyright (C) 2019 Intel Corporation
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GST_AVTP_AAF_PAY_H__
|
||||||
|
#define __GST_AVTP_AAF_PAY_H__
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
#include "gstavtpbasepayload.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GST_TYPE_AVTP_AAF_PAY (gst_avtp_aaf_pay_get_type())
|
||||||
|
#define GST_AVTP_AAF_PAY(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AVTP_AAF_PAY,GstAvtpAafPay))
|
||||||
|
#define GST_AVTP_AAF_PAY_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AVTP_AAF_PAY,GstAvtpAafPayClass))
|
||||||
|
#define GST_IS_AVTP_AAF_PAY(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AVTP_AAF_PAY))
|
||||||
|
#define GST_IS_AVTP_AAF_PAY_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AVTP_AAF_PAY))
|
||||||
|
|
||||||
|
typedef struct _GstAvtpAafPay GstAvtpAafPay;
|
||||||
|
typedef struct _GstAvtpAafPayClass GstAvtpAafPayClass;
|
||||||
|
typedef enum _GstAvtpAafTimestampMode GstAvtpAafTimestampMode;
|
||||||
|
|
||||||
|
enum _GstAvtpAafTimestampMode {
|
||||||
|
GST_AVTP_AAF_TIMESTAMP_MODE_NORMAL,
|
||||||
|
GST_AVTP_AAF_TIMESTAMP_MODE_SPARSE,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstAvtpAafPay
|
||||||
|
{
|
||||||
|
GstAvtpBasePayload payload;
|
||||||
|
|
||||||
|
GstAvtpAafTimestampMode timestamp_mode;
|
||||||
|
|
||||||
|
GstMemory *header;
|
||||||
|
gint channels;
|
||||||
|
gint depth;
|
||||||
|
gint rate;
|
||||||
|
gint format;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstAvtpAafPayClass
|
||||||
|
{
|
||||||
|
GstAvtpBasePayloadClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_avtp_aaf_pay_get_type (void);
|
||||||
|
|
||||||
|
GST_ELEMENT_REGISTER_DECLARE (avtpaafpay);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GST_AVTP_AAF_PAY_H__ */
|
262
ext/avtp/gstavtpbasedepayload.c
Normal file
262
ext/avtp/gstavtpbasedepayload.c
Normal file
|
@ -0,0 +1,262 @@
|
||||||
|
/*
|
||||||
|
* GStreamer AVTP Plugin
|
||||||
|
* Copyright (C) 2019 Intel Corporation
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gstavtpbasedepayload.h"
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (avtpbasedepayload_debug);
|
||||||
|
#define GST_CAT_DEFAULT (avtpbasedepayload_debug)
|
||||||
|
|
||||||
|
#define DEFAULT_STREAMID 0xAABBCCDDEEFF0000
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_STREAMID,
|
||||||
|
};
|
||||||
|
|
||||||
|
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
GST_PAD_SINK,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("application/x-avtp")
|
||||||
|
);
|
||||||
|
|
||||||
|
static void gst_avtp_base_depayload_class_init (GstAvtpBaseDepayloadClass *
|
||||||
|
klass);
|
||||||
|
static void gst_avtp_base_depayload_init (GstAvtpBaseDepayload *
|
||||||
|
avtpbasedepayload, gpointer g_class);
|
||||||
|
|
||||||
|
static void gst_avtp_base_depayload_set_property (GObject * object,
|
||||||
|
guint prop_id, const GValue * value, GParamSpec * pspec);
|
||||||
|
static void gst_avtp_base_depayload_get_property (GObject * object,
|
||||||
|
guint prop_id, GValue * value, GParamSpec * pspec);
|
||||||
|
|
||||||
|
static gboolean gst_avtp_base_depayload_sink_event (GstPad * pad,
|
||||||
|
GstObject * parent, GstEvent * event);
|
||||||
|
|
||||||
|
GType
|
||||||
|
gst_avtp_base_depayload_get_type (void)
|
||||||
|
{
|
||||||
|
static GType avtpbasedepayload_type = 0;
|
||||||
|
|
||||||
|
if (g_once_init_enter ((gsize *) & avtpbasedepayload_type)) {
|
||||||
|
static const GTypeInfo avtpbasedepayload_info = {
|
||||||
|
sizeof (GstAvtpBaseDepayloadClass),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
(GClassInitFunc) gst_avtp_base_depayload_class_init,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
sizeof (GstAvtpBaseDepayload),
|
||||||
|
0,
|
||||||
|
(GInstanceInitFunc) gst_avtp_base_depayload_init,
|
||||||
|
};
|
||||||
|
GType _type;
|
||||||
|
|
||||||
|
_type = g_type_register_static (GST_TYPE_ELEMENT, "GstAvtpBaseDepayload",
|
||||||
|
&avtpbasedepayload_info, G_TYPE_FLAG_ABSTRACT);
|
||||||
|
|
||||||
|
g_once_init_leave ((gsize *) & avtpbasedepayload_type, _type);
|
||||||
|
}
|
||||||
|
return avtpbasedepayload_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_avtp_base_depayload_class_init (GstAvtpBaseDepayloadClass * klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->set_property = gst_avtp_base_depayload_set_property;
|
||||||
|
object_class->get_property = gst_avtp_base_depayload_get_property;
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class, PROP_STREAMID,
|
||||||
|
g_param_spec_uint64 ("streamid", "Stream ID",
|
||||||
|
"Stream ID associated with the AVTPDU", 0, G_MAXUINT64,
|
||||||
|
DEFAULT_STREAMID, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||||
|
GST_PARAM_MUTABLE_PAUSED));
|
||||||
|
|
||||||
|
klass->chain = NULL;
|
||||||
|
klass->sink_event = GST_DEBUG_FUNCPTR (gst_avtp_base_depayload_sink_event);
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_INIT (avtpbasedepayload_debug, "avtpbasedepayload", 0,
|
||||||
|
"Base class for AVTP depayloaders");
|
||||||
|
|
||||||
|
gst_type_mark_as_plugin_api (GST_TYPE_AVTP_BASE_DEPAYLOAD, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_avtp_base_depayload_init (GstAvtpBaseDepayload * avtpbasedepayload,
|
||||||
|
gpointer g_class)
|
||||||
|
{
|
||||||
|
GstPadTemplate *templ;
|
||||||
|
GstElement *element = GST_ELEMENT (avtpbasedepayload);
|
||||||
|
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
||||||
|
GstAvtpBaseDepayloadClass *avtpbasedepayload_class =
|
||||||
|
GST_AVTP_BASE_DEPAYLOAD_CLASS (g_class);
|
||||||
|
|
||||||
|
g_assert (avtpbasedepayload_class->chain != NULL);
|
||||||
|
|
||||||
|
templ = gst_element_class_get_pad_template (element_class, "src");
|
||||||
|
g_assert (templ != NULL);
|
||||||
|
avtpbasedepayload->srcpad = gst_pad_new_from_template (templ, "src");
|
||||||
|
gst_pad_use_fixed_caps (avtpbasedepayload->srcpad);
|
||||||
|
gst_element_add_pad (element, avtpbasedepayload->srcpad);
|
||||||
|
|
||||||
|
avtpbasedepayload->sinkpad =
|
||||||
|
gst_pad_new_from_static_template (&sink_template, "sink");
|
||||||
|
gst_pad_set_chain_function (avtpbasedepayload->sinkpad,
|
||||||
|
avtpbasedepayload_class->chain);
|
||||||
|
gst_pad_set_event_function (avtpbasedepayload->sinkpad,
|
||||||
|
avtpbasedepayload_class->sink_event);
|
||||||
|
gst_element_add_pad (element, avtpbasedepayload->sinkpad);
|
||||||
|
|
||||||
|
avtpbasedepayload->streamid = DEFAULT_STREAMID;
|
||||||
|
|
||||||
|
avtpbasedepayload->prev_ptime = 0;
|
||||||
|
avtpbasedepayload->seqnum = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_avtp_base_depayload_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstAvtpBaseDepayload *avtpbasedepayload = GST_AVTP_BASE_DEPAYLOAD (object);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (avtpbasedepayload, "prop_id %u", prop_id);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_STREAMID:
|
||||||
|
avtpbasedepayload->streamid = g_value_get_uint64 (value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_avtp_base_depayload_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstAvtpBaseDepayload *avtpbasedepayload = GST_AVTP_BASE_DEPAYLOAD (object);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (avtpbasedepayload, "prop_id %u", prop_id);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_STREAMID:
|
||||||
|
g_value_set_uint64 (value, avtpbasedepayload->streamid);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_avtp_base_depayload_sink_event (GstPad * pad, GstObject * parent,
|
||||||
|
GstEvent * event)
|
||||||
|
{
|
||||||
|
GstAvtpBaseDepayload *avtpbasedepayload = GST_AVTP_BASE_DEPAYLOAD (parent);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (avtpbasedepayload, "event %s", GST_EVENT_TYPE_NAME (event));
|
||||||
|
|
||||||
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_SEGMENT:
|
||||||
|
/* Once the first AVTPDU is received, proper CAPS and SEGMENT events are
|
||||||
|
* pushed downstream. These events are expected to be pushed in that
|
||||||
|
* order by GStreamer. Since the default handling implemented by
|
||||||
|
* gst_pad_event_default() pushes the SEGMENT event downstream right
|
||||||
|
* away, it doesn't work for us and we have to handle it ourselves.
|
||||||
|
*
|
||||||
|
* Our handling is very straightforward: we discard this event and send
|
||||||
|
* a proper segment event once the first AVTPDU is received. See
|
||||||
|
* gst_avtp_base_depayload_push_segment_event() for more information.
|
||||||
|
*/
|
||||||
|
gst_event_unref (event);
|
||||||
|
return TRUE;
|
||||||
|
default:
|
||||||
|
return gst_pad_event_default (pad, parent, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helper function to convert AVTP timestamp to AVTP presentation time. Since
|
||||||
|
* AVTP timestamp represents the lower 32-bit part from AVTP presentation time,
|
||||||
|
* the helper requires a reference time ('ref' argument) to convert it properly.
|
||||||
|
* The reference time must be in gstreamer clock-time coordinate.
|
||||||
|
*/
|
||||||
|
GstClockTime
|
||||||
|
gst_avtp_base_depayload_tstamp_to_ptime (GstAvtpBaseDepayload *
|
||||||
|
avtpbasedepayload, guint32 tstamp, GstClockTime ref)
|
||||||
|
{
|
||||||
|
GstClockTime ptime;
|
||||||
|
|
||||||
|
ptime = (ref & 0xFFFFFFFF00000000ULL) | tstamp;
|
||||||
|
|
||||||
|
/* If 'ptime' is less than the our reference time, it means the higher part
|
||||||
|
* from 'ptime' needs to be incremented by 1 in order reflect the correct
|
||||||
|
* presentation time.
|
||||||
|
*/
|
||||||
|
if (ptime < ref)
|
||||||
|
ptime += (1ULL << 32);
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (avtpbasedepayload, "AVTP presentation time %" GST_TIME_FORMAT,
|
||||||
|
GST_TIME_ARGS (ptime));
|
||||||
|
return ptime;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_avtp_base_depayload_push_segment_event (GstAvtpBaseDepayload *
|
||||||
|
avtpbasedepayload, guint32 avtp_tstamp)
|
||||||
|
{
|
||||||
|
GstClock *clock;
|
||||||
|
GstEvent *event;
|
||||||
|
GstSegment segment;
|
||||||
|
GstClockTime now, base_time, avtp_ptime;
|
||||||
|
|
||||||
|
clock = GST_ELEMENT_CLOCK (avtpbasedepayload);
|
||||||
|
|
||||||
|
now = gst_clock_get_time (clock);
|
||||||
|
avtp_ptime =
|
||||||
|
gst_avtp_base_depayload_tstamp_to_ptime (avtpbasedepayload, avtp_tstamp,
|
||||||
|
now);
|
||||||
|
base_time = gst_element_get_base_time (GST_ELEMENT (avtpbasedepayload));
|
||||||
|
|
||||||
|
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||||
|
segment.base = avtp_ptime - base_time;
|
||||||
|
segment.start = avtp_ptime;
|
||||||
|
segment.stop = -1;
|
||||||
|
|
||||||
|
event = gst_event_new_segment (&segment);
|
||||||
|
if (!event) {
|
||||||
|
GST_ERROR_OBJECT (avtpbasedepayload, "Failed to create SEGMENT event");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gst_pad_push_event (avtpbasedepayload->srcpad, event)) {
|
||||||
|
GST_ERROR_OBJECT (avtpbasedepayload, "Failed to push SEGMENT event");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (avtpbasedepayload, "SEGMENT event pushed: %"
|
||||||
|
GST_SEGMENT_FORMAT, &segment);
|
||||||
|
|
||||||
|
avtpbasedepayload->prev_ptime = avtp_ptime;
|
||||||
|
return TRUE;
|
||||||
|
}
|
79
ext/avtp/gstavtpbasedepayload.h
Normal file
79
ext/avtp/gstavtpbasedepayload.h
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* GStreamer AVTP Plugin
|
||||||
|
* Copyright (C) 2019 Intel Corporation
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GST_AVTP_BASE_DEPAYLOAD_H__
|
||||||
|
#define __GST_AVTP_BASE_DEPAYLOAD_H__
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GST_TYPE_AVTP_BASE_DEPAYLOAD (gst_avtp_base_depayload_get_type())
|
||||||
|
#define GST_AVTP_BASE_DEPAYLOAD(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AVTP_BASE_DEPAYLOAD,GstAvtpBaseDepayload))
|
||||||
|
#define GST_AVTP_BASE_DEPAYLOAD_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AVTP_BASE_DEPAYLOAD,GstAvtpBaseDepayloadClass))
|
||||||
|
#define GST_IS_AVTP_BASE_DEPAYLOAD(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AVTP_BASE_DEPAYLOAD))
|
||||||
|
#define GST_IS_AVTP_BASE_DEPAYLOAD_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AVTP_BASE_DEPAYLOAD))
|
||||||
|
|
||||||
|
typedef struct _GstAvtpBaseDepayload GstAvtpBaseDepayload;
|
||||||
|
typedef struct _GstAvtpBaseDepayloadClass GstAvtpBaseDepayloadClass;
|
||||||
|
|
||||||
|
struct _GstAvtpBaseDepayload
|
||||||
|
{
|
||||||
|
GstElement element;
|
||||||
|
|
||||||
|
GstPad *sinkpad;
|
||||||
|
GstPad *srcpad;
|
||||||
|
|
||||||
|
guint64 streamid;
|
||||||
|
|
||||||
|
GstClockTime prev_ptime;
|
||||||
|
guint8 seqnum;
|
||||||
|
|
||||||
|
gpointer _gst_reserved[GST_PADDING];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstAvtpBaseDepayloadClass
|
||||||
|
{
|
||||||
|
GstElementClass parent_class;
|
||||||
|
|
||||||
|
/* Pure virtual function. */
|
||||||
|
GstPadChainFunction chain;
|
||||||
|
|
||||||
|
GstPadEventFunction sink_event;
|
||||||
|
|
||||||
|
gpointer _gst_reserved[GST_PADDING];
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_avtp_base_depayload_get_type (void);
|
||||||
|
|
||||||
|
GstClockTime gst_avtp_base_depayload_tstamp_to_ptime (GstAvtpBaseDepayload *
|
||||||
|
avtpbasedepayload, guint32 tstamp, GstClockTime ref);
|
||||||
|
|
||||||
|
gboolean gst_avtp_base_depayload_push_segment_event (GstAvtpBaseDepayload *
|
||||||
|
avtpbasedepayload, guint32 avtp_tstamp);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GST_AVTP_BASE_DEPAYLOAD_H__ */
|
257
ext/avtp/gstavtpbasepayload.c
Normal file
257
ext/avtp/gstavtpbasepayload.c
Normal file
|
@ -0,0 +1,257 @@
|
||||||
|
/*
|
||||||
|
* GStreamer AVTP Plugin
|
||||||
|
* Copyright (C) 2019 Intel Corporation
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gstavtpbasepayload.h"
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (avtpbasepayload_debug);
|
||||||
|
#define GST_CAT_DEFAULT (avtpbasepayload_debug)
|
||||||
|
|
||||||
|
#define DEFAULT_STREAMID 0xAABBCCDDEEFF0000
|
||||||
|
#define DEFAULT_MTT 50000000
|
||||||
|
#define DEFAULT_TU 1000000
|
||||||
|
#define DEFAULT_PROCESSING_DEADLINE (20 * GST_MSECOND)
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_STREAMID,
|
||||||
|
PROP_MTT,
|
||||||
|
PROP_TU,
|
||||||
|
PROP_PROCESSING_DEADLINE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
|
GST_PAD_SRC,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("application/x-avtp")
|
||||||
|
);
|
||||||
|
|
||||||
|
static void gst_avtp_base_payload_class_init (GstAvtpBasePayloadClass * klass);
|
||||||
|
static void gst_avtp_base_payload_init (GstAvtpBasePayload * avtpbasepayload,
|
||||||
|
gpointer g_class);
|
||||||
|
|
||||||
|
static void gst_avtp_base_payload_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec);
|
||||||
|
static void gst_avtp_base_payload_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec);
|
||||||
|
|
||||||
|
static gboolean gst_avtp_base_payload_sink_event (GstPad * pad,
|
||||||
|
GstObject * parent, GstEvent * event);
|
||||||
|
|
||||||
|
GType
|
||||||
|
gst_avtp_base_payload_get_type (void)
|
||||||
|
{
|
||||||
|
static GType avtpbasepayload_type = 0;
|
||||||
|
|
||||||
|
if (g_once_init_enter ((gsize *) & avtpbasepayload_type)) {
|
||||||
|
static const GTypeInfo avtpbasepayload_info = {
|
||||||
|
sizeof (GstAvtpBasePayloadClass),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
(GClassInitFunc) gst_avtp_base_payload_class_init,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
sizeof (GstAvtpBasePayload),
|
||||||
|
0,
|
||||||
|
(GInstanceInitFunc) gst_avtp_base_payload_init,
|
||||||
|
};
|
||||||
|
GType _type;
|
||||||
|
|
||||||
|
_type = g_type_register_static (GST_TYPE_ELEMENT, "GstAvtpBasePayload",
|
||||||
|
&avtpbasepayload_info, G_TYPE_FLAG_ABSTRACT);
|
||||||
|
|
||||||
|
g_once_init_leave ((gsize *) & avtpbasepayload_type, _type);
|
||||||
|
}
|
||||||
|
return avtpbasepayload_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_avtp_base_payload_class_init (GstAvtpBasePayloadClass * klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->set_property = gst_avtp_base_payload_set_property;
|
||||||
|
object_class->get_property = gst_avtp_base_payload_get_property;
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class, PROP_STREAMID,
|
||||||
|
g_param_spec_uint64 ("streamid", "Stream ID",
|
||||||
|
"Stream ID associated with the AVTPDU", 0, G_MAXUINT64,
|
||||||
|
DEFAULT_STREAMID, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||||
|
GST_PARAM_MUTABLE_READY));
|
||||||
|
g_object_class_install_property (object_class, PROP_MTT,
|
||||||
|
g_param_spec_uint ("mtt", "Maximum Transit Time",
|
||||||
|
"Maximum Transit Time (MTT) in nanoseconds", 0,
|
||||||
|
G_MAXUINT, DEFAULT_MTT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (object_class, PROP_TU,
|
||||||
|
g_param_spec_uint ("tu", "Timing Uncertainty",
|
||||||
|
"Timing Uncertainty (TU) in nanoseconds", 0,
|
||||||
|
G_MAXUINT, DEFAULT_TU, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (object_class, PROP_PROCESSING_DEADLINE,
|
||||||
|
g_param_spec_uint64 ("processing-deadline", "Processing deadline",
|
||||||
|
"Maximum amount of time (in ns) the pipeline can take for processing the buffer",
|
||||||
|
0, G_MAXUINT64, DEFAULT_PROCESSING_DEADLINE, G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
klass->chain = NULL;
|
||||||
|
klass->sink_event = GST_DEBUG_FUNCPTR (gst_avtp_base_payload_sink_event);
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_INIT (avtpbasepayload_debug, "avtpbasepayload", 0,
|
||||||
|
"Base class for AVTP payloaders");
|
||||||
|
|
||||||
|
gst_type_mark_as_plugin_api (GST_TYPE_AVTP_BASE_PAYLOAD, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_avtp_base_payload_init (GstAvtpBasePayload * avtpbasepayload,
|
||||||
|
gpointer g_class)
|
||||||
|
{
|
||||||
|
GstPadTemplate *templ;
|
||||||
|
GstElement *element = GST_ELEMENT (avtpbasepayload);
|
||||||
|
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
||||||
|
GstAvtpBasePayloadClass *avtpbasepayload_class =
|
||||||
|
GST_AVTP_BASE_PAYLOAD_CLASS (g_class);
|
||||||
|
|
||||||
|
g_assert (avtpbasepayload_class->chain != NULL);
|
||||||
|
|
||||||
|
avtpbasepayload->srcpad = gst_pad_new_from_static_template (&src_template,
|
||||||
|
"src");
|
||||||
|
gst_element_add_pad (element, avtpbasepayload->srcpad);
|
||||||
|
|
||||||
|
templ = gst_element_class_get_pad_template (element_class, "sink");
|
||||||
|
g_assert (templ != NULL);
|
||||||
|
avtpbasepayload->sinkpad = gst_pad_new_from_template (templ, "sink");
|
||||||
|
gst_pad_set_chain_function (avtpbasepayload->sinkpad,
|
||||||
|
avtpbasepayload_class->chain);
|
||||||
|
gst_pad_set_event_function (avtpbasepayload->sinkpad,
|
||||||
|
avtpbasepayload_class->sink_event);
|
||||||
|
gst_element_add_pad (element, avtpbasepayload->sinkpad);
|
||||||
|
|
||||||
|
avtpbasepayload->streamid = DEFAULT_STREAMID;
|
||||||
|
avtpbasepayload->mtt = DEFAULT_MTT;
|
||||||
|
avtpbasepayload->tu = DEFAULT_TU;
|
||||||
|
avtpbasepayload->processing_deadline = DEFAULT_PROCESSING_DEADLINE;
|
||||||
|
|
||||||
|
avtpbasepayload->latency = GST_CLOCK_TIME_NONE;
|
||||||
|
avtpbasepayload->seqnum = 0;
|
||||||
|
gst_segment_init (&avtpbasepayload->segment, GST_FORMAT_UNDEFINED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_avtp_base_payload_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstAvtpBasePayload *avtpbasepayload = GST_AVTP_BASE_PAYLOAD (object);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (avtpbasepayload, "prop_id %u", prop_id);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_STREAMID:
|
||||||
|
avtpbasepayload->streamid = g_value_get_uint64 (value);
|
||||||
|
break;
|
||||||
|
case PROP_MTT:
|
||||||
|
avtpbasepayload->mtt = g_value_get_uint (value);
|
||||||
|
break;
|
||||||
|
case PROP_TU:
|
||||||
|
avtpbasepayload->tu = g_value_get_uint (value);
|
||||||
|
break;
|
||||||
|
case PROP_PROCESSING_DEADLINE:
|
||||||
|
avtpbasepayload->processing_deadline = g_value_get_uint64 (value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_avtp_base_payload_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstAvtpBasePayload *avtpbasepayload = GST_AVTP_BASE_PAYLOAD (object);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (avtpbasepayload, "prop_id %u", prop_id);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_STREAMID:
|
||||||
|
g_value_set_uint64 (value, avtpbasepayload->streamid);
|
||||||
|
break;
|
||||||
|
case PROP_MTT:
|
||||||
|
g_value_set_uint (value, avtpbasepayload->mtt);
|
||||||
|
break;
|
||||||
|
case PROP_TU:
|
||||||
|
g_value_set_uint (value, avtpbasepayload->tu);
|
||||||
|
break;
|
||||||
|
case PROP_PROCESSING_DEADLINE:
|
||||||
|
g_value_set_uint64 (value, avtpbasepayload->processing_deadline);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_avtp_base_payload_sink_event (GstPad * pad, GstObject * parent,
|
||||||
|
GstEvent * event)
|
||||||
|
{
|
||||||
|
GstAvtpBasePayload *avtpbasepayload = GST_AVTP_BASE_PAYLOAD (parent);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (avtpbasepayload, "event %s", GST_EVENT_TYPE_NAME (event));
|
||||||
|
|
||||||
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_SEGMENT:
|
||||||
|
gst_event_copy_segment (event, &avtpbasepayload->segment);
|
||||||
|
/* Fall through */
|
||||||
|
default:
|
||||||
|
return gst_pad_event_default (pad, parent, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GstClockTime
|
||||||
|
gst_avtp_base_payload_calc_ptime (GstAvtpBasePayload * avtpbasepayload,
|
||||||
|
GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
GstClockTime base_time, running_time;
|
||||||
|
|
||||||
|
g_assert (GST_BUFFER_PTS (buffer) != GST_CLOCK_TIME_NONE);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (avtpbasepayload->latency == GST_CLOCK_TIME_NONE)) {
|
||||||
|
GstQuery *query;
|
||||||
|
|
||||||
|
query = gst_query_new_latency ();
|
||||||
|
if (!gst_pad_peer_query (avtpbasepayload->sinkpad, query))
|
||||||
|
return GST_CLOCK_TIME_NONE;
|
||||||
|
gst_query_parse_latency (query, NULL, &avtpbasepayload->latency, NULL);
|
||||||
|
gst_query_unref (query);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (avtpbasepayload, "latency %" GST_TIME_FORMAT,
|
||||||
|
GST_TIME_ARGS (avtpbasepayload->latency));
|
||||||
|
}
|
||||||
|
|
||||||
|
base_time = gst_element_get_base_time (GST_ELEMENT (avtpbasepayload));
|
||||||
|
|
||||||
|
running_time = gst_segment_to_running_time (&avtpbasepayload->segment,
|
||||||
|
avtpbasepayload->segment.format, GST_BUFFER_PTS (buffer));
|
||||||
|
|
||||||
|
return base_time + running_time + avtpbasepayload->latency +
|
||||||
|
avtpbasepayload->processing_deadline + avtpbasepayload->mtt +
|
||||||
|
avtpbasepayload->tu;
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue