Merging gst-plugins-bad

This commit is contained in:
Thibault Saunier 2021-09-24 16:14:03 -03:00
commit 07ad3439ce
2782 changed files with 1503377 additions and 0 deletions

16
.gitignore vendored Normal file
View 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
View file

@ -0,0 +1 @@
include: "https://gitlab.freedesktop.org/gstreamer/gst-ci/raw/master/gitlab/ci_template.yml"

1
.indentignore Normal file
View file

@ -0,0 +1 @@
ext/sctp/usrsctp/usrsctplib/

21
AUTHORS Normal file
View 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
View 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!

229575
ChangeLog Normal file

File diff suppressed because it is too large Load diff

12
MAINTAINERS Normal file
View 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
View 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 thats 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 dont 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
View 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
View 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 didnt 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
View 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
View 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
View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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
View file

@ -0,0 +1 @@
@GST_API_VERSION@

5
docs/index.md Normal file
View file

@ -0,0 +1,5 @@
---
short-description: GStreamer Bad Plugins API reference.
...
# GStreamer Bad Plugins

View file

@ -0,0 +1 @@
# Adaptive Demux library

View file

@ -0,0 +1 @@
c-index

6
docs/libs/audio/index.md Normal file
View 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*

View file

@ -0,0 +1 @@
gi-index

3
docs/libs/base/index.md Normal file
View file

@ -0,0 +1,3 @@
# Base classes from -bad
> NOTE: This library API is considered *unstable*

View file

@ -0,0 +1 @@
gi-index

View 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*

View file

@ -0,0 +1 @@
gi-index

View 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*

View file

@ -0,0 +1 @@
c-index

View file

@ -0,0 +1,3 @@
# GstCodecs
> NOTE: This library API is considered *unstable*

View file

@ -0,0 +1 @@
gi-index

View 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*

View file

@ -0,0 +1 @@
gi-index

104
docs/libs/mpegts/index.md Normal file
View 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"*.

View file

@ -0,0 +1 @@
gi-index

View 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*

View file

@ -0,0 +1 @@
c-index

3
docs/libs/play/index.md Normal file
View file

@ -0,0 +1,3 @@
# Play Library
> NOTE: This library API is considered *unstable*

View file

@ -0,0 +1 @@
gi-index

View file

@ -0,0 +1,3 @@
# Player Library
> NOTE: This library API is considered *unstable*

View file

@ -0,0 +1 @@
gi-index

3
docs/libs/tools/index.md Normal file
View file

@ -0,0 +1,3 @@
# Useful elements
> NOTE: This library API is considered *unstable*

View file

@ -0,0 +1 @@
gi-index

View 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*

View file

@ -0,0 +1 @@
gi-index

3
docs/libs/video/index.md Normal file
View file

@ -0,0 +1,3 @@
# Video helpers and baseclasses
> NOTE: This library API is considered *unstable*

View file

@ -0,0 +1 @@
gi-index

View 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*

View file

@ -0,0 +1 @@
gi-index

View 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*

View file

@ -0,0 +1 @@
gi-index

View 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*

View file

@ -0,0 +1 @@
gi-index

View 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*

View file

@ -0,0 +1 @@
gi-index

245
docs/meson.build Normal file
View 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

File diff suppressed because one or more lines are too long

0
docs/plugins/index.md Normal file
View file

View 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 &lt;nicolas.dufresne@collabora.com&gt;</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 &lt;nicolas.dufresne@collabora.com&gt;</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 &lt;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 &lt;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>

View 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 &lt;george.kiagiadakis@collabora.com&gt;</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 &lt;george.kiagiadakis@collabora.com&gt;</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
View file

@ -0,0 +1 @@
gst-index

17760
docs/random/ChangeLog-0.8 Normal file

File diff suppressed because it is too large Load diff

18
docs/random/LICENSE Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

141
ext/aom/gstav1enc.h Normal file
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

View 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
View 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
View 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
View 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;
}

View 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
View 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
View 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__ */

View 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;
}

View 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__ */

View 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