Merging gstreamer-vaapi

This commit is contained in:
Thibault Saunier 2021-09-24 16:14:50 -03:00
commit f21e6cdab9
282 changed files with 147735 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*~

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"

45
AUTHORS Normal file
View file

@ -0,0 +1,45 @@
Maintainers:
Gwenole Beauchesne - Lead developer
Sreerenj Balachandran - Lead developer
Halley Zhao - MPEG-4:2 decoder
This project is maintained by Intel Corporation.
Contributors (sorted by first name):
Adrian Cox
Alban Browaeys
Changzhi Wei
Cong Zhong
Emilio Lopez
Fabrice Bellet
Feng Yuan
Guangxin Xu
Haihao Xiang
Holger Kaelberer
Jacobo Aragunde Pérez
Jan Schmidt
Javier Jardon
Julien Isorce
Junfeng Xu
Kristian Hogsberg
Lim Siew Hoon
Lionel Landwerlin
Mark Nauwelaerts
Martin Sherburn
Matthew Waters
Matthieu Bouron
Michael Olbrich
Nicolas Dufresne
Olivier Crete
Philip Lorenz
Robert Bradford
Ross Burton
Sebastian Dröge
Simon Farnsworth
Thibault Saunier
Victor Manuel Jaquez Leal
Warly
Xiaowei Li
Yan Yin

502
COPYING.LIB 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!

35983
ChangeLog Normal file

File diff suppressed because it is too large Load diff

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

133
README Normal file
View file

@ -0,0 +1,133 @@
gstreamer-vaapi
VA-API support to GStreamer
Copyright (C) 2010-2011 Splitted-Desktop Systems
Copyright (C) 2011-2020 Intel Corporation
Copyright (C) 2011 Collabora Ltd.
Copyright (C) 2015-2020 Igalia, S.L.
License
-------
gstreamer-vaapi helper libraries and plugin elements are available
under the terms of the GNU Lesser General Public License v2.1+
Overview
--------
gstreamer-vaapi consists in a collection of VA-API based plugins for
GStreamer and helper libraries.
* `vaapi<CODEC>dec' is used to decode JPEG, MPEG-2, MPEG-4:2, H.264
AVC, H.264 MVC, VP8, VP9, VC-1, WMV3, HEVC videos to VA surfaces,
depending on the actual value of <CODEC> and the underlying
hardware capabilities. This plugin is also able to implicitly
download the decoded surface to raw YUV buffers.
* `vaapi<CODEC>enc' is used to encode into MPEG-2, H.264 AVC, H.264
MVC, JPEG, VP8, VP9, HEVC videos, depending on the actual value of
<CODEC> (mpeg2, h264, etc.) and the hardware capabilities. By
default, raw format bitstreams are generated, so the result may be
piped to a muxer, e.g. qtmux for MP4 containers.
* `vaapipostproc' is used to filter VA surfaces, for e.g. scaling,
deinterlacing (bob, motion-adaptive, motion-compensated), noise
reduction or sharpening. This plugin is also used to upload raw
YUV pixels into VA surfaces.
* `vaapisink' is used to render VA surfaces to an X11 or Wayland
display. This plugin also features a "headless" mode (DRM) more
suited to remote transcode scenarios, with faster throughput.
* `vaapioverlay` is a accelerated compositor that blends or
composite different video streams.
Features
--------
* VA-API support from 0.39
* JPEG, MPEG-2, MPEG-4, H.264 AVC, H.264 MVC, VP8, VC-1, HEVC and
VP9 ad-hoc decoders
* MPEG-2, H.264 AVC,H.264 MVC, JPEG, VP8, VP9 and HEVC ad-hoc
encoders
* OpenGL rendering through VA/GLX or GLX texture-from-pixmap + FBO
* Support for EGL backend
* Support for the Wayland display server
* Support for headless decode pipelines with VA/DRM
* Support for major HW video decoding solutions on Linux (AMD,
Intel, NVIDIA)
* Support for HW video encoding on Intel HD Graphics hardware
* Support for VA Video Processing APIs (VA/VPP)
- Scaling and color conversion
- Image enhancement filters: Sharpening, Noise Reductio, Color
Balance, Skin-Tone-Enhancement
- Advanced deinterlacing: Motion-Adaptive, Motion-Compensated
Requirements
------------
Hardware requirements
* Hardware supported by i965 driver or iHD, such as
- Intel Ironlake, Sandybridge, Ivybridge, Haswell, Broadwell,
Skylake, etc. (HD Graphics)
- Intel BayTrail, Braswell
- Intel Poulsbo (US15W)
- Intel Medfield or Cedar Trail
* Hardware supported by AMD Radeonsi driver, such as the list below
- AMD Carrizo, Bristol Ridge, Raven Ridge, Picasso, Renoir
- AMD Tonga, Fiji, Polaris XX, Vega XX, Navi 1X
* Other hardware supported by Mesa VA gallium state-tracker
Usage
-----
VA elements are automatically plugged into GStreamer pipelines. So,
using playbin should work as is.
However, here are a few alternate pipelines that could be manually
constructed.
* Play an H.264 video with an MP4 container in fullscreen mode
$ gst-launch-1.0 -v filesrc location=/path/to/video.mp4 ! \
qtdemux ! vaapidecodebin ! vaapisink fullscreen=true
* Play a raw MPEG-2 interlaced stream
$ gst-launch-1.0 -v filesrc location=/path/to/mpeg2.bits ! \
mpegvideoparse ! vaapimpeg2dec ! vaapipostproc ! vaapisink
* Convert from one pixel format to another, while also downscaling
$ gst-launch-1.0 -v filesrc location=/path/to/raw_video.yuv ! \
videoparse format=yuy2 width=1280 height=720 ! \
vaapipostproc format=nv12 height=480 ! vaapisink
* Encode a 1080p stream in raw I420 format into H.264
$ gst-launch-1.0 -v filesrc location=/path/to/raw_video.yuv ! \
videoparse format=i420 width=1920 height=1080 framerate=30/1 ! \
vaapih264enc rate-control=cbr tune=high-compression ! \
qtmux ! filesink location=/path/to/encoded_video.mp4
Sources
-------
gstreamer-vaapi is Open Source software, so updates to this
framework are really easy to get.
Stable source code releases can be found at:
<https://gstreamer.freedesktop.org/src/gstreamer-vaapi/>
GitLab repository for work-in-progress changes is available at:
<https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi>
Reporting Bugs
--------------
Bugs can be reported in the GStreamer's GitLab system at:
<https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/issues>

96
RELEASE Normal file
View file

@ -0,0 +1,96 @@
This is GStreamer gstreamer-vaapi 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

2018
docs/gst_plugins_cache.json Normal file

File diff suppressed because it is too large Load diff

34
docs/index.md Normal file
View file

@ -0,0 +1,34 @@
---
short-description: GStreamer plugins from gstreamer-vaapi
...
# VAAPI Plugin
## Environment variables
GStreamer-VAAPI inspects a few of environment variables to define it
usage.
**GST_VAAPI_ALL_DRIVERS.**
This environment variable can be set, independently of its value, to
disable the drivers white list. By default only intel and mesa va
drivers are loaded if they are available. The rest are ignored. With
this environment variable defined, all the available va drivers are
loaded, even if they are deprecated.
**LIBVA_DRIVER_NAME.**
This environment variable can be set with the drivers name to load. For
example, intel's driver is `i915`, meanwhile mesa is `gallium`.
**LIBVA_DRIVERS_PATH.**
This environment variable can be set to a colon-separated list of paths
(or a semicolon-separated list on Windows). libva will scan these paths
for va drivers.
**GST_VAAPI_DRM_DEVICE.**
This environment variable can be set to a specified DRM device when DRM
display is used, it is ignored when other types of displays are used.
By default /dev/dri/renderD128 is used for DRM display.

74
docs/meson.build Normal file
View file

@ -0,0 +1,74 @@
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', '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(), 'gst_plugins_cache.json')
if plugins_cache_generator.found()
plugins_doc_dep = custom_target('vaapi-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
build_hotdoc = true
hotdoc = import('hotdoc')
if not hotdoc.has_extensions(required_hotdoc_extensions)
if get_option('doc').enabled()
error('Documentation enabled but gi-extension missing')
endif
message('@0@ extensions not found, not building documentation'.format(required_hotdoc_extensions))
subdir_done()
endif
message('Plugins: @0@'.format(plugins))
libs_doc = []
plugins_doc = [hotdoc.generate_doc('vaapi',
project_version: api_version,
sitemap: 'sitemap.txt',
index: 'index.md',
gst_index: 'index.md',
gst_smart_index: true,
gst_c_sources: ['../gst/*/*.[ch]',],
gst_cache_file: plugins_cache,
gst_plugin_name: 'vaapi',
dependencies: [gstbase_dep, gstvideo_dep, gstallocators_dep, gstpbutils_dep,
libva_dep, gstlibvaapi_dep, gstgl_dep, libm] + plugins,
)]

1
docs/sitemap.txt Normal file
View file

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

1
gst-libs/gst/meson.build Normal file
View file

@ -0,0 +1 @@
subdir('vaapi')

View file

@ -0,0 +1,39 @@
/*
* egl_compat.h - EGL compatiliby layer
*
* Copyright (C) 2014 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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
*/
#ifndef EGL_COMPAT_H
#define EGL_COMPAT_H
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "ogl_compat.h"
#ifndef GL_OES_EGL_image
#define GL_OES_EGL_image 1
typedef void *GLeglImageOES;
typedef void (*PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)(GLenum target,
GLeglImageOES image);
typedef void (*PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)(GLenum target,
GLeglImageOES image);
#endif /* GL_OES_EGL_image */
#endif /* EGL_COMPAT_H */

View file

@ -0,0 +1,806 @@
/*
* egl_vtable.h - EGL function definitions
*
* Copyright (C) 2014 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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
*/
/* ------------------------------------------------------------------------- */
// Generate strings
#define GL_PROTO_GEN_STRING(x) \
GL_PROTO_GEN_STRING_I(x)
#define GL_PROTO_GEN_STRING_I(x) \
#x
/* ------------------------------------------------------------------------- */
// Concatenate arguments
#define GL_PROTO_GEN_CONCAT(a1, a2) \
GL_PROTO_GEN_CONCAT2_I(a1, a2)
#define GL_PROTO_GEN_CONCAT2(a1, a2) \
GL_PROTO_GEN_CONCAT2_I(a1, a2)
#define GL_PROTO_GEN_CONCAT2_I(a1, a2) \
a1 ## a2
#define GL_PROTO_GEN_CONCAT3(a1, a2, a3) \
GL_PROTO_GEN_CONCAT3_I(a1, a2, a3)
#define GL_PROTO_GEN_CONCAT3_I(a1, a2, a3) \
a1 ## a2 ## a3
#define GL_PROTO_GEN_CONCAT4(a1, a2, a3, a4) \
GL_PROTO_GEN_CONCAT4_I(a1, a2, a3, a4)
#define GL_PROTO_GEN_CONCAT4_I(a1, a2, a3, a4) \
a1 ## a2 ## a3 ## a4
#define GL_PROTO_GEN_CONCAT5(a1, a2, a3, a4, a5) \
GL_PROTO_GEN_CONCAT5_I(a1, a2, a3, a4, a5)
#define GL_PROTO_GEN_CONCAT5_I(a1, a2, a3, a4, a5) \
a1 ## a2 ## a3 ## a4 ## a5
/* ------------------------------------------------------------------------- */
// Default macros
#ifndef EGL_PROTO_BEGIN
#define EGL_PROTO_BEGIN(NAME, TYPE, EXTENSION)
#endif
#ifndef EGL_PROTO_ARG_LIST
#define EGL_PROTO_ARG_LIST(...) GL_PROTO_ARG_LIST(__VA_ARGS__)
#endif
#ifndef EGL_PROTO_ARG
#define EGL_PROTO_ARG(NAME, TYPE) GL_PROTO_ARG(NAME, TYPE)
#endif
#ifndef EGL_PROTO_INVOKE
#define EGL_PROTO_INVOKE(NAME, TYPE, ARGS)
#endif
#ifndef EGL_PROTO_END
#define EGL_PROTO_END()
#endif
#ifndef EGL_DEFINE_EXTENSION
#define EGL_DEFINE_EXTENSION(EXTENSION)
#endif
#ifndef GL_PROTO_BEGIN
#define GL_PROTO_BEGIN(NAME, TYPE, EXTENSION)
#endif
#ifndef GL_PROTO_ARG_LIST
#define GL_PROTO_ARG_LIST(...)
#endif
#ifndef GL_PROTO_ARG
#define GL_PROTO_ARG(NAME, TYPE)
#endif
#ifndef GL_PROTO_INVOKE
#define GL_PROTO_INVOKE(NAME, TYPE, ARGS)
#endif
#ifndef GL_PROTO_END
#define GL_PROTO_END()
#endif
#ifndef GL_DEFINE_EXTENSION
#define GL_DEFINE_EXTENSION(EXTENSION)
#endif
/* NOTE: this is auto-generated code -- do not edit! */
EGL_PROTO_BEGIN(CreateImageKHR, EGLImageKHR, KHR_image_base)
EGL_PROTO_ARG_LIST(
EGL_PROTO_ARG(dpy, EGLDisplay),
EGL_PROTO_ARG(ctx, EGLContext),
EGL_PROTO_ARG(target, EGLenum),
EGL_PROTO_ARG(buffer, EGLClientBuffer),
EGL_PROTO_ARG(attrib_list, const EGLint *))
EGL_PROTO_INVOKE(CreateImageKHR, EGLImageKHR, (dpy, ctx, target, buffer, attrib_list))
EGL_PROTO_END()
EGL_PROTO_BEGIN(DestroyImageKHR, EGLImageKHR, KHR_image_base)
EGL_PROTO_ARG_LIST(
EGL_PROTO_ARG(dpy, EGLDisplay),
EGL_PROTO_ARG(image, EGLImageKHR))
EGL_PROTO_INVOKE(DestroyImageKHR, EGLImageKHR, (dpy, image))
EGL_PROTO_END()
EGL_PROTO_BEGIN(CreateDRMImageMESA, EGLImageKHR, MESA_drm_image)
EGL_PROTO_ARG_LIST(
EGL_PROTO_ARG(dpy, EGLDisplay),
EGL_PROTO_ARG(attrib_list, const EGLint *))
EGL_PROTO_INVOKE(CreateDRMImageMESA, EGLImageKHR, (dpy, attrib_list))
EGL_PROTO_END()
EGL_PROTO_BEGIN(ExportDRMImageMESA, EGLImageKHR, MESA_drm_image)
EGL_PROTO_ARG_LIST(
EGL_PROTO_ARG(dpy, EGLDisplay),
EGL_PROTO_ARG(image, EGLImageKHR),
EGL_PROTO_ARG(name, EGLint *),
EGL_PROTO_ARG(handle, EGLint *),
EGL_PROTO_ARG(stride, EGLint *))
EGL_PROTO_INVOKE(ExportDRMImageMESA, EGLImageKHR, (dpy, image, name, handle, stride))
EGL_PROTO_END()
EGL_PROTO_BEGIN(ExportDMABUFImageMESA, EGLBoolean, MESA_image_dma_buf_export)
EGL_PROTO_ARG_LIST(
EGL_PROTO_ARG(dpy, EGLDisplay),
EGL_PROTO_ARG(image, EGLImageKHR),
EGL_PROTO_ARG(fds, int *),
EGL_PROTO_ARG(strides, EGLint *),
EGL_PROTO_ARG(offsets, EGLint *))
EGL_PROTO_INVOKE(ExportDMABUFImageMESA, EGLBoolean, (dpy, image, fds, strides, offsets))
EGL_PROTO_END()
EGL_PROTO_BEGIN(ExportDMABUFImageQueryMESA, EGLBoolean, MESA_image_dma_buf_export)
EGL_PROTO_ARG_LIST(
EGL_PROTO_ARG(dpy, EGLDisplay),
EGL_PROTO_ARG(image, EGLImageKHR),
EGL_PROTO_ARG(fourcc, int *),
EGL_PROTO_ARG(num_planes, int *),
EGL_PROTO_ARG(modifiers, EGLuint64KHR *))
EGL_PROTO_INVOKE(ExportDMABUFImageQueryMESA, EGLBoolean, (dpy, image, fourcc, num_planes, modifiers))
EGL_PROTO_END()
EGL_DEFINE_EXTENSION(EXT_image_dma_buf_import)
EGL_DEFINE_EXTENSION(KHR_create_context)
EGL_DEFINE_EXTENSION(KHR_gl_texture_2D_image)
EGL_DEFINE_EXTENSION(KHR_image_base)
EGL_DEFINE_EXTENSION(KHR_surfaceless_context)
EGL_DEFINE_EXTENSION(MESA_configless_context)
EGL_DEFINE_EXTENSION(MESA_drm_image)
EGL_DEFINE_EXTENSION(MESA_image_dma_buf_export)
GL_PROTO_BEGIN(GetError, GLenum, CORE_1_0)
GL_PROTO_ARG_LIST()
GL_PROTO_INVOKE(GetError, GLenum, ())
GL_PROTO_END()
GL_PROTO_BEGIN(GetString, const GLubyte *, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(name, GLenum))
GL_PROTO_INVOKE(GetString, const GLubyte *, (name))
GL_PROTO_END()
GL_PROTO_BEGIN(GetIntegerv, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(pname, GLenum),
GL_PROTO_ARG(params, GLint *))
GL_PROTO_INVOKE(GetIntegerv, void, (pname, params))
GL_PROTO_END()
GL_PROTO_BEGIN(Enable, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(cap, GLenum))
GL_PROTO_INVOKE(Enable, void, (cap))
GL_PROTO_END()
GL_PROTO_BEGIN(Disable, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(cap, GLenum))
GL_PROTO_INVOKE(Disable, void, (cap))
GL_PROTO_END()
GL_PROTO_BEGIN(IsEnabled, GLboolean, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(cap, GLenum))
GL_PROTO_INVOKE(IsEnabled, GLboolean, (cap))
GL_PROTO_END()
GL_PROTO_BEGIN(Finish, void, CORE_1_0)
GL_PROTO_ARG_LIST()
GL_PROTO_INVOKE(Finish, void, ())
GL_PROTO_END()
GL_PROTO_BEGIN(Flush, void, CORE_1_0)
GL_PROTO_ARG_LIST()
GL_PROTO_INVOKE(Flush, void, ())
GL_PROTO_END()
GL_PROTO_BEGIN(Begin, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(mode, GLenum))
GL_PROTO_INVOKE(Begin, void, (mode))
GL_PROTO_END()
GL_PROTO_BEGIN(End, void, CORE_1_0)
GL_PROTO_ARG_LIST()
GL_PROTO_INVOKE(End, void, ())
GL_PROTO_END()
GL_PROTO_BEGIN(Color4f, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(red, GLfloat),
GL_PROTO_ARG(green, GLfloat),
GL_PROTO_ARG(blue, GLfloat),
GL_PROTO_ARG(alpha, GLfloat))
GL_PROTO_INVOKE(Color4f, void, (red, green, blue, alpha))
GL_PROTO_END()
GL_PROTO_BEGIN(Clear, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(mask, GLbitfield))
GL_PROTO_INVOKE(Clear, void, (mask))
GL_PROTO_END()
GL_PROTO_BEGIN(ClearColor, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(red, GLclampf),
GL_PROTO_ARG(green, GLclampf),
GL_PROTO_ARG(blue, GLclampf),
GL_PROTO_ARG(alpha, GLclampf))
GL_PROTO_INVOKE(ClearColor, void, (red, green, blue, alpha))
GL_PROTO_END()
GL_PROTO_BEGIN(PushMatrix, void, CORE_1_0)
GL_PROTO_ARG_LIST()
GL_PROTO_INVOKE(PushMatrix, void, ())
GL_PROTO_END()
GL_PROTO_BEGIN(PopMatrix, void, CORE_1_0)
GL_PROTO_ARG_LIST()
GL_PROTO_INVOKE(PopMatrix, void, ())
GL_PROTO_END()
GL_PROTO_BEGIN(LoadIdentity, void, CORE_1_0)
GL_PROTO_ARG_LIST()
GL_PROTO_INVOKE(LoadIdentity, void, ())
GL_PROTO_END()
GL_PROTO_BEGIN(MatrixMode, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(mode, GLenum))
GL_PROTO_INVOKE(MatrixMode, void, (mode))
GL_PROTO_END()
GL_PROTO_BEGIN(PushAttrib, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(mask, GLbitfield))
GL_PROTO_INVOKE(PushAttrib, void, (mask))
GL_PROTO_END()
GL_PROTO_BEGIN(PopAttrib, void, CORE_1_0)
GL_PROTO_ARG_LIST()
GL_PROTO_INVOKE(PopAttrib, void, ())
GL_PROTO_END()
GL_PROTO_BEGIN(Viewport, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(x, GLint),
GL_PROTO_ARG(y, GLint),
GL_PROTO_ARG(width, GLsizei),
GL_PROTO_ARG(height, GLsizei))
GL_PROTO_INVOKE(Viewport, void, (x, y, width, height))
GL_PROTO_END()
GL_PROTO_BEGIN(Frustum, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(left, GLdouble),
GL_PROTO_ARG(right, GLdouble),
GL_PROTO_ARG(bottom, GLdouble),
GL_PROTO_ARG(top, GLdouble),
GL_PROTO_ARG(zNear, GLdouble),
GL_PROTO_ARG(zFar, GLdouble))
GL_PROTO_INVOKE(Frustum, void, (left, right, bottom, top, zNear, zFar))
GL_PROTO_END()
GL_PROTO_BEGIN(Scalef, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(x, GLfloat),
GL_PROTO_ARG(y, GLfloat),
GL_PROTO_ARG(z, GLfloat))
GL_PROTO_INVOKE(Scalef, void, (x, y, z))
GL_PROTO_END()
GL_PROTO_BEGIN(Translatef, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(x, GLfloat),
GL_PROTO_ARG(y, GLfloat),
GL_PROTO_ARG(z, GLfloat))
GL_PROTO_INVOKE(Translatef, void, (x, y, z))
GL_PROTO_END()
GL_PROTO_BEGIN(EnableClientState, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(array, GLenum))
GL_PROTO_INVOKE(EnableClientState, void, (array))
GL_PROTO_END()
GL_PROTO_BEGIN(DisableClientState, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(array, GLenum))
GL_PROTO_INVOKE(DisableClientState, void, (array))
GL_PROTO_END()
GL_PROTO_BEGIN(TexCoordPointer, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(size, GLint),
GL_PROTO_ARG(type, GLenum),
GL_PROTO_ARG(stride, GLsizei),
GL_PROTO_ARG(pointer, const GLvoid *))
GL_PROTO_INVOKE(TexCoordPointer, void, (size, type, stride, pointer))
GL_PROTO_END()
GL_PROTO_BEGIN(VertexPointer, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(size, GLint),
GL_PROTO_ARG(type, GLenum),
GL_PROTO_ARG(stride, GLsizei),
GL_PROTO_ARG(pointer, const GLvoid *))
GL_PROTO_INVOKE(VertexPointer, void, (size, type, stride, pointer))
GL_PROTO_END()
GL_PROTO_BEGIN(EnableVertexAttribArray, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(index, GLuint))
GL_PROTO_INVOKE(EnableVertexAttribArray, void, (index))
GL_PROTO_END()
GL_PROTO_BEGIN(DisableVertexAttribArray, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(index, GLuint))
GL_PROTO_INVOKE(DisableVertexAttribArray, void, (index))
GL_PROTO_END()
GL_PROTO_BEGIN(GetVertexAttribPointerv, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(index, GLuint),
GL_PROTO_ARG(pname, GLenum),
GL_PROTO_ARG(pointer, GLvoid **))
GL_PROTO_INVOKE(GetVertexAttribPointerv, void, (index, pname, pointer))
GL_PROTO_END()
GL_PROTO_BEGIN(VertexAttribPointer, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(index, GLuint),
GL_PROTO_ARG(size, GLint),
GL_PROTO_ARG(type, GLenum),
GL_PROTO_ARG(normalized, GLboolean),
GL_PROTO_ARG(stride, GLsizei),
GL_PROTO_ARG(pointer, const GLvoid *))
GL_PROTO_INVOKE(VertexAttribPointer, void, (index, size, type, normalized, stride, pointer))
GL_PROTO_END()
GL_PROTO_BEGIN(DrawArrays, void, CORE_1_1)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(mode, GLenum),
GL_PROTO_ARG(first, GLint),
GL_PROTO_ARG(count, GLsizei))
GL_PROTO_INVOKE(DrawArrays, void, (mode, first, count))
GL_PROTO_END()
GL_PROTO_BEGIN(GenTextures, void, CORE_1_1)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(n, GLsizei),
GL_PROTO_ARG(textures, GLuint *))
GL_PROTO_INVOKE(GenTextures, void, (n, textures))
GL_PROTO_END()
GL_PROTO_BEGIN(DeleteTextures, void, CORE_1_1)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(n, GLsizei),
GL_PROTO_ARG(textures, const GLuint *))
GL_PROTO_INVOKE(DeleteTextures, void, (n, textures))
GL_PROTO_END()
GL_PROTO_BEGIN(BindTexture, void, CORE_1_1)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(target, GLenum),
GL_PROTO_ARG(texture, GLuint))
GL_PROTO_INVOKE(BindTexture, void, (target, texture))
GL_PROTO_END()
GL_PROTO_BEGIN(ActiveTexture, void, CORE_1_3)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(texture, GLenum))
GL_PROTO_INVOKE(ActiveTexture, void, (texture))
GL_PROTO_END()
GL_PROTO_BEGIN(GetTexLevelParameteriv, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(target, GLenum),
GL_PROTO_ARG(level, GLint),
GL_PROTO_ARG(pname, GLenum),
GL_PROTO_ARG(params, GLint *))
GL_PROTO_INVOKE(GetTexLevelParameteriv, void, (target, level, pname, params))
GL_PROTO_END()
GL_PROTO_BEGIN(TexParameterf, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(target, GLenum),
GL_PROTO_ARG(pname, GLenum),
GL_PROTO_ARG(param, GLfloat))
GL_PROTO_INVOKE(TexParameterf, void, (target, pname, param))
GL_PROTO_END()
GL_PROTO_BEGIN(TexParameterfv, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(target, GLenum),
GL_PROTO_ARG(pname, GLenum),
GL_PROTO_ARG(params, const GLfloat *))
GL_PROTO_INVOKE(TexParameterfv, void, (target, pname, params))
GL_PROTO_END()
GL_PROTO_BEGIN(TexParameteri, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(target, GLenum),
GL_PROTO_ARG(pname, GLenum),
GL_PROTO_ARG(param, GLint))
GL_PROTO_INVOKE(TexParameteri, void, (target, pname, param))
GL_PROTO_END()
GL_PROTO_BEGIN(TexParameteriv, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(target, GLenum),
GL_PROTO_ARG(pname, GLenum),
GL_PROTO_ARG(params, const GLint *))
GL_PROTO_INVOKE(TexParameteriv, void, (target, pname, params))
GL_PROTO_END()
GL_PROTO_BEGIN(TexImage2D, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(target, GLenum),
GL_PROTO_ARG(level, GLint),
GL_PROTO_ARG(internalformat, GLint),
GL_PROTO_ARG(width, GLsizei),
GL_PROTO_ARG(height, GLsizei),
GL_PROTO_ARG(border, GLint),
GL_PROTO_ARG(format, GLenum),
GL_PROTO_ARG(type, GLenum),
GL_PROTO_ARG(pixels, const GLvoid *))
GL_PROTO_INVOKE(TexImage2D, void, (target, level, internalformat, width, height, border, format, type, pixels))
GL_PROTO_END()
GL_PROTO_BEGIN(TexSubImage2D, void, CORE_1_1)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(target, GLenum),
GL_PROTO_ARG(level, GLint),
GL_PROTO_ARG(xoffset, GLint),
GL_PROTO_ARG(yoffset, GLint),
GL_PROTO_ARG(width, GLsizei),
GL_PROTO_ARG(height, GLsizei),
GL_PROTO_ARG(format, GLenum),
GL_PROTO_ARG(type, GLenum),
GL_PROTO_ARG(UNUSED, GLuint),
GL_PROTO_ARG(pixels, const GLvoid *))
GL_PROTO_INVOKE(TexSubImage2D, void, (target, level, xoffset, yoffset, width, height, format, type, UNUSED, pixels))
GL_PROTO_END()
GL_PROTO_BEGIN(PixelStoref, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(pname, GLenum),
GL_PROTO_ARG(param, GLfloat))
GL_PROTO_INVOKE(PixelStoref, void, (pname, param))
GL_PROTO_END()
GL_PROTO_BEGIN(PixelStorei, void, CORE_1_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(pname, GLenum),
GL_PROTO_ARG(param, GLint))
GL_PROTO_INVOKE(PixelStorei, void, (pname, param))
GL_PROTO_END()
GL_PROTO_BEGIN(CreateShader, GLuint, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(type, GLenum))
GL_PROTO_INVOKE(CreateShader, GLuint, (type))
GL_PROTO_END()
GL_PROTO_BEGIN(DeleteShader, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(program, GLuint))
GL_PROTO_INVOKE(DeleteShader, void, (program))
GL_PROTO_END()
GL_PROTO_BEGIN(ShaderSource, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(shader, GLuint),
GL_PROTO_ARG(count, GLsizei),
GL_PROTO_ARG(string, const GLchar * const *),
GL_PROTO_ARG(length, const GLint *))
GL_PROTO_INVOKE(ShaderSource, void, (shader, count, string, length))
GL_PROTO_END()
GL_PROTO_BEGIN(CompileShader, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(shader, GLuint))
GL_PROTO_INVOKE(CompileShader, void, (shader))
GL_PROTO_END()
GL_PROTO_BEGIN(GetShaderiv, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(shader, GLuint),
GL_PROTO_ARG(pname, GLenum),
GL_PROTO_ARG(params, GLint *))
GL_PROTO_INVOKE(GetShaderiv, void, (shader, pname, params))
GL_PROTO_END()
GL_PROTO_BEGIN(GetShaderInfoLog, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(shader, GLuint),
GL_PROTO_ARG(bufSize, GLsizei),
GL_PROTO_ARG(length, GLsizei *),
GL_PROTO_ARG(infoLog, GLchar *))
GL_PROTO_INVOKE(GetShaderInfoLog, void, (shader, bufSize, length, infoLog))
GL_PROTO_END()
GL_PROTO_BEGIN(CreateProgram, GLuint, CORE_2_0)
GL_PROTO_ARG_LIST()
GL_PROTO_INVOKE(CreateProgram, GLuint, ())
GL_PROTO_END()
GL_PROTO_BEGIN(DeleteProgram, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(program, GLuint))
GL_PROTO_INVOKE(DeleteProgram, void, (program))
GL_PROTO_END()
GL_PROTO_BEGIN(AttachShader, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(program, GLuint),
GL_PROTO_ARG(shader, GLuint))
GL_PROTO_INVOKE(AttachShader, void, (program, shader))
GL_PROTO_END()
GL_PROTO_BEGIN(LinkProgram, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(program, GLuint))
GL_PROTO_INVOKE(LinkProgram, void, (program))
GL_PROTO_END()
GL_PROTO_BEGIN(UseProgram, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(program, GLuint))
GL_PROTO_INVOKE(UseProgram, void, (program))
GL_PROTO_END()
GL_PROTO_BEGIN(GetProgramiv, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(program, GLuint),
GL_PROTO_ARG(pname, GLenum),
GL_PROTO_ARG(params, GLint *))
GL_PROTO_INVOKE(GetProgramiv, void, (program, pname, params))
GL_PROTO_END()
GL_PROTO_BEGIN(GetProgramInfoLog, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(program, GLuint),
GL_PROTO_ARG(bufSize, GLsizei),
GL_PROTO_ARG(length, GLsizei *),
GL_PROTO_ARG(infoLog, GLchar *))
GL_PROTO_INVOKE(GetProgramInfoLog, void, (program, bufSize, length, infoLog))
GL_PROTO_END()
GL_PROTO_BEGIN(BindAttribLocation, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(program, GLuint),
GL_PROTO_ARG(index, GLuint),
GL_PROTO_ARG(name, const GLchar *))
GL_PROTO_INVOKE(BindAttribLocation, void, (program, index, name))
GL_PROTO_END()
GL_PROTO_BEGIN(GetUniformLocation, GLint, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(program, GLuint),
GL_PROTO_ARG(name, const GLchar *))
GL_PROTO_INVOKE(GetUniformLocation, GLint, (program, name))
GL_PROTO_END()
GL_PROTO_BEGIN(Uniform1f, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(v0, GLfloat))
GL_PROTO_INVOKE(Uniform1f, void, (location, v0))
GL_PROTO_END()
GL_PROTO_BEGIN(Uniform1fv, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(count, GLsizei),
GL_PROTO_ARG(value, const GLfloat *))
GL_PROTO_INVOKE(Uniform1fv, void, (location, count, value))
GL_PROTO_END()
GL_PROTO_BEGIN(Uniform1i, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(v0, GLint))
GL_PROTO_INVOKE(Uniform1i, void, (location, v0))
GL_PROTO_END()
GL_PROTO_BEGIN(Uniform1iv, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(count, GLsizei),
GL_PROTO_ARG(value, const GLint *))
GL_PROTO_INVOKE(Uniform1iv, void, (location, count, value))
GL_PROTO_END()
GL_PROTO_BEGIN(Uniform2f, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(v0, GLfloat),
GL_PROTO_ARG(v1, GLfloat))
GL_PROTO_INVOKE(Uniform2f, void, (location, v0, v1))
GL_PROTO_END()
GL_PROTO_BEGIN(Uniform2fv, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(count, GLsizei),
GL_PROTO_ARG(value, const GLfloat *))
GL_PROTO_INVOKE(Uniform2fv, void, (location, count, value))
GL_PROTO_END()
GL_PROTO_BEGIN(Uniform2i, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(v0, GLint),
GL_PROTO_ARG(v1, GLint))
GL_PROTO_INVOKE(Uniform2i, void, (location, v0, v1))
GL_PROTO_END()
GL_PROTO_BEGIN(Uniform2iv, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(count, GLsizei),
GL_PROTO_ARG(value, const GLint *))
GL_PROTO_INVOKE(Uniform2iv, void, (location, count, value))
GL_PROTO_END()
GL_PROTO_BEGIN(Uniform3f, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(v0, GLfloat),
GL_PROTO_ARG(v1, GLfloat),
GL_PROTO_ARG(v2, GLfloat))
GL_PROTO_INVOKE(Uniform3f, void, (location, v0, v1, v2))
GL_PROTO_END()
GL_PROTO_BEGIN(Uniform3fv, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(count, GLsizei),
GL_PROTO_ARG(value, const GLfloat *))
GL_PROTO_INVOKE(Uniform3fv, void, (location, count, value))
GL_PROTO_END()
GL_PROTO_BEGIN(Uniform3i, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(v0, GLint),
GL_PROTO_ARG(v1, GLint),
GL_PROTO_ARG(v2, GLint))
GL_PROTO_INVOKE(Uniform3i, void, (location, v0, v1, v2))
GL_PROTO_END()
GL_PROTO_BEGIN(Uniform3iv, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(count, GLsizei),
GL_PROTO_ARG(value, const GLint *))
GL_PROTO_INVOKE(Uniform3iv, void, (location, count, value))
GL_PROTO_END()
GL_PROTO_BEGIN(Uniform4f, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(v0, GLfloat),
GL_PROTO_ARG(v1, GLfloat),
GL_PROTO_ARG(v2, GLfloat),
GL_PROTO_ARG(v3, GLfloat))
GL_PROTO_INVOKE(Uniform4f, void, (location, v0, v1, v2, v3))
GL_PROTO_END()
GL_PROTO_BEGIN(Uniform4fv, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(count, GLsizei),
GL_PROTO_ARG(value, const GLfloat *))
GL_PROTO_INVOKE(Uniform4fv, void, (location, count, value))
GL_PROTO_END()
GL_PROTO_BEGIN(Uniform4i, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(v0, GLint),
GL_PROTO_ARG(v1, GLint),
GL_PROTO_ARG(v2, GLint),
GL_PROTO_ARG(v3, GLint))
GL_PROTO_INVOKE(Uniform4i, void, (location, v0, v1, v2, v3))
GL_PROTO_END()
GL_PROTO_BEGIN(Uniform4iv, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(count, GLsizei),
GL_PROTO_ARG(value, const GLint *))
GL_PROTO_INVOKE(Uniform4iv, void, (location, count, value))
GL_PROTO_END()
GL_PROTO_BEGIN(UniformMatrix2fv, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(count, GLsizei),
GL_PROTO_ARG(transpose, GLboolean),
GL_PROTO_ARG(value, const GLfloat *))
GL_PROTO_INVOKE(UniformMatrix2fv, void, (location, count, transpose, value))
GL_PROTO_END()
GL_PROTO_BEGIN(UniformMatrix3fv, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(count, GLsizei),
GL_PROTO_ARG(transpose, GLboolean),
GL_PROTO_ARG(value, const GLfloat *))
GL_PROTO_INVOKE(UniformMatrix3fv, void, (location, count, transpose, value))
GL_PROTO_END()
GL_PROTO_BEGIN(UniformMatrix4fv, void, CORE_2_0)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(location, GLint),
GL_PROTO_ARG(count, GLsizei),
GL_PROTO_ARG(transpose, GLboolean),
GL_PROTO_ARG(value, const GLfloat *))
GL_PROTO_INVOKE(UniformMatrix4fv, void, (location, count, transpose, value))
GL_PROTO_END()
GL_PROTO_BEGIN(EGLImageTargetTexture2DOES, void, OES_EGL_image)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(target, GLenum),
GL_PROTO_ARG(image, void *))
GL_PROTO_INVOKE(EGLImageTargetTexture2DOES, void, (target, image))
GL_PROTO_END()
GL_PROTO_BEGIN(EGLImageTargetRenderbufferStorageOES, void, OES_EGL_image)
GL_PROTO_ARG_LIST(
GL_PROTO_ARG(target, GLenum),
GL_PROTO_ARG(image, void *))
GL_PROTO_INVOKE(EGLImageTargetRenderbufferStorageOES, void, (target, image))
GL_PROTO_END()
GL_DEFINE_EXTENSION(CORE_1_0)
GL_DEFINE_EXTENSION(CORE_1_1)
GL_DEFINE_EXTENSION(CORE_1_3)
GL_DEFINE_EXTENSION(CORE_2_0)
GL_DEFINE_EXTENSION(OES_EGL_image)
#undef EGL_PROTO_BEGIN
#undef EGL_PROTO_BEGIN_I
#undef EGL_PROTO_ARG_LIST
#undef EGL_PROTO_ARG
#undef EGL_PROTO_INVOKE
#undef EGL_PROTO_INVOKE_I
#undef EGL_PROTO_END
#undef EGL_DEFINE_EXTENSION
#undef EGL_DEFINE_EXTENSION_I
#undef GL_PROTO_BEGIN
#undef GL_PROTO_BEGIN_I
#undef GL_PROTO_ARG_LIST
#undef GL_PROTO_ARG
#undef GL_PROTO_INVOKE
#undef GL_PROTO_INVOKE_I
#undef GL_PROTO_END
#undef GL_DEFINE_EXTENSION
#undef GL_DEFINE_EXTENSION_I
#undef GL_PROTO_GEN_CONCAT5
#undef GL_PROTO_GEN_CONCAT5_I
#undef GL_PROTO_GEN_CONCAT4
#undef GL_PROTO_GEN_CONCAT4_I
#undef GL_PROTO_GEN_CONCAT3
#undef GL_PROTO_GEN_CONCAT3_I
#undef GL_PROTO_GEN_CONCAT2
#undef GL_PROTO_GEN_CONCAT2_I
#undef GL_PROTO_GEN_CONCAT
#undef GL_PROTO_GEN_STRING
#undef GL_PROTO_GEN_STRING_I

View file

@ -0,0 +1,326 @@
/*
* gstvaapiblend.c - Video processing blend
*
* Copyright (C) 2019 Intel Corporation
* Author: U. Artie Eoff <ullysses.a.eoff@intel.com>
*
* 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 "sysdeps.h"
#include "gstvaapicompat.h"
#include "gstvaapiblend.h"
#include "gstvaapiutils.h"
#include "gstvaapivalue.h"
#include "gstvaapidisplay_priv.h"
#include "gstvaapisurface_priv.h"
struct _GstVaapiBlend
{
GstObject parent_instance;
GstVaapiDisplay *display;
VAConfigID va_config;
VAContextID va_context;
guint32 flags;
};
typedef struct _GstVaapiBlendClass GstVaapiBlendClass;
struct _GstVaapiBlendClass
{
GstObjectClass parent_class;
};
GST_DEBUG_CATEGORY_STATIC (gst_debug_vaapi_blend);
#ifndef GST_DISABLE_GST_DEBUG
#define GST_CAT_DEFAULT gst_debug_vaapi_blend
#else
#define GST_CAT_DEFAULT NULL
#endif
G_DEFINE_TYPE_WITH_CODE (GstVaapiBlend, gst_vaapi_blend, GST_TYPE_OBJECT,
GST_DEBUG_CATEGORY_INIT (gst_debug_vaapi_blend, "vaapiblend", 0,
"VA-API Blend"));
enum
{
PROP_DISPLAY = 1,
};
static void
gst_vaapi_blend_set_property (GObject * object, guint property_id,
const GValue * value, GParamSpec * pspec)
{
GstVaapiBlend *const blend = GST_VAAPI_BLEND (object);
switch (property_id) {
case PROP_DISPLAY:{
GstVaapiDisplay *display = g_value_get_object (value);;
if (display) {
if (GST_VAAPI_DISPLAY_HAS_VPP (display)) {
blend->display = gst_object_ref (display);
} else {
GST_WARNING_OBJECT (blend, "GstVaapiDisplay doesn't support VPP");
}
}
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
gst_vaapi_blend_get_property (GObject * object, guint property_id,
GValue * value, GParamSpec * pspec)
{
GstVaapiBlend *const blend = GST_VAAPI_BLEND (object);
switch (property_id) {
case PROP_DISPLAY:
g_value_set_object (value, blend->display);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
gst_vaapi_blend_finalize (GObject * object)
{
GstVaapiBlend *const blend = GST_VAAPI_BLEND (object);
if (!blend->display)
goto bail;
GST_VAAPI_DISPLAY_LOCK (blend->display);
if (blend->va_context != VA_INVALID_ID) {
vaDestroyContext (GST_VAAPI_DISPLAY_VADISPLAY (blend->display),
blend->va_context);
blend->va_context = VA_INVALID_ID;
}
if (blend->va_config != VA_INVALID_ID) {
vaDestroyConfig (GST_VAAPI_DISPLAY_VADISPLAY (blend->display),
blend->va_config);
blend->va_config = VA_INVALID_ID;
}
GST_VAAPI_DISPLAY_UNLOCK (blend->display);
gst_vaapi_display_replace (&blend->display, NULL);
bail:
G_OBJECT_CLASS (gst_vaapi_blend_parent_class)->finalize (object);
}
static void
gst_vaapi_blend_class_init (GstVaapiBlendClass * klass)
{
GObjectClass *const object_class = G_OBJECT_CLASS (klass);
object_class->set_property = gst_vaapi_blend_set_property;
object_class->get_property = gst_vaapi_blend_get_property;
object_class->finalize = gst_vaapi_blend_finalize;
g_object_class_install_property (object_class, PROP_DISPLAY,
g_param_spec_object ("display", "Gst VA-API Display",
"The VA-API display object to use", GST_TYPE_VAAPI_DISPLAY,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME));
}
static void
gst_vaapi_blend_init (GstVaapiBlend * blend)
{
blend->display = NULL;
blend->va_config = VA_INVALID_ID;
blend->va_context = VA_INVALID_ID;
blend->flags = 0;
}
static gboolean
gst_vaapi_blend_initialize (GstVaapiBlend * blend)
{
VAStatus status;
VAProcPipelineCaps pipeline_caps = { 0, };
if (!blend->display)
return FALSE;
status = vaCreateConfig (GST_VAAPI_DISPLAY_VADISPLAY (blend->display),
VAProfileNone, VAEntrypointVideoProc, NULL, 0, &blend->va_config);
if (!vaapi_check_status (status, "vaCreateConfig() [VPP]"))
return FALSE;
status = vaCreateContext (GST_VAAPI_DISPLAY_VADISPLAY (blend->display),
blend->va_config, 0, 0, 0, NULL, 0, &blend->va_context);
if (!vaapi_check_status (status, "vaCreateContext() [VPP]"))
return FALSE;
#if VA_CHECK_VERSION(1,1,0)
status =
vaQueryVideoProcPipelineCaps (GST_VAAPI_DISPLAY_VADISPLAY
(blend->display), blend->va_context, NULL, 0, &pipeline_caps);
if (vaapi_check_status (status, "vaQueryVideoProcPipelineCaps()"))
blend->flags = pipeline_caps.blend_flags;
if (!(blend->flags & VA_BLEND_GLOBAL_ALPHA)) {
GST_WARNING_OBJECT (blend, "VPP does not support global alpha blending");
return FALSE;
}
#else
return FALSE;
#endif
return TRUE;
}
GstVaapiBlend *
gst_vaapi_blend_new (GstVaapiDisplay * display)
{
GstVaapiBlend *blend = g_object_new (GST_TYPE_VAAPI_BLEND,
"display", display, NULL);
if (!gst_vaapi_blend_initialize (blend)) {
gst_object_unref (blend);
blend = NULL;
}
return blend;
}
void
gst_vaapi_blend_replace (GstVaapiBlend ** old_blend_ptr,
GstVaapiBlend * new_blend)
{
g_return_if_fail (old_blend_ptr != NULL);
gst_object_replace ((GstObject **) old_blend_ptr, GST_OBJECT (new_blend));
}
static gboolean
gst_vaapi_blend_process_unlocked (GstVaapiBlend * blend,
GstVaapiSurface * output, GstVaapiBlendSurfaceNextFunc next,
gpointer user_data)
{
VAStatus va_status;
VADisplay va_display;
GstVaapiBlendSurface *current;
va_display = GST_VAAPI_DISPLAY_VADISPLAY (blend->display);
va_status = vaBeginPicture (va_display, blend->va_context,
GST_VAAPI_SURFACE_ID (output));
if (!vaapi_check_status (va_status, "vaBeginPicture()"))
return FALSE;
current = next (user_data);
for (; current; current = next (user_data)) {
VAProcPipelineParameterBuffer *param = NULL;
VABufferID id = VA_INVALID_ID;
VARectangle src_rect = { 0, };
VARectangle dst_rect = { 0, };
#if VA_CHECK_VERSION(1,1,0)
VABlendState blend_state;
#endif
if (!current->surface)
return FALSE;
/* Build surface region (source) */
src_rect.width = GST_VAAPI_SURFACE_WIDTH (current->surface);
src_rect.height = GST_VAAPI_SURFACE_HEIGHT (current->surface);
if (current->crop) {
if ((current->crop->x + current->crop->width > src_rect.width) ||
(current->crop->y + current->crop->height > src_rect.height))
return FALSE;
src_rect.x = current->crop->x;
src_rect.y = current->crop->y;
src_rect.width = current->crop->width;
src_rect.height = current->crop->height;
}
/* Build output region (target) */
dst_rect.x = current->target.x;
dst_rect.y = current->target.y;
dst_rect.width = current->target.width;
dst_rect.height = current->target.height;
if (!vaapi_create_buffer (va_display, blend->va_context,
VAProcPipelineParameterBufferType, sizeof (*param), NULL, &id,
(gpointer *) & param))
return FALSE;
memset (param, 0, sizeof (*param));
param->surface = GST_VAAPI_SURFACE_ID (current->surface);
param->surface_region = &src_rect;
param->output_region = &dst_rect;
param->output_background_color = 0xff000000;
#if VA_CHECK_VERSION(1,1,0)
blend_state.flags = VA_BLEND_GLOBAL_ALPHA;
blend_state.global_alpha = current->alpha;
param->blend_state = &blend_state;
#endif
vaapi_unmap_buffer (va_display, id, NULL);
va_status = vaRenderPicture (va_display, blend->va_context, &id, 1);
vaapi_destroy_buffer (va_display, &id);
if (!vaapi_check_status (va_status, "vaRenderPicture()"))
return FALSE;
}
va_status = vaEndPicture (va_display, blend->va_context);
if (!vaapi_check_status (va_status, "vaEndPicture()"))
return FALSE;
return TRUE;
}
/**
* gst_vaapi_blend_process:
* @blend: a #GstVaapiBlend instance.
* @output: a #GstVaapiSurface to be composed.
* @next: a function to fetch the next #GstVaapiBlendSurface to
* process.
* @data: state storage for @next.
*
* This function will process all the input surfaces defined through
* #GstVaapiBlendSurface and will blend them onto the @output surface.
*
* Returns: %TRUE if the blend process succeed; otherwise %FALSE.
**/
gboolean
gst_vaapi_blend_process (GstVaapiBlend * blend, GstVaapiSurface * output,
GstVaapiBlendSurfaceNextFunc next, gpointer user_data)
{
gboolean result;
g_return_val_if_fail (blend != NULL, FALSE);
g_return_val_if_fail (output != NULL, FALSE);
g_return_val_if_fail (next != NULL, FALSE);
GST_VAAPI_DISPLAY_LOCK (blend->display);
result = gst_vaapi_blend_process_unlocked (blend, output, next, user_data);
GST_VAAPI_DISPLAY_UNLOCK (blend->display);
return result;
}

View file

@ -0,0 +1,68 @@
/*
* gstvaapiblend.h - Video processing blend
*
* Copyright (C) 2019 Intel Corporation
* Author: U. Artie Eoff <ullysses.a.eoff@intel.com>
*
* 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_VAAPI_BLEND_H
#define GST_VAAPI_BLEND_H
#include <gst/vaapi/gstvaapisurface.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_BLEND \
(gst_vaapi_blend_get_type ())
#define GST_VAAPI_BLEND(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_BLEND, GstVaapiBlend))
#define GST_IS_VAAPI_BLEND(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_BLEND))
typedef struct _GstVaapiBlend GstVaapiBlend;
typedef struct _GstVaapiBlendSurface GstVaapiBlendSurface;
struct _GstVaapiBlendSurface
{
GstVaapiSurface const *surface;
const GstVaapiRectangle *crop;
GstVaapiRectangle target;
gdouble alpha;
};
typedef GstVaapiBlendSurface* (*GstVaapiBlendSurfaceNextFunc)(gpointer data);
GstVaapiBlend *
gst_vaapi_blend_new (GstVaapiDisplay * display);
void
gst_vaapi_blend_replace (GstVaapiBlend ** old_blend_ptr,
GstVaapiBlend * new_blend);
gboolean
gst_vaapi_blend_process (GstVaapiBlend * blend, GstVaapiSurface * output,
GstVaapiBlendSurfaceNextFunc next, gpointer user_data);
GType
gst_vaapi_blend_get_type (void) G_GNUC_CONST;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiBlend, gst_object_unref)
G_END_DECLS
#endif /* GST_VAAPI_FILTER_H */

View file

@ -0,0 +1,297 @@
/*
* gstvaapibufferproxy.c - Buffer proxy abstraction
*
* Copyright (C) 2014 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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 "sysdeps.h"
#include "gstvaapicompat.h"
#include "gstvaapibufferproxy.h"
#include "gstvaapibufferproxy_priv.h"
#include "gstvaapisurface_priv.h"
#include "gstvaapiutils.h"
#define DEBUG 1
#include "gstvaapidebug.h"
static gboolean
gst_vaapi_buffer_proxy_acquire_handle (GstVaapiBufferProxy * proxy)
{
GstVaapiDisplay *display;
const guint mem_type = proxy->va_info.mem_type;
VAStatus va_status;
if (proxy->va_info.handle)
return TRUE;
if (!proxy->surface || proxy->va_buf == VA_INVALID_ID)
return FALSE;
display = GST_VAAPI_SURFACE_DISPLAY (GST_VAAPI_SURFACE (proxy->surface));
GST_VAAPI_DISPLAY_LOCK (display);
va_status = vaAcquireBufferHandle (GST_VAAPI_DISPLAY_VADISPLAY (display),
proxy->va_buf, &proxy->va_info);
GST_VAAPI_DISPLAY_UNLOCK (display);
if (!vaapi_check_status (va_status, "vaAcquireBufferHandle()"))
return FALSE;
if (proxy->va_info.mem_type != mem_type)
return FALSE;
return TRUE;
}
static gboolean
gst_vaapi_buffer_proxy_release_handle (GstVaapiBufferProxy * proxy)
{
GstVaapiDisplay *display;
VAStatus va_status;
if (!proxy->va_info.handle)
return TRUE;
if (!proxy->surface || proxy->va_buf == VA_INVALID_ID)
return FALSE;
display = GST_VAAPI_SURFACE_DISPLAY (GST_VAAPI_SURFACE (proxy->surface));
GST_VAAPI_DISPLAY_LOCK (display);
va_status = vaReleaseBufferHandle (GST_VAAPI_DISPLAY_VADISPLAY (display),
proxy->va_buf);
GST_VAAPI_DISPLAY_UNLOCK (display);
if (!vaapi_check_status (va_status, "vaReleaseBufferHandle()"))
return FALSE;
return TRUE;
}
static void
gst_vaapi_buffer_proxy_finalize (GstVaapiBufferProxy * proxy)
{
gst_vaapi_buffer_proxy_release_handle (proxy);
/* Notify the user function that the object is now destroyed */
if (proxy->destroy_func)
proxy->destroy_func (proxy->destroy_data);
proxy->surface = NULL;
}
static inline const GstVaapiMiniObjectClass *
gst_vaapi_buffer_proxy_class (void)
{
static const GstVaapiMiniObjectClass GstVaapiBufferProxyClass = {
sizeof (GstVaapiBufferProxy),
(GDestroyNotify) gst_vaapi_buffer_proxy_finalize
};
return &GstVaapiBufferProxyClass;
}
GstVaapiBufferProxy *
gst_vaapi_buffer_proxy_new (guintptr handle, guint type, gsize size,
GDestroyNotify destroy_func, gpointer user_data)
{
GstVaapiBufferProxy *proxy;
g_return_val_if_fail (handle != 0, NULL);
g_return_val_if_fail (size > 0, NULL);
proxy = (GstVaapiBufferProxy *)
gst_vaapi_mini_object_new (gst_vaapi_buffer_proxy_class ());
if (!proxy)
return NULL;
proxy->surface = NULL;
proxy->destroy_func = destroy_func;
proxy->destroy_data = user_data;
proxy->type = type;
proxy->va_buf = VA_INVALID_ID;
proxy->va_info.handle = handle;
proxy->va_info.type = VAImageBufferType;
proxy->va_info.mem_type = from_GstVaapiBufferMemoryType (proxy->type);
proxy->va_info.mem_size = size;
if (!proxy->va_info.mem_type)
goto error_unsupported_mem_type;
return proxy;
/* ERRORS */
error_unsupported_mem_type:
{
GST_ERROR ("unsupported buffer type (%d)", proxy->type);
gst_vaapi_buffer_proxy_unref (proxy);
return NULL;
}
}
GstVaapiBufferProxy *
gst_vaapi_buffer_proxy_new_from_surface (GstMiniObject * surface,
VABufferID buf_id, guint type, GDestroyNotify destroy_func, gpointer data)
{
GstVaapiBufferProxy *proxy;
g_return_val_if_fail (surface != NULL, NULL);
proxy = (GstVaapiBufferProxy *)
gst_vaapi_mini_object_new (gst_vaapi_buffer_proxy_class ());
if (!proxy)
return NULL;
proxy->surface = surface;
proxy->destroy_func = destroy_func;
proxy->destroy_data = data;
proxy->type = type;
proxy->va_buf = buf_id;
memset (&proxy->va_info, 0, sizeof (proxy->va_info));
proxy->va_info.mem_type = from_GstVaapiBufferMemoryType (proxy->type);
if (!proxy->va_info.mem_type)
goto error_unsupported_mem_type;
if (!gst_vaapi_buffer_proxy_acquire_handle (proxy))
goto error_acquire_handle;
return proxy;
/* ERRORS */
error_unsupported_mem_type:
{
GST_ERROR ("unsupported buffer type (%d)", proxy->type);
gst_vaapi_buffer_proxy_unref (proxy);
return NULL;
}
error_acquire_handle:
{
GST_ERROR ("failed to acquire the underlying VA buffer handle");
gst_vaapi_buffer_proxy_unref (proxy);
return NULL;
}
}
/**
* gst_vaapi_buffer_proxy_ref:
* @proxy: a #GstVaapiBufferProxy
*
* Atomically increases the reference count of the given @proxy by one.
*
* Returns: The same @proxy argument
*/
GstVaapiBufferProxy *
gst_vaapi_buffer_proxy_ref (GstVaapiBufferProxy * proxy)
{
g_return_val_if_fail (proxy != NULL, NULL);
return (GstVaapiBufferProxy *)
gst_vaapi_mini_object_ref (GST_VAAPI_MINI_OBJECT (proxy));
}
/**
* gst_vaapi_buffer_proxy_unref:
* @proxy: a #GstVaapiBufferProxy
*
* Atomically decreases the reference count of the @proxy by one. If
* the reference count reaches zero, the object will be free'd.
*/
void
gst_vaapi_buffer_proxy_unref (GstVaapiBufferProxy * proxy)
{
g_return_if_fail (proxy != NULL);
gst_vaapi_mini_object_unref (GST_VAAPI_MINI_OBJECT (proxy));
}
/**
* gst_vaapi_buffer_proxy_replace:
* @old_proxy_ptr: a pointer to a #GstVaapiBufferProxy
* @new_proxy: a #GstVaapiBufferProxy
*
* Atomically replaces the proxy object held in @old_proxy_ptr with
* @new_proxy. This means that @old_proxy_ptr shall reference a valid
* object. However, @new_proxy can be NULL.
*/
void
gst_vaapi_buffer_proxy_replace (GstVaapiBufferProxy ** old_proxy_ptr,
GstVaapiBufferProxy * new_proxy)
{
g_return_if_fail (old_proxy_ptr != NULL);
gst_vaapi_mini_object_replace ((GstVaapiMiniObject **) (old_proxy_ptr),
GST_VAAPI_MINI_OBJECT (new_proxy));
}
/**
* gst_vaapi_buffer_proxy_get_type:
* @proxy: a #GstVaapiBufferProxy
*
* Returns the underlying VA buffer memory type.
*
* Return value: the buffer memory type
*/
guint
gst_vaapi_buffer_proxy_get_type (GstVaapiBufferProxy * proxy)
{
g_return_val_if_fail (proxy != NULL, 0);
return GST_VAAPI_BUFFER_PROXY_TYPE (proxy);
}
/**
* gst_vaapi_buffer_proxy_get_handle:
* @proxy: a #GstVaapiBufferProxy
*
* Returns the underlying VA buffer handle stored in the @proxy.
*
* Return value: the buffer handle
*/
guintptr
gst_vaapi_buffer_proxy_get_handle (GstVaapiBufferProxy * proxy)
{
g_return_val_if_fail (proxy != NULL, 0);
return GST_VAAPI_BUFFER_PROXY_HANDLE (proxy);
}
/**
* gst_vaapi_buffer_proxy_get_size:
* @proxy: a #GstVaapiBufferProxy
*
* Returns the underlying VA buffer memory size in bytes.
*
* Return value: the buffer size in bytes
*/
gsize
gst_vaapi_buffer_proxy_get_size (GstVaapiBufferProxy * proxy)
{
g_return_val_if_fail (proxy != NULL, 0);
return GST_VAAPI_BUFFER_PROXY_SIZE (proxy);
}
/**
* gst_vaapi_buffer_proxy_release_data:
* @proxy: a #GstVaapiBufferProxy
*
* Notifies the user to destroy the user's data, though the @proxy is
* not going to be destroyed.
**/
void
gst_vaapi_buffer_proxy_release_data (GstVaapiBufferProxy * proxy)
{
g_return_if_fail (proxy != NULL);
if (proxy->destroy_func) {
proxy->destroy_func (proxy->destroy_data);
proxy->destroy_func = NULL;
proxy->destroy_data = NULL;
}
}

View file

@ -0,0 +1,106 @@
/*
* gstvaapibufferproxy.h - Buffer proxy abstraction
*
* Copyright (C) 2014 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_BUFFER_PROXY_H
#define GST_VAAPI_BUFFER_PROXY_H
G_BEGIN_DECLS
#define GST_VAAPI_BUFFER_PROXY(obj) \
((GstVaapiBufferProxy *)(obj))
/**
* GST_VAAPI_BUFFER_PROXY_TYPE:
* @buf: a #GstVaapiBufferProxy
*
* Macro that evaluates to the type of the underlying VA buffer @buf
*/
#define GST_VAAPI_BUFFER_PROXY_TYPE(buf) \
gst_vaapi_buffer_proxy_get_type (GST_VAAPI_BUFFER_PROXY (buf))
/**
* GST_VAAPI_BUFFER_PROXY_HANDLE:
* @buf: a #GstVaapiBufferProxy
*
* Macro that evaluates to the handle of the underlying VA buffer @buf
*/
#define GST_VAAPI_BUFFER_PROXY_HANDLE(buf) \
gst_vaapi_buffer_proxy_get_handle (GST_VAAPI_BUFFER_PROXY (buf))
/**
* GST_VAAPI_BUFFER_PROXY_SIZE:
* @buf: a #GstVaapiBufferProxy
*
* Macro that evaluates to the size of the underlying VA buffer @buf
*/
#define GST_VAAPI_BUFFER_PROXY_SIZE(buf) \
gst_vaapi_buffer_proxy_get_size (GST_VAAPI_BUFFER_PROXY (buf))
typedef struct _GstVaapiBufferProxy GstVaapiBufferProxy;
/**
* GstVaapiBufferMemoryType:
* @GST_VAAPI_BUFFER_MEMORY_TYPE_DMA_BUF: DRM PRIME buffer memory type (old version).
* @GST_VAAPI_BUFFER_MEMORY_TYPE_DMA_BUF2: DRM PRIME buffer memory type.
* @GST_VAAPI_BUFFER_MEMORY_TYPE_GEM_BUF: Kernel DRM buffer memory type.
* @GST_VAAPI_BUFFER_MEMORY_TYPE_V4L2: V4L2 buffer memory type.
* @GST_VAAPI_BUFFER_MEMORY_TYPE_USER_PTR: User pointer memory type.
*
* Set of underlying VA buffer memory types.
*/
typedef enum {
GST_VAAPI_BUFFER_MEMORY_TYPE_DMA_BUF = 1,
GST_VAAPI_BUFFER_MEMORY_TYPE_DMA_BUF2,
GST_VAAPI_BUFFER_MEMORY_TYPE_GEM_BUF,
GST_VAAPI_BUFFER_MEMORY_TYPE_V4L2,
GST_VAAPI_BUFFER_MEMORY_TYPE_USER_PTR,
} GstVaapiBufferMemoryType;
GstVaapiBufferProxy *
gst_vaapi_buffer_proxy_new (guintptr handle, guint type, gsize size,
GDestroyNotify destroy_func, gpointer user_data);
GstVaapiBufferProxy *
gst_vaapi_buffer_proxy_ref (GstVaapiBufferProxy * proxy);
void
gst_vaapi_buffer_proxy_unref (GstVaapiBufferProxy * proxy);
void
gst_vaapi_buffer_proxy_replace (GstVaapiBufferProxy ** old_proxy_ptr,
GstVaapiBufferProxy * new_proxy);
guint
gst_vaapi_buffer_proxy_get_type (GstVaapiBufferProxy * proxy);
guintptr
gst_vaapi_buffer_proxy_get_handle (GstVaapiBufferProxy * proxy);
gsize
gst_vaapi_buffer_proxy_get_size (GstVaapiBufferProxy * proxy);
void
gst_vaapi_buffer_proxy_release_data (GstVaapiBufferProxy * proxy);
G_END_DECLS
#endif /* GST_VAAPI_BUFFER_PROXY_H */

View file

@ -0,0 +1,88 @@
/*
* gstvaapibufferproxy_priv.h - Buffer proxy abstraction (private definitions)
*
* Copyright (C) 2014 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_BUFFER_PROXY_PRIV_H
#define GST_VAAPI_BUFFER_PROXY_PRIV_H
#include "gstvaapibufferproxy.h"
#include "gstvaapiminiobject.h"
G_BEGIN_DECLS
/**
* GST_VAAPI_BUFFER_PROXY_TYPE:
* @buf: a #GstVaapiBufferProxy
*
* Macro that evaluates to the type of the underlying VA buffer @buf
*/
#undef GST_VAAPI_BUFFER_PROXY_TYPE
#define GST_VAAPI_BUFFER_PROXY_TYPE(buf) \
(GST_VAAPI_BUFFER_PROXY (buf)->type)
/**
* GST_VAAPI_BUFFER_PROXY_HANDLE:
* @buf: a #GstVaapiBufferProxy
*
* Macro that evaluates to the handle of the underlying VA buffer @buf
*/
#undef GST_VAAPI_BUFFER_PROXY_HANDLE
#define GST_VAAPI_BUFFER_PROXY_HANDLE(buf) \
(GST_VAAPI_BUFFER_PROXY (buf)->va_info.handle)
/**
* GST_VAAPI_BUFFER_PROXY_SIZE:
* @buf: a #GstVaapiBufferProxy
*
* Macro that evaluates to the size of the underlying VA buffer @buf
*/
#undef GST_VAAPI_BUFFER_PROXY_SIZE
#define GST_VAAPI_BUFFER_PROXY_SIZE(buf) \
(GST_VAAPI_BUFFER_PROXY (buf)->va_info.mem_size)
struct _GstVaapiBufferProxy {
/*< private >*/
GstVaapiMiniObject parent_instance;
GstMiniObject *surface;
GDestroyNotify destroy_func;
gpointer destroy_data;
guint type;
VABufferID va_buf;
VABufferInfo va_info;
};
G_GNUC_INTERNAL
GstVaapiBufferProxy *
gst_vaapi_buffer_proxy_new_from_surface (GstMiniObject * surface,
VABufferID buf_id, guint type, GDestroyNotify destroy_func, gpointer data);
G_GNUC_INTERNAL
guint
from_GstVaapiBufferMemoryType (guint type);
G_GNUC_INTERNAL
guint
to_GstVaapiBufferMemoryType (guint va_type);
G_END_DECLS
#endif /* GST_VAAPI_BUFFER_PROXY_PRIV_H */

View file

@ -0,0 +1,255 @@
/*
* gstvaapicodec_objects.c - VA codec objects abstraction
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
* Copyright (C) 2011-2014 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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 "sysdeps.h"
#include <gst/vaapi/gstvaapicontext.h>
#include "gstvaapicodec_objects.h"
#include "gstvaapidecoder_priv.h"
#include "gstvaapicompat.h"
#include "gstvaapiutils.h"
#define DEBUG 1
#include "gstvaapidebug.h"
/* ------------------------------------------------------------------------- */
/* --- Base Codec Object --- */
/* ------------------------------------------------------------------------- */
#define GST_VAAPI_CODEC_OBJECT_GET_CLASS(object) \
gst_vaapi_codec_object_get_class(object)
const GstVaapiCodecObjectClass *
gst_vaapi_codec_object_get_class (GstVaapiCodecObject * object)
{
return (const GstVaapiCodecObjectClass *)
GST_VAAPI_MINI_OBJECT_GET_CLASS (object);
}
static gboolean
gst_vaapi_codec_object_create (GstVaapiCodecObject * object,
const GstVaapiCodecObjectConstructorArgs * args)
{
const GstVaapiCodecObjectClass *klass;
g_return_val_if_fail (args->param_size > 0, FALSE);
if (GST_VAAPI_MINI_OBJECT_FLAG_IS_SET (object,
GST_VAAPI_CODEC_OBJECT_FLAG_CONSTRUCTED))
return TRUE;
klass = GST_VAAPI_CODEC_OBJECT_GET_CLASS (object);
if (!klass->create || !klass->create (object, args))
return FALSE;
GST_VAAPI_MINI_OBJECT_FLAG_SET (object,
GST_VAAPI_CODEC_OBJECT_FLAG_CONSTRUCTED);
return TRUE;
}
GstVaapiCodecObject *
gst_vaapi_codec_object_new_with_param_num (const GstVaapiCodecObjectClass *
object_class, GstVaapiCodecBase * codec, gconstpointer param,
guint param_size, guint param_num, gconstpointer data,
guint data_size, guint flags)
{
GstVaapiCodecObject *obj;
GstVaapiCodecObjectConstructorArgs args;
obj = (GstVaapiCodecObject *)
gst_vaapi_mini_object_new0 (GST_VAAPI_MINI_OBJECT_CLASS (object_class));
if (!obj)
return NULL;
obj = GST_VAAPI_CODEC_OBJECT (obj);
obj->codec = codec;
args.param = param;
args.param_size = param_size;
args.param_num = param_num;
args.data = data;
args.data_size = data_size;
args.flags = flags;
if (gst_vaapi_codec_object_create (obj, &args))
return obj;
gst_vaapi_codec_object_unref (obj);
return NULL;
}
GstVaapiCodecObject *
gst_vaapi_codec_object_new (const GstVaapiCodecObjectClass * object_class,
GstVaapiCodecBase * codec, gconstpointer param, guint param_size,
gconstpointer data, guint data_size, guint flags)
{
return gst_vaapi_codec_object_new_with_param_num (object_class, codec, param,
param_size, 1, data, data_size, flags);
}
#define GET_DECODER(obj) GST_VAAPI_DECODER_CAST((obj)->parent_instance.codec)
#define GET_VA_DISPLAY(obj) GET_DECODER(obj)->va_display
#define GET_VA_CONTEXT(obj) GET_DECODER(obj)->va_context
/* ------------------------------------------------------------------------- */
/* --- Inverse Quantization Matrices --- */
/* ------------------------------------------------------------------------- */
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiIqMatrix, gst_vaapi_iq_matrix);
void
gst_vaapi_iq_matrix_destroy (GstVaapiIqMatrix * iq_matrix)
{
vaapi_destroy_buffer (GET_VA_DISPLAY (iq_matrix), &iq_matrix->param_id);
iq_matrix->param = NULL;
}
gboolean
gst_vaapi_iq_matrix_create (GstVaapiIqMatrix * iq_matrix,
const GstVaapiCodecObjectConstructorArgs * args)
{
iq_matrix->param_id = VA_INVALID_ID;
return vaapi_create_buffer (GET_VA_DISPLAY (iq_matrix),
GET_VA_CONTEXT (iq_matrix), VAIQMatrixBufferType,
args->param_size, args->param, &iq_matrix->param_id, &iq_matrix->param);
}
GstVaapiIqMatrix *
gst_vaapi_iq_matrix_new (GstVaapiDecoder * decoder,
gconstpointer param, guint param_size)
{
GstVaapiCodecObject *object;
object = gst_vaapi_codec_object_new (&GstVaapiIqMatrixClass,
GST_VAAPI_CODEC_BASE (decoder), param, param_size, NULL, 0, 0);
if (!object)
return NULL;
return GST_VAAPI_IQ_MATRIX_CAST (object);
}
/* ------------------------------------------------------------------------- */
/* --- VC-1 Bit Planes --- */
/* ------------------------------------------------------------------------- */
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiBitPlane, gst_vaapi_bitplane);
void
gst_vaapi_bitplane_destroy (GstVaapiBitPlane * bitplane)
{
vaapi_destroy_buffer (GET_VA_DISPLAY (bitplane), &bitplane->data_id);
bitplane->data = NULL;
}
gboolean
gst_vaapi_bitplane_create (GstVaapiBitPlane * bitplane,
const GstVaapiCodecObjectConstructorArgs * args)
{
bitplane->data_id = VA_INVALID_ID;
return vaapi_create_buffer (GET_VA_DISPLAY (bitplane),
GET_VA_CONTEXT (bitplane), VABitPlaneBufferType, args->param_size,
args->param, &bitplane->data_id, (void **) &bitplane->data);
}
GstVaapiBitPlane *
gst_vaapi_bitplane_new (GstVaapiDecoder * decoder, guint8 * data,
guint data_size)
{
GstVaapiCodecObject *object;
object = gst_vaapi_codec_object_new (&GstVaapiBitPlaneClass,
GST_VAAPI_CODEC_BASE (decoder), data, data_size, NULL, 0, 0);
if (!object)
return NULL;
return GST_VAAPI_BITPLANE_CAST (object);
}
/* ------------------------------------------------------------------------- */
/* --- JPEG Huffman Tables --- */
/* ------------------------------------------------------------------------- */
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiHuffmanTable, gst_vaapi_huffman_table);
void
gst_vaapi_huffman_table_destroy (GstVaapiHuffmanTable * huf_table)
{
vaapi_destroy_buffer (GET_VA_DISPLAY (huf_table), &huf_table->param_id);
huf_table->param = NULL;
}
gboolean
gst_vaapi_huffman_table_create (GstVaapiHuffmanTable * huf_table,
const GstVaapiCodecObjectConstructorArgs * args)
{
huf_table->param_id = VA_INVALID_ID;
return vaapi_create_buffer (GET_VA_DISPLAY (huf_table),
GET_VA_CONTEXT (huf_table), VAHuffmanTableBufferType, args->param_size,
args->param, &huf_table->param_id, (void **) &huf_table->param);
}
GstVaapiHuffmanTable *
gst_vaapi_huffman_table_new (GstVaapiDecoder * decoder,
guint8 * data, guint data_size)
{
GstVaapiCodecObject *object;
object = gst_vaapi_codec_object_new (&GstVaapiHuffmanTableClass,
GST_VAAPI_CODEC_BASE (decoder), data, data_size, NULL, 0, 0);
if (!object)
return NULL;
return GST_VAAPI_HUFFMAN_TABLE_CAST (object);
}
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiProbabilityTable,
gst_vaapi_probability_table);
void
gst_vaapi_probability_table_destroy (GstVaapiProbabilityTable * prob_table)
{
vaapi_destroy_buffer (GET_VA_DISPLAY (prob_table), &prob_table->param_id);
prob_table->param = NULL;
}
gboolean
gst_vaapi_probability_table_create (GstVaapiProbabilityTable * prob_table,
const GstVaapiCodecObjectConstructorArgs * args)
{
prob_table->param_id = VA_INVALID_ID;
return vaapi_create_buffer (GET_VA_DISPLAY (prob_table),
GET_VA_CONTEXT (prob_table),
VAProbabilityBufferType,
args->param_size, args->param, &prob_table->param_id, &prob_table->param);
}
GstVaapiProbabilityTable *
gst_vaapi_probability_table_new (GstVaapiDecoder * decoder,
gconstpointer param, guint param_size)
{
GstVaapiCodecObject *object;
object = gst_vaapi_codec_object_new (&GstVaapiProbabilityTableClass,
GST_VAAPI_CODEC_BASE (decoder), param, param_size, NULL, 0, 0);
if (!object)
return NULL;
return GST_VAAPI_PROBABILITY_TABLE_CAST (object);
}

View file

@ -0,0 +1,275 @@
/*
* gstvaapicodec_objects.h - VA codec objects abstraction
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
* Copyright (C) 2011-2014 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_CODEC_COMMON_H
#define GST_VAAPI_CODEC_COMMON_H
#include <gst/vaapi/gstvaapiminiobject.h>
#include <gst/vaapi/gstvaapidecoder.h>
G_BEGIN_DECLS
typedef gpointer GstVaapiCodecBase;
typedef struct _GstVaapiCodecObject GstVaapiCodecObject;
typedef struct _GstVaapiCodecObjectClass GstVaapiCodecObjectClass;
typedef struct _GstVaapiIqMatrix GstVaapiIqMatrix;
typedef struct _GstVaapiBitPlane GstVaapiBitPlane;
typedef struct _GstVaapiHuffmanTable GstVaapiHuffmanTable;
typedef struct _GstVaapiProbabilityTable GstVaapiProbabilityTable;
/* ------------------------------------------------------------------------- */
/* --- Base Codec Object --- */
/* ------------------------------------------------------------------------- */
/* XXX: remove when a common base class for decoder and encoder is available */
#define GST_VAAPI_CODEC_BASE(obj) \
((GstVaapiCodecBase *) (obj))
#define GST_VAAPI_CODEC_OBJECT(obj) \
((GstVaapiCodecObject *) (obj))
enum
{
GST_VAAPI_CODEC_OBJECT_FLAG_CONSTRUCTED = (1 << 0),
GST_VAAPI_CODEC_OBJECT_FLAG_LAST = (1 << 1)
};
typedef struct
{
gconstpointer param;
guint param_size;
guint param_num;
gconstpointer data;
guint data_size;
guint flags;
} GstVaapiCodecObjectConstructorArgs;
typedef gboolean
(*GstVaapiCodecObjectCreateFunc)(GstVaapiCodecObject * object,
const GstVaapiCodecObjectConstructorArgs * args);
typedef GDestroyNotify GstVaapiCodecObjectDestroyFunc;
/**
* GstVaapiCodecObject:
*
* A #GstVaapiMiniObject holding the base codec object data
*/
struct _GstVaapiCodecObject
{
/*< private >*/
GstVaapiMiniObject parent_instance;
GstVaapiCodecBase *codec;
};
/**
* GstVaapiCodecObjectClass:
*
* The #GstVaapiCodecObject base class.
*/
struct _GstVaapiCodecObjectClass
{
/*< private >*/
GstVaapiMiniObjectClass parent_class;
GstVaapiCodecObjectCreateFunc create;
};
G_GNUC_INTERNAL
const GstVaapiCodecObjectClass *
gst_vaapi_codec_object_get_class (GstVaapiCodecObject * object) G_GNUC_CONST;
G_GNUC_INTERNAL
GstVaapiCodecObject *
gst_vaapi_codec_object_new (const GstVaapiCodecObjectClass * object_class,
GstVaapiCodecBase * codec, gconstpointer param, guint param_size,
gconstpointer data, guint data_size, guint flags);
G_GNUC_INTERNAL
GstVaapiCodecObject *
gst_vaapi_codec_object_new_with_param_num (const GstVaapiCodecObjectClass *
object_class, GstVaapiCodecBase * codec, gconstpointer param,
guint param_size, guint param_num, gconstpointer data,
guint data_size, guint flags);
#define gst_vaapi_codec_object_ref(object) \
((gpointer) gst_vaapi_mini_object_ref (GST_VAAPI_MINI_OBJECT (object)))
#define gst_vaapi_codec_object_unref(object) \
gst_vaapi_mini_object_unref (GST_VAAPI_MINI_OBJECT (object))
#define gst_vaapi_codec_object_replace(old_object_ptr, new_object) \
gst_vaapi_mini_object_replace ((GstVaapiMiniObject **) (old_object_ptr), \
GST_VAAPI_MINI_OBJECT (new_object))
/* ------------------------------------------------------------------------- */
/* --- Inverse Quantization Matrices --- */
/* ------------------------------------------------------------------------- */
#define GST_VAAPI_IQ_MATRIX_CAST(obj) \
((GstVaapiIqMatrix *) (obj))
/**
* GstVaapiIqMatrix:
*
* A #GstVaapiCodecObject holding an inverse quantization matrix parameter.
*/
struct _GstVaapiIqMatrix
{
/*< private >*/
GstVaapiCodecObject parent_instance;
VABufferID param_id;
/*< public >*/
gpointer param;
};
G_GNUC_INTERNAL
GstVaapiIqMatrix *
gst_vaapi_iq_matrix_new (GstVaapiDecoder * decoder, gconstpointer param,
guint param_size);
/* ------------------------------------------------------------------------- */
/* --- VC-1 Bit Planes --- */
/* ------------------------------------------------------------------------- */
#define GST_VAAPI_BITPLANE_CAST(obj) \
((GstVaapiBitPlane *) (obj))
/**
* GstVaapiBitPlane:
*
* A #GstVaapiCodecObject holding a VC-1 bit plane parameter.
*/
struct _GstVaapiBitPlane
{
/*< private >*/
GstVaapiCodecObject parent_instance;
VABufferID data_id;
/*< public >*/
guint8 *data;
};
G_GNUC_INTERNAL
GstVaapiBitPlane *
gst_vaapi_bitplane_new (GstVaapiDecoder * decoder, guint8 * data,
guint data_size);
/* ------------------------------------------------------------------------- */
/* --- JPEG Huffman Tables --- */
/* ------------------------------------------------------------------------- */
#define GST_VAAPI_HUFFMAN_TABLE_CAST(obj) \
((GstVaapiHuffmanTable *) (obj))
/**
* GstVaapiHuffmanTable:
*
* A #GstVaapiCodecObject holding huffman table.
*/
struct _GstVaapiHuffmanTable
{
/*< private >*/
GstVaapiCodecObject parent_instance;
VABufferID param_id;
/*< public >*/
gpointer param;
};
G_GNUC_INTERNAL
GstVaapiHuffmanTable *
gst_vaapi_huffman_table_new (GstVaapiDecoder * decoder, guint8 * data,
guint data_size);
/* ------------------------------------------------------------------------- */
/* --- Probability (Update) Table --- */
/* ------------------------------------------------------------------------- */
#define GST_VAAPI_PROBABILITY_TABLE_CAST(obj) \
((GstVaapiProbabilityTable *)(obj))
/**
* GstVaapiProbabilityTable:
*
* A #GstVaapiCodecObject holding an Probability (Update) Table for RAC decoding
*/
struct _GstVaapiProbabilityTable
{
/*< private > */
GstVaapiCodecObject parent_instance;
VABufferID param_id;
/*< public > */
gpointer param;
};
G_GNUC_INTERNAL
GstVaapiProbabilityTable *
gst_vaapi_probability_table_new (GstVaapiDecoder * decoder,
gconstpointer param, guint param_size);
/* ------------------------------------------------------------------------- */
/* --- Helpers to create codec-dependent objects --- */
/* ------------------------------------------------------------------------- */
#define GST_VAAPI_CODEC_DEFINE_TYPE(type, prefix) \
G_GNUC_INTERNAL \
void \
G_PASTE (prefix, _destroy) (type *); \
\
G_GNUC_INTERNAL \
gboolean \
G_PASTE (prefix, _create) (type *, \
const GstVaapiCodecObjectConstructorArgs * args); \
\
static const GstVaapiCodecObjectClass G_PASTE (type, Class) = { \
.parent_class = { \
.size = sizeof (type), \
.finalize = (GstVaapiCodecObjectDestroyFunc) \
G_PASTE (prefix, _destroy) \
}, \
.create = (GstVaapiCodecObjectCreateFunc) \
G_PASTE (prefix, _create), \
}
#define GST_VAAPI_IQ_MATRIX_NEW(codec, decoder) \
gst_vaapi_iq_matrix_new (GST_VAAPI_DECODER_CAST (decoder), \
NULL, sizeof (G_PASTE (VAIQMatrixBuffer, codec)))
#define GST_VAAPI_BITPLANE_NEW(decoder, size) \
gst_vaapi_bitplane_new (GST_VAAPI_DECODER_CAST (decoder), NULL, size)
#define GST_VAAPI_HUFFMAN_TABLE_NEW(codec, decoder) \
gst_vaapi_huffman_table_new (GST_VAAPI_DECODER_CAST (decoder), \
NULL, sizeof (G_PASTE (VAHuffmanTableBuffer, codec)))
#define GST_VAAPI_PROBABILITY_TABLE_NEW(codec, decoder) \
gst_vaapi_probability_table_new (GST_VAAPI_DECODER_CAST (decoder), \
NULL, sizeof (G_PASTE (VAProbabilityDataBuffer, codec)))
G_END_DECLS
#endif /* GST_VAAPI_CODEC_OBJECTS_H */

View file

@ -0,0 +1,251 @@
/*
* gstvaapicodedbuffer.c - VA coded buffer abstraction
*
* Copyright (C) 2013 Intel Corporation
* Author: Wind Yuan <feng.yuan@intel.com>
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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 "sysdeps.h"
#include "gstvaapicodedbuffer.h"
#include "gstvaapicodedbuffer_priv.h"
#include "gstvaapiencoder_priv.h"
#include "gstvaapiutils.h"
#define DEBUG 1
#include "gstvaapidebug.h"
static gboolean
coded_buffer_create (GstVaapiCodedBuffer * buf, guint buf_size,
GstVaapiContext * context)
{
GstVaapiDisplay *const display = GST_VAAPI_CODED_BUFFER_DISPLAY (buf);
VABufferID buf_id;
gboolean success;
GST_VAAPI_DISPLAY_LOCK (display);
success = vaapi_create_buffer (GST_VAAPI_DISPLAY_VADISPLAY (display),
GST_VAAPI_CONTEXT_ID (context), VAEncCodedBufferType, buf_size,
NULL, &buf_id, NULL);
GST_VAAPI_DISPLAY_UNLOCK (display);
if (!success)
return FALSE;
GST_DEBUG ("coded buffer %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (buf_id));
GST_VAAPI_CODED_BUFFER_ID (buf) = buf_id;
return TRUE;
}
static void
coded_buffer_free (GstVaapiCodedBuffer * buf)
{
GstVaapiDisplay *const display = GST_VAAPI_CODED_BUFFER_DISPLAY (buf);
VABufferID buf_id;
buf_id = GST_VAAPI_CODED_BUFFER_ID (buf);
GST_DEBUG ("coded buffer %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (buf_id));
if (buf_id != VA_INVALID_ID) {
GST_VAAPI_DISPLAY_LOCK (display);
vaapi_destroy_buffer (GST_VAAPI_DISPLAY_VADISPLAY (display), &buf_id);
GST_VAAPI_DISPLAY_UNLOCK (display);
GST_VAAPI_CODED_BUFFER_ID (buf) = VA_INVALID_ID;
}
gst_vaapi_display_replace (&GST_VAAPI_CODED_BUFFER_DISPLAY (buf), NULL);
g_slice_free1 (sizeof (GstVaapiCodedBuffer), buf);
}
static gboolean
coded_buffer_map (GstVaapiCodedBuffer * buf)
{
GstVaapiDisplay *const display = GST_VAAPI_CODED_BUFFER_DISPLAY (buf);
if (buf->segment_list)
return TRUE;
GST_VAAPI_DISPLAY_LOCK (display);
buf->segment_list =
vaapi_map_buffer (GST_VAAPI_DISPLAY_VADISPLAY (display),
GST_VAAPI_CODED_BUFFER_ID (buf));
GST_VAAPI_DISPLAY_UNLOCK (display);
return buf->segment_list != NULL;
}
static void
coded_buffer_unmap (GstVaapiCodedBuffer * buf)
{
GstVaapiDisplay *const display = GST_VAAPI_CODED_BUFFER_DISPLAY (buf);
if (!buf->segment_list)
return;
GST_VAAPI_DISPLAY_LOCK (display);
vaapi_unmap_buffer (GST_VAAPI_DISPLAY_VADISPLAY (display),
GST_VAAPI_CODED_BUFFER_ID (buf), (void **) &buf->segment_list);
GST_VAAPI_DISPLAY_UNLOCK (display);
}
GST_DEFINE_MINI_OBJECT_TYPE (GstVaapiCodedBuffer, gst_vaapi_coded_buffer);
/*
* gst_vaapi_coded_buffer_new:
* @context: the parent #GstVaapiContext object
* @buf_size: the buffer size in bytes
*
* Creates a new VA coded buffer bound to the supplied @context.
*
* Return value: the newly allocated #GstVaapiCodedBuffer object, or
* %NULL if an error occurred
*/
GstVaapiCodedBuffer *
gst_vaapi_coded_buffer_new (GstVaapiContext * context, guint buf_size)
{
GstVaapiCodedBuffer *buf;
GstVaapiDisplay *display;
g_return_val_if_fail (context != NULL, NULL);
g_return_val_if_fail (buf_size > 0, NULL);
display = GST_VAAPI_CONTEXT_DISPLAY (context);
g_return_val_if_fail (display != NULL, NULL);
buf = g_slice_new (GstVaapiCodedBuffer);
if (!buf)
return NULL;
gst_mini_object_init (GST_MINI_OBJECT_CAST (buf), 0,
GST_TYPE_VAAPI_CODED_BUFFER, NULL, NULL,
(GstMiniObjectFreeFunction) coded_buffer_free);
GST_VAAPI_CODED_BUFFER_DISPLAY (buf) = gst_object_ref (display);
GST_VAAPI_CODED_BUFFER_ID (buf) = VA_INVALID_ID;
buf->segment_list = NULL;
if (!coded_buffer_create (buf, buf_size, context))
goto error;
return buf;
/* ERRORS */
error:
{
gst_vaapi_coded_buffer_unref (buf);
return NULL;
}
}
/*
* gst_vaapi_coded_buffer_map:
* @buf: a #GstVaapiCodedBuffer
* @data: pointer to the mapped buffer data (VACodedBufferSegment)
*
* Maps the VA coded buffer and returns the data pointer into @data.
*
* Return value: %TRUE if successful, %FALSE otherwise
*/
gboolean
gst_vaapi_coded_buffer_map (GstVaapiCodedBuffer * buf,
VACodedBufferSegment ** out_segment_list_ptr)
{
g_return_val_if_fail (buf != NULL, FALSE);
g_return_val_if_fail (out_segment_list_ptr != NULL, FALSE);
if (!coded_buffer_map (buf))
return FALSE;
*out_segment_list_ptr = buf->segment_list;
return TRUE;
}
/*
* gst_vaapi_coded_buffer_unmap:
* @buf: a #GstVaapiCodedBuffer
*
* Unamps the VA coded buffer.
*/
void
gst_vaapi_coded_buffer_unmap (GstVaapiCodedBuffer * buf)
{
g_return_if_fail (buf != NULL);
coded_buffer_unmap (buf);
}
/**
* gst_vaapi_coded_buffer_get_size:
* @buf: a #GstVaapiCodedBuffer
*
* Returns the VA coded buffer size in bytes. That represents the
* exact buffer size, as filled in so far, not the size of the
* allocated buffer.
*
* Return value: the size of the VA coded buffer, or -1 on error
*/
gssize
gst_vaapi_coded_buffer_get_size (GstVaapiCodedBuffer * buf)
{
VACodedBufferSegment *segment;
gssize size;
g_return_val_if_fail (buf != NULL, -1);
if (!coded_buffer_map (buf))
return -1;
size = 0;
for (segment = buf->segment_list; segment != NULL; segment = segment->next)
size += segment->size;
coded_buffer_unmap (buf);
return size;
}
/**
* gst_vaapi_coded_buffer_copy_into:
* @dest: the destination #GstBuffer
* @src: the source #GstVaapiCodedBuffer
*
* Copies the coded buffer data from @src into the regular buffer @dest.
*
* Return value: %TRUE if successful, %FALSE otherwise
*/
gboolean
gst_vaapi_coded_buffer_copy_into (GstBuffer * dest, GstVaapiCodedBuffer * src)
{
VACodedBufferSegment *segment;
goffset offset;
gsize size;
g_return_val_if_fail (src != NULL, FALSE);
g_return_val_if_fail (dest != NULL, FALSE);
if (!coded_buffer_map (src))
return FALSE;
offset = 0;
for (segment = src->segment_list; segment != NULL; segment = segment->next) {
size = gst_buffer_fill (dest, offset, segment->buf, segment->size);
if (size != segment->size)
break;
offset += segment->size;
}
coded_buffer_unmap (src);
return segment == NULL;
}

View file

@ -0,0 +1,73 @@
/*
* gstvaapicodedbuffer.h - VA coded buffer abstraction
*
* Copyright (C) 2013 Intel Corporation
* Author: Wind Yuan <feng.yuan@intel.com>
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_CODED_BUFFER_H
#define GST_VAAPI_CODED_BUFFER_H
G_BEGIN_DECLS
#define GST_VAAPI_CODED_BUFFER(obj) \
((GstVaapiCodedBuffer *)(obj))
/**
* GST_VAAPI_CODED_BUFFER_SIZE:
* @buf: a #GstVaapiCodedBuffer
*
* Macro that evaluates to the size of the underlying VA coded buffer @buf
*/
#define GST_VAAPI_CODED_BUFFER_SIZE(buf) \
gst_vaapi_coded_buffer_get_size (GST_VAAPI_CODED_BUFFER(buf))
typedef struct _GstVaapiCodedBuffer GstVaapiCodedBuffer;
typedef struct _GstVaapiCodedBufferProxy GstVaapiCodedBufferProxy;
typedef struct _GstVaapiCodedBufferPool GstVaapiCodedBufferPool;
#define GST_TYPE_VAAPI_CODED_BUFFER (gst_vaapi_coded_buffer_get_type ())
GType
gst_vaapi_coded_buffer_get_type (void) G_GNUC_CONST;
/**
* gst_vaapi_coded_buffer_unref: (skip)
* @buf: (transfer full): a #GstVaapiCodedBuffer.
*
* Decreases the refcount of @buf. If the refcount reaches 0, the
* @buf will be freed.
*/
static inline void
gst_vaapi_coded_buffer_unref (GstVaapiCodedBuffer * buf)
{
gst_mini_object_unref (GST_MINI_OBJECT_CAST (buf));
}
gssize
gst_vaapi_coded_buffer_get_size (GstVaapiCodedBuffer * buf);
gboolean
gst_vaapi_coded_buffer_copy_into (GstBuffer * dest, GstVaapiCodedBuffer * src);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiCodedBuffer, gst_vaapi_coded_buffer_unref)
G_END_DECLS
#endif /* GST_VAAPI_CODED_BUFFER_H */

View file

@ -0,0 +1,84 @@
/*
* gstvaapicodedbuffer_priv.h - VA coded buffer abstraction (private defs)
*
* Copyright (C) 2013 Intel Corporation
* Author: Wind Yuan <feng.yuan@intel.com>
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_CODED_BUFFER_PRIV_H
#define GST_VAAPI_CODED_BUFFER_PRIV_H
#include <gst/vaapi/gstvaapicontext.h>
#include "gstvaapicodedbuffer.h"
G_BEGIN_DECLS
#define GST_VAAPI_CODED_BUFFER_CAST(obj) \
((GstVaapiCodedBuffer *)(obj))
/**
* GstVaapiCodedBuffer:
*
* A VA coded buffer object wrapper.
*/
struct _GstVaapiCodedBuffer
{
/*< private >*/
GstMiniObject mini_object;
GstVaapiDisplay *display;
GstVaapiID object_id;
/*< public >*/
VACodedBufferSegment *segment_list;
};
/**
* GST_VAAPI_CODED_BUFFER_DISPLAY:
* @buf: a #GstVaapiCodedBuffer
*
* Macro that evaluates to the #GstVaapiDisplay of @buf
*/
#undef GST_VAAPI_CODED_BUFFER_DISPLAY
#define GST_VAAPI_CODED_BUFFER_DISPLAY(buf) (GST_VAAPI_CODED_BUFFER (buf)->display)
/**
* GST_VAAPI_CODED_BUFFER_ID:
* @buf: a #GstVaapiCodedBuffer
*
* Macro that evaluates to the object ID of @buf
*/
#undef GST_VAAPI_CODED_BUFFER_ID
#define GST_VAAPI_CODED_BUFFER_ID(buf) (GST_VAAPI_CODED_BUFFER (buf)->object_id)
G_GNUC_INTERNAL
GstVaapiCodedBuffer *
gst_vaapi_coded_buffer_new (GstVaapiContext * context, guint buf_size);
G_GNUC_INTERNAL
gboolean
gst_vaapi_coded_buffer_map (GstVaapiCodedBuffer * buf,
VACodedBufferSegment ** out_segment_list_ptr);
G_GNUC_INTERNAL
void
gst_vaapi_coded_buffer_unmap (GstVaapiCodedBuffer * buf);
G_END_DECLS
#endif /* GST_VAAPI_CODED_BUFFER_PRIV_H */

View file

@ -0,0 +1,132 @@
/*
* gstvaapicodedbufferpool.c - VA coded buffer pool
*
* Copyright (C) 2013-2014 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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 "sysdeps.h"
#include "gstvaapicodedbufferpool.h"
#include "gstvaapicodedbuffer_priv.h"
#include "gstvaapivideopool_priv.h"
#include "gstvaapiencoder_priv.h"
#define DEBUG 1
#include "gstvaapidebug.h"
/**
* GstVaapiCodedBufferPool:
*
* A pool of lazily allocated #GstVaapiCodedBuffer objects.
*/
struct _GstVaapiCodedBufferPool
{
/*< private > */
GstVaapiVideoPool parent_instance;
GstVaapiContext *context;
gsize buf_size;
};
static void
coded_buffer_pool_init (GstVaapiCodedBufferPool * pool,
GstVaapiContext * context, gsize buf_size)
{
pool->context = gst_vaapi_context_ref (context);
pool->buf_size = buf_size;
}
static void
coded_buffer_pool_finalize (GstVaapiCodedBufferPool * pool)
{
gst_vaapi_video_pool_finalize (GST_VAAPI_VIDEO_POOL (pool));
gst_vaapi_context_unref (pool->context);
pool->context = NULL;
}
static gpointer
coded_buffer_pool_alloc_object (GstVaapiVideoPool * base_pool)
{
GstVaapiCodedBufferPool *const pool = GST_VAAPI_CODED_BUFFER_POOL (base_pool);
return gst_vaapi_coded_buffer_new (pool->context, pool->buf_size);
}
static inline const GstVaapiMiniObjectClass *
gst_vaapi_coded_buffer_pool_class (void)
{
static const GstVaapiVideoPoolClass GstVaapiCodedBufferPoolClass = {
{sizeof (GstVaapiCodedBufferPool),
(GDestroyNotify) coded_buffer_pool_finalize}
,
.alloc_object = coded_buffer_pool_alloc_object
};
return GST_VAAPI_MINI_OBJECT_CLASS (&GstVaapiCodedBufferPoolClass);
}
/**
* gst_vaapi_coded_buffer_pool_new:
* @encoder: a #GstVaapiEncoder
* @buf_size: the max size of #GstVaapiCodedBuffer objects, in bytes
*
* Creates a new #GstVaapiVideoPool of #GstVaapiCodedBuffer objects
* with the supplied maximum size in bytes, and bound to the specified
* @encoder object.
*
* Return value: the newly allocated #GstVaapiVideoPool
*/
GstVaapiVideoPool *
gst_vaapi_coded_buffer_pool_new (GstVaapiEncoder * encoder, gsize buf_size)
{
GstVaapiVideoPool *pool;
GstVaapiContext *context;
g_return_val_if_fail (encoder != NULL, NULL);
g_return_val_if_fail (buf_size > 0, NULL);
context = GST_VAAPI_ENCODER_CONTEXT (encoder);
g_return_val_if_fail (context != NULL, NULL);
pool = (GstVaapiVideoPool *)
gst_vaapi_mini_object_new (gst_vaapi_coded_buffer_pool_class ());
if (!pool)
return NULL;
gst_vaapi_video_pool_init (pool, GST_VAAPI_CONTEXT_DISPLAY (context),
GST_VAAPI_VIDEO_POOL_OBJECT_TYPE_CODED_BUFFER);
coded_buffer_pool_init (GST_VAAPI_CODED_BUFFER_POOL (pool),
context, buf_size);
return pool;
}
/**
* gst_vaapi_coded_buffer_pool_get_buffer_size:
* @pool: a #GstVaapiCodedBufferPool
*
* Determines the maximum size of each #GstVaapiCodedBuffer held in
* the @pool.
*
* Return value: size of a #GstVaapiCodedBuffer in @pool
*/
gsize
gst_vaapi_coded_buffer_pool_get_buffer_size (GstVaapiCodedBufferPool * pool)
{
g_return_val_if_fail (pool != NULL, 0);
return pool->buf_size;
}

View file

@ -0,0 +1,45 @@
/*
* gstvaapicodedbufferpool.h - VA coded buffer pool
*
* Copyright (C) 2013-2014 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_CODED_BUFFER_POOL_H
#define GST_VAAPI_CODED_BUFFER_POOL_H
#include <gst/vaapi/gstvaapivideopool.h>
#include <gst/vaapi/gstvaapiencoder.h>
G_BEGIN_DECLS
#define GST_VAAPI_CODED_BUFFER_POOL(obj) \
((GstVaapiCodedBufferPool *)(obj))
struct _GstVaapiEncoder;
GstVaapiVideoPool *
gst_vaapi_coded_buffer_pool_new (struct _GstVaapiEncoder * encoder,
gsize buf_size);
gsize
gst_vaapi_coded_buffer_pool_get_buffer_size (GstVaapiCodedBufferPool * pool);
G_END_DECLS
#endif /* GST_VAAPI_CODED_BUFFER_POOL_H */

View file

@ -0,0 +1,256 @@
/*
* gstvaapicodedbufferproxy.c - VA coded buffer proxy
*
* Copyright (C) 2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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 "sysdeps.h"
#include "gstvaapicodedbufferproxy.h"
#include "gstvaapicodedbufferproxy_priv.h"
#include "gstvaapivideopool_priv.h"
#define DEBUG 1
#include "gstvaapidebug.h"
static void
coded_buffer_proxy_set_user_data (GstVaapiCodedBufferProxy * proxy,
gpointer user_data, GDestroyNotify destroy_func)
{
if (proxy->user_data_destroy)
proxy->user_data_destroy (proxy->user_data);
proxy->user_data = user_data;
proxy->user_data_destroy = destroy_func;
}
static void
coded_buffer_proxy_finalize (GstVaapiCodedBufferProxy * proxy)
{
if (proxy->buffer) {
if (proxy->pool)
gst_vaapi_video_pool_put_object (proxy->pool, proxy->buffer);
gst_vaapi_coded_buffer_unref (proxy->buffer);
proxy->buffer = NULL;
}
gst_vaapi_video_pool_replace (&proxy->pool, NULL);
coded_buffer_proxy_set_user_data (proxy, NULL, NULL);
/* Notify the user function that the object is now destroyed */
if (proxy->destroy_func)
proxy->destroy_func (proxy->destroy_data);
}
static inline const GstVaapiMiniObjectClass *
gst_vaapi_coded_buffer_proxy_class (void)
{
static const GstVaapiMiniObjectClass GstVaapiCodedBufferProxyClass = {
sizeof (GstVaapiCodedBufferProxy),
(GDestroyNotify) coded_buffer_proxy_finalize
};
return &GstVaapiCodedBufferProxyClass;
}
/**
* gst_vaapi_coded_buffer_proxy_new_from_pool:
* @pool: a #GstVaapiCodedBufferPool
*
* Allocates a new coded buffer from the supplied @pool and creates
* the wrapped coded buffer proxy object from it. When the last
* reference to the proxy object is released, then the underlying VA
* coded buffer is pushed back to its parent pool.
*
* Returns: The same newly allocated @proxy object, or %NULL on error
*/
GstVaapiCodedBufferProxy *
gst_vaapi_coded_buffer_proxy_new_from_pool (GstVaapiCodedBufferPool * pool)
{
GstVaapiCodedBufferProxy *proxy;
g_return_val_if_fail (pool != NULL, NULL);
g_return_val_if_fail (GST_VAAPI_VIDEO_POOL (pool)->object_type ==
GST_VAAPI_VIDEO_POOL_OBJECT_TYPE_CODED_BUFFER, NULL);
proxy = (GstVaapiCodedBufferProxy *)
gst_vaapi_mini_object_new (gst_vaapi_coded_buffer_proxy_class ());
if (!proxy)
return NULL;
proxy->destroy_func = NULL;
proxy->user_data_destroy = NULL;
proxy->pool = gst_vaapi_video_pool_ref (GST_VAAPI_VIDEO_POOL (pool));
proxy->buffer = gst_vaapi_video_pool_get_object (proxy->pool);
if (!proxy->buffer)
goto error;
gst_mini_object_ref (GST_MINI_OBJECT_CAST (proxy->buffer));
return proxy;
/* ERRORS */
error:
{
gst_vaapi_coded_buffer_proxy_unref (proxy);
return NULL;
}
}
/**
* gst_vaapi_coded_buffer_proxy_ref:
* @proxy: a #GstVaapiCodedBufferProxy
*
* Atomically increases the reference count of the given @proxy by one.
*
* Returns: The same @proxy argument
*/
GstVaapiCodedBufferProxy *
gst_vaapi_coded_buffer_proxy_ref (GstVaapiCodedBufferProxy * proxy)
{
g_return_val_if_fail (proxy != NULL, NULL);
return GST_VAAPI_CODED_BUFFER_PROXY (gst_vaapi_mini_object_ref
(GST_VAAPI_MINI_OBJECT (proxy)));
}
/**
* gst_vaapi_coded_buffer_proxy_unref:
* @proxy: a #GstVaapiCodedBufferProxy
*
* Atomically decreases the reference count of the @proxy by one. If
* the reference count reaches zero, the object will be free'd.
*/
void
gst_vaapi_coded_buffer_proxy_unref (GstVaapiCodedBufferProxy * proxy)
{
g_return_if_fail (proxy != NULL);
gst_vaapi_mini_object_unref (GST_VAAPI_MINI_OBJECT (proxy));
}
/**
* gst_vaapi_coded_buffer_proxy_replace:
* @old_proxy_ptr: a pointer to a #GstVaapiCodedBufferProxy
* @new_proxy: a #GstVaapiCodedBufferProxy
*
* Atomically replaces the proxy object held in @old_proxy_ptr with
* @new_proxy. This means that @old_proxy_ptr shall reference a valid
* object. However, @new_proxy can be NULL.
*/
void
gst_vaapi_coded_buffer_proxy_replace (GstVaapiCodedBufferProxy ** old_proxy_ptr,
GstVaapiCodedBufferProxy * new_proxy)
{
g_return_if_fail (old_proxy_ptr != NULL);
gst_vaapi_mini_object_replace ((GstVaapiMiniObject **) old_proxy_ptr,
GST_VAAPI_MINI_OBJECT (new_proxy));
}
/**
* gst_vaapi_coded_buffer_proxy_get_buffer:
* @proxy: a #GstVaapiCodedBufferProxy
*
* Returns the #GstVaapiCodedBuffer stored in the @proxy.
*
* Return value: the #GstVaapiCodedBuffer, or %NULL if an error occurred
*/
GstVaapiCodedBuffer *
gst_vaapi_coded_buffer_proxy_get_buffer (GstVaapiCodedBufferProxy * proxy)
{
g_return_val_if_fail (proxy != NULL, NULL);
return GST_VAAPI_CODED_BUFFER_PROXY_BUFFER (proxy);
}
/**
* gst_vaapi_coded_buffer_proxy_get_buffer_size:
* @proxy: a #GstVaapiCodedBufferProxy
*
* Returns the size of the underlying #GstVaapiCodedBuffer object
* stored in the @proxy.
*
* Return value: the underlying #GstVaapiCodedBuffer size, or -1 if an
* error occurred
*/
gssize
gst_vaapi_coded_buffer_proxy_get_buffer_size (GstVaapiCodedBufferProxy * proxy)
{
g_return_val_if_fail (proxy != NULL, -1);
return GST_VAAPI_CODED_BUFFER_PROXY_BUFFER_SIZE (proxy);
}
/**
* gst_vaapi_coded_buffer_proxy_set_destroy_notify:
* @proxy: a @GstVaapiCodedBufferProxy
* @destroy_func: a #GDestroyNotify function
* @user_data: some extra data to pass to the @destroy_func function
*
* Sets @destroy_func as the function to call when the coded buffer
* @proxy was released. At this point, the proxy object is considered
* released, i.e. the underlying data storage is no longer valid and
* the callback function shall not expect anything from that.
*/
void
gst_vaapi_coded_buffer_proxy_set_destroy_notify (GstVaapiCodedBufferProxy *
proxy, GDestroyNotify destroy_func, gpointer user_data)
{
g_return_if_fail (proxy != NULL);
proxy->destroy_func = destroy_func;
proxy->destroy_data = user_data;
}
/**
* gst_vaapi_coded_buffer_proxy_get_user_data:
* @proxy: a #GstVaapiCodedBufferProxy
*
* Gets private data previously set on the VA coded buffer proxy
* object through the gst_vaapi_coded_buffer_proxy_set_user_data()
* function.
*
* Return value: the previously set user-data
*/
gpointer
gst_vaapi_coded_buffer_proxy_get_user_data (GstVaapiCodedBufferProxy * proxy)
{
g_return_val_if_fail (proxy != NULL, NULL);
return proxy->user_data;
}
/**
* gst_vaapi_coded_buffer_proxy_set_user_data:
* @proxy: a #GstVaapiCodedBufferProxy
* @user_data: user-defined data
* @destroy_func: a #GDestroyNotify
*
* Sets @user_data on the VA coded buffer proxy object and the
* #GDestroyNotify function that will be called when the coded buffer
* proxy object is released.
*
* If a @user_data was previously set, then the previously set
* @destroy_func function, if any, will be called before the
* @user_data is replaced.
*/
void
gst_vaapi_coded_buffer_proxy_set_user_data (GstVaapiCodedBufferProxy * proxy,
gpointer user_data, GDestroyNotify destroy_func)
{
g_return_if_fail (proxy != NULL);
coded_buffer_proxy_set_user_data (proxy, user_data, destroy_func);
}

View file

@ -0,0 +1,82 @@
/*
* gstvaapicodedbufferproxy_priv.h - VA coded buffer proxy
*
* Copyright (C) 2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_CODED_BUFFER_PROXY_H
#define GST_VAAPI_CODED_BUFFER_PROXY_H
#include <gst/vaapi/gstvaapicodedbuffer.h>
#include <gst/vaapi/gstvaapicodedbufferpool.h>
G_BEGIN_DECLS
/**
* GST_VAAPI_CODED_BUFFER_PROXY_BUFFER:
* @proxy: a #GstVaapiCodedBufferProxy
*
* Macro that evaluated to the underlying #GstVaapiCodedBuffer of @proxy.
*/
#define GST_VAAPI_CODED_BUFFER_PROXY_BUFFER(proxy) \
gst_vaapi_coded_buffer_proxy_get_buffer(proxy)
/**
* GST_VAAPI_CODED_BUFFER_PROXY_BUFFER_SIZE:
* @proxy: a #GstVaapiCodedBufferProxy
*
* Macro that evaluated to the underlying #GstVaapiCodedBuffer size of
* @proxy.
*/
#define GST_VAAPI_CODED_BUFFER_PROXY_BUFFER_SIZE(proxy) \
gst_vaapi_coded_buffer_proxy_get_buffer_size(proxy)
GstVaapiCodedBufferProxy *
gst_vaapi_coded_buffer_proxy_new_from_pool (GstVaapiCodedBufferPool * pool);
GstVaapiCodedBufferProxy *
gst_vaapi_coded_buffer_proxy_ref (GstVaapiCodedBufferProxy * proxy);
void
gst_vaapi_coded_buffer_proxy_unref (GstVaapiCodedBufferProxy * proxy);
void
gst_vaapi_coded_buffer_proxy_replace (GstVaapiCodedBufferProxy ** old_proxy_ptr,
GstVaapiCodedBufferProxy * new_proxy);
GstVaapiCodedBuffer *
gst_vaapi_coded_buffer_proxy_get_buffer (GstVaapiCodedBufferProxy * proxy);
gssize
gst_vaapi_coded_buffer_proxy_get_buffer_size (GstVaapiCodedBufferProxy * proxy);
void
gst_vaapi_coded_buffer_proxy_set_destroy_notify (GstVaapiCodedBufferProxy *
proxy, GDestroyNotify destroy_func, gpointer user_data);
gpointer
gst_vaapi_coded_buffer_proxy_get_user_data (GstVaapiCodedBufferProxy * proxy);
void
gst_vaapi_coded_buffer_proxy_set_user_data (GstVaapiCodedBufferProxy * proxy,
gpointer user_data, GDestroyNotify destroy_func);
G_END_DECLS
#endif /* GST_VAAPI_CODED_BUFFER_PROXY_H */

View file

@ -0,0 +1,70 @@
/*
* gstvaapicodedbufferproxy_priv.h - VA coded buffer proxy (private defs)
*
* Copyright (C) 2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_CODED_BUFFER_PROXY_PRIV_H
#define GST_VAAPI_CODED_BUFFER_PROXY_PRIV_H
#include "gstvaapicodedbuffer_priv.h"
#include "gstvaapiminiobject.h"
G_BEGIN_DECLS
#define GST_VAAPI_CODED_BUFFER_PROXY(proxy) \
((GstVaapiCodedBufferProxy *)(proxy))
struct _GstVaapiCodedBufferProxy
{
/*< private >*/
GstVaapiMiniObject parent_instance;
GstVaapiVideoPool *pool;
GstVaapiCodedBuffer *buffer;
GDestroyNotify destroy_func;
gpointer destroy_data;
GDestroyNotify user_data_destroy;
gpointer user_data;
};
/**
* GST_VAAPI_CODED_BUFFER_PROXY_BUFFER:
* @proxy: a #GstVaapiCodedBufferProxy
*
* Macro that evaluated to the underlying #GstVaapiCodedBuffer of @proxy.
*/
#undef GST_VAAPI_CODED_BUFFER_PROXY_BUFFER
#define GST_VAAPI_CODED_BUFFER_PROXY_BUFFER(proxy) \
GST_VAAPI_CODED_BUFFER_PROXY(proxy)->buffer
/**
* GST_VAAPI_CODED_BUFFER_PROXY_BUFFER_SIZE:
* @proxy: a #GstVaapiCodedBufferProxy
*
* Macro that evaluated to the underlying #GstVaapiCodedBuffer size of
* @proxy.
*/
#undef GST_VAAPI_CODED_BUFFER_PROXY_BUFFER_SIZE
#define GST_VAAPI_CODED_BUFFER_PROXY_BUFFER_SIZE(proxy) \
GST_VAAPI_CODED_BUFFER_SIZE(GST_VAAPI_CODED_BUFFER_PROXY_BUFFER(proxy))
G_END_DECLS
#endif /* GST_VAAPI_CODED_BUFFER_PROXY_PRIV_H */

View file

@ -0,0 +1,41 @@
/*
* gstvapicompat.h - VA-API compatibility glue
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
* Copyright (C) 2012 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_COMPAT_H
#define GST_VAAPI_COMPAT_H
#include <va/va.h>
#if VA_CHECK_VERSION(1,0,0)
#define VA_ROI_RC_QP_DELTA_SUPPORT(x) x->bits.roi_rc_qp_delta_support
#define VA_ENC_PACKED_HEADER_H264_SEI VAEncPackedHeaderRawData
#else
#define VA_ROI_RC_QP_DELTA_SUPPORT(x) x->bits.roi_rc_qp_delat_support
#define VA_ENC_PACKED_HEADER_H264_SEI VAEncPackedHeaderH264_SEI
#endif
#include <va/va_compat.h>
#include <va/va_drmcommon.h>
#endif /* GST_VAAPI_COMPAT_H */

View file

@ -0,0 +1,788 @@
/*
* gstvaapicontext.c - VA context abstraction
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
* Copyright (C) 2011-2014 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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:gstvaapicontext
* @short_description: VA context abstraction
*/
#include "sysdeps.h"
#include "gstvaapicompat.h"
#include "gstvaapicontext.h"
#include "gstvaapidisplay_priv.h"
#include "gstvaapisurface_priv.h"
#include "gstvaapisurfacepool.h"
#include "gstvaapisurfaceproxy.h"
#include "gstvaapivideopool_priv.h"
#include "gstvaapiutils.h"
/* Define default VA surface chroma format to YUV 4:2:0 */
#define DEFAULT_CHROMA_TYPE (GST_VAAPI_CHROMA_TYPE_YUV420)
/* Number of scratch surfaces beyond those used as reference */
#define SCRATCH_SURFACES_COUNT (4)
/* Debug category for GstVaapiContext */
GST_DEBUG_CATEGORY (gst_debug_vaapi_context);
#define GST_CAT_DEFAULT gst_debug_vaapi_context
static void
_init_vaapi_context_debug (void)
{
#ifndef GST_DISABLE_GST_DEBUG
static gsize _init = 0;
if (g_once_init_enter (&_init)) {
GST_DEBUG_CATEGORY_INIT (gst_debug_vaapi_context, "vaapicontext", 0,
"VA-API context");
g_once_init_leave (&_init, 1);
}
#endif
}
static inline gboolean
_context_is_broken_jpeg_decoder (GstVaapiContext * context)
{
GstVaapiDisplay *const display = GST_VAAPI_CONTEXT_DISPLAY (context);
return (context->info.profile == GST_VAAPI_PROFILE_JPEG_BASELINE
&& context->info.entrypoint == GST_VAAPI_ENTRYPOINT_VLD
&& gst_vaapi_display_has_driver_quirks (display,
GST_VAAPI_DRIVER_QUIRK_JPEG_DEC_BROKEN_FORMATS));
}
static gboolean
ensure_attributes (GstVaapiContext * context)
{
if (G_LIKELY (context->attribs))
return TRUE;
context->attribs =
gst_vaapi_config_surface_attributes_get (GST_VAAPI_CONTEXT_DISPLAY
(context), context->va_config);
if (!context->attribs)
return FALSE;
if (_context_is_broken_jpeg_decoder (context)) {
GstVideoFormat fmt = GST_VIDEO_FORMAT_NV12;
g_array_prepend_val (context->attribs->formats, fmt);
context->attribs->mem_types &= ~VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
}
return TRUE;
}
/* XXX(victor): verify the preferred video format concords with the
* chroma type; otherwise it is changed for the (very arbritrary)
* preferred format from the requested context chroma type, in the
* context attributes */
static void
ensure_preferred_format (GstVaapiContext * context)
{
const GstVaapiContextInfo *const cip = &context->info;
GArray *formats;
guint i;
if (context->preferred_format != GST_VIDEO_FORMAT_UNKNOWN)
return;
if (_context_is_broken_jpeg_decoder (context))
return;
if (!ensure_attributes (context) || !context->attribs->formats)
return;
formats = context->attribs->formats;
for (i = 0; i < formats->len; i++) {
GstVideoFormat format = g_array_index (formats, GstVideoFormat, i);
if (format == gst_vaapi_video_format_from_chroma (cip->chroma_type)) {
context->preferred_format = format;
break;
}
}
return;
}
static inline gboolean
context_get_attribute (GstVaapiContext * context, VAConfigAttribType type,
guint * out_value_ptr)
{
return gst_vaapi_get_config_attribute (GST_VAAPI_CONTEXT_DISPLAY (context),
context->va_profile, context->va_entrypoint, type, out_value_ptr);
}
static void
context_destroy_surfaces (GstVaapiContext * context)
{
if (context->surfaces) {
g_ptr_array_unref (context->surfaces);
context->surfaces = NULL;
}
context->preferred_format = GST_VIDEO_FORMAT_UNKNOWN;
gst_vaapi_video_pool_replace (&context->surfaces_pool, NULL);
}
static void
context_destroy (GstVaapiContext * context)
{
GstVaapiDisplay *const display = GST_VAAPI_CONTEXT_DISPLAY (context);
VAContextID context_id;
VAStatus status;
context_id = GST_VAAPI_CONTEXT_ID (context);
GST_DEBUG ("context 0x%08x / config 0x%08x", context_id, context->va_config);
if (context_id != VA_INVALID_ID) {
GST_VAAPI_DISPLAY_LOCK (display);
status = vaDestroyContext (GST_VAAPI_DISPLAY_VADISPLAY (display),
context_id);
GST_VAAPI_DISPLAY_UNLOCK (display);
if (!vaapi_check_status (status, "vaDestroyContext()"))
GST_WARNING ("failed to destroy context 0x%08x", context_id);
GST_VAAPI_CONTEXT_ID (context) = VA_INVALID_ID;
}
if (context->va_config != VA_INVALID_ID) {
GST_VAAPI_DISPLAY_LOCK (display);
status = vaDestroyConfig (GST_VAAPI_DISPLAY_VADISPLAY (display),
context->va_config);
GST_VAAPI_DISPLAY_UNLOCK (display);
if (!vaapi_check_status (status, "vaDestroyConfig()"))
GST_WARNING ("failed to destroy config 0x%08x", context->va_config);
context->va_config = VA_INVALID_ID;
}
if (context->attribs) {
gst_vaapi_config_surface_attributes_free (context->attribs);
context->attribs = NULL;
}
}
static gboolean
context_ensure_surfaces (GstVaapiContext * context)
{
GstVaapiDisplay *display = GST_VAAPI_CONTEXT_DISPLAY (context);
const GstVaapiContextInfo *const cip = &context->info;
const guint num_surfaces = cip->ref_frames + SCRATCH_SURFACES_COUNT;
GstVaapiSurface *surface;
GstVideoFormat format;
guint i, capacity;
ensure_preferred_format (context);
format = context->preferred_format;
for (i = context->surfaces->len; i < num_surfaces; i++) {
if (format != GST_VIDEO_FORMAT_UNKNOWN) {
surface = gst_vaapi_surface_new_with_format (display, format, cip->width,
cip->height, 0);
} else {
surface = gst_vaapi_surface_new (display, cip->chroma_type, cip->width,
cip->height);
}
if (!surface)
return FALSE;
g_ptr_array_add (context->surfaces, surface);
if (!gst_vaapi_video_pool_add_object (context->surfaces_pool, surface))
return FALSE;
}
capacity = cip->usage == GST_VAAPI_CONTEXT_USAGE_DECODE ? 0 : num_surfaces;
gst_vaapi_video_pool_set_capacity (context->surfaces_pool, capacity);
return TRUE;
}
static gboolean
context_create_surfaces (GstVaapiContext * context)
{
const GstVaapiContextInfo *const cip = &context->info;
GstVaapiDisplay *const display = GST_VAAPI_CONTEXT_DISPLAY (context);
guint num_surfaces;
num_surfaces = cip->ref_frames + SCRATCH_SURFACES_COUNT;
if (!context->surfaces) {
context->surfaces = g_ptr_array_new_full (num_surfaces,
(GDestroyNotify) gst_mini_object_unref);
if (!context->surfaces)
return FALSE;
}
if (!context->surfaces_pool) {
context->surfaces_pool =
gst_vaapi_surface_pool_new_with_chroma_type (display, cip->chroma_type,
cip->width, cip->height, 0);
if (!context->surfaces_pool)
return FALSE;
}
return context_ensure_surfaces (context);
}
static gboolean
context_create (GstVaapiContext * context)
{
const GstVaapiContextInfo *const cip = &context->info;
GstVaapiDisplay *const display = GST_VAAPI_CONTEXT_DISPLAY (context);
VAContextID context_id;
VASurfaceID surface_id;
VASurfaceID *surfaces_data = NULL;
VAStatus status;
GArray *surfaces = NULL;
gboolean success = FALSE;
guint i;
gint num_surfaces = 0;
if (!context->surfaces && !context_create_surfaces (context))
goto cleanup;
/* Create VA surfaces list for vaCreateContext() */
surfaces = g_array_sized_new (FALSE,
FALSE, sizeof (VASurfaceID), context->surfaces->len);
if (!surfaces)
goto cleanup;
for (i = 0; i < context->surfaces->len; i++) {
GstVaapiSurface *const surface = g_ptr_array_index (context->surfaces, i);
if (!surface)
goto cleanup;
surface_id = GST_VAAPI_SURFACE_ID (surface);
g_array_append_val (surfaces, surface_id);
}
g_assert (surfaces->len == context->surfaces->len);
/* vaCreateContext() doesn't really need an array of VASurfaceIDs (see
* https://lists.01.org/pipermail/intel-vaapi-media/2017-July/000052.html and
* https://github.com/intel/libva/issues/251); pass a dummy list of valid
* (non-null) IDs until the signature gets updated. */
if (cip->usage != GST_VAAPI_CONTEXT_USAGE_DECODE) {
surfaces_data = (VASurfaceID *) surfaces->data;
num_surfaces = surfaces->len;
}
GST_VAAPI_DISPLAY_LOCK (display);
status = vaCreateContext (GST_VAAPI_DISPLAY_VADISPLAY (display),
context->va_config, cip->width, cip->height, VA_PROGRESSIVE,
surfaces_data, num_surfaces, &context_id);
GST_VAAPI_DISPLAY_UNLOCK (display);
if (!vaapi_check_status (status, "vaCreateContext()"))
goto cleanup;
GST_VAAPI_CONTEXT_ID (context) = context_id;
success = TRUE;
cleanup:
if (surfaces)
g_array_unref (surfaces);
return success;
}
static gboolean
config_create (GstVaapiContext * context)
{
const GstVaapiContextInfo *const cip = &context->info;
GstVaapiDisplay *const display = GST_VAAPI_CONTEXT_DISPLAY (context);
VAConfigAttrib attribs[7], *attrib;
VAStatus status;
guint value, va_chroma_format, attrib_index;
/* Reset profile and entrypoint */
if (cip->profile == GST_VAAPI_PROFILE_UNKNOWN
|| cip->entrypoint == GST_VAAPI_ENTRYPOINT_INVALID)
goto cleanup;
context->va_profile = gst_vaapi_profile_get_va_profile (cip->profile);
context->va_entrypoint =
gst_vaapi_entrypoint_get_va_entrypoint (cip->entrypoint);
attrib_index = 0;
attrib = &attribs[attrib_index];
g_assert (attrib_index < G_N_ELEMENTS (attribs));
/* Validate VA surface format */
va_chroma_format = from_GstVaapiChromaType (cip->chroma_type);
if (!va_chroma_format)
goto cleanup;
attrib->type = VAConfigAttribRTFormat;
if (!context_get_attribute (context, attrib->type, &value))
goto cleanup;
if (!(value & va_chroma_format)) {
GST_ERROR ("unsupported chroma format (%s)",
string_of_va_chroma_format (va_chroma_format));
goto cleanup;
}
attrib->value = va_chroma_format;
attrib = &attribs[++attrib_index];
g_assert (attrib_index < G_N_ELEMENTS (attribs));
switch (cip->usage) {
#if USE_ENCODERS
case GST_VAAPI_CONTEXT_USAGE_ENCODE:
{
const GstVaapiConfigInfoEncoder *const config = &cip->config.encoder;
guint va_rate_control;
/* Rate control */
va_rate_control = from_GstVaapiRateControl (config->rc_mode);
if (va_rate_control != VA_RC_NONE) {
attrib->type = VAConfigAttribRateControl;
if (!context_get_attribute (context, attrib->type, &value))
goto cleanup;
if ((value & va_rate_control) != va_rate_control) {
GST_ERROR ("unsupported %s rate control",
string_of_VARateControl (va_rate_control));
goto cleanup;
}
attrib->value = va_rate_control;
attrib = &attribs[++attrib_index];
g_assert (attrib_index < G_N_ELEMENTS (attribs));
}
/* Packed headers */
if (config->packed_headers) {
attrib->type = VAConfigAttribEncPackedHeaders;
if (!context_get_attribute (context, attrib->type, &value))
goto cleanup;
if ((value & config->packed_headers) != config->packed_headers) {
GST_ERROR ("unsupported packed headers 0x%08x",
config->packed_headers & ~(value & config->packed_headers));
goto cleanup;
}
attrib->value = config->packed_headers;
attrib = &attribs[++attrib_index];
g_assert (attrib_index < G_N_ELEMENTS (attribs));
}
if (cip->profile == GST_VAAPI_PROFILE_JPEG_BASELINE) {
attrib->type = VAConfigAttribEncJPEG;
if (!context_get_attribute (context, attrib->type, &value))
goto cleanup;
attrib->value = value;
attrib = &attribs[++attrib_index];
g_assert (attrib_index < G_N_ELEMENTS (attribs));
}
#if VA_CHECK_VERSION(0,39,1)
if (config->roi_capability) {
VAConfigAttribValEncROI *roi_config;
attrib->type = VAConfigAttribEncROI;
if (!context_get_attribute (context, attrib->type, &value))
goto cleanup;
roi_config = (VAConfigAttribValEncROI *) & value;
if (roi_config->bits.num_roi_regions != config->roi_num_supported) {
GST_ERROR ("Mismatched ROI support: number of regions supported: %d",
roi_config->bits.num_roi_regions);
goto cleanup;
}
if (config->rc_mode != GST_VAAPI_RATECONTROL_CQP
&& VA_ROI_RC_QP_DELTA_SUPPORT (roi_config) == 0) {
GST_ERROR ("Mismatched ROI support: ROI delta QP: %d",
VA_ROI_RC_QP_DELTA_SUPPORT (roi_config));
goto cleanup;
}
attrib->value = value;
attrib = &attribs[++attrib_index];
g_assert (attrib_index < G_N_ELEMENTS (attribs));
}
#endif
break;
}
#endif
default:
break;
}
GST_VAAPI_DISPLAY_LOCK (display);
status = vaCreateConfig (GST_VAAPI_DISPLAY_VADISPLAY (display),
context->va_profile, context->va_entrypoint, attribs, attrib_index,
&context->va_config);
GST_VAAPI_DISPLAY_UNLOCK (display);
if (!vaapi_check_status (status, "vaCreateConfig()"))
goto cleanup;
return TRUE;
cleanup:
GST_WARNING ("Failed to create vaConfig");
return FALSE;
}
/** Updates config for encoding. Returns %TRUE if config changed */
static gboolean
context_update_config_encoder (GstVaapiContext * context,
const GstVaapiConfigInfoEncoder * new_config)
{
GstVaapiConfigInfoEncoder *const config = &context->info.config.encoder;
gboolean config_changed = FALSE;
g_assert (context->info.usage == GST_VAAPI_CONTEXT_USAGE_ENCODE);
if (config->rc_mode != new_config->rc_mode) {
config->rc_mode = new_config->rc_mode;
config_changed = TRUE;
}
if (config->packed_headers != new_config->packed_headers) {
config->packed_headers = new_config->packed_headers;
config_changed = TRUE;
}
if (config->roi_capability != new_config->roi_capability ||
config->roi_num_supported != new_config->roi_num_supported) {
config->roi_capability = new_config->roi_capability;
config->roi_num_supported = new_config->roi_num_supported;
config_changed = TRUE;
}
return config_changed;
}
static inline void
gst_vaapi_context_init (GstVaapiContext * context,
const GstVaapiContextInfo * new_cip)
{
GstVaapiContextInfo *const cip = &context->info;
*cip = *new_cip;
if (!cip->chroma_type)
cip->chroma_type = DEFAULT_CHROMA_TYPE;
context->va_config = VA_INVALID_ID;
context->reset_on_resize = TRUE;
context->attribs = NULL;
context->preferred_format = GST_VIDEO_FORMAT_UNKNOWN;
}
/**
* gst_vaapi_context_new:
* @display: a #GstVaapiDisplay
* @cip: a pointer to the #GstVaapiContextInfo
*
* Creates a new #GstVaapiContext with the configuration specified by
* @cip, thus including profile, entry-point, encoded size and maximum
* number of reference frames reported by the bitstream.
*
* Return value: the newly allocated #GstVaapiContext object
*/
GstVaapiContext *
gst_vaapi_context_new (GstVaapiDisplay * display,
const GstVaapiContextInfo * cip)
{
GstVaapiContext *context;
g_return_val_if_fail (display, NULL);
_init_vaapi_context_debug ();
if (cip->profile == GST_VAAPI_PROFILE_UNKNOWN
|| cip->entrypoint == GST_VAAPI_ENTRYPOINT_INVALID)
return NULL;
context = g_slice_new (GstVaapiContext);
if (!context)
return NULL;
GST_VAAPI_CONTEXT_DISPLAY (context) = gst_object_ref (display);
GST_VAAPI_CONTEXT_ID (context) = VA_INVALID_ID;
g_atomic_int_set (&context->ref_count, 1);
context->surfaces = NULL;
context->surfaces_pool = NULL;
gst_vaapi_context_init (context, cip);
if (!config_create (context))
goto error;
/* this means we don't want to create a VAcontext */
if (cip->width == 0 && cip->height == 0)
goto done;
/* this is not valid */
if (cip->width == 0 || cip->height == 0)
goto error;
if (!context_create (context))
goto error;
done:
GST_DEBUG ("context 0x%08" G_GSIZE_MODIFIER "x / config 0x%08x",
GST_VAAPI_CONTEXT_ID (context), context->va_config);
return context;
/* ERRORS */
error:
{
gst_vaapi_context_unref (context);
return NULL;
}
}
/**
* gst_vaapi_context_reset:
* @context: a #GstVaapiContext
* @new_cip: a pointer to the new #GstVaapiContextInfo details
*
* Resets @context to the configuration specified by @new_cip, thus
* including profile, entry-point, encoded size and maximum number of
* reference frames reported by the bitstream.
*
* Return value: %TRUE on success
*/
gboolean
gst_vaapi_context_reset (GstVaapiContext * context,
const GstVaapiContextInfo * new_cip)
{
GstVaapiContextInfo *const cip = &context->info;
gboolean reset_surfaces = FALSE, reset_config = FALSE;
gboolean grow_surfaces = FALSE;
GstVaapiChromaType chroma_type;
if (new_cip->profile == GST_VAAPI_PROFILE_UNKNOWN
|| new_cip->entrypoint == GST_VAAPI_ENTRYPOINT_INVALID)
return FALSE;
chroma_type = new_cip->chroma_type ? new_cip->chroma_type :
DEFAULT_CHROMA_TYPE;
if (cip->chroma_type != chroma_type) {
cip->chroma_type = chroma_type;
reset_surfaces = TRUE;
}
if (cip->width != new_cip->width || cip->height != new_cip->height) {
cip->width = new_cip->width;
cip->height = new_cip->height;
reset_surfaces = TRUE;
}
if (cip->profile != new_cip->profile ||
cip->entrypoint != new_cip->entrypoint) {
cip->profile = new_cip->profile;
cip->entrypoint = new_cip->entrypoint;
reset_config = TRUE;
}
if (cip->ref_frames < new_cip->ref_frames) {
cip->ref_frames = new_cip->ref_frames;
grow_surfaces = TRUE;
}
if (cip->usage != new_cip->usage) {
cip->usage = new_cip->usage;
reset_config = TRUE;
memcpy (&cip->config, &new_cip->config, sizeof (cip->config));
} else if (new_cip->usage == GST_VAAPI_CONTEXT_USAGE_ENCODE) {
if (context_update_config_encoder (context, &new_cip->config.encoder))
reset_config = TRUE;
} else if (new_cip->usage == GST_VAAPI_CONTEXT_USAGE_DECODE) {
if ((reset_surfaces && context->reset_on_resize) || grow_surfaces)
reset_config = TRUE;
}
if (reset_surfaces)
context_destroy_surfaces (context);
if (reset_config)
context_destroy (context);
if (reset_config && !(config_create (context) && context_create (context)))
return FALSE;
if (reset_surfaces && !context_create_surfaces (context))
return FALSE;
else if (grow_surfaces && !context_ensure_surfaces (context))
return FALSE;
return TRUE;
}
/**
* gst_vaapi_context_get_id:
* @context: a #GstVaapiContext
*
* Returns the underlying VAContextID of the @context.
*
* Return value: the underlying VA context id
*/
GstVaapiID
gst_vaapi_context_get_id (GstVaapiContext * context)
{
g_return_val_if_fail (context != NULL, VA_INVALID_ID);
return GST_VAAPI_CONTEXT_ID (context);
}
/**
* gst_vaapi_context_get_surface_proxy:
* @context: a #GstVaapiContext
*
* Acquires a free surface, wrapped into a #GstVaapiSurfaceProxy. The
* returned surface will be automatically released when the proxy is
* destroyed. So, it is enough to call gst_vaapi_surface_proxy_unref()
* after usage.
*
* This function returns %NULL if there is no free surface available
* in the pool. The surfaces are pre-allocated during context creation
* though.
*
* Return value: a free surface, or %NULL if none is available
*/
GstVaapiSurfaceProxy *
gst_vaapi_context_get_surface_proxy (GstVaapiContext * context)
{
g_return_val_if_fail (context != NULL, NULL);
return
gst_vaapi_surface_proxy_new_from_pool (GST_VAAPI_SURFACE_POOL
(context->surfaces_pool));
}
/**
* gst_vaapi_context_get_surface_count:
* @context: a #GstVaapiContext
*
* Retrieves the number of free surfaces left in the pool.
*
* Return value: the number of free surfaces available in the pool
*/
guint
gst_vaapi_context_get_surface_count (GstVaapiContext * context)
{
g_return_val_if_fail (context != NULL, 0);
if (gst_vaapi_video_pool_get_capacity (context->surfaces_pool) == 0)
return G_MAXUINT;
return gst_vaapi_video_pool_get_size (context->surfaces_pool);
}
/**
* gst_vaapi_context_reset_on_resize:
* @context: a #GstVaapiContext
* @reset_on_resize: Should the context be reset on size change
*
* Sets whether the underlying context should be reset when a size change
* happens. The proper setting for this is codec dependent.
*/
void
gst_vaapi_context_reset_on_resize (GstVaapiContext * context,
gboolean reset_on_resize)
{
g_return_if_fail (context != NULL);
context->reset_on_resize = reset_on_resize;
}
/**
* gst_vaapi_context_get_surface_formats:
* @context: a #GstVaapiContext
*
* Determines the set of supported formats by the surfaces associated
* to @context. The caller owns an extra reference of the resulting
* array of #GstVideoFormat elements, so it shall be released with
* g_array_unref after usage.
*
* Return value: (transfer full): the set of target formats supported
* by the surfaces in @context.
*/
GArray *
gst_vaapi_context_get_surface_formats (GstVaapiContext * context)
{
g_return_val_if_fail (context, NULL);
if (!ensure_attributes (context))
return NULL;
if (context->attribs->formats)
return g_array_ref (context->attribs->formats);
return NULL;
}
/**
* gst_vaapi_context_get_surface_attributes:
* @context: a #GstVaapiContext
* @out_attribs: an allocated #GstVaapiConfigSurfaceAttributes
*
* Copy context's surface restrictions to @out_attribs, EXCEPT the
* color formats. Use gst_vaapi_context_get_surface_formats() to get
* them.
*
* Returns: %TRUE if the attributes were extracted and copied; %FALSE,
* otherwise
**/
gboolean
gst_vaapi_context_get_surface_attributes (GstVaapiContext * context,
GstVaapiConfigSurfaceAttributes * out_attribs)
{
g_return_val_if_fail (context, FALSE);
if (!ensure_attributes (context))
return FALSE;
if (out_attribs) {
out_attribs->min_width = context->attribs->min_width;
out_attribs->min_height = context->attribs->min_height;
out_attribs->max_width = context->attribs->max_width;
out_attribs->max_height = context->attribs->max_height;
out_attribs->mem_types = context->attribs->mem_types;
out_attribs->formats = NULL;
}
return TRUE;
}
/**
* gst_vaapi_context_ref:
* @context: a #GstVaapiContext
*
* Atomically increases the reference count of the given @context by one.
*
* Returns: The same @context argument
*/
GstVaapiContext *
gst_vaapi_context_ref (GstVaapiContext * context)
{
g_return_val_if_fail (context != NULL, NULL);
g_atomic_int_inc (&context->ref_count);
return context;
}
/**
* gst_vaapi_context_unref:
* @context: a #GstVaapiContext
*
* Atomically decreases the reference count of the @context by one. If
* the reference count reaches zero, the object will be free'd.
*/
void
gst_vaapi_context_unref (GstVaapiContext * context)
{
g_return_if_fail (context != NULL);
g_return_if_fail (context->ref_count > 0);
if (g_atomic_int_dec_and_test (&context->ref_count)) {
context_destroy (context);
context_destroy_surfaces (context);
gst_vaapi_display_replace (&context->display, NULL);
g_slice_free (GstVaapiContext, context);
}
}

View file

@ -0,0 +1,170 @@
/*
* gstvaapicontext.h - VA context abstraction (private)
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
* Copyright (C) 2011-2014 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_CONTEXT_H
#define GST_VAAPI_CONTEXT_H
#include "gstvaapiprofile.h"
#include "gstvaapidisplay.h"
#include "gstvaapisurface.h"
#include "gstvaapiutils_core.h"
#include "gstvaapivideopool.h"
G_BEGIN_DECLS
#define GST_VAAPI_CONTEXT(obj) \
((GstVaapiContext *) (obj))
typedef struct _GstVaapiConfigInfoEncoder GstVaapiConfigInfoEncoder;
typedef struct _GstVaapiContextInfo GstVaapiContextInfo;
typedef struct _GstVaapiContext GstVaapiContext;
/**
* GstVaapiContextUsage:
* @GST_VAAPI_CONTEXT_MODE_DECODE: context used for decoding.
* @GST_VAAPI_CONTEXT_MODE_ENCODE: context used for encoding.
* @GST_VAAPI_CONTEXT_MODE_VPP: context used for video processing.
*
* The set of supported VA context usages.
*/
typedef enum {
GST_VAAPI_CONTEXT_USAGE_DECODE = 1,
GST_VAAPI_CONTEXT_USAGE_ENCODE,
GST_VAAPI_CONTEXT_USAGE_VPP,
} GstVaapiContextUsage;
/**
* GstVaapiConfigInfoEncoder:
* @rc_mode: rate-control mode (#GstVaapiRateControl).
* @packed_headers: notify encoder that packed headers are submitted (mask).
* @roi_capability: if encoder supports regions-of-interest.
* @roi_num_supported: The number of regions-of-interest supported.
*
* Extra configuration for encoding.
*/
struct _GstVaapiConfigInfoEncoder
{
GstVaapiRateControl rc_mode;
guint packed_headers;
gboolean roi_capability;
guint roi_num_supported;
};
/**
* GstVaapiContextInfo:
*
* Structure holding VA context info like encoded size, decoder
* profile and entry-point to use, and maximum number of reference
* frames reported by the bitstream.
*/
struct _GstVaapiContextInfo
{
GstVaapiContextUsage usage;
GstVaapiProfile profile;
GstVaapiEntrypoint entrypoint;
GstVaapiChromaType chroma_type;
guint width;
guint height;
guint ref_frames;
union _GstVaapiConfigInfo {
GstVaapiConfigInfoEncoder encoder;
} config;
};
/**
* GstVaapiContext:
*
* A VA context wrapper.
*/
struct _GstVaapiContext
{
/*< private >*/
gint ref_count;
GstVaapiDisplay *display;
GstVaapiID object_id;
/*< public >*/
GstVaapiContextInfo info;
VAProfile va_profile;
VAEntrypoint va_entrypoint;
VAConfigID va_config;
GPtrArray *surfaces;
GstVaapiVideoPool *surfaces_pool;
gboolean reset_on_resize;
GstVaapiConfigSurfaceAttributes *attribs;
GstVideoFormat preferred_format;
};
#define GST_VAAPI_CONTEXT_ID(context) (((GstVaapiContext *)(context))->object_id)
#define GST_VAAPI_CONTEXT_DISPLAY(context) (((GstVaapiContext *)(context))->display)
G_GNUC_INTERNAL
GstVaapiContext *
gst_vaapi_context_new (GstVaapiDisplay * display,
const GstVaapiContextInfo * cip);
G_GNUC_INTERNAL
gboolean
gst_vaapi_context_reset (GstVaapiContext * context,
const GstVaapiContextInfo * new_cip);
G_GNUC_INTERNAL
GstVaapiID
gst_vaapi_context_get_id (GstVaapiContext * context);
G_GNUC_INTERNAL
GstVaapiSurfaceProxy *
gst_vaapi_context_get_surface_proxy (GstVaapiContext * context);
G_GNUC_INTERNAL
guint
gst_vaapi_context_get_surface_count (GstVaapiContext * context);
G_GNUC_INTERNAL
void
gst_vaapi_context_reset_on_resize (GstVaapiContext * context,
gboolean reset_on_resize);
G_GNUC_INTERNAL
GArray *
gst_vaapi_context_get_surface_formats (GstVaapiContext * context);
G_GNUC_INTERNAL
gboolean
gst_vaapi_context_get_surface_attributes (GstVaapiContext * context,
GstVaapiConfigSurfaceAttributes * out_attribs);
G_GNUC_INTERNAL
GstVaapiContext *
gst_vaapi_context_ref (GstVaapiContext * context);
G_GNUC_INTERNAL
void
gst_vaapi_context_unref (GstVaapiContext * context);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiContext, gst_vaapi_context_unref)
G_END_DECLS
#endif /* GST_VAAPI_CONTEXT_H */

View file

@ -0,0 +1,38 @@
/*
* gstvaapidebug.h - VA-API debugging utilities
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
*
* 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_VAAPI_DEBUG_H
#define GST_VAAPI_DEBUG_H
#include <gst/gstinfo.h>
#if DEBUG
GST_DEBUG_CATEGORY_EXTERN(gst_debug_vaapi);
#define GST_CAT_DEFAULT gst_debug_vaapi
#endif
#if DEBUG_VAAPI_DISPLAY
GST_DEBUG_CATEGORY_EXTERN(gst_debug_vaapi_display);
#define GST_CAT_DEFAULT gst_debug_vaapi_display
#endif
#endif /* GST_VAAPI_DEBUG_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,148 @@
/*
* gstvaapidecoder.h - VA decoder abstraction
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
* Copyright (C) 2011-2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DECODER_H
#define GST_VAAPI_DECODER_H
#include <gst/gstbuffer.h>
#include <gst/base/gstadapter.h>
#include <gst/vaapi/gstvaapisurfaceproxy.h>
#include <gst/video/gstvideoutils.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_DECODER \
(gst_vaapi_decoder_get_type ())
#define GST_VAAPI_DECODER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_DECODER, GstVaapiDecoder))
#define GST_VAAPI_IS_DECODER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_DECODER))
typedef struct _GstVaapiDecoder GstVaapiDecoder;
typedef void (*GstVaapiDecoderStateChangedFunc) (GstVaapiDecoder * decoder,
const GstVideoCodecState * codec_state, gpointer user_data);
/**
* GstVaapiDecoderStatus:
* @GST_VAAPI_DECODER_STATUS_SUCCESS: Success.
* @GST_VAAPI_DECODER_STATUS_END_OF_STREAM: End-Of-Stream.
* @GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED: No memory left.
* @GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED: Decoder initialization failure.
* @GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC: Unsupported codec.
* @GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA: Not enough input data to decode.
* @GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE: No surface left to hold the decoded picture.
* @GST_VAAPI_DECODER_STATUS_ERROR_INVALID_SURFACE: Invalid surface.
* @GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER: Invalid or unsupported bitstream data.
* @GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE: Unsupported codec profile.
* @GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT: Unsupported chroma format.
* @GST_VAAPI_DECODER_STATUS_ERROR_INVALID_PARAMETER: Unsupported parameter.
* @GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN: Unknown error.
*
* Decoder status for gst_vaapi_decoder_get_surface().
*/
typedef enum {
GST_VAAPI_DECODER_STATUS_SUCCESS = 0,
GST_VAAPI_DECODER_STATUS_END_OF_STREAM,
GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED,
GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED,
GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC,
GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA,
GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE,
GST_VAAPI_DECODER_STATUS_ERROR_INVALID_SURFACE,
GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER,
GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE,
GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT,
GST_VAAPI_DECODER_STATUS_ERROR_INVALID_PARAMETER,
GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN = -1
} GstVaapiDecoderStatus;
GType
gst_vaapi_decoder_get_type (void) G_GNUC_CONST;
void
gst_vaapi_decoder_replace (GstVaapiDecoder ** old_decoder_ptr,
GstVaapiDecoder * new_decoder);
gpointer
gst_vaapi_decoder_get_user_data (GstVaapiDecoder * decoder);
void
gst_vaapi_decoder_set_user_data (GstVaapiDecoder * decoder, gpointer user_data);
GstVaapiCodec
gst_vaapi_decoder_get_codec (GstVaapiDecoder * decoder);
GstVideoCodecState *
gst_vaapi_decoder_get_codec_state (GstVaapiDecoder * decoder);
void
gst_vaapi_decoder_set_codec_state_changed_func (GstVaapiDecoder * decoder,
GstVaapiDecoderStateChangedFunc func, gpointer user_data);
GstCaps *
gst_vaapi_decoder_get_caps (GstVaapiDecoder * decoder);
gboolean
gst_vaapi_decoder_put_buffer (GstVaapiDecoder * decoder, GstBuffer * buf);
GstVaapiDecoderStatus
gst_vaapi_decoder_get_surface (GstVaapiDecoder * decoder,
GstVaapiSurfaceProxy ** out_proxy_ptr);
GstVaapiDecoderStatus
gst_vaapi_decoder_get_frame (GstVaapiDecoder * decoder,
GstVideoCodecFrame ** out_frame_ptr);
GstVaapiDecoderStatus
gst_vaapi_decoder_get_frame_with_timeout (GstVaapiDecoder * decoder,
GstVideoCodecFrame ** out_frame_ptr, guint64 timeout);
GstVaapiDecoderStatus
gst_vaapi_decoder_parse (GstVaapiDecoder * decoder,
GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos,
guint * got_unit_size_ptr, gboolean * got_frame_ptr);
GstVaapiDecoderStatus
gst_vaapi_decoder_decode (GstVaapiDecoder * decoder,
GstVideoCodecFrame * frame);
GstVaapiDecoderStatus
gst_vaapi_decoder_flush (GstVaapiDecoder * decoder);
GstVaapiDecoderStatus
gst_vaapi_decoder_reset (GstVaapiDecoder * decoder);
gboolean
gst_vaapi_decoder_update_caps (GstVaapiDecoder * decoder, GstCaps * caps);
GArray *
gst_vaapi_decoder_get_surface_attributes (GstVaapiDecoder * decoder,
gint * min_width, gint * min_height, gint * max_width, gint * max_height,
guint * mem_types);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiDecoder, gst_object_unref)
G_END_DECLS
#endif /* GST_VAAPI_DECODER_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,47 @@
/*
* gstvaapidecoder_av1.h - AV1 decoder
*
* Copyright (C) 2019-2020 Intel Corporation
* Author: Junyan He <junyan.he@hotmail.com>
*
* 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_VAAPI_DECODER_AV1_H
#define GST_VAAPI_DECODER_AV1_H
#include <gst/vaapi/gstvaapidecoder.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_DECODER_AV1 \
(gst_vaapi_decoder_av1_get_type ())
#define GST_VAAPI_DECODER_AV1(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_DECODER_AV1, GstVaapiDecoderAV1))
#define GST_VAAPI_IS_DECODER_AV1(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_DECODER_AV1))
typedef struct _GstVaapiDecoderAV1 GstVaapiDecoderAV1;
GType
gst_vaapi_decoder_av1_get_type (void) G_GNUC_CONST;
GstVaapiDecoder *
gst_vaapi_decoder_av1_new (GstVaapiDisplay * display, GstCaps * caps);
G_END_DECLS
#endif /* GST_VAAPI_DECODER_AV1_H */

View file

@ -0,0 +1,421 @@
/*
* gstvaapidecoder_dpb.c - Decoded Picture Buffer
*
* Copyright (C) 2012-2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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 "sysdeps.h"
#include "gstvaapidecoder_dpb.h"
#define DEBUG 1
#include "gstvaapidebug.h"
#define GST_VAAPI_DPB_CLASS(klass) \
((GstVaapiDpbClass *)(klass))
#define GST_VAAPI_DPB_GET_CLASS(obj) \
GST_VAAPI_DPB_CLASS(GST_VAAPI_MINI_OBJECT_GET_CLASS(obj))
/**
* GstVaapiDpb:
*
* A decoded picture buffer (DPB) object.
*/
struct _GstVaapiDpb
{
/*< private > */
GstVaapiMiniObject parent_instance;
/*< protected > */
GstVaapiPicture **pictures;
guint num_pictures;
guint max_pictures;
};
/**
* GstVaapiDpbClass:
*
* The #GstVaapiDpb base class.
*/
struct _GstVaapiDpbClass
{
/*< private > */
GstVaapiMiniObjectClass parent_class;
/*< protected > */
void (*flush) (GstVaapiDpb * dpb);
gboolean (*add) (GstVaapiDpb * dpb, GstVaapiPicture * picture);
void (*get_neighbours) (GstVaapiDpb * dpb, GstVaapiPicture * picture,
GstVaapiPicture ** prev_picture_ptr, GstVaapiPicture ** next_picture_ptr);
};
static const GstVaapiMiniObjectClass *gst_vaapi_dpb_class (void);
static const GstVaapiMiniObjectClass *gst_vaapi_dpb2_class (void);
/* ------------------------------------------------------------------------- */
/* --- Common utilities --- */
/* ------------------------------------------------------------------------- */
static inline GstVaapiDpb *
dpb_new (guint max_pictures)
{
GstVaapiDpb *dpb;
g_return_val_if_fail (max_pictures > 0, NULL);
dpb =
(GstVaapiDpb *) gst_vaapi_mini_object_new (max_pictures ==
2 ? gst_vaapi_dpb2_class () : gst_vaapi_dpb_class ());
if (!dpb)
return NULL;
dpb->num_pictures = 0;
dpb->max_pictures = max_pictures;
dpb->pictures = g_new0 (GstVaapiPicture *, max_pictures);
if (!dpb->pictures)
goto error;
return dpb;
/* ERRORS */
error:
{
gst_vaapi_dpb_unref (dpb);
return NULL;
}
}
static gint
dpb_get_oldest (GstVaapiDpb * dpb, gboolean output)
{
gint i, lowest_pts_index;
for (i = 0; i < dpb->num_pictures; i++) {
if ((GST_VAAPI_PICTURE_IS_OUTPUT (dpb->pictures[i]) ^ output) == 0)
break;
}
if (i == dpb->num_pictures)
return -1;
lowest_pts_index = i++;
for (; i < dpb->num_pictures; i++) {
GstVaapiPicture *const picture = dpb->pictures[i];
if ((GST_VAAPI_PICTURE_IS_OUTPUT (picture) ^ output) != 0)
continue;
if (picture->poc < dpb->pictures[lowest_pts_index]->poc)
lowest_pts_index = i;
}
return lowest_pts_index;
}
static void
dpb_remove_index (GstVaapiDpb * dpb, guint index)
{
GstVaapiPicture **const pictures = dpb->pictures;
guint num_pictures = --dpb->num_pictures;
if (index != num_pictures)
gst_vaapi_picture_replace (&pictures[index], pictures[num_pictures]);
gst_vaapi_picture_replace (&pictures[num_pictures], NULL);
}
static inline gboolean
dpb_output (GstVaapiDpb * dpb, GstVaapiPicture * picture)
{
return gst_vaapi_picture_output (picture);
}
static gboolean
dpb_bump (GstVaapiDpb * dpb)
{
gint index;
gboolean success;
index = dpb_get_oldest (dpb, FALSE);
if (index < 0)
return FALSE;
success = dpb_output (dpb, dpb->pictures[index]);
if (!GST_VAAPI_PICTURE_IS_REFERENCE (dpb->pictures[index]))
dpb_remove_index (dpb, index);
return success;
}
static void
dpb_clear (GstVaapiDpb * dpb)
{
guint i;
for (i = 0; i < dpb->num_pictures; i++)
gst_vaapi_picture_replace (&dpb->pictures[i], NULL);
dpb->num_pictures = 0;
}
static void
dpb_flush (GstVaapiDpb * dpb)
{
while (dpb_bump (dpb));
dpb_clear (dpb);
}
/* ------------------------------------------------------------------------- */
/* --- Generic implementation --- */
/* ------------------------------------------------------------------------- */
static gboolean
dpb_add (GstVaapiDpb * dpb, GstVaapiPicture * picture)
{
guint i;
// Remove all unused pictures
i = 0;
while (i < dpb->num_pictures) {
GstVaapiPicture *const picture = dpb->pictures[i];
if (GST_VAAPI_PICTURE_IS_OUTPUT (picture) &&
!GST_VAAPI_PICTURE_IS_REFERENCE (picture))
dpb_remove_index (dpb, i);
else
i++;
}
// Store reference decoded picture into the DPB
if (GST_VAAPI_PICTURE_IS_REFERENCE (picture)) {
while (dpb->num_pictures == dpb->max_pictures) {
if (!dpb_bump (dpb))
return FALSE;
}
}
// Store non-reference decoded picture into the DPB
else {
if (GST_VAAPI_PICTURE_IS_SKIPPED (picture))
return TRUE;
while (dpb->num_pictures == dpb->max_pictures) {
for (i = 0; i < dpb->num_pictures; i++) {
if (!GST_VAAPI_PICTURE_IS_OUTPUT (picture) &&
dpb->pictures[i]->poc < picture->poc)
break;
}
if (i == dpb->num_pictures)
return dpb_output (dpb, picture);
if (!dpb_bump (dpb))
return FALSE;
}
}
gst_vaapi_picture_replace (&dpb->pictures[dpb->num_pictures++], picture);
return TRUE;
}
static void
dpb_get_neighbours (GstVaapiDpb * dpb, GstVaapiPicture * picture,
GstVaapiPicture ** prev_picture_ptr, GstVaapiPicture ** next_picture_ptr)
{
GstVaapiPicture *prev_picture = NULL;
GstVaapiPicture *next_picture = NULL;
guint i;
/* Find the first picture with POC > specified picture POC */
for (i = 0; i < dpb->num_pictures; i++) {
GstVaapiPicture *const ref_picture = dpb->pictures[i];
if (ref_picture->poc == picture->poc) {
if (i > 0)
prev_picture = dpb->pictures[i - 1];
if (i + 1 < dpb->num_pictures)
next_picture = dpb->pictures[i + 1];
break;
} else if (ref_picture->poc > picture->poc) {
next_picture = ref_picture;
if (i > 0)
prev_picture = dpb->pictures[i - 1];
break;
}
}
g_assert (next_picture ? next_picture->poc > picture->poc : TRUE);
g_assert (prev_picture ? prev_picture->poc < picture->poc : TRUE);
if (prev_picture_ptr)
*prev_picture_ptr = prev_picture;
if (next_picture_ptr)
*next_picture_ptr = next_picture;
}
/* ------------------------------------------------------------------------- */
/* --- Optimized implementation for 2 reference pictures --- */
/* ------------------------------------------------------------------------- */
static gboolean
dpb2_add (GstVaapiDpb * dpb, GstVaapiPicture * picture)
{
GstVaapiPicture *ref_picture;
gint index = -1;
g_return_val_if_fail (GST_VAAPI_IS_DPB (dpb), FALSE);
g_return_val_if_fail (dpb->max_pictures == 2, FALSE);
/*
* Purpose: only store reference decoded pictures into the DPB
*
* This means:
* - non-reference decoded pictures are output immediately
* - ... thus causing older reference pictures to be output, if not already
* - the oldest reference picture is replaced with the new reference picture
*/
if (G_LIKELY (dpb->num_pictures == 2)) {
index = (dpb->pictures[0]->poc > dpb->pictures[1]->poc);
ref_picture = dpb->pictures[index];
if (!GST_VAAPI_PICTURE_IS_OUTPUT (ref_picture)) {
if (!dpb_output (dpb, ref_picture))
return FALSE;
}
}
if (!GST_VAAPI_PICTURE_IS_REFERENCE (picture))
return dpb_output (dpb, picture);
if (index < 0)
index = dpb->num_pictures++;
gst_vaapi_picture_replace (&dpb->pictures[index], picture);
return TRUE;
}
static void
dpb2_get_neighbours (GstVaapiDpb * dpb, GstVaapiPicture * picture,
GstVaapiPicture ** prev_picture_ptr, GstVaapiPicture ** next_picture_ptr)
{
GstVaapiPicture *ref_picture, *ref_pictures[2];
GstVaapiPicture **picture_ptr;
guint i, index;
g_return_if_fail (GST_VAAPI_IS_DPB (dpb));
g_return_if_fail (dpb->max_pictures == 2);
g_return_if_fail (GST_VAAPI_IS_PICTURE (picture));
ref_pictures[0] = NULL;
ref_pictures[1] = NULL;
for (i = 0; i < dpb->num_pictures; i++) {
ref_picture = dpb->pictures[i];
index = ref_picture->poc > picture->poc;
picture_ptr = &ref_pictures[index];
if (!*picture_ptr || ((*picture_ptr)->poc > ref_picture->poc) == index)
*picture_ptr = ref_picture;
}
if (prev_picture_ptr)
*prev_picture_ptr = ref_pictures[0];
if (next_picture_ptr)
*next_picture_ptr = ref_pictures[1];
}
/* ------------------------------------------------------------------------- */
/* --- Interface --- */
/* ------------------------------------------------------------------------- */
static void
gst_vaapi_dpb_finalize (GstVaapiDpb * dpb)
{
dpb_clear (dpb);
g_free (dpb->pictures);
}
static const GstVaapiMiniObjectClass *
gst_vaapi_dpb_class (void)
{
static const GstVaapiDpbClass GstVaapiDpbClass = {
{sizeof (GstVaapiDpb),
(GDestroyNotify) gst_vaapi_dpb_finalize}
,
dpb_flush,
dpb_add,
dpb_get_neighbours
};
return &GstVaapiDpbClass.parent_class;
}
static const GstVaapiMiniObjectClass *
gst_vaapi_dpb2_class (void)
{
static const GstVaapiDpbClass GstVaapiDpb2Class = {
{sizeof (GstVaapiDpb),
(GDestroyNotify) gst_vaapi_dpb_finalize}
,
dpb_flush,
dpb2_add,
dpb2_get_neighbours
};
return &GstVaapiDpb2Class.parent_class;
}
GstVaapiDpb *
gst_vaapi_dpb_new (guint max_pictures)
{
return dpb_new (max_pictures);
}
void
gst_vaapi_dpb_flush (GstVaapiDpb * dpb)
{
const GstVaapiDpbClass *klass;
g_return_if_fail (GST_VAAPI_IS_DPB (dpb));
klass = GST_VAAPI_DPB_GET_CLASS (dpb);
if (G_UNLIKELY (!klass || !klass->add))
return;
klass->flush (dpb);
}
gboolean
gst_vaapi_dpb_add (GstVaapiDpb * dpb, GstVaapiPicture * picture)
{
const GstVaapiDpbClass *klass;
g_return_val_if_fail (GST_VAAPI_IS_DPB (dpb), FALSE);
g_return_val_if_fail (GST_VAAPI_IS_PICTURE (picture), FALSE);
klass = GST_VAAPI_DPB_GET_CLASS (dpb);
if (G_UNLIKELY (!klass || !klass->add))
return FALSE;
return klass->add (dpb, picture);
}
guint
gst_vaapi_dpb_size (GstVaapiDpb * dpb)
{
g_return_val_if_fail (GST_VAAPI_IS_DPB (dpb), 0);
return dpb->num_pictures;
}
void
gst_vaapi_dpb_get_neighbours (GstVaapiDpb * dpb, GstVaapiPicture * picture,
GstVaapiPicture ** prev_picture_ptr, GstVaapiPicture ** next_picture_ptr)
{
const GstVaapiDpbClass *klass;
g_return_if_fail (GST_VAAPI_IS_DPB (dpb));
g_return_if_fail (GST_VAAPI_IS_PICTURE (picture));
klass = GST_VAAPI_DPB_GET_CLASS (dpb);
if (G_UNLIKELY (!klass || !klass->get_neighbours))
return;
klass->get_neighbours (dpb, picture, prev_picture_ptr, next_picture_ptr);
}

View file

@ -0,0 +1,80 @@
/*
* gstvaapidecoder_dpb.h - Decoded Picture Buffer
*
* Copyright (C) 2012-2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DECODER_DPB_H
#define GST_VAAPI_DECODER_DPB_H
#include <gst/vaapi/gstvaapidecoder_objects.h>
G_BEGIN_DECLS
typedef struct _GstVaapiDpb GstVaapiDpb;
typedef struct _GstVaapiDpbClass GstVaapiDpbClass;
/* ------------------------------------------------------------------------- */
/* --- Decoded Picture Buffer --- */
/* ------------------------------------------------------------------------- */
#define GST_VAAPI_DPB(obj) \
((GstVaapiDpb *)(obj))
#define GST_VAAPI_IS_DPB(obj) \
(GST_VAAPI_DPB(obj) != NULL)
G_GNUC_INTERNAL
GstVaapiDpb *
gst_vaapi_dpb_new(guint max_pictures);
G_GNUC_INTERNAL
void
gst_vaapi_dpb_flush(GstVaapiDpb *dpb);
G_GNUC_INTERNAL
gboolean
gst_vaapi_dpb_add(GstVaapiDpb *dpb, GstVaapiPicture *picture);
G_GNUC_INTERNAL
guint
gst_vaapi_dpb_size(GstVaapiDpb *dpb);
G_GNUC_INTERNAL
void
gst_vaapi_dpb_get_neighbours(
GstVaapiDpb *dpb,
GstVaapiPicture *picture,
GstVaapiPicture **prev_picture_ptr,
GstVaapiPicture **next_picture_ptr
);
#define gst_vaapi_dpb_ref(dpb) \
gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(dpb))
#define gst_vaapi_dpb_unref(dpb) \
gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(dpb))
#define gst_vaapi_dpb_replace(old_dpb_ptr, new_dpb) \
gst_vaapi_mini_object_replace((GstVaapiMiniObject **)(old_dpb_ptr), \
(GstVaapiMiniObject *)(new_dpb))
G_END_DECLS
#endif /* GST_VAAPI_DECODER_DPB */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,80 @@
/*
* gstvaapidecoder_h264.h - H.264 decoder
*
* Copyright (C) 2011-2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DECODER_H264_H
#define GST_VAAPI_DECODER_H264_H
#include <gst/vaapi/gstvaapidecoder.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_DECODER_H264 \
(gst_vaapi_decoder_h264_get_type ())
#define GST_VAAPI_DECODER_H264(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_DECODER_H264, GstVaapiDecoderH264))
#define GST_VAAPI_IS_DECODER_H264(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_DECODER_H264))
typedef struct _GstVaapiDecoderH264 GstVaapiDecoderH264;
/**
* GstVaapiStreamAlignH264:
* @GST_VAAPI_STREAM_ALIGN_H264_NONE: Generic H.264 stream buffers
* @GST_VAAPI_STREAM_ALIGN_H264_NALU: H.264 stream buffers aligned NAL
* unit boundaries
* @GST_VAAPI_STREAM_ALIGN_H264_AU: H.264 stream buffers aligned on
* access unit boundaries
*
* Set of possible buffer alignments for H.264 streams.
*/
typedef enum {
GST_VAAPI_STREAM_ALIGN_H264_NONE,
GST_VAAPI_STREAM_ALIGN_H264_NALU,
GST_VAAPI_STREAM_ALIGN_H264_AU
} GstVaapiStreamAlignH264;
GType
gst_vaapi_decoder_h264_get_type (void) G_GNUC_CONST;
GstVaapiDecoder *
gst_vaapi_decoder_h264_new (GstVaapiDisplay *display, GstCaps *caps);
void
gst_vaapi_decoder_h264_set_alignment(GstVaapiDecoderH264 *decoder,
GstVaapiStreamAlignH264 alignment);
gboolean
gst_vaapi_decoder_h264_get_low_latency(GstVaapiDecoderH264 * decoder);
void
gst_vaapi_decoder_h264_set_low_latency(GstVaapiDecoderH264 * decoder,
gboolean force_low_latency);
void
gst_vaapi_decoder_h264_set_base_only(GstVaapiDecoderH264 * decoder,
gboolean base_only);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiDecoderH264, gst_object_unref)
G_END_DECLS
#endif /* GST_VAAPI_DECODER_H264_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,70 @@
/*
* gstvaapidecoder_h265.h - H.265 decoder
*
* Copyright (C) 2015 Intel Corporation
* Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DECODER_H265_H
#define GST_VAAPI_DECODER_H265_H
#include <gst/vaapi/gstvaapidecoder.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_DECODER_H265 \
(gst_vaapi_decoder_h265_get_type ())
#define GST_VAAPI_DECODER_H265(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_DECODER_H265, GstVaapiDecoderH265))
#define GST_VAAPI_IS_DECODER_H265(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_DECODER_H265))
typedef struct _GstVaapiDecoderH265 GstVaapiDecoderH265;
/**
* GstVaapiStreamAlignH265:
* @GST_VAAPI_STREAM_ALIGN_H265_NONE: Generic H.265 stream buffers
* @GST_VAAPI_STREAM_ALIGN_H265_NALU: H.265 stream buffers aligned NAL
* unit boundaries
* @GST_VAAPI_STREAM_ALIGN_H265_AU: H.265 stream buffers aligned on
* access unit boundaries
*
* Set of possible buffer alignments for H.265 streams.
*/
typedef enum {
GST_VAAPI_STREAM_ALIGN_H265_NONE,
GST_VAAPI_STREAM_ALIGN_H265_NALU,
GST_VAAPI_STREAM_ALIGN_H265_AU
} GstVaapiStreamAlignH265;
GType
gst_vaapi_decoder_h265_get_type (void) G_GNUC_CONST;
GstVaapiDecoder *
gst_vaapi_decoder_h265_new (GstVaapiDisplay *display, GstCaps *caps);
void
gst_vaapi_decoder_h265_set_alignment (GstVaapiDecoderH265 *decoder,
GstVaapiStreamAlignH265 alignment);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiDecoderH265, gst_object_unref)
G_END_DECLS
#endif /* GST_VAAPI_DECODER_H265_H */

View file

@ -0,0 +1,964 @@
/*
* gstvaapidecoder_jpeg.c - JPEG decoder
*
* Copyright (C) 2011-2013 Intel Corporation
* Author: Wind Yuan <feng.yuan@intel.com>
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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:gstvaapidecoder_jpeg
* @short_description: JPEG decoder
*/
#include "sysdeps.h"
#include <gst/codecparsers/gstjpegparser.h>
#include "gstvaapicompat.h"
#include "gstvaapidecoder_jpeg.h"
#include "gstvaapidecoder_objects.h"
#include "gstvaapidecoder_priv.h"
#include "gstvaapidisplay_priv.h"
#define DEBUG 1
#include "gstvaapidebug.h"
#define GST_VAAPI_DECODER_JPEG_CAST(decoder) \
((GstVaapiDecoderJpeg *)(decoder))
typedef struct _GstVaapiDecoderJpegPrivate GstVaapiDecoderJpegPrivate;
typedef struct _GstVaapiDecoderJpegClass GstVaapiDecoderJpegClass;
typedef enum
{
GST_JPEG_VIDEO_STATE_GOT_SOI = 1 << 0,
GST_JPEG_VIDEO_STATE_GOT_SOF = 1 << 1,
GST_JPEG_VIDEO_STATE_GOT_SOS = 1 << 2,
GST_JPEG_VIDEO_STATE_GOT_HUF_TABLE = 1 << 3,
GST_JPEG_VIDEO_STATE_GOT_IQ_TABLE = 1 << 4,
GST_JPEG_VIDEO_STATE_VALID_PICTURE = (GST_JPEG_VIDEO_STATE_GOT_SOI |
GST_JPEG_VIDEO_STATE_GOT_SOF | GST_JPEG_VIDEO_STATE_GOT_SOS),
} GstJpegVideoState;
struct _GstVaapiDecoderJpegPrivate
{
GstVaapiProfile profile;
guint width;
guint height;
GstVaapiPicture *current_picture;
GstJpegFrameHdr frame_hdr;
GstJpegHuffmanTables huf_tables;
GstJpegQuantTables quant_tables;
guint mcu_restart;
guint parser_state;
guint decoder_state;
guint is_opened:1;
guint profile_changed:1;
guint size_changed:1;
};
/**
* GstVaapiDecoderJpeg:
*
* A decoder based on Jpeg.
*/
struct _GstVaapiDecoderJpeg
{
/*< private > */
GstVaapiDecoder parent_instance;
GstVaapiDecoderJpegPrivate priv;
};
/**
* GstVaapiDecoderJpegClass:
*
* A decoder class based on Jpeg.
*/
struct _GstVaapiDecoderJpegClass
{
/*< private > */
GstVaapiDecoderClass parent_class;
};
G_DEFINE_TYPE (GstVaapiDecoderJpeg, gst_vaapi_decoder_jpeg,
GST_TYPE_VAAPI_DECODER);
static inline void
unit_set_marker_code (GstVaapiDecoderUnit * unit, GstJpegMarker marker)
{
unit->parsed_info = GSIZE_TO_POINTER (marker);
}
static inline GstJpegMarker
unit_get_marker_code (GstVaapiDecoderUnit * unit)
{
return GPOINTER_TO_SIZE (unit->parsed_info);
}
static void
gst_vaapi_decoder_jpeg_close (GstVaapiDecoderJpeg * decoder)
{
GstVaapiDecoderJpegPrivate *const priv = &decoder->priv;
gst_vaapi_picture_replace (&priv->current_picture, NULL);
/* Reset all */
priv->profile = GST_VAAPI_PROFILE_JPEG_BASELINE;
priv->width = 0;
priv->height = 0;
priv->is_opened = FALSE;
priv->profile_changed = TRUE;
priv->size_changed = TRUE;
}
static gboolean
gst_vaapi_decoder_jpeg_open (GstVaapiDecoderJpeg * decoder)
{
GstVaapiDecoderJpegPrivate *const priv = &decoder->priv;
gst_vaapi_decoder_jpeg_close (decoder);
priv->parser_state = 0;
priv->decoder_state = 0;
return TRUE;
}
static void
gst_vaapi_decoder_jpeg_destroy (GstVaapiDecoder * base_decoder)
{
GstVaapiDecoderJpeg *const decoder =
GST_VAAPI_DECODER_JPEG_CAST (base_decoder);
gst_vaapi_decoder_jpeg_close (decoder);
}
static gboolean
gst_vaapi_decoder_jpeg_create (GstVaapiDecoder * base_decoder)
{
GstVaapiDecoderJpeg *const decoder =
GST_VAAPI_DECODER_JPEG_CAST (base_decoder);
GstVaapiDecoderJpegPrivate *const priv = &decoder->priv;
priv->profile = GST_VAAPI_PROFILE_JPEG_BASELINE;
priv->profile_changed = TRUE;
priv->size_changed = TRUE;
return TRUE;
}
static GstVaapiDecoderStatus
gst_vaapi_decoder_jpeg_reset (GstVaapiDecoder * base_decoder)
{
gst_vaapi_decoder_jpeg_destroy (base_decoder);
gst_vaapi_decoder_jpeg_create (base_decoder);
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static gboolean
get_chroma_type (GstJpegFrameHdr * frame_hdr, GstVaapiChromaType * chroma_type)
{
int h0 = frame_hdr->components[0].horizontal_factor;
int h1 = frame_hdr->components[1].horizontal_factor;
int h2 = frame_hdr->components[2].horizontal_factor;
int v0 = frame_hdr->components[0].vertical_factor;
int v1 = frame_hdr->components[1].vertical_factor;
int v2 = frame_hdr->components[2].vertical_factor;
if (frame_hdr->num_components == 1) {
*chroma_type = GST_VAAPI_CHROMA_TYPE_YUV400;
return TRUE;
}
if (h1 != h2 || v1 != v2)
return FALSE;
if (h0 == h1) {
if (v0 == v1)
*chroma_type = GST_VAAPI_CHROMA_TYPE_YUV444;
else if (v0 == 2 * v1)
*chroma_type = GST_VAAPI_CHROMA_TYPE_YUV422;
else
return FALSE;
} else if (h0 == 2 * h1) {
if (v0 == v1)
*chroma_type = GST_VAAPI_CHROMA_TYPE_YUV422;
else if (v0 == 2 * v1)
*chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
else
return FALSE;
} else if (h0 == 4 * h1) {
if (v0 == v1)
*chroma_type = GST_VAAPI_CHROMA_TYPE_YUV411;
else
return FALSE;
} else
return FALSE;
return TRUE;
}
static GstVaapiDecoderStatus
ensure_context (GstVaapiDecoderJpeg * decoder)
{
GstVaapiDecoderJpegPrivate *const priv = &decoder->priv;
GstJpegFrameHdr *const frame_hdr = &priv->frame_hdr;
GstVaapiChromaType chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
GstVaapiProfile profiles[2];
GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
guint i, n_profiles = 0;
gboolean reset_context = FALSE;
if (priv->profile_changed) {
GST_DEBUG ("profile changed");
priv->profile_changed = FALSE;
reset_context = TRUE;
profiles[n_profiles++] = priv->profile;
//if (priv->profile == GST_VAAPI_PROFILE_JPEG_EXTENDED)
// profiles[n_profiles++] = GST_VAAPI_PROFILE_JPEG_BASELINE;
for (i = 0; i < n_profiles; i++) {
if (gst_vaapi_display_has_decoder (GST_VAAPI_DECODER_DISPLAY (decoder),
profiles[i], entrypoint))
break;
}
if (i == n_profiles)
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
priv->profile = profiles[i];
}
if (priv->size_changed) {
GST_DEBUG ("size changed");
priv->size_changed = FALSE;
reset_context = TRUE;
}
if (reset_context) {
GstVaapiContextInfo info;
info.profile = priv->profile;
info.entrypoint = entrypoint;
info.width = priv->width;
info.height = priv->height;
info.ref_frames = 2;
if (!get_chroma_type (frame_hdr, &chroma_type))
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT;
info.chroma_type = chroma_type;
reset_context =
gst_vaapi_decoder_ensure_context (GST_VAAPI_DECODER (decoder), &info);
if (!reset_context)
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
}
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static inline gboolean
is_valid_state (guint state, guint ref_state)
{
return (state & ref_state) == ref_state;
}
#define VALID_STATE(TYPE, STATE) \
is_valid_state(priv->G_PASTE(TYPE,_state), \
G_PASTE(GST_JPEG_VIDEO_STATE_,STATE))
static GstVaapiDecoderStatus
decode_current_picture (GstVaapiDecoderJpeg * decoder)
{
GstVaapiDecoderJpegPrivate *const priv = &decoder->priv;
GstVaapiPicture *const picture = priv->current_picture;
if (!VALID_STATE (decoder, VALID_PICTURE))
goto drop_frame;
priv->decoder_state = 0;
if (!picture)
return GST_VAAPI_DECODER_STATUS_SUCCESS;
if (!gst_vaapi_picture_decode (picture))
goto error;
if (!gst_vaapi_picture_output (picture))
goto error;
gst_vaapi_picture_replace (&priv->current_picture, NULL);
return GST_VAAPI_DECODER_STATUS_SUCCESS;
/* ERRORS */
error:
{
gst_vaapi_picture_replace (&priv->current_picture, NULL);
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
}
drop_frame:
{
priv->decoder_state = 0;
return (GstVaapiDecoderStatus) GST_VAAPI_DECODER_STATUS_DROP_FRAME;
}
}
static gboolean
fill_picture (GstVaapiDecoderJpeg * decoder,
GstVaapiPicture * picture, GstJpegFrameHdr * frame_hdr)
{
VAPictureParameterBufferJPEGBaseline *const pic_param = picture->param;
guint i;
memset (pic_param, 0, sizeof (VAPictureParameterBufferJPEGBaseline));
pic_param->picture_width = frame_hdr->width;
pic_param->picture_height = frame_hdr->height;
pic_param->num_components = frame_hdr->num_components;
if (frame_hdr->num_components > 4)
return FALSE;
for (i = 0; i < pic_param->num_components; i++) {
pic_param->components[i].component_id = frame_hdr->components[i].identifier;
pic_param->components[i].h_sampling_factor =
frame_hdr->components[i].horizontal_factor;
pic_param->components[i].v_sampling_factor =
frame_hdr->components[i].vertical_factor;
pic_param->components[i].quantiser_table_selector =
frame_hdr->components[i].quant_table_selector;
}
return TRUE;
}
static GstVaapiDecoderStatus
fill_quantization_table (GstVaapiDecoderJpeg * decoder,
GstVaapiPicture * picture)
{
GstVaapiDecoderJpegPrivate *const priv = &decoder->priv;
VAIQMatrixBufferJPEGBaseline *iq_matrix;
guint i, j, num_tables;
if (!VALID_STATE (decoder, GOT_IQ_TABLE))
gst_jpeg_get_default_quantization_tables (&priv->quant_tables);
picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW (JPEGBaseline, decoder);
if (!picture->iq_matrix) {
GST_ERROR ("failed to allocate quantiser table");
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
}
iq_matrix = picture->iq_matrix->param;
num_tables = MIN (G_N_ELEMENTS (iq_matrix->quantiser_table),
GST_JPEG_MAX_QUANT_ELEMENTS);
for (i = 0; i < num_tables; i++) {
GstJpegQuantTable *const quant_table = &priv->quant_tables.quant_tables[i];
iq_matrix->load_quantiser_table[i] = quant_table->valid;
if (!iq_matrix->load_quantiser_table[i])
continue;
if (quant_table->quant_precision != 0) {
// Only Baseline profile is supported, thus 8-bit Qk values
GST_ERROR ("unsupported quantization table element precision");
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT;
}
for (j = 0; j < GST_JPEG_MAX_QUANT_ELEMENTS; j++)
iq_matrix->quantiser_table[i][j] = quant_table->quant_table[j];
iq_matrix->load_quantiser_table[i] = 1;
quant_table->valid = FALSE;
}
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static gboolean
huffman_tables_updated (const GstJpegHuffmanTables * huf_tables)
{
guint i;
for (i = 0; i < G_N_ELEMENTS (huf_tables->dc_tables); i++)
if (huf_tables->dc_tables[i].valid)
return TRUE;
for (i = 0; i < G_N_ELEMENTS (huf_tables->ac_tables); i++)
if (huf_tables->ac_tables[i].valid)
return TRUE;
return FALSE;
}
static void
huffman_tables_reset (GstJpegHuffmanTables * huf_tables)
{
guint i;
for (i = 0; i < G_N_ELEMENTS (huf_tables->dc_tables); i++)
huf_tables->dc_tables[i].valid = FALSE;
for (i = 0; i < G_N_ELEMENTS (huf_tables->ac_tables); i++)
huf_tables->ac_tables[i].valid = FALSE;
}
static void
fill_huffman_table (GstVaapiHuffmanTable * huf_table,
const GstJpegHuffmanTables * huf_tables)
{
VAHuffmanTableBufferJPEGBaseline *const huffman_table = huf_table->param;
guint i, num_tables;
num_tables = MIN (G_N_ELEMENTS (huffman_table->huffman_table),
GST_JPEG_MAX_SCAN_COMPONENTS);
for (i = 0; i < num_tables; i++) {
huffman_table->load_huffman_table[i] =
huf_tables->dc_tables[i].valid && huf_tables->ac_tables[i].valid;
if (!huffman_table->load_huffman_table[i])
continue;
memcpy (huffman_table->huffman_table[i].num_dc_codes,
huf_tables->dc_tables[i].huf_bits,
sizeof (huffman_table->huffman_table[i].num_dc_codes));
memcpy (huffman_table->huffman_table[i].dc_values,
huf_tables->dc_tables[i].huf_values,
sizeof (huffman_table->huffman_table[i].dc_values));
memcpy (huffman_table->huffman_table[i].num_ac_codes,
huf_tables->ac_tables[i].huf_bits,
sizeof (huffman_table->huffman_table[i].num_ac_codes));
memcpy (huffman_table->huffman_table[i].ac_values,
huf_tables->ac_tables[i].huf_values,
sizeof (huffman_table->huffman_table[i].ac_values));
memset (huffman_table->huffman_table[i].pad,
0, sizeof (huffman_table->huffman_table[i].pad));
}
}
static void
get_max_sampling_factors (const GstJpegFrameHdr * frame_hdr,
guint * h_max_ptr, guint * v_max_ptr)
{
guint h_max = frame_hdr->components[0].horizontal_factor;
guint v_max = frame_hdr->components[0].vertical_factor;
guint i;
for (i = 1; i < frame_hdr->num_components; i++) {
const GstJpegFrameComponent *const fcp = &frame_hdr->components[i];
if (h_max < fcp->horizontal_factor)
h_max = fcp->horizontal_factor;
if (v_max < fcp->vertical_factor)
v_max = fcp->vertical_factor;
}
if (h_max_ptr)
*h_max_ptr = h_max;
if (v_max_ptr)
*v_max_ptr = v_max;
}
static const GstJpegFrameComponent *
get_component (const GstJpegFrameHdr * frame_hdr, guint selector)
{
guint i;
for (i = 0; i < frame_hdr->num_components; i++) {
const GstJpegFrameComponent *const fcp = &frame_hdr->components[i];
if (fcp->identifier == selector)
return fcp;
}
return NULL;
}
static GstVaapiDecoderStatus
decode_picture (GstVaapiDecoderJpeg * decoder, GstJpegSegment * seg)
{
GstVaapiDecoderJpegPrivate *const priv = &decoder->priv;
GstJpegFrameHdr *const frame_hdr = &priv->frame_hdr;
if (!VALID_STATE (decoder, GOT_SOI))
return GST_VAAPI_DECODER_STATUS_SUCCESS;
switch (seg->marker) {
case GST_JPEG_MARKER_SOF_MIN:
priv->profile = GST_VAAPI_PROFILE_JPEG_BASELINE;
break;
default:
GST_ERROR ("unsupported profile %d", seg->marker);
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
}
memset (frame_hdr, 0, sizeof (*frame_hdr));
if (!gst_jpeg_segment_parse_frame_header (seg, frame_hdr)) {
GST_ERROR ("failed to parse image");
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
}
if (priv->height != frame_hdr->height || priv->width != frame_hdr->width)
priv->size_changed = TRUE;
priv->height = frame_hdr->height;
priv->width = frame_hdr->width;
priv->decoder_state |= GST_JPEG_VIDEO_STATE_GOT_SOF;
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
decode_huffman_table (GstVaapiDecoderJpeg * decoder, GstJpegSegment * seg)
{
GstVaapiDecoderJpegPrivate *const priv = &decoder->priv;
if (!VALID_STATE (decoder, GOT_SOI))
return GST_VAAPI_DECODER_STATUS_SUCCESS;
if (!gst_jpeg_segment_parse_huffman_table (seg, &priv->huf_tables)) {
GST_ERROR ("failed to parse Huffman table");
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
}
priv->decoder_state |= GST_JPEG_VIDEO_STATE_GOT_HUF_TABLE;
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
decode_quant_table (GstVaapiDecoderJpeg * decoder, GstJpegSegment * seg)
{
GstVaapiDecoderJpegPrivate *const priv = &decoder->priv;
if (!VALID_STATE (decoder, GOT_SOI))
return GST_VAAPI_DECODER_STATUS_SUCCESS;
if (!gst_jpeg_segment_parse_quantization_table (seg, &priv->quant_tables)) {
GST_ERROR ("failed to parse quantization table");
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
}
priv->decoder_state |= GST_JPEG_VIDEO_STATE_GOT_IQ_TABLE;
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
decode_restart_interval (GstVaapiDecoderJpeg * decoder, GstJpegSegment * seg)
{
GstVaapiDecoderJpegPrivate *const priv = &decoder->priv;
if (!VALID_STATE (decoder, GOT_SOI))
return GST_VAAPI_DECODER_STATUS_SUCCESS;
if (!gst_jpeg_segment_parse_restart_interval (seg, &priv->mcu_restart)) {
GST_ERROR ("failed to parse restart interval");
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
}
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
decode_scan (GstVaapiDecoderJpeg * decoder, GstJpegSegment * seg)
{
GstVaapiDecoderJpegPrivate *const priv = &decoder->priv;
GstVaapiPicture *const picture = priv->current_picture;
GstVaapiSlice *slice;
VASliceParameterBufferJPEGBaseline *slice_param;
GstJpegScanHdr scan_hdr;
guint scan_hdr_size, scan_data_size;
guint i, h_max, v_max, mcu_width, mcu_height;
if (!VALID_STATE (decoder, GOT_SOF))
return GST_VAAPI_DECODER_STATUS_SUCCESS;
scan_hdr_size = (seg->data[seg->offset] << 8) | seg->data[seg->offset + 1];
scan_data_size = seg->size - scan_hdr_size;
memset (&scan_hdr, 0, sizeof (scan_hdr));
if (!gst_jpeg_segment_parse_scan_header (seg, &scan_hdr)) {
GST_ERROR ("failed to parse scan header");
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
}
slice = GST_VAAPI_SLICE_NEW (JPEGBaseline, decoder,
seg->data + seg->offset + scan_hdr_size, scan_data_size);
if (!slice) {
GST_ERROR ("failed to allocate slice");
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
}
gst_vaapi_picture_add_slice (picture, slice);
if (!VALID_STATE (decoder, GOT_HUF_TABLE))
gst_jpeg_get_default_huffman_tables (&priv->huf_tables);
// Update VA Huffman table if it changed for this scan
if (huffman_tables_updated (&priv->huf_tables)) {
slice->huf_table = GST_VAAPI_HUFFMAN_TABLE_NEW (JPEGBaseline, decoder);
if (!slice->huf_table) {
GST_ERROR ("failed to allocate Huffman tables");
huffman_tables_reset (&priv->huf_tables);
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
}
fill_huffman_table (slice->huf_table, &priv->huf_tables);
huffman_tables_reset (&priv->huf_tables);
}
slice_param = slice->param;
slice_param->num_components = scan_hdr.num_components;
for (i = 0; i < scan_hdr.num_components; i++) {
slice_param->components[i].component_selector =
scan_hdr.components[i].component_selector;
slice_param->components[i].dc_table_selector =
scan_hdr.components[i].dc_selector;
slice_param->components[i].ac_table_selector =
scan_hdr.components[i].ac_selector;
}
slice_param->restart_interval = priv->mcu_restart;
slice_param->slice_horizontal_position = 0;
slice_param->slice_vertical_position = 0;
get_max_sampling_factors (&priv->frame_hdr, &h_max, &v_max);
mcu_width = 8 * h_max;
mcu_height = 8 * v_max;
if (scan_hdr.num_components == 1) { // Non-interleaved
const guint Csj = slice_param->components[0].component_selector;
const GstJpegFrameComponent *const fcp =
get_component (&priv->frame_hdr, Csj);
if (!fcp || fcp->horizontal_factor == 0 || fcp->vertical_factor == 0) {
GST_ERROR ("failed to validate image component %u", Csj);
return GST_VAAPI_DECODER_STATUS_ERROR_INVALID_PARAMETER;
}
mcu_width /= fcp->horizontal_factor;
mcu_height /= fcp->vertical_factor;
}
slice_param->num_mcus =
((priv->frame_hdr.width + mcu_width - 1) / mcu_width) *
((priv->frame_hdr.height + mcu_height - 1) / mcu_height);
priv->decoder_state |= GST_JPEG_VIDEO_STATE_GOT_SOS;
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
decode_segment (GstVaapiDecoderJpeg * decoder, GstJpegSegment * seg)
{
GstVaapiDecoderJpegPrivate *const priv = &decoder->priv;
GstVaapiDecoderStatus status;
// Decode segment
status = GST_VAAPI_DECODER_STATUS_SUCCESS;
switch (seg->marker) {
case GST_JPEG_MARKER_SOI:
priv->mcu_restart = 0;
priv->decoder_state |= GST_JPEG_VIDEO_STATE_GOT_SOI;
break;
case GST_JPEG_MARKER_EOI:
priv->decoder_state = 0;
break;
case GST_JPEG_MARKER_DAC:
GST_ERROR ("unsupported arithmetic coding mode");
status = GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
break;
case GST_JPEG_MARKER_DHT:
status = decode_huffman_table (decoder, seg);
break;
case GST_JPEG_MARKER_DQT:
status = decode_quant_table (decoder, seg);
break;
case GST_JPEG_MARKER_DRI:
status = decode_restart_interval (decoder, seg);
break;
case GST_JPEG_MARKER_SOS:
status = decode_scan (decoder, seg);
break;
default:
// SOFn segments
if (seg->marker >= GST_JPEG_MARKER_SOF_MIN &&
seg->marker <= GST_JPEG_MARKER_SOF_MAX)
status = decode_picture (decoder, seg);
break;
}
return status;
}
static GstVaapiDecoderStatus
ensure_decoder (GstVaapiDecoderJpeg * decoder)
{
GstVaapiDecoderJpegPrivate *const priv = &decoder->priv;
if (!priv->is_opened) {
priv->is_opened = gst_vaapi_decoder_jpeg_open (decoder);
if (!priv->is_opened)
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
}
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static gboolean
is_scan_complete (GstJpegMarker marker)
{
// Scan is assumed to be complete when the new segment is not RSTi
return marker < GST_JPEG_MARKER_RST_MIN || marker > GST_JPEG_MARKER_RST_MAX;
}
static GstVaapiDecoderStatus
gst_vaapi_decoder_jpeg_parse (GstVaapiDecoder * base_decoder,
GstAdapter * adapter, gboolean at_eos, GstVaapiDecoderUnit * unit)
{
GstVaapiDecoderJpeg *const decoder =
GST_VAAPI_DECODER_JPEG_CAST (base_decoder);
GstVaapiDecoderJpegPrivate *const priv = &decoder->priv;
GstVaapiParserState *const ps = GST_VAAPI_PARSER_STATE (base_decoder);
GstVaapiDecoderStatus status;
GstJpegMarker marker;
GstJpegSegment seg;
const guchar *buf;
guint buf_size, flags;
gint ofs1, ofs2;
status = ensure_decoder (decoder);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
return status;
/* Expect at least 2 bytes for the marker */
buf_size = gst_adapter_available (adapter);
if (buf_size < 2)
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
buf = gst_adapter_map (adapter, buf_size);
if (!buf)
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
ofs1 = ps->input_offset1 - 2;
if (ofs1 < 0)
ofs1 = 0;
for (;;) {
// Skip any garbage until we reach SOI, if needed
if (!gst_jpeg_parse (&seg, buf, buf_size, ofs1)) {
gst_adapter_unmap (adapter);
ps->input_offset1 = buf_size;
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
}
ofs1 = seg.offset;
marker = seg.marker;
if (!VALID_STATE (parser, GOT_SOI) && marker != GST_JPEG_MARKER_SOI)
continue;
if (marker == GST_JPEG_MARKER_SOS) {
ofs2 = ps->input_offset2 - 2;
if (ofs2 < ofs1 + seg.size)
ofs2 = ofs1 + seg.size;
// Parse the whole scan + ECSs, including RSTi
for (;;) {
if (!gst_jpeg_parse (&seg, buf, buf_size, ofs2)) {
gst_adapter_unmap (adapter);
ps->input_offset1 = ofs1;
ps->input_offset2 = buf_size;
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
}
if (is_scan_complete (seg.marker))
break;
ofs2 = seg.offset + seg.size;
}
ofs2 = seg.offset - 2;
} else {
// Check that the whole segment is actually available (in buffer)
ofs2 = ofs1 + seg.size;
if (ofs2 > buf_size) {
gst_adapter_unmap (adapter);
ps->input_offset1 = ofs1;
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
}
}
break;
}
gst_adapter_unmap (adapter);
unit->size = ofs2 - ofs1;
unit_set_marker_code (unit, marker);
gst_adapter_flush (adapter, ofs1);
ps->input_offset1 = 2;
ps->input_offset2 = 2;
flags = 0;
switch (marker) {
case GST_JPEG_MARKER_SOI:
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
priv->parser_state |= GST_JPEG_VIDEO_STATE_GOT_SOI;
break;
case GST_JPEG_MARKER_EOI:
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
priv->parser_state = 0;
break;
case GST_JPEG_MARKER_SOS:
flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
priv->parser_state |= GST_JPEG_VIDEO_STATE_GOT_SOS;
break;
case GST_JPEG_MARKER_DAC:
case GST_JPEG_MARKER_DHT:
case GST_JPEG_MARKER_DQT:
if (priv->parser_state & GST_JPEG_VIDEO_STATE_GOT_SOF)
flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
break;
case GST_JPEG_MARKER_DRI:
if (priv->parser_state & GST_JPEG_VIDEO_STATE_GOT_SOS)
flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
break;
case GST_JPEG_MARKER_DNL:
flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
break;
case GST_JPEG_MARKER_COM:
flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
break;
default:
/* SOFn segments */
if (marker >= GST_JPEG_MARKER_SOF_MIN &&
marker <= GST_JPEG_MARKER_SOF_MAX)
priv->parser_state |= GST_JPEG_VIDEO_STATE_GOT_SOF;
/* Application segments */
else if (marker >= GST_JPEG_MARKER_APP_MIN &&
marker <= GST_JPEG_MARKER_APP_MAX)
flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
/* Reserved */
else if (marker >= 0x02 && marker <= 0xbf)
flags |= GST_VAAPI_DECODER_UNIT_FLAG_SKIP;
break;
}
GST_VAAPI_DECODER_UNIT_FLAG_SET (unit, flags);
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
gst_vaapi_decoder_jpeg_decode (GstVaapiDecoder * base_decoder,
GstVaapiDecoderUnit * unit)
{
GstVaapiDecoderJpeg *const decoder =
GST_VAAPI_DECODER_JPEG_CAST (base_decoder);
GstVaapiDecoderStatus status;
GstJpegSegment seg;
GstBuffer *const buffer =
GST_VAAPI_DECODER_CODEC_FRAME (decoder)->input_buffer;
GstMapInfo map_info;
status = ensure_decoder (decoder);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
return status;
if (!gst_buffer_map (buffer, &map_info, GST_MAP_READ)) {
GST_ERROR ("failed to map buffer");
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
}
seg.marker = unit_get_marker_code (unit);
seg.data = map_info.data;
seg.offset = unit->offset;
seg.size = unit->size;
status = decode_segment (decoder, &seg);
gst_buffer_unmap (buffer, &map_info);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
return status;
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
gst_vaapi_decoder_jpeg_start_frame (GstVaapiDecoder * base_decoder,
GstVaapiDecoderUnit * base_unit)
{
GstVaapiDecoderJpeg *const decoder =
GST_VAAPI_DECODER_JPEG_CAST (base_decoder);
GstVaapiDecoderJpegPrivate *const priv = &decoder->priv;
GstVaapiPicture *picture;
GstVaapiDecoderStatus status;
if (!VALID_STATE (decoder, GOT_SOF))
return GST_VAAPI_DECODER_STATUS_SUCCESS;
status = ensure_context (decoder);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
GST_ERROR ("failed to reset context");
return status;
}
picture = GST_VAAPI_PICTURE_NEW (JPEGBaseline, decoder);
if (!picture) {
GST_ERROR ("failed to allocate picture");
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
}
gst_vaapi_picture_replace (&priv->current_picture, picture);
gst_vaapi_picture_unref (picture);
if (!fill_picture (decoder, picture, &priv->frame_hdr))
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
status = fill_quantization_table (decoder, picture);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
return status;
/* Update presentation time */
picture->pts = GST_VAAPI_DECODER_CODEC_FRAME (decoder)->pts;
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
gst_vaapi_decoder_jpeg_end_frame (GstVaapiDecoder * base_decoder)
{
GstVaapiDecoderJpeg *const decoder =
GST_VAAPI_DECODER_JPEG_CAST (base_decoder);
return decode_current_picture (decoder);
}
static void
gst_vaapi_decoder_jpeg_finalize (GObject * object)
{
GstVaapiDecoder *const base_decoder = GST_VAAPI_DECODER (object);
gst_vaapi_decoder_jpeg_destroy (base_decoder);
G_OBJECT_CLASS (gst_vaapi_decoder_jpeg_parent_class)->finalize (object);
}
static void
gst_vaapi_decoder_jpeg_class_init (GstVaapiDecoderJpegClass * klass)
{
GObjectClass *const object_class = G_OBJECT_CLASS (klass);
GstVaapiDecoderClass *const decoder_class = GST_VAAPI_DECODER_CLASS (klass);
object_class->finalize = gst_vaapi_decoder_jpeg_finalize;
decoder_class->reset = gst_vaapi_decoder_jpeg_reset;
decoder_class->parse = gst_vaapi_decoder_jpeg_parse;
decoder_class->decode = gst_vaapi_decoder_jpeg_decode;
decoder_class->start_frame = gst_vaapi_decoder_jpeg_start_frame;
decoder_class->end_frame = gst_vaapi_decoder_jpeg_end_frame;
}
static void
gst_vaapi_decoder_jpeg_init (GstVaapiDecoderJpeg * decoder)
{
GstVaapiDecoder *const base_decoder = GST_VAAPI_DECODER (decoder);
gst_vaapi_decoder_jpeg_create (base_decoder);
}
/**
* gst_vaapi_decoder_jpeg_new:
* @display: a #GstVaapiDisplay
* @caps: a #GstCaps holding codec information
*
* Creates a new #GstVaapiDecoder for JPEG decoding. The @caps can
* hold extra information like codec-data and pictured coded size.
*
* Return value: the newly allocated #GstVaapiDecoder object
*/
GstVaapiDecoder *
gst_vaapi_decoder_jpeg_new (GstVaapiDisplay * display, GstCaps * caps)
{
return g_object_new (GST_TYPE_VAAPI_DECODER_JPEG, "display", display,
"caps", caps, NULL);
}

View file

@ -0,0 +1,51 @@
/*
* gstvaapidecoder_jpeg.h - JPEG decoder
*
* Copyright (C) 2011-2013 Intel Corporation
* Author: Wind Yuan <feng.yuan@intel.com>
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DECODER_JPEG_H
#define GST_VAAPI_DECODER_JPEG_H
#include <gst/vaapi/gstvaapidecoder.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_DECODER_JPEG \
(gst_vaapi_decoder_jpeg_get_type ())
#define GST_VAAPI_DECODER_JPEG(decoder) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_DECODER_JPEG, GstVaapiDecoderJpeg))
#define GST_VAAPI_IS_DECODER_JPEG(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_DECODER_JPEG))
typedef struct _GstVaapiDecoderJpeg GstVaapiDecoderJpeg;
GType
gst_vaapi_decoder_jpeg_get_type (void) G_GNUC_CONST;
GstVaapiDecoder *
gst_vaapi_decoder_jpeg_new (GstVaapiDisplay *display, GstCaps *caps);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiDecoderJpeg, gst_object_unref)
G_END_DECLS
#endif /* GST_VAAPI_DECODER_JPEG_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,50 @@
/*
* gstvaapidecoder_mpeg2.h - MPEG-2 decoder
*
* Copyright (C) 2011-2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DECODER_MPEG2_H
#define GST_VAAPI_DECODER_MPEG2_H
#include <gst/vaapi/gstvaapidecoder.h>
#include <gst/base/gstadapter.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_DECODER_MPEG2 \
(gst_vaapi_decoder_mpeg2_get_type ())
#define GST_VAAPI_DECODER_MPEG2(decoder) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_DECODER_MPEG2, GstVaapiDecoderMpeg2))
#define GST_VAAPI_IS_DECODER_MPEG2(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_DECODER_MPEG2))
typedef struct _GstVaapiDecoderMpeg2 GstVaapiDecoderMpeg2;
GType
gst_vaapi_decoder_mpeg2_get_type (void) G_GNUC_CONST;
GstVaapiDecoder *
gst_vaapi_decoder_mpeg2_new (GstVaapiDisplay *display, GstCaps *caps);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiDecoderMpeg2, gst_object_unref)
G_END_DECLS
#endif /* GST_VAAPI_DECODER_MPEG2_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,49 @@
/*
* gstvaapidecoder_mpeg4.h - MPEG-4 decoder
*
* Copyright (C) 2011-2013 Intel Corporation
* Author: Halley Zhao <halley.zhao@intel.com>
*
* 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_VAAPI_DECODER_MPEG4_H
#define GST_VAAPI_DECODER_MPEG4_H
#include <gst/vaapi/gstvaapidecoder.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_DECODER_MPEG4 \
(gst_vaapi_decoder_mpeg4_get_type ())
#define GST_VAAPI_DECODER_MPEG4(decoder) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_DECODER_MPEG4, GstVaapiDecoderMpeg4))
#define GST_VAAPI_IS_DECODER_MPEG4(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_DECODER_MPEG4))
typedef struct _GstVaapiDecoderMpeg4 GstVaapiDecoderMpeg4;
GType
gst_vaapi_decoder_mpeg4_get_type (void) G_GNUC_CONST;
GstVaapiDecoder *
gst_vaapi_decoder_mpeg4_new (GstVaapiDisplay *display, GstCaps *caps);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiDecoderMpeg4, gst_object_unref)
G_END_DECLS
#endif /* GST_VAAPI_DECODER_MPEG4_H */

View file

@ -0,0 +1,507 @@
/*
* gstvaapidecoder_objects.c - VA decoder objects helpers
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
* Copyright (C) 2011-2014 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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 "sysdeps.h"
#include <gst/vaapi/gstvaapicontext.h>
#include "gstvaapidecoder_objects.h"
#include "gstvaapidecoder_priv.h"
#include "gstvaapisurfaceproxy_priv.h"
#include "gstvaapicompat.h"
#include "gstvaapiutils.h"
#define DEBUG 1
#include "gstvaapidebug.h"
#define GET_DECODER(obj) GST_VAAPI_DECODER_CAST((obj)->parent_instance.codec)
#define GET_CONTEXT(obj) GET_DECODER(obj)->context
#define GET_VA_DISPLAY(obj) GET_DECODER(obj)->va_display
#define GET_VA_CONTEXT(obj) GET_DECODER(obj)->va_context
static inline void
gst_video_codec_frame_clear (GstVideoCodecFrame ** frame_ptr)
{
if (!*frame_ptr)
return;
gst_video_codec_frame_unref (*frame_ptr);
*frame_ptr = NULL;
}
/* ------------------------------------------------------------------------- */
/* --- Pictures --- */
/* ------------------------------------------------------------------------- */
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiPicture, gst_vaapi_picture);
enum
{
GST_VAAPI_CREATE_PICTURE_FLAG_CLONE = 1 << 0,
GST_VAAPI_CREATE_PICTURE_FLAG_FIELD = 1 << 1,
};
void
gst_vaapi_picture_destroy (GstVaapiPicture * picture)
{
if (picture->slices) {
g_ptr_array_unref (picture->slices);
picture->slices = NULL;
}
gst_vaapi_codec_object_replace (&picture->iq_matrix, NULL);
gst_vaapi_codec_object_replace (&picture->huf_table, NULL);
gst_vaapi_codec_object_replace (&picture->bitplane, NULL);
gst_vaapi_codec_object_replace (&picture->prob_table, NULL);
if (picture->proxy) {
gst_vaapi_surface_proxy_unref (picture->proxy);
picture->proxy = NULL;
}
picture->surface_id = VA_INVALID_ID;
picture->surface = NULL;
vaapi_destroy_buffer (GET_VA_DISPLAY (picture), &picture->param_id);
picture->param = NULL;
gst_video_codec_frame_clear (&picture->frame);
gst_vaapi_picture_replace (&picture->parent_picture, NULL);
}
gboolean
gst_vaapi_picture_create (GstVaapiPicture * picture,
const GstVaapiCodecObjectConstructorArgs * args)
{
gboolean success;
picture->param_id = VA_INVALID_ID;
if (args->flags & GST_VAAPI_CREATE_PICTURE_FLAG_CLONE) {
GstVaapiPicture *const parent_picture = GST_VAAPI_PICTURE (args->data);
picture->parent_picture = gst_vaapi_picture_ref (parent_picture);
picture->proxy = gst_vaapi_surface_proxy_ref (parent_picture->proxy);
picture->type = parent_picture->type;
picture->pts = parent_picture->pts;
picture->poc = parent_picture->poc;
picture->voc = parent_picture->voc;
picture->view_id = parent_picture->view_id;
// Copy all picture flags but "output"
GST_VAAPI_PICTURE_FLAG_SET (picture,
GST_VAAPI_PICTURE_FLAGS (parent_picture) &
(GST_VAAPI_PICTURE_FLAG_SKIPPED |
GST_VAAPI_PICTURE_FLAG_REFERENCE |
GST_VAAPI_PICTURE_FLAG_INTERLACED |
GST_VAAPI_PICTURE_FLAG_FF | GST_VAAPI_PICTURE_FLAG_TFF |
GST_VAAPI_PICTURE_FLAG_ONEFIELD |
GST_VAAPI_PICTURE_FLAG_RFF | GST_VAAPI_PICTURE_FLAG_MVC));
// Propagate "corrupted" flag while not presuming that the second
// field is itself corrupted if the first one was marked as such
if (GST_VAAPI_PICTURE_IS_CORRUPTED (parent_picture) &&
!(args->flags & GST_VAAPI_CREATE_PICTURE_FLAG_FIELD))
GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_CORRUPTED);
picture->structure = parent_picture->structure;
if ((args->flags & GST_VAAPI_CREATE_PICTURE_FLAG_FIELD) &&
GST_VAAPI_PICTURE_IS_INTERLACED (picture)) {
switch (picture->structure) {
case GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD:
picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
break;
case GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD:
picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
break;
}
GST_VAAPI_PICTURE_FLAG_UNSET (picture, GST_VAAPI_PICTURE_FLAG_FF);
}
if (parent_picture->has_crop_rect) {
picture->has_crop_rect = TRUE;
picture->crop_rect = parent_picture->crop_rect;
}
} else {
picture->type = GST_VAAPI_PICTURE_TYPE_NONE;
picture->pts = GST_CLOCK_TIME_NONE;
picture->proxy =
gst_vaapi_context_get_surface_proxy (GET_CONTEXT (picture));
if (!picture->proxy)
return FALSE;
picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_FF);
}
picture->surface = GST_VAAPI_SURFACE_PROXY_SURFACE (picture->proxy);
picture->surface_id = GST_VAAPI_SURFACE_PROXY_SURFACE_ID (picture->proxy);
success = vaapi_create_buffer (GET_VA_DISPLAY (picture),
GET_VA_CONTEXT (picture), VAPictureParameterBufferType,
args->param_size, args->param, &picture->param_id, &picture->param);
if (!success)
return FALSE;
picture->param_size = args->param_size;
picture->slices = g_ptr_array_new_with_free_func ((GDestroyNotify)
gst_vaapi_mini_object_unref);
if (!picture->slices)
return FALSE;
picture->frame =
gst_video_codec_frame_ref (GST_VAAPI_DECODER_CODEC_FRAME (GET_DECODER
(picture)));
return TRUE;
}
GstVaapiPicture *
gst_vaapi_picture_new (GstVaapiDecoder * decoder,
gconstpointer param, guint param_size)
{
GstVaapiCodecObject *object;
object = gst_vaapi_codec_object_new (&GstVaapiPictureClass,
GST_VAAPI_CODEC_BASE (decoder), param, param_size, NULL, 0, 0);
if (!object)
return NULL;
return GST_VAAPI_PICTURE_CAST (object);
}
GstVaapiPicture *
gst_vaapi_picture_new_field (GstVaapiPicture * picture)
{
GstVaapiDecoder *const decoder = GET_DECODER (picture);
GstVaapiCodecObject *object;
object = gst_vaapi_codec_object_new (gst_vaapi_codec_object_get_class
(&picture->parent_instance), GST_VAAPI_CODEC_BASE (decoder), NULL,
picture->param_size, picture, 0,
(GST_VAAPI_CREATE_PICTURE_FLAG_CLONE |
GST_VAAPI_CREATE_PICTURE_FLAG_FIELD));
if (!object)
return NULL;
return GST_VAAPI_PICTURE_CAST (object);
}
GstVaapiPicture *
gst_vaapi_picture_new_clone (GstVaapiPicture * picture)
{
GstVaapiDecoder *const decoder = GET_DECODER (picture);
GstVaapiCodecObject *object;
object = gst_vaapi_codec_object_new (gst_vaapi_codec_object_get_class
(&picture->parent_instance), GST_VAAPI_CODEC_BASE (decoder), NULL,
picture->param_size, picture, 0, GST_VAAPI_CREATE_PICTURE_FLAG_CLONE);
if (!object)
return NULL;
return GST_VAAPI_PICTURE_CAST (object);
}
void
gst_vaapi_picture_add_slice (GstVaapiPicture * picture, GstVaapiSlice * slice)
{
g_return_if_fail (GST_VAAPI_IS_PICTURE (picture));
g_return_if_fail (GST_VAAPI_IS_SLICE (slice));
g_ptr_array_add (picture->slices, slice);
}
static gboolean
do_decode (VADisplay dpy, VAContextID ctx, VABufferID * buf_id, void **buf_ptr)
{
VAStatus status;
vaapi_unmap_buffer (dpy, *buf_id, buf_ptr);
status = vaRenderPicture (dpy, ctx, buf_id, 1);
if (!vaapi_check_status (status, "vaRenderPicture()"))
return FALSE;
/* XXX: vaRenderPicture() is meant to destroy the VA buffer implicitly */
vaapi_destroy_buffer (dpy, buf_id);
return TRUE;
}
gboolean
gst_vaapi_picture_decode_with_surface_id (GstVaapiPicture * picture,
VASurfaceID surface_id)
{
GstVaapiIqMatrix *iq_matrix;
GstVaapiBitPlane *bitplane;
GstVaapiHuffmanTable *huf_table;
GstVaapiProbabilityTable *prob_table;
VADisplay va_display;
VAContextID va_context;
VAStatus status;
guint i;
g_return_val_if_fail (GST_VAAPI_IS_PICTURE (picture), FALSE);
g_return_val_if_fail (surface_id != VA_INVALID_SURFACE, FALSE);
va_display = GET_VA_DISPLAY (picture);
va_context = GET_VA_CONTEXT (picture);
GST_DEBUG ("decode picture 0x%08x", surface_id);
status = vaBeginPicture (va_display, va_context, surface_id);
if (!vaapi_check_status (status, "vaBeginPicture()"))
return FALSE;
if (!do_decode (va_display, va_context, &picture->param_id, &picture->param))
return FALSE;
iq_matrix = picture->iq_matrix;
if (iq_matrix && !do_decode (va_display, va_context,
&iq_matrix->param_id, &iq_matrix->param))
return FALSE;
bitplane = picture->bitplane;
if (bitplane && !do_decode (va_display, va_context,
&bitplane->data_id, (void **) &bitplane->data))
return FALSE;
huf_table = picture->huf_table;
if (huf_table && !do_decode (va_display, va_context,
&huf_table->param_id, (void **) &huf_table->param))
return FALSE;
prob_table = picture->prob_table;
if (prob_table && !do_decode (va_display, va_context,
&prob_table->param_id, (void **) &prob_table->param))
return FALSE;
for (i = 0; i < picture->slices->len; i++) {
GstVaapiSlice *const slice = g_ptr_array_index (picture->slices, i);
VABufferID va_buffers[2];
huf_table = slice->huf_table;
if (huf_table && !do_decode (va_display, va_context,
&huf_table->param_id, (void **) &huf_table->param))
return FALSE;
vaapi_unmap_buffer (va_display, slice->param_id, NULL);
va_buffers[0] = slice->param_id;
va_buffers[1] = slice->data_id;
status = vaRenderPicture (va_display, va_context, va_buffers, 2);
if (!vaapi_check_status (status, "vaRenderPicture()"))
return FALSE;
}
status = vaEndPicture (va_display, va_context);
for (i = 0; i < picture->slices->len; i++) {
GstVaapiSlice *const slice = g_ptr_array_index (picture->slices, i);
vaapi_destroy_buffer (va_display, &slice->param_id);
vaapi_destroy_buffer (va_display, &slice->data_id);
}
if (!vaapi_check_status (status, "vaEndPicture()"))
return FALSE;
return TRUE;
}
gboolean
gst_vaapi_picture_decode (GstVaapiPicture * picture)
{
g_return_val_if_fail (GST_VAAPI_IS_PICTURE (picture), FALSE);
return gst_vaapi_picture_decode_with_surface_id (picture,
picture->surface_id);
}
/* Mark picture as output for internal purposes only. Don't push frame out */
static void
do_output_internal (GstVaapiPicture * picture)
{
if (GST_VAAPI_PICTURE_IS_OUTPUT (picture))
return;
gst_video_codec_frame_clear (&picture->frame);
GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_OUTPUT);
}
static gboolean
do_output (GstVaapiPicture * picture)
{
GstVideoCodecFrame *const out_frame = picture->frame;
GstVaapiSurfaceProxy *proxy;
guint flags = 0;
if (GST_VAAPI_PICTURE_IS_OUTPUT (picture))
return TRUE;
if (!picture->proxy)
return FALSE;
proxy = gst_vaapi_surface_proxy_ref (picture->proxy);
if (picture->has_crop_rect)
gst_vaapi_surface_proxy_set_crop_rect (proxy, &picture->crop_rect);
gst_video_codec_frame_set_user_data (out_frame,
proxy, (GDestroyNotify) gst_vaapi_mini_object_unref);
out_frame->pts = picture->pts;
if (GST_VAAPI_PICTURE_IS_SKIPPED (picture))
GST_VIDEO_CODEC_FRAME_FLAG_SET (out_frame,
GST_VIDEO_CODEC_FRAME_FLAG_DECODE_ONLY);
if (GST_VAAPI_PICTURE_IS_CORRUPTED (picture))
flags |= GST_VAAPI_SURFACE_PROXY_FLAG_CORRUPTED;
if (GST_VAAPI_PICTURE_IS_MVC (picture)) {
if (picture->voc == 0)
flags |= GST_VAAPI_SURFACE_PROXY_FLAG_FFB;
GST_VAAPI_SURFACE_PROXY_VIEW_ID (proxy) = picture->view_id;
}
if (GST_VAAPI_PICTURE_IS_INTERLACED (picture)) {
flags |= GST_VAAPI_SURFACE_PROXY_FLAG_INTERLACED;
if (GST_VAAPI_PICTURE_IS_TFF (picture))
flags |= GST_VAAPI_SURFACE_PROXY_FLAG_TFF;
if (GST_VAAPI_PICTURE_IS_RFF (picture))
flags |= GST_VAAPI_SURFACE_PROXY_FLAG_RFF;
if (GST_VAAPI_PICTURE_IS_ONEFIELD (picture))
flags |= GST_VAAPI_SURFACE_PROXY_FLAG_ONEFIELD;
}
GST_VAAPI_SURFACE_PROXY_FLAG_SET (proxy, flags);
gst_vaapi_decoder_push_frame (GET_DECODER (picture), out_frame);
gst_video_codec_frame_clear (&picture->frame);
GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_OUTPUT);
return TRUE;
}
gboolean
gst_vaapi_picture_output (GstVaapiPicture * picture)
{
g_return_val_if_fail (GST_VAAPI_IS_PICTURE (picture), FALSE);
if (G_UNLIKELY (picture->parent_picture)) {
/* Emit the first field to GstVideoDecoder so that to release
the underlying GstVideoCodecFrame. However, mark this
picture as skipped so that to not display it */
GstVaapiPicture *const parent_picture = picture->parent_picture;
do {
if (!GST_VAAPI_PICTURE_IS_INTERLACED (parent_picture))
break;
if (!GST_VAAPI_PICTURE_IS_FIRST_FIELD (parent_picture))
break;
if (parent_picture->frame == picture->frame)
do_output_internal (parent_picture);
else {
GST_VAAPI_PICTURE_FLAG_SET (parent_picture,
GST_VAAPI_PICTURE_FLAG_SKIPPED);
if (!do_output (parent_picture))
return FALSE;
}
} while (0);
}
return do_output (picture);
}
void
gst_vaapi_picture_set_crop_rect (GstVaapiPicture * picture,
const GstVaapiRectangle * crop_rect)
{
g_return_if_fail (GST_VAAPI_IS_PICTURE (picture));
picture->has_crop_rect = crop_rect != NULL;
if (picture->has_crop_rect)
picture->crop_rect = *crop_rect;
}
/* ------------------------------------------------------------------------- */
/* --- Slices --- */
/* ------------------------------------------------------------------------- */
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiSlice, gst_vaapi_slice);
void
gst_vaapi_slice_destroy (GstVaapiSlice * slice)
{
VADisplay const va_display = GET_VA_DISPLAY (slice);
gst_vaapi_codec_object_replace (&slice->huf_table, NULL);
vaapi_destroy_buffer (va_display, &slice->data_id);
vaapi_destroy_buffer (va_display, &slice->param_id);
slice->param = NULL;
}
gboolean
gst_vaapi_slice_create (GstVaapiSlice * slice,
const GstVaapiCodecObjectConstructorArgs * args)
{
VASliceParameterBufferBase *slice_param;
gboolean success;
slice->param_id = VA_INVALID_ID;
slice->data_id = VA_INVALID_ID;
success = vaapi_create_buffer (GET_VA_DISPLAY (slice), GET_VA_CONTEXT (slice),
VASliceDataBufferType, args->data_size, args->data, &slice->data_id,
NULL);
if (!success)
return FALSE;
g_assert (args->param_num >= 1);
success = vaapi_create_n_elements_buffer (GET_VA_DISPLAY (slice),
GET_VA_CONTEXT (slice), VASliceParameterBufferType, args->param_size,
args->param, &slice->param_id, &slice->param, args->param_num);
if (!success)
return FALSE;
slice_param = slice->param;
slice_param->slice_data_size = args->data_size;
slice_param->slice_data_offset = 0;
slice_param->slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
return TRUE;
}
GstVaapiSlice *
gst_vaapi_slice_new (GstVaapiDecoder * decoder,
gconstpointer param, guint param_size, const guchar * data, guint data_size)
{
GstVaapiCodecObject *object;
object = gst_vaapi_codec_object_new (&GstVaapiSliceClass,
GST_VAAPI_CODEC_BASE (decoder), param, param_size, data, data_size, 0);
return GST_VAAPI_SLICE_CAST (object);
}
GstVaapiSlice *
gst_vaapi_slice_new_n_params (GstVaapiDecoder * decoder,
gconstpointer param, guint param_size, guint param_num, const guchar * data,
guint data_size)
{
GstVaapiCodecObject *object;
object = gst_vaapi_codec_object_new_with_param_num (&GstVaapiSliceClass,
GST_VAAPI_CODEC_BASE (decoder), param, param_size, param_num, data,
data_size, 0);
return GST_VAAPI_SLICE_CAST (object);
}

View file

@ -0,0 +1,294 @@
/*
* gstvaapidecoder_objects.h - VA decoder objects
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
* Copyright (C) 2011-2014 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DECODER_OBJECTS_H
#define GST_VAAPI_DECODER_OBJECTS_H
#include <gst/vaapi/gstvaapicodec_objects.h>
G_BEGIN_DECLS
typedef struct _GstVaapiPicture GstVaapiPicture;
typedef struct _GstVaapiSlice GstVaapiSlice;
/* ------------------------------------------------------------------------- */
/* --- Pictures --- */
/* ------------------------------------------------------------------------- */
#define GST_VAAPI_PICTURE_CAST(obj) \
((GstVaapiPicture *) (obj))
#define GST_VAAPI_PICTURE(obj) \
GST_VAAPI_PICTURE_CAST (obj)
#define GST_VAAPI_IS_PICTURE(obj) \
(GST_VAAPI_PICTURE (obj) != NULL)
typedef enum
{
GST_VAAPI_PICTURE_TYPE_NONE = 0, // Undefined
GST_VAAPI_PICTURE_TYPE_I, // Intra
GST_VAAPI_PICTURE_TYPE_P, // Predicted
GST_VAAPI_PICTURE_TYPE_B, // Bi-directional predicted
GST_VAAPI_PICTURE_TYPE_S, // S(GMC)-VOP (MPEG-4)
GST_VAAPI_PICTURE_TYPE_SI, // Switching Intra
GST_VAAPI_PICTURE_TYPE_SP, // Switching Predicted
GST_VAAPI_PICTURE_TYPE_BI, // BI type (VC-1)
} GstVaapiPictureType;
/**
* GstVaapiPictureFlags:
* @GST_VAAPI_PICTURE_FLAG_SKIPPED: skipped frame
* @GST_VAAPI_PICTURE_FLAG_REFERENCE: reference frame
* @GST_VAAPI_PICTURE_FLAG_OUTPUT: frame was output
* @GST_VAAPI_PICTURE_FLAG_INTERLACED: interlaced frame
* @GST_VAAPI_PICTURE_FLAG_FF: first-field
* @GST_VAAPI_PICTURE_FLAG_TFF: top-field-first
* @GST_VAAPI_PICTURE_FLAG_ONEFIELD: only one field is valid
* @GST_VAAPI_PICTURE_FLAG_MVC: multiview component
* @GST_VAAPI_PICTURE_FLAG_RFF: repeat-first-field
* @GST_VAAPI_PICTURE_FLAG_CORRUPTED: picture was reconstructed from
* corrupted references
* @GST_VAAPI_PICTURE_FLAG_LAST: first flag that can be used by subclasses
*
* Enum values used for #GstVaapiPicture flags.
*/
typedef enum
{
GST_VAAPI_PICTURE_FLAG_SKIPPED = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 0),
GST_VAAPI_PICTURE_FLAG_REFERENCE = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 1),
GST_VAAPI_PICTURE_FLAG_OUTPUT = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 2),
GST_VAAPI_PICTURE_FLAG_INTERLACED = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 3),
GST_VAAPI_PICTURE_FLAG_FF = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 4),
GST_VAAPI_PICTURE_FLAG_TFF = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 5),
GST_VAAPI_PICTURE_FLAG_ONEFIELD = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 6),
GST_VAAPI_PICTURE_FLAG_MVC = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 7),
GST_VAAPI_PICTURE_FLAG_RFF = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 8),
GST_VAAPI_PICTURE_FLAG_CORRUPTED = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 9),
GST_VAAPI_PICTURE_FLAG_LAST = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 10),
} GstVaapiPictureFlags;
#define GST_VAAPI_PICTURE_FLAGS GST_VAAPI_MINI_OBJECT_FLAGS
#define GST_VAAPI_PICTURE_FLAG_IS_SET GST_VAAPI_MINI_OBJECT_FLAG_IS_SET
#define GST_VAAPI_PICTURE_FLAG_SET GST_VAAPI_MINI_OBJECT_FLAG_SET
#define GST_VAAPI_PICTURE_FLAG_UNSET GST_VAAPI_MINI_OBJECT_FLAG_UNSET
#define GST_VAAPI_PICTURE_IS_SKIPPED(picture) \
GST_VAAPI_PICTURE_FLAG_IS_SET (picture, GST_VAAPI_PICTURE_FLAG_SKIPPED)
#define GST_VAAPI_PICTURE_IS_REFERENCE(picture) \
GST_VAAPI_PICTURE_FLAG_IS_SET (picture, GST_VAAPI_PICTURE_FLAG_REFERENCE)
#define GST_VAAPI_PICTURE_IS_OUTPUT(picture) \
GST_VAAPI_PICTURE_FLAG_IS_SET (picture, GST_VAAPI_PICTURE_FLAG_OUTPUT)
#define GST_VAAPI_PICTURE_IS_INTERLACED(picture) \
GST_VAAPI_PICTURE_FLAG_IS_SET (picture, GST_VAAPI_PICTURE_FLAG_INTERLACED)
#define GST_VAAPI_PICTURE_IS_FIRST_FIELD(picture) \
GST_VAAPI_PICTURE_FLAG_IS_SET (picture, GST_VAAPI_PICTURE_FLAG_FF)
#define GST_VAAPI_PICTURE_IS_TFF(picture) \
GST_VAAPI_PICTURE_FLAG_IS_SET (picture, GST_VAAPI_PICTURE_FLAG_TFF)
#define GST_VAAPI_PICTURE_IS_RFF(picture) \
GST_VAAPI_PICTURE_FLAG_IS_SET (picture, GST_VAAPI_PICTURE_FLAG_RFF)
#define GST_VAAPI_PICTURE_IS_ONEFIELD(picture) \
GST_VAAPI_PICTURE_FLAG_IS_SET (picture, GST_VAAPI_PICTURE_FLAG_ONEFIELD)
#define GST_VAAPI_PICTURE_IS_FRAME(picture) \
(GST_VAAPI_PICTURE (picture)->structure == GST_VAAPI_PICTURE_STRUCTURE_FRAME)
#define GST_VAAPI_PICTURE_IS_COMPLETE(picture) \
(GST_VAAPI_PICTURE_IS_FRAME (picture) || \
GST_VAAPI_PICTURE_IS_ONEFIELD (picture) || \
!GST_VAAPI_PICTURE_IS_FIRST_FIELD (picture))
#define GST_VAAPI_PICTURE_IS_MVC(picture) \
(GST_VAAPI_PICTURE_FLAG_IS_SET (picture, GST_VAAPI_PICTURE_FLAG_MVC))
#define GST_VAAPI_PICTURE_IS_CORRUPTED(picture) \
(GST_VAAPI_PICTURE_FLAG_IS_SET (picture, GST_VAAPI_PICTURE_FLAG_CORRUPTED))
/**
* GstVaapiPicture:
*
* A #GstVaapiCodecObject holding a picture parameter.
*/
struct _GstVaapiPicture
{
/*< private >*/
GstVaapiCodecObject parent_instance;
GstVaapiPicture *parent_picture;
GstVideoCodecFrame *frame;
GstVaapiSurface *surface;
GstVaapiSurfaceProxy *proxy;
VABufferID param_id;
guint param_size;
/*< public >*/
GstVaapiPictureType type;
VASurfaceID surface_id;
gpointer param;
GPtrArray *slices;
GstVaapiIqMatrix *iq_matrix;
GstVaapiHuffmanTable *huf_table;
GstVaapiBitPlane *bitplane;
GstVaapiProbabilityTable *prob_table;
GstClockTime pts;
gint32 poc;
guint16 voc;
guint16 view_id;
guint structure;
GstVaapiRectangle crop_rect;
guint has_crop_rect:1;
};
G_GNUC_INTERNAL
void
gst_vaapi_picture_destroy (GstVaapiPicture * picture);
G_GNUC_INTERNAL
gboolean
gst_vaapi_picture_create (GstVaapiPicture * picture,
const GstVaapiCodecObjectConstructorArgs * args);
G_GNUC_INTERNAL
GstVaapiPicture *
gst_vaapi_picture_new (GstVaapiDecoder * decoder,
gconstpointer param, guint param_size);
G_GNUC_INTERNAL
GstVaapiPicture *
gst_vaapi_picture_new_field (GstVaapiPicture * picture);
G_GNUC_INTERNAL
GstVaapiPicture *
gst_vaapi_picture_new_clone (GstVaapiPicture * picture);
G_GNUC_INTERNAL
void
gst_vaapi_picture_add_slice (GstVaapiPicture * picture, GstVaapiSlice * slice);
G_GNUC_INTERNAL
gboolean
gst_vaapi_picture_decode (GstVaapiPicture * picture);
G_GNUC_INTERNAL
gboolean
gst_vaapi_picture_decode_with_surface_id (GstVaapiPicture * picture,
VASurfaceID surface_id);
G_GNUC_INTERNAL
gboolean
gst_vaapi_picture_output (GstVaapiPicture * picture);
G_GNUC_INTERNAL
void
gst_vaapi_picture_set_crop_rect (GstVaapiPicture * picture,
const GstVaapiRectangle * crop_rect);
#define gst_vaapi_picture_ref(picture) \
gst_vaapi_codec_object_ref (picture)
#define gst_vaapi_picture_unref(picture) \
gst_vaapi_codec_object_unref (picture)
#define gst_vaapi_picture_replace(old_picture_ptr, new_picture) \
gst_vaapi_codec_object_replace (old_picture_ptr, new_picture)
/* ------------------------------------------------------------------------- */
/* --- Slices --- */
/* ------------------------------------------------------------------------- */
#define GST_VAAPI_SLICE_CAST(obj) \
((GstVaapiSlice *) (obj))
#define GST_VAAPI_SLICE(obj) \
GST_VAAPI_SLICE_CAST (obj)
#define GST_VAAPI_IS_SLICE(obj) \
(GST_VAAPI_SLICE (obj) != NULL)
/**
* GstVaapiSlice:
*
* A #GstVaapiCodecObject holding a slice parameter.
*/
struct _GstVaapiSlice
{
/*< private >*/
GstVaapiCodecObject parent_instance;
/*< public >*/
VABufferID param_id;
VABufferID data_id;
gpointer param;
/* Per-slice overrides */
GstVaapiHuffmanTable *huf_table;
};
G_GNUC_INTERNAL
void
gst_vaapi_slice_destroy (GstVaapiSlice * slice);
G_GNUC_INTERNAL
gboolean
gst_vaapi_slice_create (GstVaapiSlice * slice,
const GstVaapiCodecObjectConstructorArgs * args);
G_GNUC_INTERNAL
GstVaapiSlice *
gst_vaapi_slice_new (GstVaapiDecoder * decoder, gconstpointer param,
guint param_size, const guchar * data, guint data_size);
G_GNUC_INTERNAL
GstVaapiSlice *
gst_vaapi_slice_new_n_params (GstVaapiDecoder * decoder,
gconstpointer param, guint param_size, guint param_num, const guchar * data,
guint data_size);
/* ------------------------------------------------------------------------- */
/* --- Helpers to create codec-dependent objects --- */
/* ------------------------------------------------------------------------- */
#define GST_VAAPI_PICTURE_NEW(codec, decoder) \
gst_vaapi_picture_new (GST_VAAPI_DECODER_CAST (decoder), \
NULL, sizeof (G_PASTE (VAPictureParameterBuffer, codec)))
#define GST_VAAPI_SLICE_NEW(codec, decoder, buf, buf_size) \
gst_vaapi_slice_new (GST_VAAPI_DECODER_CAST (decoder), \
NULL, sizeof (G_PASTE (VASliceParameterBuffer, codec)), \
buf, buf_size)
#define GST_VAAPI_SLICE_NEW_N_PARAMS(codec, decoder, buf, buf_size, n) \
gst_vaapi_slice_new_n_params (GST_VAAPI_DECODER_CAST (decoder), \
NULL, sizeof (G_PASTE (VASliceParameterBuffer, codec)), n, \
buf, buf_size)
G_END_DECLS
#endif /* GST_VAAPI_DECODER_OBJECTS_H */

View file

@ -0,0 +1,275 @@
/*
* gstvaapidecoder_priv.h - VA decoder abstraction (private definitions)
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
* Copyright (C) 2011-2014 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DECODER_PRIV_H
#define GST_VAAPI_DECODER_PRIV_H
#include "sysdeps.h"
#include <gst/vaapi/gstvaapidecoder.h>
#include <gst/vaapi/gstvaapidecoder_unit.h>
#include <gst/vaapi/gstvaapicontext.h>
G_BEGIN_DECLS
#define GST_VAAPI_DECODER_CAST(decoder) \
((GstVaapiDecoder *)(decoder))
#define GST_VAAPI_DECODER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VAAPI_DECODER, GstVaapiDecoderClass))
#define GST_VAAPI_IS_DECODER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VAAPI_DECODER))
#define GST_VAAPI_DECODER_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VAAPI_DECODER, GstVaapiDecoderClass))
typedef struct _GstVaapiDecoderClass GstVaapiDecoderClass;
/**
* GST_VAAPI_PARSER_STATE:
* @decoder: a #GstVaapiDecoder
*
* Macro that evaluates to the #GstVaapiParserState of @decoder.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_PARSER_STATE
#define GST_VAAPI_PARSER_STATE(decoder) \
(&GST_VAAPI_DECODER_CAST(decoder)->parser_state)
/**
* GST_VAAPI_DECODER_DISPLAY:
* @decoder: a #GstVaapiDecoder
*
* Macro that evaluates to the #GstVaapiDisplay of @decoder.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_DECODER_DISPLAY
#define GST_VAAPI_DECODER_DISPLAY(decoder) \
GST_VAAPI_DECODER_CAST(decoder)->display
/**
* GST_VAAPI_DECODER_CONTEXT:
* @decoder: a #GstVaapiDecoder
*
* Macro that evaluates to the #GstVaapiContext of @decoder.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_DECODER_CONTEXT
#define GST_VAAPI_DECODER_CONTEXT(decoder) \
GST_VAAPI_DECODER_CAST(decoder)->context
/**
* GST_VAAPI_DECODER_CODEC:
* @decoder: a #GstVaapiDecoder
*
* Macro that evaluates to the #GstVaapiCodec of @decoder.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_DECODER_CODEC
#define GST_VAAPI_DECODER_CODEC(decoder) \
GST_VAAPI_DECODER_CAST(decoder)->codec
/**
* GST_VAAPI_DECODER_CODEC_STATE:
* @decoder: a #GstVaapiDecoder
*
* Macro that evaluates to the #GstVideoCodecState holding codec state
* for @decoder.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_DECODER_CODEC_STATE
#define GST_VAAPI_DECODER_CODEC_STATE(decoder) \
GST_VAAPI_DECODER_CAST(decoder)->codec_state
/**
* GST_VAAPI_DECODER_CODEC_DATA:
* @decoder: a #GstVaapiDecoder
*
* Macro that evaluates to the #GstBuffer holding optional codec data
* for @decoder.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_DECODER_CODEC_DATA
#define GST_VAAPI_DECODER_CODEC_DATA(decoder) \
GST_VAAPI_DECODER_CODEC_STATE(decoder)->codec_data
/**
* GST_VAAPI_DECODER_CODEC_FRAME:
* @decoder: a #GstVaapiDecoder
*
* Macro that evaluates to the #GstVideoCodecFrame holding decoder
* units for the current frame.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_DECODER_CODEC_FRAME
#define GST_VAAPI_DECODER_CODEC_FRAME(decoder) \
GST_VAAPI_PARSER_STATE(decoder)->current_frame
/**
* GST_VAAPI_DECODER_WIDTH:
* @decoder: a #GstVaapiDecoder
*
* Macro that evaluates to the coded width of the picture
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_DECODER_WIDTH
#define GST_VAAPI_DECODER_WIDTH(decoder) \
GST_VAAPI_DECODER_CODEC_STATE(decoder)->info.width
/**
* GST_VAAPI_DECODER_HEIGHT:
* @decoder: a #GstVaapiDecoder
*
* Macro that evaluates to the coded height of the picture
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_DECODER_HEIGHT
#define GST_VAAPI_DECODER_HEIGHT(decoder) \
GST_VAAPI_DECODER_CODEC_STATE(decoder)->info.height
/* End-of-Stream buffer */
#define GST_BUFFER_FLAG_EOS (GST_BUFFER_FLAG_LAST + 0)
#define GST_BUFFER_IS_EOS(buffer) \
GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_EOS)
#define GST_VAAPI_DECODER_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), \
GST_VAAPI_TYPE_DECODER, \
GstVaapiDecoderPrivate))
typedef enum {
GST_VAAPI_DECODER_STATUS_DROP_FRAME = -2
} GstVaapiDecoderStatusPrivate;
typedef struct _GstVaapiParserState GstVaapiParserState;
struct _GstVaapiParserState
{
GstVideoCodecFrame *current_frame;
guint32 current_frame_number;
GstAdapter *current_adapter;
GstAdapter *input_adapter;
gint input_offset1;
gint input_offset2;
GstAdapter *output_adapter;
GstVaapiDecoderUnit next_unit;
guint next_unit_pending:1;
guint at_eos:1;
};
/**
* GstVaapiDecoder:
*
* A VA decoder base instance.
*/
struct _GstVaapiDecoder
{
/*< private >*/
GstObject parent_instance;
gpointer user_data;
GstVaapiDisplay *display;
VADisplay va_display;
GstVaapiContext *context;
VAContextID va_context;
GstVaapiCodec codec;
GstVideoCodecState *codec_state;
GAsyncQueue *buffers;
GAsyncQueue *frames;
GstVaapiParserState parser_state;
GstVaapiDecoderStateChangedFunc codec_state_changed_func;
gpointer codec_state_changed_data;
};
/**
* GstVaapiDecoderClass:
*
* A VA decoder base class.
*/
struct _GstVaapiDecoderClass
{
/*< private >*/
GstObjectClass parent_class;
GstVaapiDecoderStatus (*parse) (GstVaapiDecoder * decoder,
GstAdapter * adapter, gboolean at_eos,
struct _GstVaapiDecoderUnit * unit);
GstVaapiDecoderStatus (*decode) (GstVaapiDecoder * decoder,
struct _GstVaapiDecoderUnit * unit);
GstVaapiDecoderStatus (*start_frame) (GstVaapiDecoder * decoder,
struct _GstVaapiDecoderUnit * unit);
GstVaapiDecoderStatus (*end_frame) (GstVaapiDecoder * decoder);
GstVaapiDecoderStatus (*flush) (GstVaapiDecoder * decoder);
GstVaapiDecoderStatus (*reset) (GstVaapiDecoder * decoder);
GstVaapiDecoderStatus (*decode_codec_data) (GstVaapiDecoder * decoder,
const guchar * buf, guint buf_size);
};
G_GNUC_INTERNAL
void
gst_vaapi_decoder_set_picture_size (GstVaapiDecoder * decoder,
guint width, guint height);
G_GNUC_INTERNAL
void
gst_vaapi_decoder_set_framerate (GstVaapiDecoder * decoder,
guint fps_n, guint fps_d);
G_GNUC_INTERNAL
void
gst_vaapi_decoder_set_pixel_aspect_ratio (GstVaapiDecoder * decoder,
guint par_n, guint par_d);
G_GNUC_INTERNAL
void
gst_vaapi_decoder_set_interlace_mode (GstVaapiDecoder * decoder,
GstVideoInterlaceMode mode);
G_GNUC_INTERNAL
void
gst_vaapi_decoder_set_interlaced (GstVaapiDecoder * decoder,
gboolean interlaced);
G_GNUC_INTERNAL
void
gst_vaapi_decoder_set_multiview_mode (GstVaapiDecoder * decoder,
gint views, GstVideoMultiviewMode mv_mode, GstVideoMultiviewFlags mv_flags);
G_GNUC_INTERNAL
gboolean
gst_vaapi_decoder_ensure_context (GstVaapiDecoder * decoder,
GstVaapiContextInfo * cip);
G_GNUC_INTERNAL
void
gst_vaapi_decoder_push_frame (GstVaapiDecoder * decoder,
GstVideoCodecFrame * frame);
G_GNUC_INTERNAL
GstVaapiDecoderStatus
gst_vaapi_decoder_decode_codec_data (GstVaapiDecoder * decoder);
G_END_DECLS
#endif /* GST_VAAPI_DECODER_PRIV_H */

View file

@ -0,0 +1,89 @@
/*
* gstvaapidecoder_unit.c - VA decoder units
*
* Copyright (C) 2012-2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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:gstvaapidecoder_unit
* @short_description: Decoder unit
*/
#include "sysdeps.h"
#include "gstvaapidecoder_unit.h"
/**
* gst_vaapi_decoder_unit_init:
* @unit: a #GstVaapiDecoderUnit
*
* Initializes internal resources bound to the supplied decoder @unit.
*
* @note This is an internal function used to implement lightweight
* sub-classes.
*/
void
gst_vaapi_decoder_unit_init (GstVaapiDecoderUnit * unit)
{
unit->flags = 0;
unit->size = 0;
unit->offset = 0;
unit->parsed_info = NULL;
unit->parsed_info_destroy_notify = NULL;
}
/**
* gst_vaapi_decoder_unit_clear:
* @unit: a #GstVaapiDecoderUnit
*
* Deallocates any internal resources bound to the supplied decoder
* @unit.
*
* @note This is an internal function used to implement lightweight
* sub-classes.
*/
void
gst_vaapi_decoder_unit_clear (GstVaapiDecoderUnit * unit)
{
gst_vaapi_decoder_unit_set_parsed_info (unit, NULL, NULL);
}
/**
* gst_vaapi_decoder_unit_set_parsed_info:
* @unit: a #GstVaapiDecoderUnit
* @parsed_info: parser info
* @destroy_notify: (closure parsed_info): a #GDestroyNotify
*
* Sets @parsed_info on the object and the #GDestroyNotify that will be
* called when the data is freed.
*
* If some @parsed_info was previously set, then the former @destroy_notify
* function will be called before the @parsed_info is replaced.
*/
void
gst_vaapi_decoder_unit_set_parsed_info (GstVaapiDecoderUnit * unit,
gpointer parsed_info, GDestroyNotify destroy_notify)
{
g_return_if_fail (GST_VAAPI_IS_DECODER_UNIT (unit));
if (unit->parsed_info && unit->parsed_info_destroy_notify)
unit->parsed_info_destroy_notify (unit->parsed_info);
unit->parsed_info = parsed_info;
unit->parsed_info_destroy_notify = destroy_notify;
}

View file

@ -0,0 +1,189 @@
/*
* gstvaapidecoder_unit.h - VA decoder units
*
* Copyright (C) 2012-2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DECODER_UNIT_H
#define GST_VAAPI_DECODER_UNIT_H
G_BEGIN_DECLS
typedef struct _GstVaapiDecoderUnit GstVaapiDecoderUnit;
#define GST_VAAPI_DECODER_UNIT(unit) \
((GstVaapiDecoderUnit *)(unit))
#define GST_VAAPI_IS_DECODER_UNIT(unit) \
(GST_VAAPI_DECODER_UNIT(unit) != NULL)
/**
* GstVaapiDecoderUnitFlags:
* @GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START: marks the start of a frame.
* @GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END: marks the end of a frame.
* @GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END: marks the end of a stream.
* @GST_VAAPI_DECODER_UNIT_FLAG_SLICE: the unit contains slice data.
* @GST_VAAPI_DECODER_UNIT_FLAG_SKIP: marks the unit as unused/skipped.
*
* Flags for #GstVaapiDecoderUnit.
*/
typedef enum {
GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START = (1 << 0),
GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END = (1 << 1),
GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END = (1 << 2),
GST_VAAPI_DECODER_UNIT_FLAG_SLICE = (1 << 3),
GST_VAAPI_DECODER_UNIT_FLAG_SKIP = (1 << 4),
GST_VAAPI_DECODER_UNIT_FLAG_LAST = (1 << 5)
} GstVaapiDecoderUnitFlags;
/**
* GST_VAAPI_DECODER_UNIT_FLAGS:
* @unit: a #GstVaapiDecoderUnit
*
* The entire set of flags for the @unit
*/
#define GST_VAAPI_DECODER_UNIT_FLAGS(unit) \
((unit)->flags)
/**
* GST_VAAPI_DECODER_UNIT_FLAG_IS_SET:
* @unit: a #GstVaapiDecoderUnit
* @flag: a flag to check for
*
* Checks whether the given @flag is set
*/
#define GST_VAAPI_DECODER_UNIT_FLAG_IS_SET(unit, flag) \
((GST_VAAPI_DECODER_UNIT_FLAGS(unit) & (flag)) != 0)
/**
* GST_VAAPI_DECODER_UNIT_FLAG_SET:
* @unit: a #GstVaapiDecoderUnit
* @flags: flags to set
*
* This macro sets the given bits
*/
#define GST_VAAPI_DECODER_UNIT_FLAG_SET(unit, flags) \
(GST_VAAPI_DECODER_UNIT_FLAGS(unit) |= (flags))
/**
* GST_VAAPI_DECODER_UNIT_FLAG_UNSET:
* @unit: a #GstVaapiDecoderUnit
* @flags: flags to unset
*
* This macro unsets the given bits.
*/
#define GST_VAAPI_DECODER_UNIT_FLAG_UNSET(unit, flags) \
(GST_VAAPI_DECODER_UNIT_FLAGS(unit) &= ~(flags))
/**
* GST_VAAPI_DECODER_UNIT_IS_FRAME_START:
* @unit: a #GstVaapiDecoderUnit
*
* Tests if the decoder unit marks the start of a frame.
*
* The start of a frame is codec dependent but it may include any new
* sequence header.
*/
#define GST_VAAPI_DECODER_UNIT_IS_FRAME_START(unit) \
(GST_VAAPI_DECODER_UNIT_FLAG_IS_SET(unit, \
GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START))
/**
* GST_VAAPI_DECODER_UNIT_IS_FRAME_END:
* @unit: a #GstVaapiDecoderUnit
*
* Tests if the decoder unit marks the end of a frame.
*
* The end of a frame is codec dependent but it is usually represented
* by the last bitstream chunk that holds valid slice data.
*/
#define GST_VAAPI_DECODER_UNIT_IS_FRAME_END(unit) \
(GST_VAAPI_DECODER_UNIT_FLAG_IS_SET(unit, \
GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END))
/**
* GST_VAAPI_DECODER_UNIT_IS_STREAM_END:
* @unit: a #GstVaapiDecoderUnit
*
* Tests if the decoder unit marks the end of the stream.
*/
#define GST_VAAPI_DECODER_UNIT_IS_STREAM_END(unit) \
(GST_VAAPI_DECODER_UNIT_FLAG_IS_SET(unit, \
GST_VAAPI_DECODER_UNIT_FLAG_STREAM_END))
/**
* GST_VAAPI_DECODER_UNIT_IS_SLICE:
* @unit: a #GstVaapiDecoderUnit
*
* Tests if the decoder unit contains slice data.
*/
#define GST_VAAPI_DECODER_UNIT_IS_SLICE(unit) \
(GST_VAAPI_DECODER_UNIT_FLAG_IS_SET(unit, \
GST_VAAPI_DECODER_UNIT_FLAG_SLICE))
/**
* GST_VAAPI_DECODER_UNIT_IS_SKIPPED:
* @unit: a #GstVaapiDecoderUnit
*
* Tests if the decoder unit is not needed for decoding an can be skipped.
* i.e. #GstVaapiDecoder sub-classes won't see this chunk of bitstream
* data.
*/
#define GST_VAAPI_DECODER_UNIT_IS_SKIPPED(unit) \
(GST_VAAPI_DECODER_UNIT_FLAG_IS_SET(unit, \
GST_VAAPI_DECODER_UNIT_FLAG_SKIP))
/**
* GstVaapiDecoderUnit:
* @size: size in bytes of this bitstream unit
* @offset: relative offset in bytes to bitstream unit within the
* associated #GstVideoCodecFrame input_buffer
* @parsed_info: parser-specific data (this is codec specific)
* @parsed_info_destroy_notify: function used to release @parsed_info data
*
* A chunk of bitstream data that was parsed.
*/
struct _GstVaapiDecoderUnit {
guint flags;
guint size;
guint offset;
gpointer parsed_info;
GDestroyNotify parsed_info_destroy_notify;
};
G_GNUC_INTERNAL
void
gst_vaapi_decoder_unit_init(GstVaapiDecoderUnit *unit);
G_GNUC_INTERNAL
void
gst_vaapi_decoder_unit_clear(GstVaapiDecoderUnit *unit);
G_GNUC_INTERNAL
GstVaapiDecoderUnit *
gst_vaapi_decoder_unit_new(void);
G_GNUC_INTERNAL
void
gst_vaapi_decoder_unit_set_parsed_info(GstVaapiDecoderUnit *unit,
gpointer parsed_info, GDestroyNotify destroy_notify);
G_END_DECLS
#endif /* GST_VAAPI_DECODER_UNIT_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,49 @@
/*
* gstvaapidecoder_vc1.h - VC-1 decoder
*
* Copyright (C) 2011-2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DECODER_VC1_H
#define GST_VAAPI_DECODER_VC1_H
#include <gst/vaapi/gstvaapidecoder.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_DECODER_VC1 \
(gst_vaapi_decoder_vc1_get_type ())
#define GST_VAAPI_DECODER_VC1(decoder) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_DECODER_VC1, GstVaapiDecoderVC1))
#define GST_VAAPI_IS_DECODER_VC1(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_DECODER_VC1))
typedef struct _GstVaapiDecoderVC1 GstVaapiDecoderVC1;
GType
gst_vaapi_decoder_vc1_get_type (void) G_GNUC_CONST;
GstVaapiDecoder *
gst_vaapi_decoder_vc1_new (GstVaapiDisplay *display, GstCaps *caps);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiDecoderVC1, gst_object_unref)
G_END_DECLS
#endif /* GST_VAAPI_DECODER_VC1_H */

View file

@ -0,0 +1,677 @@
/*
* gstvaapidecoder_vp8.c - VP8 decoder
*
* Copyright (C) 2013-2014 Intel Corporation
* Author: Halley Zhao <halley.zhao@intel.com>
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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:gstvaapidecoder_vp8
* @short_description: VP8 decoder
*/
#include "sysdeps.h"
#include <gst/codecparsers/gstvp8parser.h>
#include "gstvaapidecoder_vp8.h"
#include "gstvaapidecoder_objects.h"
#include "gstvaapidecoder_priv.h"
#include "gstvaapidisplay_priv.h"
#include "gstvaapicompat.h"
#define DEBUG 1
#include "gstvaapidebug.h"
#define GST_VAAPI_DECODER_VP8_CAST(decoder) \
((GstVaapiDecoderVp8 *)(decoder))
typedef struct _GstVaapiDecoderVp8Private GstVaapiDecoderVp8Private;
typedef struct _GstVaapiDecoderVp8Class GstVaapiDecoderVp8Class;
struct _GstVaapiDecoderVp8Private
{
GstVaapiProfile profile;
guint width;
guint height;
GstVp8Parser parser;
GstVp8FrameHdr frame_hdr;
GstVaapiPicture *last_picture;
GstVaapiPicture *golden_ref_picture;
GstVaapiPicture *alt_ref_picture;
GstVaapiPicture *current_picture;
guint size_changed:1;
};
/**
* GstVaapiDecoderVp8:
*
* A decoder based on Vp8.
*/
struct _GstVaapiDecoderVp8
{
/*< private > */
GstVaapiDecoder parent_instance;
GstVaapiDecoderVp8Private priv;
};
/**
* GstVaapiDecoderVp8Class:
*
* A decoder class based on Vp8.
*/
struct _GstVaapiDecoderVp8Class
{
/*< private > */
GstVaapiDecoderClass parent_class;
};
G_DEFINE_TYPE (GstVaapiDecoderVp8, gst_vaapi_decoder_vp8,
GST_TYPE_VAAPI_DECODER);
static GstVaapiDecoderStatus
get_status (GstVp8ParserResult result)
{
GstVaapiDecoderStatus status;
switch (result) {
case GST_VP8_PARSER_OK:
status = GST_VAAPI_DECODER_STATUS_SUCCESS;
break;
case GST_VP8_PARSER_ERROR:
status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
break;
default:
status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
break;
}
return status;
}
static void
gst_vaapi_decoder_vp8_close (GstVaapiDecoderVp8 * decoder)
{
GstVaapiDecoderVp8Private *const priv = &decoder->priv;
gst_vaapi_picture_replace (&priv->last_picture, NULL);
gst_vaapi_picture_replace (&priv->golden_ref_picture, NULL);
gst_vaapi_picture_replace (&priv->alt_ref_picture, NULL);
gst_vaapi_picture_replace (&priv->current_picture, NULL);
}
static gboolean
gst_vaapi_decoder_vp8_open (GstVaapiDecoderVp8 * decoder)
{
GstVaapiDecoderVp8Private *const priv = &decoder->priv;
gst_vaapi_decoder_vp8_close (decoder);
gst_vp8_parser_init (&priv->parser);
return TRUE;
}
static void
gst_vaapi_decoder_vp8_destroy (GstVaapiDecoder * base_decoder)
{
GstVaapiDecoderVp8 *const decoder = GST_VAAPI_DECODER_VP8_CAST (base_decoder);
gst_vaapi_decoder_vp8_close (decoder);
}
static gboolean
gst_vaapi_decoder_vp8_create (GstVaapiDecoder * base_decoder)
{
GstVaapiDecoderVp8 *const decoder = GST_VAAPI_DECODER_VP8_CAST (base_decoder);
GstVaapiDecoderVp8Private *const priv = &decoder->priv;
if (!gst_vaapi_decoder_vp8_open (decoder))
return FALSE;
priv->profile = GST_VAAPI_PROFILE_UNKNOWN;
return TRUE;
}
static GstVaapiDecoderStatus
gst_vaapi_decoder_vp8_reset (GstVaapiDecoder * base_decoder)
{
gst_vaapi_decoder_vp8_destroy (base_decoder);
if (gst_vaapi_decoder_vp8_create (base_decoder))
return GST_VAAPI_DECODER_STATUS_SUCCESS;
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
}
static GstVaapiDecoderStatus
ensure_context (GstVaapiDecoderVp8 * decoder)
{
GstVaapiDecoderVp8Private *const priv = &decoder->priv;
const GstVaapiProfile profile = GST_VAAPI_PROFILE_VP8;
const GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
gboolean reset_context = FALSE;
if (priv->profile != profile) {
if (!gst_vaapi_display_has_decoder (GST_VAAPI_DECODER_DISPLAY (decoder),
profile, entrypoint))
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
priv->profile = profile;
reset_context = TRUE;
}
if (priv->size_changed) {
GST_DEBUG ("size changed");
priv->size_changed = FALSE;
reset_context = TRUE;
}
if (reset_context) {
GstVaapiContextInfo info;
info.profile = priv->profile;
info.entrypoint = entrypoint;
info.chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
info.width = priv->width;
info.height = priv->height;
info.ref_frames = 3;
reset_context =
gst_vaapi_decoder_ensure_context (GST_VAAPI_DECODER (decoder), &info);
if (!reset_context)
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
}
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
ensure_quant_matrix (GstVaapiDecoderVp8 * decoder, GstVaapiPicture * picture)
{
GstVaapiDecoderVp8Private *const priv = &decoder->priv;
GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;
GstVp8Segmentation *const seg = &priv->parser.segmentation;
VAIQMatrixBufferVP8 *iq_matrix;
const gint8 QI_MAX = 127;
gint8 qi, qi_base;
gint i;
picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW (VP8, decoder);
if (!picture->iq_matrix) {
GST_ERROR ("failed to allocate IQ matrix");
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
}
iq_matrix = picture->iq_matrix->param;
/* Fill in VAIQMatrixBufferVP8 */
for (i = 0; i < 4; i++) {
if (seg->segmentation_enabled) {
qi_base = seg->quantizer_update_value[i];
if (!seg->segment_feature_mode) // 0 means delta update
qi_base += frame_hdr->quant_indices.y_ac_qi;
} else
qi_base = frame_hdr->quant_indices.y_ac_qi;
qi = qi_base;
iq_matrix->quantization_index[i][0] = CLAMP (qi, 0, QI_MAX);
qi = qi_base + frame_hdr->quant_indices.y_dc_delta;
iq_matrix->quantization_index[i][1] = CLAMP (qi, 0, QI_MAX);
qi = qi_base + frame_hdr->quant_indices.y2_dc_delta;
iq_matrix->quantization_index[i][2] = CLAMP (qi, 0, QI_MAX);
qi = qi_base + frame_hdr->quant_indices.y2_ac_delta;
iq_matrix->quantization_index[i][3] = CLAMP (qi, 0, QI_MAX);
qi = qi_base + frame_hdr->quant_indices.uv_dc_delta;
iq_matrix->quantization_index[i][4] = CLAMP (qi, 0, QI_MAX);
qi = qi_base + frame_hdr->quant_indices.uv_ac_delta;
iq_matrix->quantization_index[i][5] = CLAMP (qi, 0, QI_MAX);
}
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
ensure_probability_table (GstVaapiDecoderVp8 * decoder,
GstVaapiPicture * picture)
{
GstVaapiDecoderVp8Private *const priv = &decoder->priv;
GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;
VAProbabilityDataBufferVP8 *prob_table;
picture->prob_table = GST_VAAPI_PROBABILITY_TABLE_NEW (VP8, decoder);
if (!picture->prob_table) {
GST_ERROR ("failed to allocate probality table");
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
}
prob_table = picture->prob_table->param;
/* Fill in VAProbabilityDataBufferVP8 */
memcpy (prob_table->dct_coeff_probs, frame_hdr->token_probs.prob,
sizeof (frame_hdr->token_probs.prob));
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static void
init_picture (GstVaapiDecoderVp8 * decoder, GstVaapiPicture * picture)
{
GstVaapiDecoderVp8Private *const priv = &decoder->priv;
GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;
picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
picture->type = frame_hdr->key_frame ? GST_VAAPI_PICTURE_TYPE_I :
GST_VAAPI_PICTURE_TYPE_P;
picture->pts = GST_VAAPI_DECODER_CODEC_FRAME (decoder)->pts;
if (!frame_hdr->show_frame)
GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_SKIPPED);
}
static gboolean
fill_picture (GstVaapiDecoderVp8 * decoder, GstVaapiPicture * picture)
{
GstVaapiDecoderVp8Private *const priv = &decoder->priv;
VAPictureParameterBufferVP8 *const pic_param = picture->param;
GstVp8Parser *const parser = &priv->parser;
GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;
GstVp8Segmentation *const seg = &parser->segmentation;
gint i;
/* Fill in VAPictureParameterBufferVP8 */
pic_param->frame_width = priv->width;
pic_param->frame_height = priv->height;
pic_param->last_ref_frame = VA_INVALID_SURFACE;
pic_param->golden_ref_frame = VA_INVALID_SURFACE;
pic_param->alt_ref_frame = VA_INVALID_SURFACE;
if (!frame_hdr->key_frame) {
if (priv->last_picture)
pic_param->last_ref_frame = priv->last_picture->surface_id;
if (priv->golden_ref_picture)
pic_param->golden_ref_frame = priv->golden_ref_picture->surface_id;
if (priv->alt_ref_picture)
pic_param->alt_ref_frame = priv->alt_ref_picture->surface_id;
}
pic_param->out_of_loop_frame = VA_INVALID_SURFACE; // not used currently
pic_param->pic_fields.value = 0;
pic_param->pic_fields.bits.key_frame = !frame_hdr->key_frame;
pic_param->pic_fields.bits.version = frame_hdr->version;
pic_param->pic_fields.bits.segmentation_enabled = seg->segmentation_enabled;
pic_param->pic_fields.bits.update_mb_segmentation_map =
seg->update_mb_segmentation_map;
pic_param->pic_fields.bits.update_segment_feature_data =
seg->update_segment_feature_data;
pic_param->pic_fields.bits.filter_type = frame_hdr->filter_type;
pic_param->pic_fields.bits.sharpness_level = frame_hdr->sharpness_level;
pic_param->pic_fields.bits.loop_filter_adj_enable =
parser->mb_lf_adjust.loop_filter_adj_enable;
pic_param->pic_fields.bits.mode_ref_lf_delta_update =
parser->mb_lf_adjust.mode_ref_lf_delta_update;
pic_param->pic_fields.bits.sign_bias_golden = frame_hdr->sign_bias_golden;
pic_param->pic_fields.bits.sign_bias_alternate =
frame_hdr->sign_bias_alternate;
pic_param->pic_fields.bits.mb_no_coeff_skip = frame_hdr->mb_no_skip_coeff;
for (i = 0; i < 3; i++)
pic_param->mb_segment_tree_probs[i] = seg->segment_prob[i];
for (i = 0; i < 4; i++) {
gint8 level;
if (seg->segmentation_enabled) {
level = seg->lf_update_value[i];
if (!seg->segment_feature_mode) // 0 means delta update
level += frame_hdr->loop_filter_level;
} else
level = frame_hdr->loop_filter_level;
pic_param->loop_filter_level[i] = CLAMP (level, 0, 63);
pic_param->loop_filter_deltas_ref_frame[i] =
parser->mb_lf_adjust.ref_frame_delta[i];
pic_param->loop_filter_deltas_mode[i] =
parser->mb_lf_adjust.mb_mode_delta[i];
}
/* In decoding, the only loop filter settings that matter are those
in the frame header (9.1) */
pic_param->pic_fields.bits.loop_filter_disable =
frame_hdr->loop_filter_level == 0;
pic_param->prob_skip_false = frame_hdr->prob_skip_false;
pic_param->prob_intra = frame_hdr->prob_intra;
pic_param->prob_last = frame_hdr->prob_last;
pic_param->prob_gf = frame_hdr->prob_gf;
memcpy (pic_param->y_mode_probs, frame_hdr->mode_probs.y_prob,
sizeof (frame_hdr->mode_probs.y_prob));
memcpy (pic_param->uv_mode_probs, frame_hdr->mode_probs.uv_prob,
sizeof (frame_hdr->mode_probs.uv_prob));
memcpy (pic_param->mv_probs, frame_hdr->mv_probs.prob,
sizeof (frame_hdr->mv_probs));
pic_param->bool_coder_ctx.range = frame_hdr->rd_range;
pic_param->bool_coder_ctx.value = frame_hdr->rd_value;
pic_param->bool_coder_ctx.count = frame_hdr->rd_count;
return TRUE;
}
static gboolean
fill_slice (GstVaapiDecoderVp8 * decoder, GstVaapiSlice * slice)
{
GstVaapiDecoderVp8Private *const priv = &decoder->priv;
VASliceParameterBufferVP8 *const slice_param = slice->param;
GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;
gint i;
/* Fill in VASliceParameterBufferVP8 */
slice_param->slice_data_offset = frame_hdr->data_chunk_size;
slice_param->macroblock_offset = frame_hdr->header_size;
slice_param->num_of_partitions =
(1 << frame_hdr->log2_nbr_of_dct_partitions) + 1;
slice_param->partition_size[0] =
frame_hdr->first_part_size - ((slice_param->macroblock_offset + 7) >> 3);
for (i = 1; i < slice_param->num_of_partitions; i++)
slice_param->partition_size[i] = frame_hdr->partition_size[i - 1];
for (; i < G_N_ELEMENTS (slice_param->partition_size); i++)
slice_param->partition_size[i] = 0;
return TRUE;
}
static GstVaapiDecoderStatus
decode_slice (GstVaapiDecoderVp8 * decoder, GstVaapiPicture * picture,
const guchar * buf, guint buf_size)
{
GstVaapiSlice *slice;
slice = GST_VAAPI_SLICE_NEW (VP8, decoder, buf, buf_size);
if (!slice) {
GST_ERROR ("failed to allocate slice");
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
}
if (!fill_slice (decoder, slice)) {
gst_vaapi_mini_object_unref (GST_VAAPI_MINI_OBJECT (slice));
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
}
gst_vaapi_picture_add_slice (GST_VAAPI_PICTURE_CAST (picture), slice);
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
decode_picture (GstVaapiDecoderVp8 * decoder, const guchar * buf,
guint buf_size)
{
GstVaapiDecoderVp8Private *const priv = &decoder->priv;
GstVaapiPicture *picture;
GstVaapiDecoderStatus status;
status = ensure_context (decoder);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
return status;
/* Create new picture */
picture = GST_VAAPI_PICTURE_NEW (VP8, decoder);
if (!picture) {
GST_ERROR ("failed to allocate picture");
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
}
gst_vaapi_picture_replace (&priv->current_picture, picture);
gst_vaapi_picture_unref (picture);
status = ensure_quant_matrix (decoder, picture);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
return status;
status = ensure_probability_table (decoder, picture);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
return status;
init_picture (decoder, picture);
if (!fill_picture (decoder, picture))
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
return decode_slice (decoder, picture, buf, buf_size);
}
static void
update_ref_frames (GstVaapiDecoderVp8 * decoder)
{
GstVaapiDecoderVp8Private *const priv = &decoder->priv;
GstVaapiPicture *picture = priv->current_picture;
GstVp8FrameHdr *const frame_hdr = &priv->frame_hdr;
// update picture reference
if (frame_hdr->key_frame) {
gst_vaapi_picture_replace (&priv->golden_ref_picture, picture);
gst_vaapi_picture_replace (&priv->alt_ref_picture, picture);
} else {
// process refresh_alternate_frame/copy_buffer_to_alternate first
if (frame_hdr->refresh_alternate_frame) {
gst_vaapi_picture_replace (&priv->alt_ref_picture, picture);
} else {
switch (frame_hdr->copy_buffer_to_alternate) {
case 0:
// do nothing
break;
case 1:
gst_vaapi_picture_replace (&priv->alt_ref_picture,
priv->last_picture);
break;
case 2:
gst_vaapi_picture_replace (&priv->alt_ref_picture,
priv->golden_ref_picture);
break;
default:
GST_WARNING
("WARNING: VP8 decoder: unrecognized copy_buffer_to_alternate");
}
}
if (frame_hdr->refresh_golden_frame) {
gst_vaapi_picture_replace (&priv->golden_ref_picture, picture);
} else {
switch (frame_hdr->copy_buffer_to_golden) {
case 0:
// do nothing
break;
case 1:
gst_vaapi_picture_replace (&priv->golden_ref_picture,
priv->last_picture);
break;
case 2:
gst_vaapi_picture_replace (&priv->golden_ref_picture,
priv->alt_ref_picture);
break;
default:
GST_WARNING
("WARNING: VP8 decoder: unrecognized copy_buffer_to_golden");
}
}
}
if (frame_hdr->key_frame || frame_hdr->refresh_last)
gst_vaapi_picture_replace (&priv->last_picture, picture);
}
static GstVaapiDecoderStatus
decode_current_picture (GstVaapiDecoderVp8 * decoder)
{
GstVaapiDecoderVp8Private *const priv = &decoder->priv;
GstVaapiPicture *const picture = priv->current_picture;
if (!picture)
return GST_VAAPI_DECODER_STATUS_SUCCESS;
update_ref_frames (decoder);
if (!gst_vaapi_picture_decode (picture))
goto error;
if (!gst_vaapi_picture_output (picture))
goto error;
gst_vaapi_picture_replace (&priv->current_picture, NULL);
return GST_VAAPI_DECODER_STATUS_SUCCESS;
/* ERRORS */
error:
{
/* XXX: fix for cases where first field failed to be decoded */
gst_vaapi_picture_replace (&priv->current_picture, NULL);
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
}
}
static GstVaapiDecoderStatus
parse_frame_header (GstVaapiDecoderVp8 * decoder, const guchar * buf,
guint buf_size, GstVp8FrameHdr * frame_hdr)
{
GstVaapiDecoderVp8Private *const priv = &decoder->priv;
GstVp8ParserResult result;
memset (frame_hdr, 0, sizeof (*frame_hdr));
result = gst_vp8_parser_parse_frame_header (&priv->parser, frame_hdr,
buf, buf_size);
if (result != GST_VP8_PARSER_OK)
return get_status (result);
if (frame_hdr->key_frame &&
(frame_hdr->width != priv->width || frame_hdr->height != priv->height)) {
priv->width = frame_hdr->width;
priv->height = frame_hdr->height;
priv->size_changed = TRUE;
}
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
gst_vaapi_decoder_vp8_parse (GstVaapiDecoder * base_decoder,
GstAdapter * adapter, gboolean at_eos, GstVaapiDecoderUnit * unit)
{
guint flags = 0;
unit->size = gst_adapter_available (adapter);
/* The whole frame is available */
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
GST_VAAPI_DECODER_UNIT_FLAG_SET (unit, flags);
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
decode_buffer (GstVaapiDecoderVp8 * decoder, const guchar * buf, guint buf_size)
{
GstVaapiDecoderVp8Private *const priv = &decoder->priv;
GstVaapiDecoderStatus status;
status = parse_frame_header (decoder, buf, buf_size, &priv->frame_hdr);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
return status;
return decode_picture (decoder, buf, buf_size);
}
static GstVaapiDecoderStatus
gst_vaapi_decoder_vp8_decode (GstVaapiDecoder * base_decoder,
GstVaapiDecoderUnit * unit)
{
GstVaapiDecoderVp8 *const decoder = GST_VAAPI_DECODER_VP8_CAST (base_decoder);
GstVaapiDecoderStatus status;
GstBuffer *const buffer =
GST_VAAPI_DECODER_CODEC_FRAME (decoder)->input_buffer;
GstMapInfo map_info;
if (!gst_buffer_map (buffer, &map_info, GST_MAP_READ)) {
GST_ERROR ("failed to map buffer");
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
}
status = decode_buffer (decoder, map_info.data + unit->offset, unit->size);
gst_buffer_unmap (buffer, &map_info);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
return status;
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
gst_vaapi_decoder_vp8_start_frame (GstVaapiDecoder * base_decoder,
GstVaapiDecoderUnit * base_unit)
{
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
gst_vaapi_decoder_vp8_end_frame (GstVaapiDecoder * base_decoder)
{
GstVaapiDecoderVp8 *const decoder = GST_VAAPI_DECODER_VP8_CAST (base_decoder);
return decode_current_picture (decoder);
}
static GstVaapiDecoderStatus
gst_vaapi_decoder_vp8_flush (GstVaapiDecoder * base_decoder)
{
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static void
gst_vaapi_decoder_vp8_finalize (GObject * object)
{
GstVaapiDecoder *const base_decoder = GST_VAAPI_DECODER (object);
gst_vaapi_decoder_vp8_destroy (base_decoder);
G_OBJECT_CLASS (gst_vaapi_decoder_vp8_parent_class)->finalize (object);
}
static void
gst_vaapi_decoder_vp8_class_init (GstVaapiDecoderVp8Class * klass)
{
GObjectClass *const object_class = G_OBJECT_CLASS (klass);
GstVaapiDecoderClass *const decoder_class = GST_VAAPI_DECODER_CLASS (klass);
object_class->finalize = gst_vaapi_decoder_vp8_finalize;
decoder_class->reset = gst_vaapi_decoder_vp8_reset;
decoder_class->parse = gst_vaapi_decoder_vp8_parse;
decoder_class->decode = gst_vaapi_decoder_vp8_decode;
decoder_class->start_frame = gst_vaapi_decoder_vp8_start_frame;
decoder_class->end_frame = gst_vaapi_decoder_vp8_end_frame;
decoder_class->flush = gst_vaapi_decoder_vp8_flush;
}
static void
gst_vaapi_decoder_vp8_init (GstVaapiDecoderVp8 * decoder)
{
GstVaapiDecoder *const base_decoder = GST_VAAPI_DECODER (decoder);
gst_vaapi_decoder_vp8_create (base_decoder);
}
/**
* gst_vaapi_decoder_vp8_new:
* @display: a #GstVaapiDisplay
* @caps: a #GstCaps holding codec information
*
* Creates a new #GstVaapiDecoder for VP8 decoding. The @caps can
* hold extra information like codec-data and pictured coded size.
*
* Return value: the newly allocated #GstVaapiDecoder object
*/
GstVaapiDecoder *
gst_vaapi_decoder_vp8_new (GstVaapiDisplay * display, GstCaps * caps)
{
return g_object_new (GST_TYPE_VAAPI_DECODER_VP8, "display", display,
"caps", caps, NULL);
}

View file

@ -0,0 +1,50 @@
/*
* gstvaapidecoder_vp8.h - VP8 decoder
*
* Copyright (C) 2013-2014 Intel Corporation
* Author: Halley Zhao <halley.zhao@intel.com>
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DECODER_VP8_H
#define GST_VAAPI_DECODER_VP8_H
#include <gst/vaapi/gstvaapidecoder.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_DECODER_VP8 \
(gst_vaapi_decoder_vp8_get_type ())
#define GST_VAAPI_DECODER_VP8(decoder) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_DECODER_VP8, GstVaapiDecoderVp8))
#define GST_VAAPI_IS_DECODER_VP8(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_DECODER_VP8))
typedef struct _GstVaapiDecoderVp8 GstVaapiDecoderVp8;
GType
gst_vaapi_decoder_vp8_get_type (void) G_GNUC_CONST;
GstVaapiDecoder *
gst_vaapi_decoder_vp8_new (GstVaapiDisplay * display, GstCaps * caps);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiDecoderVp8, gst_object_unref)
G_END_DECLS
#endif /* GST_VAAPI_DECODER_VP8_H */

View file

@ -0,0 +1,833 @@
/*
* gstvaapidecoder_vp9.c - VP9 decoder
*
* Copyright (C) 2014-2015 Intel Corporation
* Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
*
* 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:gstvaapidecoder_vp9
* @short_description: VP9 decoder
*/
#include "sysdeps.h"
#include <gst/codecparsers/gstvp9parser.h>
#include "gstvaapidecoder_vp9.h"
#include "gstvaapidecoder_objects.h"
#include "gstvaapidecoder_priv.h"
#include "gstvaapidisplay_priv.h"
#include "gstvaapicompat.h"
#define DEBUG 1
#include "gstvaapidebug.h"
#define GST_VAAPI_DECODER_VP9_CAST(decoder) \
((GstVaapiDecoderVp9 *)(decoder))
typedef struct _GstVaapiDecoderVp9Private GstVaapiDecoderVp9Private;
typedef struct _GstVaapiDecoderVp9Class GstVaapiDecoderVp9Class;
struct _GstVaapiDecoderVp9Private
{
GstVaapiProfile profile;
guint width;
guint height;
GstVp9Parser *parser;
GstVp9FrameHdr frame_hdr;
GstVaapiPicture *current_picture;
GstVaapiPicture *ref_frames[GST_VP9_REF_FRAMES]; /* reference frames in ref_slots[max_ref] */
guint num_frames; /* number of frames in a super frame */
guint frame_sizes[8]; /* size of frames in a super frame */
guint frame_cnt; /* frame count variable for super frame */
guint total_idx_size; /* super frame index size (full block size) */
guint had_superframe_hdr:1; /* indicate the presense of super frame */
guint size_changed:1;
};
/**
* GstVaapiDecoderVp9:
*
* A decoder based on Vp9.
*/
struct _GstVaapiDecoderVp9
{
/*< private > */
GstVaapiDecoder parent_instance;
GstVaapiDecoderVp9Private priv;
};
/**
* GstVaapiDecoderVp9Class:
*
* A decoder class based on Vp9.
*/
struct _GstVaapiDecoderVp9Class
{
/*< private > */
GstVaapiDecoderClass parent_class;
};
G_DEFINE_TYPE (GstVaapiDecoderVp9, gst_vaapi_decoder_vp9,
GST_TYPE_VAAPI_DECODER);
static GstVaapiDecoderStatus
get_status (GstVp9ParserResult result)
{
GstVaapiDecoderStatus status;
switch (result) {
case GST_VP9_PARSER_OK:
status = GST_VAAPI_DECODER_STATUS_SUCCESS;
break;
case GST_VP9_PARSER_ERROR:
status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
break;
default:
status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
break;
}
return status;
}
static void
gst_vaapi_decoder_vp9_close (GstVaapiDecoderVp9 * decoder)
{
GstVaapiDecoderVp9Private *const priv = &decoder->priv;
guint i;
for (i = 0; i < GST_VP9_REF_FRAMES; i++)
gst_vaapi_picture_replace (&priv->ref_frames[i], NULL);
g_clear_pointer (&priv->parser, gst_vp9_parser_free);
}
static gboolean
gst_vaapi_decoder_vp9_open (GstVaapiDecoderVp9 * decoder)
{
GstVaapiDecoderVp9Private *const priv = &decoder->priv;
gst_vaapi_decoder_vp9_close (decoder);
priv->parser = gst_vp9_parser_new ();
return TRUE;
}
static void
gst_vaapi_decoder_vp9_destroy (GstVaapiDecoder * base_decoder)
{
GstVaapiDecoderVp9 *const decoder = GST_VAAPI_DECODER_VP9_CAST (base_decoder);
gst_vaapi_decoder_vp9_close (decoder);
}
static gboolean
gst_vaapi_decoder_vp9_create (GstVaapiDecoder * base_decoder)
{
GstVaapiDecoderVp9 *const decoder = GST_VAAPI_DECODER_VP9_CAST (base_decoder);
GstVaapiDecoderVp9Private *const priv = &decoder->priv;
if (!gst_vaapi_decoder_vp9_open (decoder))
return FALSE;
priv->profile = GST_VAAPI_PROFILE_UNKNOWN;
return TRUE;
}
static GstVaapiDecoderStatus
gst_vaapi_decoder_vp9_reset (GstVaapiDecoder * base_decoder)
{
gst_vaapi_decoder_vp9_destroy (base_decoder);
if (gst_vaapi_decoder_vp9_create (base_decoder))
return GST_VAAPI_DECODER_STATUS_SUCCESS;
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
}
/* Returns GstVaapiProfile from VP9 frame_hdr profile value */
static GstVaapiProfile
get_profile (guint profile_idc)
{
GstVaapiProfile profile;
switch (profile_idc) {
case GST_VP9_PROFILE_0:
profile = GST_VAAPI_PROFILE_VP9_0;
break;
case GST_VP9_PROFILE_1:
profile = GST_VAAPI_PROFILE_VP9_1;
break;
case GST_VP9_PROFILE_2:
profile = GST_VAAPI_PROFILE_VP9_2;
break;
case GST_VP9_PROFILE_3:
profile = GST_VAAPI_PROFILE_VP9_3;
break;
default:
GST_DEBUG ("unsupported profile_idc value");
profile = GST_VAAPI_PROFILE_UNKNOWN;
break;
}
return profile;
}
static gboolean
get_chroma_type (GstVp9FrameHdr * frame_hdr, GstVp9Parser * parser,
GstVaapiContextInfo * info)
{
switch (frame_hdr->profile) {
case GST_VP9_PROFILE_0:
info->chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
break;
case GST_VP9_PROFILE_1:
if (parser->subsampling_x == 1 && parser->subsampling_y == 0)
info->chroma_type = GST_VAAPI_CHROMA_TYPE_YUV422;
else if (parser->subsampling_x == 0 && parser->subsampling_y == 0)
info->chroma_type = GST_VAAPI_CHROMA_TYPE_YUV444;
else
return FALSE;
break;
case GST_VP9_PROFILE_2:
if (parser->bit_depth == 10)
info->chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420_10BPP;
else
info->chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420_12BPP;
break;
case GST_VP9_PROFILE_3:
if (parser->subsampling_x == 1 && parser->subsampling_y == 0) {
if (parser->bit_depth == 10)
info->chroma_type = GST_VAAPI_CHROMA_TYPE_YUV422_10BPP;
else
info->chroma_type = GST_VAAPI_CHROMA_TYPE_YUV422_12BPP;
} else if (parser->subsampling_x == 0 && parser->subsampling_y == 0) {
if (parser->bit_depth == 10)
info->chroma_type = GST_VAAPI_CHROMA_TYPE_YUV444_10BPP;
else
info->chroma_type = GST_VAAPI_CHROMA_TYPE_YUV444_12BPP;
} else
return FALSE;
break;
default:
return FALSE;
break;
}
return TRUE;
}
static GstVaapiDecoderStatus
ensure_context (GstVaapiDecoderVp9 * decoder)
{
GstVaapiDecoderVp9Private *const priv = &decoder->priv;
GstVp9FrameHdr *frame_hdr = &priv->frame_hdr;
GstVp9Parser *parser = priv->parser;
GstVaapiProfile profile;
const GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
gboolean reset_context = FALSE;
profile = get_profile (frame_hdr->profile);
if (priv->profile != profile) {
if (!gst_vaapi_display_has_decoder (GST_VAAPI_DECODER_DISPLAY (decoder),
profile, entrypoint))
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
priv->profile = profile;
reset_context = TRUE;
}
if (priv->size_changed) {
GST_DEBUG ("size changed");
priv->size_changed = FALSE;
reset_context = TRUE;
}
if (reset_context) {
GstVaapiContextInfo info;
info.profile = priv->profile;
info.entrypoint = entrypoint;
info.width = priv->width;
info.height = priv->height;
info.ref_frames = 8;
if (!get_chroma_type (frame_hdr, parser, &info))
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT;
reset_context =
gst_vaapi_decoder_ensure_context (GST_VAAPI_DECODER (decoder), &info);
if (!reset_context)
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
gst_vaapi_context_reset_on_resize (GST_VAAPI_DECODER_CONTEXT (decoder),
FALSE);
}
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static void
init_picture (GstVaapiDecoderVp9 * decoder, GstVaapiPicture * picture)
{
GstVaapiDecoderVp9Private *const priv = &decoder->priv;
GstVp9FrameHdr *const frame_hdr = &priv->frame_hdr;
picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
picture->type =
(frame_hdr->frame_type ==
GST_VP9_KEY_FRAME) ? GST_VAAPI_PICTURE_TYPE_I : GST_VAAPI_PICTURE_TYPE_P;
picture->pts = GST_VAAPI_DECODER_CODEC_FRAME (decoder)->pts;
if (!frame_hdr->show_frame)
GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_SKIPPED);
}
static void
vaapi_fill_ref_frames (GstVaapiDecoderVp9 * decoder, GstVaapiPicture * picture,
GstVp9FrameHdr * frame_hdr, VADecPictureParameterBufferVP9 * pic_param)
{
GstVaapiDecoderVp9Private *const priv = &decoder->priv;
guint i;
if (frame_hdr->frame_type != GST_VP9_KEY_FRAME) {
pic_param->pic_fields.bits.last_ref_frame =
frame_hdr->ref_frame_indices[GST_VP9_REF_FRAME_LAST - 1];
pic_param->pic_fields.bits.last_ref_frame_sign_bias =
frame_hdr->ref_frame_sign_bias[GST_VP9_REF_FRAME_LAST - 1];
pic_param->pic_fields.bits.golden_ref_frame =
frame_hdr->ref_frame_indices[GST_VP9_REF_FRAME_GOLDEN - 1];
pic_param->pic_fields.bits.golden_ref_frame_sign_bias =
frame_hdr->ref_frame_sign_bias[GST_VP9_REF_FRAME_GOLDEN - 1];
pic_param->pic_fields.bits.alt_ref_frame =
frame_hdr->ref_frame_indices[GST_VP9_REF_FRAME_ALTREF - 1];
pic_param->pic_fields.bits.alt_ref_frame_sign_bias =
frame_hdr->ref_frame_sign_bias[GST_VP9_REF_FRAME_ALTREF - 1];
}
for (i = 0; i < G_N_ELEMENTS (priv->ref_frames); i++) {
pic_param->reference_frames[i] = priv->ref_frames[i] ?
priv->ref_frames[i]->surface_id : VA_INVALID_SURFACE;
}
}
static gboolean
fill_picture (GstVaapiDecoderVp9 * decoder, GstVaapiPicture * picture)
{
GstVaapiDecoderVp9Private *priv = &decoder->priv;
VADecPictureParameterBufferVP9 *pic_param = picture->param;
GstVp9Parser *parser = priv->parser;
GstVp9FrameHdr *frame_hdr = &priv->frame_hdr;
/* Fill in VAPictureParameterBufferVP9 */
pic_param->frame_width = frame_hdr->width;
pic_param->frame_height = frame_hdr->height;
/* Fill in ReferenceFrames */
vaapi_fill_ref_frames (decoder, picture, frame_hdr, pic_param);
#define COPY_FIELD(s, f) \
pic_param->f = (s)->f
#define COPY_BFM(a, s, f) \
pic_param->a.bits.f = (s)->f
COPY_BFM (pic_fields, parser, subsampling_x);
COPY_BFM (pic_fields, parser, subsampling_y);
COPY_BFM (pic_fields, frame_hdr, frame_type);
COPY_BFM (pic_fields, frame_hdr, show_frame);
COPY_BFM (pic_fields, frame_hdr, error_resilient_mode);
COPY_BFM (pic_fields, frame_hdr, intra_only);
COPY_BFM (pic_fields, frame_hdr, allow_high_precision_mv);
COPY_BFM (pic_fields, frame_hdr, mcomp_filter_type);
COPY_BFM (pic_fields, frame_hdr, frame_parallel_decoding_mode);
COPY_BFM (pic_fields, frame_hdr, reset_frame_context);
COPY_BFM (pic_fields, frame_hdr, refresh_frame_context);
COPY_BFM (pic_fields, frame_hdr, frame_context_idx);
COPY_BFM (pic_fields, frame_hdr, lossless_flag);
pic_param->pic_fields.bits.segmentation_enabled =
frame_hdr->segmentation.enabled;
pic_param->pic_fields.bits.segmentation_temporal_update =
frame_hdr->segmentation.temporal_update;
pic_param->pic_fields.bits.segmentation_update_map =
frame_hdr->segmentation.update_map;
COPY_FIELD (&frame_hdr->loopfilter, filter_level);
COPY_FIELD (&frame_hdr->loopfilter, sharpness_level);
COPY_FIELD (frame_hdr, log2_tile_rows);
COPY_FIELD (frame_hdr, log2_tile_columns);
COPY_FIELD (frame_hdr, frame_header_length_in_bytes);
COPY_FIELD (frame_hdr, first_partition_size);
COPY_FIELD (frame_hdr, profile);
#if VA_CHECK_VERSION (0, 39, 0)
COPY_FIELD (parser, bit_depth);
#endif
g_assert (G_N_ELEMENTS (pic_param->mb_segment_tree_probs) ==
G_N_ELEMENTS (parser->mb_segment_tree_probs));
g_assert (G_N_ELEMENTS (pic_param->segment_pred_probs) ==
G_N_ELEMENTS (parser->segment_pred_probs));
memcpy (pic_param->mb_segment_tree_probs, parser->mb_segment_tree_probs,
sizeof (parser->mb_segment_tree_probs));
if (frame_hdr->segmentation.temporal_update) {
memcpy (pic_param->segment_pred_probs, parser->segment_pred_probs,
sizeof (parser->segment_pred_probs));
} else {
memset (pic_param->segment_pred_probs, 255,
sizeof (pic_param->segment_pred_probs));
}
return TRUE;
}
static gboolean
fill_slice (GstVaapiDecoderVp9 * decoder, GstVaapiSlice * slice)
{
GstVaapiDecoderVp9Private *const priv = &decoder->priv;
GstVp9Parser *parser = priv->parser;
VASliceParameterBufferVP9 *const slice_param = slice->param;
guint i;
#define COPY_SEG_FIELD(s, f) \
seg_param->f = (s)->f
/* Fill in VASliceParameterBufferVP9 */
for (i = 0; i < GST_VP9_MAX_SEGMENTS; i++) {
VASegmentParameterVP9 *seg_param = &slice_param->seg_param[i];
GstVp9Segmentation *seg = &parser->segmentation[i];
memcpy (seg_param->filter_level, seg->filter_level,
sizeof (seg->filter_level));
COPY_SEG_FIELD (seg, luma_ac_quant_scale);
COPY_SEG_FIELD (seg, luma_dc_quant_scale);
COPY_SEG_FIELD (seg, chroma_ac_quant_scale);
COPY_SEG_FIELD (seg, chroma_dc_quant_scale);
seg_param->segment_flags.fields.segment_reference_skipped =
seg->reference_skip;
seg_param->segment_flags.fields.segment_reference_enabled =
seg->reference_frame_enabled;
seg_param->segment_flags.fields.segment_reference = seg->reference_frame;
}
/* Fixme: When segmentation is disabled, only seg_param[0] has valid values,
* all other entries should be populated with 0 ? */
return TRUE;
}
static GstVaapiDecoderStatus
decode_slice (GstVaapiDecoderVp9 * decoder, GstVaapiPicture * picture,
const guchar * buf, guint buf_size)
{
GstVaapiSlice *slice;
slice = GST_VAAPI_SLICE_NEW (VP9, decoder, buf, buf_size);
if (!slice) {
GST_ERROR ("failed to allocate slice");
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
}
if (!fill_slice (decoder, slice)) {
gst_vaapi_mini_object_unref (GST_VAAPI_MINI_OBJECT (slice));
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
}
gst_vaapi_picture_add_slice (GST_VAAPI_PICTURE_CAST (picture), slice);
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static void
update_ref_frames (GstVaapiDecoderVp9 * decoder)
{
GstVaapiDecoderVp9Private *const priv = &decoder->priv;
GstVaapiPicture *picture = priv->current_picture;
GstVp9FrameHdr *const frame_hdr = &priv->frame_hdr;
guint8 refresh_frame_flags, mask, i = 0;
if (frame_hdr->frame_type == GST_VP9_KEY_FRAME)
refresh_frame_flags = (1 << GST_VP9_REF_FRAMES) - 1;
else
refresh_frame_flags = frame_hdr->refresh_frame_flags;
for (mask = refresh_frame_flags; mask; mask >>= 1, ++i) {
if (mask & 1)
gst_vaapi_picture_replace (&priv->ref_frames[i], picture);
}
}
#ifdef GST_VAAPI_PICTURE_NEW
#undef GST_VAAPI_PICTURE_NEW
#endif
#define GST_VAAPI_PICTURE_NEW(codec, decoder) \
gst_vaapi_picture_new (GST_VAAPI_DECODER_CAST (decoder), \
NULL, sizeof (G_PASTE (VADecPictureParameterBuffer, codec)))
static GstVaapiDecoderStatus
decode_picture (GstVaapiDecoderVp9 * decoder, const guchar * buf,
guint buf_size)
{
GstVaapiDecoderVp9Private *const priv = &decoder->priv;
GstVp9FrameHdr *frame_hdr = &priv->frame_hdr;
GstVaapiPicture *picture;
GstVaapiDecoderStatus status;
guint crop_width = 0, crop_height = 0;
gboolean is_clone_pic = FALSE;
status = ensure_context (decoder);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
return status;
/* if show_exising_frame flag is true, we just need to return
* the existing frame in ref frame array, so creating a clone
* of already decoded frame */
if (frame_hdr->show_existing_frame) {
GstVaapiPicture *existing_frame =
priv->ref_frames[frame_hdr->frame_to_show];
if (!existing_frame) {
GST_ERROR ("Failed to get the existing frame from dpb");
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
}
picture = gst_vaapi_picture_new_clone (existing_frame);
if (!picture) {
GST_ERROR ("Failed to create clone picture");
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
}
is_clone_pic = TRUE;
/* for cloned picture we should always unset the skip flag since
* the previously decoded frame might be decode-only but repeat-frame
* should make it ready for display */
GST_VAAPI_PICTURE_FLAG_UNSET (picture, GST_VAAPI_PICTURE_FLAG_SKIPPED);
/* reset picture pts with whatever set in VideoCodecFrame */
picture->pts = GST_VAAPI_DECODER_CODEC_FRAME (decoder)->pts;
} else {
/* Create new picture */
picture = GST_VAAPI_PICTURE_NEW (VP9, decoder);
if (!picture) {
GST_ERROR ("failed to allocate picture");
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
}
}
gst_vaapi_picture_replace (&priv->current_picture, picture);
gst_vaapi_picture_unref (picture);
if (is_clone_pic)
return GST_VAAPI_DECODER_STATUS_SUCCESS;
if (priv->width > frame_hdr->width || priv->height > frame_hdr->height) {
crop_width = frame_hdr->width;
crop_height = frame_hdr->height;
}
if (crop_width || crop_height) {
GstVaapiRectangle crop_rect;
crop_rect.x = 0;
crop_rect.y = 0;
crop_rect.width = crop_width;
crop_rect.height = crop_height;
gst_vaapi_picture_set_crop_rect (picture, &crop_rect);
}
init_picture (decoder, picture);
if (!fill_picture (decoder, picture))
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
return decode_slice (decoder, picture, buf, buf_size);
}
static GstVaapiDecoderStatus
decode_current_picture (GstVaapiDecoderVp9 * decoder)
{
GstVaapiDecoderVp9Private *const priv = &decoder->priv;
GstVaapiPicture *const picture = priv->current_picture;
GstVp9FrameHdr *const frame_hdr = &priv->frame_hdr;
if (!picture)
return GST_VAAPI_DECODER_STATUS_SUCCESS;
if (frame_hdr->show_existing_frame)
goto ret;
if (!gst_vaapi_picture_decode (picture))
goto error;
update_ref_frames (decoder);
ret:
if (!gst_vaapi_picture_output (picture))
goto error;
gst_vaapi_picture_replace (&priv->current_picture, NULL);
return GST_VAAPI_DECODER_STATUS_SUCCESS;
/* ERRORS */
error:
{
/* XXX: fix for cases where first field failed to be decoded */
gst_vaapi_picture_replace (&priv->current_picture, NULL);
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
}
}
static gboolean
parse_super_frame (const guchar * data, guint data_size,
guint * frame_sizes, guint * frame_count, guint * total_idx_size)
{
guint8 marker;
guint32 num_frames = 1, frame_size_length, total_index_size;
guint i, j;
if (data_size <= 0)
return FALSE;
marker = data[data_size - 1];
if ((marker & 0xe0) == 0xc0) {
GST_DEBUG ("Got VP9-Super Frame, size %d", data_size);
num_frames = (marker & 0x7) + 1;
frame_size_length = ((marker >> 3) & 0x3) + 1;
total_index_size = 2 + num_frames * frame_size_length;
if ((data_size >= total_index_size)
&& (data[data_size - total_index_size] == marker)) {
const guint8 *x = &data[data_size - total_index_size + 1];
for (i = 0; i < num_frames; i++) {
guint32 cur_frame_size = 0;
for (j = 0; j < frame_size_length; j++)
cur_frame_size |= (*x++) << (j * 8);
frame_sizes[i] = cur_frame_size;
}
*frame_count = num_frames;
*total_idx_size = total_index_size;
} else {
GST_ERROR ("Failed to parse Super-frame");
return FALSE;
}
} else {
*frame_count = num_frames;
frame_sizes[0] = data_size;
*total_idx_size = 0;
}
return TRUE;
}
static GstVaapiDecoderStatus
parse_frame_header (GstVaapiDecoderVp9 * decoder, const guchar * buf,
guint buf_size, GstVp9FrameHdr * frame_hdr)
{
GstVaapiDecoderVp9Private *const priv = &decoder->priv;
GstVp9ParserResult result;
guint width, height;
result = gst_vp9_parser_parse_frame_header (priv->parser, frame_hdr,
buf, buf_size);
if (result != GST_VP9_PARSER_OK)
return get_status (result);
/* Unlike other decoders, vp9 decoder doesn't need to reset the
* whole context and surfaces for each resolution change. Calling
* ensure_context() again is only needed if the resolution of any frame
* is greater than what was previously configured, so that new, larger
* surfaces can be allocated. There are streams where a bigger
* resolution set in ivf header or webm header but actual resolution
* of all frames are less. Also it is possible to have inter-prediction
* between these multi resolution frames */
width = GST_VAAPI_DECODER_WIDTH (decoder);
height = GST_VAAPI_DECODER_HEIGHT (decoder);
if (priv->width < width || priv->height < height) {
priv->width = GST_VAAPI_DECODER_WIDTH (decoder);
priv->height = GST_VAAPI_DECODER_HEIGHT (decoder);
priv->size_changed = TRUE;
}
if ((frame_hdr->width > priv->width || frame_hdr->height > priv->height)) {
priv->width = frame_hdr->width;
priv->height = frame_hdr->height;
priv->size_changed = TRUE;
}
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
gst_vaapi_decoder_vp9_parse (GstVaapiDecoder * base_decoder,
GstAdapter * adapter, gboolean at_eos, GstVaapiDecoderUnit * unit)
{
GstVaapiDecoderVp9 *const decoder = GST_VAAPI_DECODER_VP9_CAST (base_decoder);
GstVaapiDecoderVp9Private *const priv = &decoder->priv;
guchar *buf;
guint buf_size, flags = 0;
buf_size = gst_adapter_available (adapter);
if (!buf_size)
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
buf = (guchar *) gst_adapter_map (adapter, buf_size);
if (!buf)
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
if (!priv->had_superframe_hdr) {
if (!parse_super_frame (buf, buf_size, priv->frame_sizes, &priv->num_frames,
&priv->total_idx_size))
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
if (priv->num_frames > 1)
priv->had_superframe_hdr = TRUE;
}
unit->size = priv->frame_sizes[priv->frame_cnt++];
if (priv->frame_cnt == priv->num_frames) {
priv->num_frames = 0;
priv->frame_cnt = 0;
priv->had_superframe_hdr = FALSE;
unit->size += priv->total_idx_size;
}
/* The whole frame is available */
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_START;
flags |= GST_VAAPI_DECODER_UNIT_FLAG_SLICE;
flags |= GST_VAAPI_DECODER_UNIT_FLAG_FRAME_END;
GST_VAAPI_DECODER_UNIT_FLAG_SET (unit, flags);
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
decode_buffer (GstVaapiDecoderVp9 * decoder, const guchar * buf, guint buf_size)
{
GstVaapiDecoderVp9Private *const priv = &decoder->priv;
GstVaapiDecoderStatus status;
guint size = buf_size;
if (priv->total_idx_size && !priv->had_superframe_hdr) {
size -= priv->total_idx_size;
priv->total_idx_size = 0;
}
status = parse_frame_header (decoder, buf, size, &priv->frame_hdr);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
return status;
return decode_picture (decoder, buf, size);
}
static GstVaapiDecoderStatus
gst_vaapi_decoder_vp9_decode (GstVaapiDecoder * base_decoder,
GstVaapiDecoderUnit * unit)
{
GstVaapiDecoderVp9 *const decoder = GST_VAAPI_DECODER_VP9_CAST (base_decoder);
GstVaapiDecoderStatus status;
GstBuffer *const buffer =
GST_VAAPI_DECODER_CODEC_FRAME (decoder)->input_buffer;
GstMapInfo map_info;
if (!gst_buffer_map (buffer, &map_info, GST_MAP_READ)) {
GST_ERROR ("failed to map buffer");
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
}
status = decode_buffer (decoder, map_info.data + unit->offset, unit->size);
gst_buffer_unmap (buffer, &map_info);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
return status;
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
gst_vaapi_decoder_vp9_start_frame (GstVaapiDecoder * base_decoder,
GstVaapiDecoderUnit * base_unit)
{
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus
gst_vaapi_decoder_vp9_end_frame (GstVaapiDecoder * base_decoder)
{
GstVaapiDecoderVp9 *const decoder = GST_VAAPI_DECODER_VP9_CAST (base_decoder);
return decode_current_picture (decoder);
}
static GstVaapiDecoderStatus
gst_vaapi_decoder_vp9_flush (GstVaapiDecoder * base_decoder)
{
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static void
gst_vaapi_decoder_vp9_finalize (GObject * object)
{
GstVaapiDecoder *const base_decoder = GST_VAAPI_DECODER (object);
gst_vaapi_decoder_vp9_destroy (base_decoder);
G_OBJECT_CLASS (gst_vaapi_decoder_vp9_parent_class)->finalize (object);
}
static void
gst_vaapi_decoder_vp9_class_init (GstVaapiDecoderVp9Class * klass)
{
GObjectClass *const object_class = G_OBJECT_CLASS (klass);
GstVaapiDecoderClass *const decoder_class = GST_VAAPI_DECODER_CLASS (klass);
object_class->finalize = gst_vaapi_decoder_vp9_finalize;
decoder_class->reset = gst_vaapi_decoder_vp9_reset;
decoder_class->parse = gst_vaapi_decoder_vp9_parse;
decoder_class->decode = gst_vaapi_decoder_vp9_decode;
decoder_class->start_frame = gst_vaapi_decoder_vp9_start_frame;
decoder_class->end_frame = gst_vaapi_decoder_vp9_end_frame;
decoder_class->flush = gst_vaapi_decoder_vp9_flush;
}
static void
gst_vaapi_decoder_vp9_init (GstVaapiDecoderVp9 * decoder)
{
GstVaapiDecoder *const base_decoder = GST_VAAPI_DECODER (decoder);
gst_vaapi_decoder_vp9_create (base_decoder);
}
/**
* gst_vaapi_decoder_vp9_new:
* @display: a #GstVaapiDisplay
* @caps: a #GstCaps holding codec information
*
* Creates a new #GstVaapiDecoder for VP9 decoding. The @caps can
* hold extra information like codec-data and pictured coded size.
*
* Return value: the newly allocated #GstVaapiDecoder object
*/
GstVaapiDecoder *
gst_vaapi_decoder_vp9_new (GstVaapiDisplay * display, GstCaps * caps)
{
return g_object_new (GST_TYPE_VAAPI_DECODER_VP9, "display", display,
"caps", caps, NULL);
}

View file

@ -0,0 +1,49 @@
/*
* gstvaapidecoder_vp9.h - VP9 decoder
*
* Copyright (C) 2015-2016 Intel Corporation
* Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
*
* 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_VAAPI_DECODER_VP9_H
#define GST_VAAPI_DECODER_VP9_H
#include <gst/vaapi/gstvaapidecoder.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_DECODER_VP9 \
(gst_vaapi_decoder_vp9_get_type ())
#define GST_VAAPI_DECODER_VP9(decoder) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_DECODER_VP9, GstVaapiDecoderVp9))
#define GST_VAAPI_IS_DECODER_VP9(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_DECODER_VP9))
typedef struct _GstVaapiDecoderVp9 GstVaapiDecoderVp9;
GType
gst_vaapi_decoder_vp9_get_type (void) G_GNUC_CONST;
GstVaapiDecoder *
gst_vaapi_decoder_vp9_new (GstVaapiDisplay * display, GstCaps * caps);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiDecoderVp9, gst_object_unref)
G_END_DECLS
#endif /* GST_VAAPI_DECODER_VP9_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,293 @@
/*
* gstvaapidisplay.h - VA display abstraction
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
* Copyright (C) 2011-2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DISPLAY_H
#define GST_VAAPI_DISPLAY_H
#include <va/va.h>
#include <gst/gst.h>
#include <gst/vaapi/gstvaapitypes.h>
#include <gst/vaapi/gstvaapiprofile.h>
#include <gst/vaapi/video-format.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_DISPLAY (gst_vaapi_display_get_type ())
#define GST_VAAPI_DISPLAY(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_DISPLAY, GstVaapiDisplay))
#define GST_VAAPI_IS_DISPLAY(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_DISPLAY))
/**
* GST_VAAPI_DISPLAY_GET_CLASS_TYPE:
* @display: a #GstVaapiDisplay
*
* Returns the #display class type
*/
#define GST_VAAPI_DISPLAY_GET_CLASS_TYPE(display) \
gst_vaapi_display_get_class_type (GST_VAAPI_DISPLAY (display))
/**
* GST_VAAPI_DISPLAY_VADISPLAY_TYPE:
* @display: a #GstVaapiDisplay
*
* Returns the underlying VADisplay @display type.
*/
#define GST_VAAPI_DISPLAY_VADISPLAY_TYPE(display) \
gst_vaapi_display_get_display_type (GST_VAAPI_DISPLAY (display))
/**
* GST_VAAPI_DISPLAY_VADISPLAY:
* @display_: a #GstVaapiDisplay
*
* Macro that evaluates to the #VADisplay of @display.
*/
#define GST_VAAPI_DISPLAY_VADISPLAY(display) \
gst_vaapi_display_get_display (GST_VAAPI_DISPLAY (display))
/**
* GST_VAAPI_DISPLAY_LOCK:
* @display: a #GstVaapiDisplay
*
* Locks @display
*/
#define GST_VAAPI_DISPLAY_LOCK(display) \
gst_vaapi_display_lock (GST_VAAPI_DISPLAY (display))
/**
* GST_VAAPI_DISPLAY_UNLOCK:
* @display: a #GstVaapiDisplay
*
* Unlocks @display
*/
#define GST_VAAPI_DISPLAY_UNLOCK(display) \
gst_vaapi_display_unlock (GST_VAAPI_DISPLAY (display))
typedef struct _GstVaapiDisplayInfo GstVaapiDisplayInfo;
typedef struct _GstVaapiDisplay GstVaapiDisplay;
/**
* GstVaapiDriverQuirks:
* @GST_VAAPI_DRIVER_QUIRK_NO_CHECK_SURFACE_PUT_IMAGE: if driver
* crashes when try to put an image in a reused surface.
* https://gitlab.freedesktop.org/mesa/mesa/merge_requests/2016
* @GST_VAAPI_DRIVER_QUIRK_NO_CHECK_VPP_COLOR_STD: if driver does not
* properly report supported vpp color standards.
* @GST_VAAPI_DRIVER_QUIRK_MISSING_RGBA_IMAGE_FORMAT: i965 driver doesn't
* report to support ARGB format, but if it's forced to create a RGBA
* surface, it works. Driver issue:
* https://github.com/intel/intel-vaapi-driver/issues/500
* @GST_VAAPI_DRIVER_QUIRK_JPEG_ENC_SHIFT_VALUE_BY_50: if the driver shifts
* the value by 50 when calculating quantization from quality level
* @GST_VAAPI_DRIVER_QUIRK_HEVC_ENC_SLICE_NOT_SPAN_TILE: The requirement
* that one slice should not span tiles when tile is enabled.
* @GST_VAAPI_DRIVER_QUIRK_JPEG_DEC_BROKEN_FORMATS: i965 driver does not
* report all the handled formats for JPEG decoding.
*/
typedef enum
{
GST_VAAPI_DRIVER_QUIRK_NO_CHECK_SURFACE_PUT_IMAGE = (1U << 0),
GST_VAAPI_DRIVER_QUIRK_NO_CHECK_VPP_COLOR_STD = (1U << 1),
GST_VAAPI_DRIVER_QUIRK_MISSING_RGBA_IMAGE_FORMAT = (1U << 3),
GST_VAAPI_DRIVER_QUIRK_JPEG_ENC_SHIFT_VALUE_BY_50 = (1U << 4),
GST_VAAPI_DRIVER_QUIRK_HEVC_ENC_SLICE_NOT_SPAN_TILE = (1U << 5),
GST_VAAPI_DRIVER_QUIRK_JPEG_DEC_BROKEN_FORMATS = (1U << 6),
} GstVaapiDriverQuirks;
/**
* GstVaapiDisplayType:
* @GST_VAAPI_DISPLAY_TYPE_ANY: Automatic detection of the display type.
* @GST_VAAPI_DISPLAY_TYPE_X11: VA/X11 display.
* @GST_VAAPI_DISPLAY_TYPE_GLX: VA/GLX display.
* @GST_VAAPI_DISPLAY_TYPE_WAYLAND: VA/Wayland display.
* @GST_VAAPI_DISPLAY_TYPE_DRM: VA/DRM display.
* @GST_VAAPI_DISPLAY_TYPE_EGL: VA/EGL display.
*/
typedef enum
{
GST_VAAPI_DISPLAY_TYPE_ANY = 0,
GST_VAAPI_DISPLAY_TYPE_X11,
GST_VAAPI_DISPLAY_TYPE_GLX,
GST_VAAPI_DISPLAY_TYPE_WAYLAND,
GST_VAAPI_DISPLAY_TYPE_DRM,
GST_VAAPI_DISPLAY_TYPE_EGL,
} GstVaapiDisplayType;
#define GST_VAAPI_TYPE_DISPLAY_TYPE \
(gst_vaapi_display_type_get_type())
GType
gst_vaapi_display_type_get_type (void) G_GNUC_CONST;
GType
gst_vaapi_display_get_type (void) G_GNUC_CONST;
gboolean
gst_vaapi_display_type_is_compatible (GstVaapiDisplayType type1,
GstVaapiDisplayType type2);
/**
* GstVaapiDisplayInfo:
*
* Generic class to retrieve VA display info
*/
struct _GstVaapiDisplayInfo
{
GstVaapiDisplay *display;
gchar *display_name;
VADisplay va_display;
gpointer native_display;
};
/**
* GstVaapiDisplayProperties:
* @GST_VAAPI_DISPLAY_PROP_RENDER_MODE: rendering mode (#GstVaapiRenderMode).
* @GST_VAAPI_DISPLAY_PROP_ROTATION: rotation angle (#GstVaapiRotation).
* @GST_VAAPI_DISPLAY_PROP_HUE: hue (float: [-180 ; 180], default: 0).
* @GST_VAAPI_DISPLAY_PROP_SATURATION: saturation (float: [0 ; 2], default: 1).
* @GST_VAAPI_DISPLAY_PROP_BRIGHTNESS: brightness (float: [-1 ; 1], default: 0).
* @GST_VAAPI_DISPLAY_PROP_CONTRAST: contrast (float: [0 ; 2], default: 1).
*/
#define GST_VAAPI_DISPLAY_PROP_RENDER_MODE "render-mode"
#define GST_VAAPI_DISPLAY_PROP_ROTATION "rotation"
#define GST_VAAPI_DISPLAY_PROP_HUE "hue"
#define GST_VAAPI_DISPLAY_PROP_SATURATION "saturation"
#define GST_VAAPI_DISPLAY_PROP_BRIGHTNESS "brightness"
#define GST_VAAPI_DISPLAY_PROP_CONTRAST "contrast"
GstVaapiDisplay *
gst_vaapi_display_new_with_display (VADisplay va_display);
void
gst_vaapi_display_replace (GstVaapiDisplay ** old_display_ptr,
GstVaapiDisplay * new_display);
void
gst_vaapi_display_lock (GstVaapiDisplay * display);
void
gst_vaapi_display_unlock (GstVaapiDisplay * display);
void
gst_vaapi_display_sync (GstVaapiDisplay * display);
void
gst_vaapi_display_flush (GstVaapiDisplay * display);
GstVaapiDisplayType
gst_vaapi_display_get_class_type (GstVaapiDisplay * display);
GstVaapiDisplayType
gst_vaapi_display_get_display_type (GstVaapiDisplay * display);
const gchar *
gst_vaapi_display_get_display_name (GstVaapiDisplay * display);
VADisplay
gst_vaapi_display_get_display (GstVaapiDisplay * display);
guint
gst_vaapi_display_get_width (GstVaapiDisplay * display);
guint
gst_vaapi_display_get_height (GstVaapiDisplay * display);
void
gst_vaapi_display_get_size (GstVaapiDisplay * display, guint * pwidth,
guint * pheight);
void
gst_vaapi_display_get_pixel_aspect_ratio (GstVaapiDisplay * display,
guint * par_n, guint * par_d);
gboolean
gst_vaapi_display_has_video_processing (GstVaapiDisplay * display);
GArray *
gst_vaapi_display_get_decode_profiles (GstVaapiDisplay * display);
gboolean
gst_vaapi_display_has_decoder (GstVaapiDisplay * display,
GstVaapiProfile profile, GstVaapiEntrypoint entrypoint);
GArray *
gst_vaapi_display_get_encode_profiles (GstVaapiDisplay * display);
GArray *
gst_vaapi_display_get_encode_profiles_by_codec (GstVaapiDisplay * display,
GstVaapiCodec codec);
gboolean
gst_vaapi_display_has_encoder (GstVaapiDisplay * display,
GstVaapiProfile profile, GstVaapiEntrypoint entrypoint);
GArray *
gst_vaapi_display_get_image_formats (GstVaapiDisplay * display);
gboolean
gst_vaapi_display_has_image_format (GstVaapiDisplay * display,
GstVideoFormat format);
GArray *
gst_vaapi_display_get_subpicture_formats (GstVaapiDisplay * display);
gboolean
gst_vaapi_display_has_subpicture_format (GstVaapiDisplay * display,
GstVideoFormat format, guint * flags_ptr);
gboolean
gst_vaapi_display_has_property (GstVaapiDisplay * display, const gchar * name);
gboolean
gst_vaapi_display_get_render_mode (GstVaapiDisplay * display,
GstVaapiRenderMode * pmode);
gboolean
gst_vaapi_display_set_render_mode (GstVaapiDisplay * display,
GstVaapiRenderMode mode);
GstVaapiRotation
gst_vaapi_display_get_rotation (GstVaapiDisplay * display);
gboolean
gst_vaapi_display_set_rotation (GstVaapiDisplay * display,
GstVaapiRotation rotation);
const gchar *
gst_vaapi_display_get_vendor_string (GstVaapiDisplay * display);
gboolean
gst_vaapi_display_has_opengl (GstVaapiDisplay * display);
void
gst_vaapi_display_reset_texture_map (GstVaapiDisplay * display);
gboolean
gst_vaapi_display_has_driver_quirks (GstVaapiDisplay * display, guint quirks);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiDisplay, gst_object_unref)
G_END_DECLS
#endif /* GST_VAAPI_DISPLAY_H */

View file

@ -0,0 +1,470 @@
/*
* gstvaapidisplay_drm.c - VA/DRM display abstraction
*
* Copyright (C) 2012-2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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:gstvaapidisplay_drm
* @short_description: VA/DRM display abstraction
*/
#define _GNU_SOURCE
#include "sysdeps.h"
#include <unistd.h>
#include <fcntl.h>
#include <libudev.h>
#include <xf86drm.h>
#include <va/va_drm.h>
#include "gstvaapiutils.h"
#include "gstvaapidisplay_priv.h"
#include "gstvaapidisplay_drm.h"
#include "gstvaapidisplay_drm_priv.h"
#include "gstvaapiwindow_drm.h"
#define DEBUG_VAAPI_DISPLAY 1
#include "gstvaapidebug.h"
#ifndef MAXPATHLEN
#if defined(PATH_MAX)
#define MAXPATHLEN PATH_MAX
#elif defined(_PC_PATH_MAX)
#define MAXPATHLEN sysconf(_PC_PATH_MAX)
#else
#define MAXPATHLEN 2048
#endif
#endif
G_DEFINE_TYPE_WITH_PRIVATE (GstVaapiDisplayDRM, gst_vaapi_display_drm,
GST_TYPE_VAAPI_DISPLAY);
typedef enum
{
DRM_DEVICE_LEGACY = 1,
DRM_DEVICE_RENDERNODES,
} DRMDeviceType;
static DRMDeviceType g_drm_device_type;
static GMutex g_drm_device_type_lock;
static const gchar *allowed_subsystems[] = { "pci", "platform", NULL };
static gboolean
supports_vaapi (int fd)
{
gboolean ret;
VADisplay va_dpy;
va_dpy = vaGetDisplayDRM (fd);
if (!va_dpy)
return FALSE;
ret = vaapi_initialize (va_dpy);
vaTerminate (va_dpy);
return ret;
}
/* Get default device path. Actually, the first match in the DRM subsystem */
static const gchar *
get_default_device_path (GstVaapiDisplay * display)
{
GstVaapiDisplayDRMPrivate *const priv =
GST_VAAPI_DISPLAY_DRM_PRIVATE (display);
const gchar *syspath, *devpath;
struct udev *udev = NULL;
struct udev_device *device, *parent;
struct udev_enumerate *e = NULL;
struct udev_list_entry *l;
gint i;
int fd;
if (!priv->device_path_default) {
udev = udev_new ();
if (!udev)
goto end;
e = udev_enumerate_new (udev);
if (!e)
goto end;
udev_enumerate_add_match_subsystem (e, "drm");
switch (g_drm_device_type) {
case DRM_DEVICE_LEGACY:
udev_enumerate_add_match_sysname (e, "card[0-9]*");
break;
case DRM_DEVICE_RENDERNODES:
udev_enumerate_add_match_sysname (e, "renderD[0-9]*");
break;
default:
GST_ERROR ("unknown drm device type (%d)", g_drm_device_type);
goto end;
}
udev_enumerate_scan_devices (e);
udev_list_entry_foreach (l, udev_enumerate_get_list_entry (e)) {
syspath = udev_list_entry_get_name (l);
device = udev_device_new_from_syspath (udev, syspath);
parent = udev_device_get_parent (device);
for (i = 0; allowed_subsystems[i] != NULL; i++)
if (g_strcmp0 (udev_device_get_subsystem (parent),
allowed_subsystems[i]) == 0)
break;
if (allowed_subsystems[i] == NULL) {
udev_device_unref (device);
continue;
}
devpath = udev_device_get_devnode (device);
fd = open (devpath, O_RDWR | O_CLOEXEC);
if (fd < 0) {
udev_device_unref (device);
continue;
}
if (supports_vaapi (fd))
priv->device_path_default = g_strdup (devpath);
close (fd);
udev_device_unref (device);
if (priv->device_path_default)
break;
}
end:
if (e)
udev_enumerate_unref (e);
if (udev)
udev_unref (udev);
}
return priv->device_path_default;
}
/* Reconstruct a device path without our prefix */
static const gchar *
get_device_path (GstVaapiDisplay * display)
{
GstVaapiDisplayDRMPrivate *const priv =
GST_VAAPI_DISPLAY_DRM_PRIVATE (display);
const gchar *device_path = priv->device_path;
if (!device_path || *device_path == '\0')
return NULL;
return device_path;
}
/* Mangle device path with our prefix */
static gboolean
set_device_path (GstVaapiDisplay * display, const gchar * device_path)
{
GstVaapiDisplayDRMPrivate *const priv =
GST_VAAPI_DISPLAY_DRM_PRIVATE (display);
g_free (priv->device_path);
priv->device_path = NULL;
if (!device_path) {
device_path = get_default_device_path (display);
if (!device_path)
return FALSE;
}
priv->device_path = g_strdup (device_path);
return priv->device_path != NULL;
}
/* Set device path from file descriptor */
static gboolean
set_device_path_from_fd (GstVaapiDisplay * display, gint drm_device)
{
GstVaapiDisplayDRMPrivate *const priv =
GST_VAAPI_DISPLAY_DRM_PRIVATE (display);
gboolean success = FALSE;
gchar fd_name[MAXPATHLEN];
GError *error = NULL;
g_free (priv->device_path);
priv->device_path = NULL;
if (drm_device < 0)
goto end;
sprintf (fd_name, "/proc/%d/fd/%d", getpid (), drm_device);
priv->device_path = g_file_read_link (fd_name, &error);
if (error) {
g_error_free (error);
goto end;
}
if (g_str_has_prefix (priv->device_path, "/dev/dri/card") ||
g_str_has_prefix (priv->device_path, "/dev/dri/renderD"))
success = TRUE;
else {
g_free (priv->device_path);
priv->device_path = NULL;
}
end:
return success;
}
static gboolean
gst_vaapi_display_drm_bind_display (GstVaapiDisplay * display,
gpointer native_display)
{
GstVaapiDisplayDRMPrivate *const priv =
GST_VAAPI_DISPLAY_DRM_PRIVATE (display);
priv->drm_device = GPOINTER_TO_INT (native_display);
priv->use_foreign_display = TRUE;
if (!set_device_path_from_fd (display, priv->drm_device))
return FALSE;
return TRUE;
}
static gboolean
gst_vaapi_display_drm_open_display (GstVaapiDisplay * display,
const gchar * name)
{
GstVaapiDisplayDRMPrivate *const priv =
GST_VAAPI_DISPLAY_DRM_PRIVATE (display);
if (!set_device_path (display, name))
return FALSE;
priv->drm_device = open (get_device_path (display), O_RDWR | O_CLOEXEC);
if (priv->drm_device < 0)
return FALSE;
priv->use_foreign_display = FALSE;
return TRUE;
}
static void
gst_vaapi_display_drm_close_display (GstVaapiDisplay * display)
{
GstVaapiDisplayDRMPrivate *const priv =
GST_VAAPI_DISPLAY_DRM_PRIVATE (display);
if (priv->drm_device >= 0) {
if (!priv->use_foreign_display)
close (priv->drm_device);
priv->drm_device = -1;
}
g_clear_pointer (&priv->device_path, g_free);
g_clear_pointer (&priv->device_path_default, g_free);
}
static gboolean
gst_vaapi_display_drm_get_display_info (GstVaapiDisplay * display,
GstVaapiDisplayInfo * info)
{
GstVaapiDisplayDRMPrivate *const priv =
GST_VAAPI_DISPLAY_DRM_PRIVATE (display);
info->native_display = GINT_TO_POINTER (priv->drm_device);
info->display_name = priv->device_path;
if (!info->va_display) {
info->va_display = vaGetDisplayDRM (priv->drm_device);
if (!info->va_display)
return FALSE;
}
return TRUE;
}
static GstVaapiWindow *
gst_vaapi_display_drm_create_window (GstVaapiDisplay * display, GstVaapiID id,
guint width, guint height)
{
return id != GST_VAAPI_ID_INVALID ?
NULL : gst_vaapi_window_drm_new (display, width, height);
}
static void
gst_vaapi_display_drm_init (GstVaapiDisplayDRM * display)
{
GstVaapiDisplayDRMPrivate *const priv =
gst_vaapi_display_drm_get_instance_private (display);
display->priv = priv;
priv->drm_device = -1;
}
static void
gst_vaapi_display_drm_class_init (GstVaapiDisplayDRMClass * klass)
{
GstVaapiDisplayClass *const dpy_class = GST_VAAPI_DISPLAY_CLASS (klass);
dpy_class->display_type = GST_VAAPI_DISPLAY_TYPE_DRM;
dpy_class->bind_display = gst_vaapi_display_drm_bind_display;
dpy_class->open_display = gst_vaapi_display_drm_open_display;
dpy_class->close_display = gst_vaapi_display_drm_close_display;
dpy_class->get_display = gst_vaapi_display_drm_get_display_info;
dpy_class->create_window = gst_vaapi_display_drm_create_window;
}
/**
* gst_vaapi_display_drm_new:
* @device_path: the DRM device path
*
* Opens an DRM file descriptor using @device_path and returns a newly
* allocated #GstVaapiDisplay object. The DRM display will be cloed
* when the reference count of the object reaches zero.
*
* If @device_path is NULL, the DRM device path will be automatically
* determined as the first positive match in the list of available DRM
* devices.
*
* Return value: a newly allocated #GstVaapiDisplay object
*/
GstVaapiDisplay *
gst_vaapi_display_drm_new (const gchar * device_path)
{
GstVaapiDisplay *display;
guint types[3], i, num_types = 0;
gpointer device_paths[3];
g_mutex_lock (&g_drm_device_type_lock);
if (device_path) {
device_paths[num_types] = (gpointer) device_path;
types[num_types++] = 0;
} else if (g_drm_device_type) {
device_paths[num_types] = (gpointer) device_path;
types[num_types++] = g_drm_device_type;
} else {
const gchar *user_choice = g_getenv ("GST_VAAPI_DRM_DEVICE");
if (user_choice) {
device_paths[num_types] = (gpointer) user_choice;
types[num_types++] = 0;
} else {
device_paths[num_types] = (gpointer) device_path;
types[num_types++] = DRM_DEVICE_RENDERNODES;
device_paths[num_types] = (gpointer) device_path;
types[num_types++] = DRM_DEVICE_LEGACY;
}
}
for (i = 0; i < num_types; i++) {
g_drm_device_type = types[i];
display = g_object_new (GST_TYPE_VAAPI_DISPLAY_DRM, NULL);
display = gst_vaapi_display_config (display,
GST_VAAPI_DISPLAY_INIT_FROM_DISPLAY_NAME, device_paths[i]);
if (display || device_path)
break;
}
g_mutex_unlock (&g_drm_device_type_lock);
return display;
}
/**
* gst_vaapi_display_drm_new_with_device:
* @device: an open DRM device (file descriptor)
*
* Creates a #GstVaapiDisplay based on the open DRM @device. The
* caller still owns the device file descriptor and must call close()
* when all #GstVaapiDisplay references are released. Doing so too
* early can yield undefined behaviour.
*
* Return value: a newly allocated #GstVaapiDisplay object
*/
GstVaapiDisplay *
gst_vaapi_display_drm_new_with_device (gint device)
{
GstVaapiDisplay *display;
g_return_val_if_fail (device >= 0, NULL);
display = g_object_new (GST_TYPE_VAAPI_DISPLAY_DRM, NULL);
return gst_vaapi_display_config (display,
GST_VAAPI_DISPLAY_INIT_FROM_NATIVE_DISPLAY, GINT_TO_POINTER (device));
}
/**
* gst_vaapi_display_drm_new_with_va_display:
* @va_display: a VADisplay #va_display
* @fd: an open DRM device (file descriptor) #fd
*
* Creates a #GstVaapiDisplay based on the VADisplay @va_display and
* the open DRM device @fd.
* The caller still owns the device file descriptor and must call close()
* when all #GstVaapiDisplay references are released.
*
* Return value: a newly allocated #GstVaapiDisplay object
*/
GstVaapiDisplay *
gst_vaapi_display_drm_new_with_va_display (VADisplay va_display, gint fd)
{
GstVaapiDisplay *display;
GstVaapiDisplayInfo info = {
.va_display = va_display,
.native_display = GINT_TO_POINTER (fd),
};
g_return_val_if_fail (fd >= 0, NULL);
display = g_object_new (GST_TYPE_VAAPI_DISPLAY_DRM, NULL);
if (!gst_vaapi_display_config (display,
GST_VAAPI_DISPLAY_INIT_FROM_VA_DISPLAY, &info)) {
gst_object_unref (display);
return NULL;
}
return display;
}
/**
* gst_vaapi_display_drm_get_device:
* @display: a #GstVaapiDisplayDRM
*
* Returns the underlying DRM device file descriptor that was created
* by gst_vaapi_display_drm_new() or that was bound from
* gst_vaapi_display_drm_new_with_device().
*
* Return value: the DRM file descriptor attached to @display
*/
gint
gst_vaapi_display_drm_get_device (GstVaapiDisplayDRM * display)
{
g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_DRM (display), -1);
return GST_VAAPI_DISPLAY_DRM_DEVICE (display);
}
/**
* gst_vaapi_display_drm_get_device_path:
* @display: a #GstVaapiDisplayDRM
*
* Returns the underlying DRM device path name was created by
* gst_vaapi_display_drm_new() or that was bound from
* gst_vaapi_display_drm_new_with_device().
*
* Note: the #GstVaapiDisplayDRM object owns the resulting string, so
* it shall not be deallocated.
*
* Return value: the DRM device path name attached to @display
*/
const gchar *
gst_vaapi_display_drm_get_device_path (GstVaapiDisplayDRM * display)
{
g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_DRM (display), NULL);
return get_device_path (GST_VAAPI_DISPLAY_CAST (display));
}

View file

@ -0,0 +1,59 @@
/*
* gstvaapidisplay_drm.h - VA/DRM display abstraction
*
* Copyright (C) 2012-2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DISPLAY_DRM_H
#define GST_VAAPI_DISPLAY_DRM_H
#include <gst/vaapi/gstvaapidisplay.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_DISPLAY_DRM (gst_vaapi_display_drm_get_type ())
#define GST_VAAPI_DISPLAY_DRM(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_DISPLAY_DRM, GstVaapiDisplayDRM))
typedef struct _GstVaapiDisplayDRM GstVaapiDisplayDRM;
GstVaapiDisplay *
gst_vaapi_display_drm_new (const gchar * device_path);
GstVaapiDisplay *
gst_vaapi_display_drm_new_with_device (gint device);
GstVaapiDisplay *
gst_vaapi_display_drm_new_with_va_display (VADisplay va_display, gint fd);
gint
gst_vaapi_display_drm_get_device (GstVaapiDisplayDRM * display);
const gchar *
gst_vaapi_display_drm_get_device_path (GstVaapiDisplayDRM *
display);
GType
gst_vaapi_display_drm_get_type (void) G_GNUC_CONST;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiDisplayDRM, gst_object_unref)
G_END_DECLS
#endif /* GST_VAAPI_DISPLAY_DRM_H */

View file

@ -0,0 +1,90 @@
/*
* gstvaapidisplay_drm_priv.h - Internal VA/DRM interface
*
* Copyright (C) 2012-2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DISPLAY_DRM_PRIV_H
#define GST_VAAPI_DISPLAY_DRM_PRIV_H
#include <gst/vaapi/gstvaapidisplay_drm.h>
#include "gstvaapidisplay_priv.h"
G_BEGIN_DECLS
#define GST_VAAPI_IS_DISPLAY_DRM(display) \
(G_TYPE_CHECK_INSTANCE_TYPE ((display), GST_TYPE_VAAPI_DISPLAY_DRM))
#define GST_VAAPI_DISPLAY_DRM_CAST(display) \
((GstVaapiDisplayDRM *)(display))
#define GST_VAAPI_DISPLAY_DRM_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VAAPI_DISPLAY_DRM, GstVaapiDisplayDRMClass))
#define GST_VAAPI_DISPLAY_DRM_PRIVATE(display) \
(GST_VAAPI_DISPLAY_DRM_CAST(display)->priv)
typedef struct _GstVaapiDisplayDRMPrivate GstVaapiDisplayDRMPrivate;
typedef struct _GstVaapiDisplayDRMClass GstVaapiDisplayDRMClass;
/**
* GST_VAAPI_DISPLAY_DRM_DEVICE:
* @display: a #GstVaapiDisplay
*
* Macro that evaluates to the underlying DRM file descriptor of @display
*/
#undef GST_VAAPI_DISPLAY_DRM_DEVICE
#define GST_VAAPI_DISPLAY_DRM_DEVICE(display) \
GST_VAAPI_DISPLAY_DRM_PRIVATE(display)->drm_device
struct _GstVaapiDisplayDRMPrivate
{
gchar *device_path_default;
gchar *device_path;
gint drm_device;
guint use_foreign_display:1; // Foreign native_display?
};
/**
* GstVaapiDisplayDRM:
*
* VA/DRM display wrapper.
*/
struct _GstVaapiDisplayDRM
{
/*< private >*/
GstVaapiDisplay parent_instance;
GstVaapiDisplayDRMPrivate *priv;
};
/**
* GstVaapiDisplayDRMClass:
*
* VA/DRM display wrapper clas.
*/
struct _GstVaapiDisplayDRMClass
{
/*< private >*/
GstVaapiDisplayClass parent_class;
};
G_END_DECLS
#endif /* GST_VAAPI_DISPLAY_DRM_PRIV_H */

View file

@ -0,0 +1,471 @@
/*
* gstvaapidisplay_egl.c - VA/EGL display abstraction
*
* Copyright (C) 2014 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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 "sysdeps.h"
#include "gstvaapidisplay_egl.h"
#include "gstvaapidisplay_egl_priv.h"
#include "gstvaapiwindow.h"
#include "gstvaapiwindow_egl.h"
#include "gstvaapiwindow_priv.h"
#include "gstvaapitexture_egl.h"
#if USE_X11
#include "gstvaapidisplay_x11.h"
#endif
#if USE_WAYLAND
#include "gstvaapidisplay_wayland.h"
#endif
#define DEBUG_VAAPI_DISPLAY 1
#include "gstvaapidebug.h"
G_DEFINE_TYPE (GstVaapiDisplayEGL, gst_vaapi_display_egl,
GST_TYPE_VAAPI_DISPLAY);
/* ------------------------------------------------------------------------- */
/* --- EGL backend implementation --- */
/* ------------------------------------------------------------------------- */
typedef struct
{
gpointer display;
guint display_type;
guint gles_version;
gpointer gl_display;
} InitParams;
static gboolean
reset_context (GstVaapiDisplayEGL * display, EGLContext gl_context)
{
EglConfig *config;
EglContext *ctx;
egl_object_replace (&display->egl_context, NULL);
if (gl_context != EGL_NO_CONTEXT)
ctx = egl_context_new_wrapped (display->egl_display, gl_context);
else {
config = egl_config_new (display->egl_display, display->gles_version,
GST_VIDEO_FORMAT_RGB);
if (!config)
return FALSE;
ctx = egl_context_new (display->egl_display, config, NULL);
egl_object_unref (config);
}
if (!ctx)
return FALSE;
egl_object_replace (&display->egl_context, ctx);
egl_object_unref (ctx);
return TRUE;
}
static inline gboolean
ensure_context (GstVaapiDisplayEGL * display)
{
return display->egl_context || reset_context (display, EGL_NO_CONTEXT);
}
static inline gboolean
ensure_context_is_wrapped (GstVaapiDisplayEGL * display, EGLContext gl_context)
{
return (display->egl_context &&
display->egl_context->base.handle.p == gl_context) ||
reset_context (display, gl_context);
}
static gboolean
gst_vaapi_display_egl_bind_display (GstVaapiDisplay * base_display,
gpointer native_params)
{
GstVaapiDisplay *native_vaapi_display;
GstVaapiDisplayEGL *display = GST_VAAPI_DISPLAY_EGL (base_display);
EglDisplay *egl_display;
EGLDisplay *native_egl_display;
guint gl_platform = EGL_PLATFORM_UNKNOWN;
const InitParams *params = (InitParams *) native_params;
GstVaapiDisplayPrivate *const priv = GST_VAAPI_DISPLAY_GET_PRIVATE (display);
native_vaapi_display = params->display;
native_egl_display = params->gl_display;
if (!native_vaapi_display) {
#if USE_X11
if (params->display_type == GST_VAAPI_DISPLAY_TYPE_ANY
|| params->display_type == GST_VAAPI_DISPLAY_TYPE_X11
|| params->display_type == GST_VAAPI_DISPLAY_TYPE_EGL)
native_vaapi_display = gst_vaapi_display_x11_new (NULL);
#endif
#if USE_WAYLAND
if (!native_vaapi_display)
native_vaapi_display = gst_vaapi_display_wayland_new (NULL);
#endif
} else {
/* thus it could be assigned to parent */
gst_object_ref (native_vaapi_display);
}
if (!native_vaapi_display)
return FALSE;
gst_vaapi_display_replace (&display->display, native_vaapi_display);
priv->parent = native_vaapi_display;
switch (GST_VAAPI_DISPLAY_GET_CLASS_TYPE (display->display)) {
case GST_VAAPI_DISPLAY_TYPE_X11:
gl_platform = EGL_PLATFORM_X11;
break;
case GST_VAAPI_DISPLAY_TYPE_WAYLAND:
gl_platform = EGL_PLATFORM_WAYLAND;
break;
default:
break;
}
if (native_egl_display) {
egl_display = egl_display_new_wrapped (native_egl_display);
} else {
egl_display = egl_display_new (GST_VAAPI_DISPLAY_NATIVE (display->display),
gl_platform);
}
if (!egl_display)
return FALSE;
egl_object_replace (&display->egl_display, egl_display);
egl_object_unref (egl_display);
display->gles_version = params->gles_version;
return TRUE;
}
static void
gst_vaapi_display_egl_close_display (GstVaapiDisplay * base_display)
{
GstVaapiDisplayEGL *display = GST_VAAPI_DISPLAY_EGL (base_display);
gst_vaapi_display_replace (&display->display, NULL);
}
static void
gst_vaapi_display_egl_lock (GstVaapiDisplay * base_display)
{
GstVaapiDisplayEGL *display = GST_VAAPI_DISPLAY_EGL (base_display);
GstVaapiDisplayClass *const klass =
GST_VAAPI_DISPLAY_GET_CLASS (display->display);
if (klass->lock)
klass->lock (display->display);
}
static void
gst_vaapi_display_egl_unlock (GstVaapiDisplay * base_display)
{
GstVaapiDisplayEGL *display = GST_VAAPI_DISPLAY_EGL (base_display);
GstVaapiDisplayClass *const klass =
GST_VAAPI_DISPLAY_GET_CLASS (display->display);
if (klass->unlock)
klass->unlock (display->display);
}
static void
gst_vaapi_display_egl_sync (GstVaapiDisplay * base_display)
{
GstVaapiDisplayEGL *display = GST_VAAPI_DISPLAY_EGL (base_display);
GstVaapiDisplayClass *const klass =
GST_VAAPI_DISPLAY_GET_CLASS (display->display);
if (klass->sync)
klass->sync (display->display);
else if (klass->flush)
klass->flush (display->display);
}
static void
gst_vaapi_display_egl_flush (GstVaapiDisplay * base_display)
{
GstVaapiDisplayEGL *display = GST_VAAPI_DISPLAY_EGL (base_display);
GstVaapiDisplayClass *const klass =
GST_VAAPI_DISPLAY_GET_CLASS (display->display);
if (klass->flush)
klass->flush (display->display);
}
static gboolean
gst_vaapi_display_egl_get_display_info (GstVaapiDisplay * base_display,
GstVaapiDisplayInfo * info)
{
GstVaapiDisplayEGL *display = GST_VAAPI_DISPLAY_EGL (base_display);
GstVaapiDisplayClass *const klass =
GST_VAAPI_DISPLAY_GET_CLASS (display->display);
info->va_display = GST_VAAPI_DISPLAY_VADISPLAY (display->display);
if (klass->get_display && !klass->get_display (display->display, info))
return FALSE;
return TRUE;
}
static void
gst_vaapi_display_egl_get_size (GstVaapiDisplay * base_display,
guint * width_ptr, guint * height_ptr)
{
GstVaapiDisplayEGL *display = GST_VAAPI_DISPLAY_EGL (base_display);
GstVaapiDisplayClass *const klass =
GST_VAAPI_DISPLAY_GET_CLASS (display->display);
if (klass->get_size)
klass->get_size (display->display, width_ptr, height_ptr);
}
static void
gst_vaapi_display_egl_get_size_mm (GstVaapiDisplay * base_display,
guint * width_ptr, guint * height_ptr)
{
GstVaapiDisplayEGL *display = GST_VAAPI_DISPLAY_EGL (base_display);
GstVaapiDisplayClass *const klass =
GST_VAAPI_DISPLAY_GET_CLASS (display->display);
if (klass->get_size_mm)
klass->get_size_mm (display->display, width_ptr, height_ptr);
}
static guintptr
gst_vaapi_display_egl_get_visual_id (GstVaapiDisplay * base_display,
GstVaapiWindow * window)
{
GstVaapiDisplayEGL *display = GST_VAAPI_DISPLAY_EGL (base_display);
if (!ensure_context (display))
return 0;
return display->egl_context->config->visual_id;
}
static GstVaapiWindow *
gst_vaapi_display_egl_create_window (GstVaapiDisplay * display, GstVaapiID id,
guint width, guint height)
{
if (id != GST_VAAPI_ID_INVALID)
return NULL;
return gst_vaapi_window_egl_new (display, width, height);
}
static void
ensure_texture_map (GstVaapiDisplayEGL * display)
{
if (!display->texture_map)
display->texture_map = gst_vaapi_texture_map_new ();
}
static GstVaapiTexture *
gst_vaapi_display_egl_create_texture (GstVaapiDisplay * display, GstVaapiID id,
guint target, guint format, guint width, guint height)
{
GstVaapiDisplayEGL *dpy = GST_VAAPI_DISPLAY_EGL (display);
GstVaapiTexture *texture;
if (id == GST_VAAPI_ID_INVALID)
return gst_vaapi_texture_egl_new (display, target, format, width, height);
ensure_texture_map (dpy);
if (!(texture = gst_vaapi_texture_map_lookup (dpy->texture_map, id))) {
if ((texture =
gst_vaapi_texture_egl_new_wrapped (display, id, target, format,
width, height))) {
gst_vaapi_texture_map_add (dpy->texture_map, texture, id);
}
}
return texture;
}
static GstVaapiTextureMap *
gst_vaapi_display_egl_get_texture_map (GstVaapiDisplay * display)
{
return GST_VAAPI_DISPLAY_EGL (display)->texture_map;
}
static void
gst_vaapi_display_egl_finalize (GObject * object)
{
GstVaapiDisplayEGL *dpy = GST_VAAPI_DISPLAY_EGL (object);
if (dpy->texture_map)
gst_object_unref (dpy->texture_map);
/* HACK to avoid to call twice vaTerminate() since this and the
* proxied display share the same vaDisplay */
GST_VAAPI_DISPLAY_VADISPLAY (object) = NULL;
egl_object_replace (&dpy->egl_display, NULL);
egl_object_replace (&dpy->egl_context, NULL);
gst_vaapi_display_replace (&dpy->display, NULL);
G_OBJECT_CLASS (gst_vaapi_display_egl_parent_class)->finalize (object);
}
static void
gst_vaapi_display_egl_init (GstVaapiDisplayEGL * display)
{
}
static void
gst_vaapi_display_egl_class_init (GstVaapiDisplayEGLClass * klass)
{
GObjectClass *const object_class = G_OBJECT_CLASS (klass);
GstVaapiDisplayClass *const dpy_class = GST_VAAPI_DISPLAY_CLASS (klass);
object_class->finalize = gst_vaapi_display_egl_finalize;
dpy_class->display_type = GST_VAAPI_DISPLAY_TYPE_EGL;
dpy_class->bind_display = gst_vaapi_display_egl_bind_display;
dpy_class->close_display = gst_vaapi_display_egl_close_display;
dpy_class->lock = gst_vaapi_display_egl_lock;
dpy_class->unlock = gst_vaapi_display_egl_unlock;
dpy_class->sync = gst_vaapi_display_egl_sync;
dpy_class->flush = gst_vaapi_display_egl_flush;
dpy_class->get_display = gst_vaapi_display_egl_get_display_info;
dpy_class->get_size = gst_vaapi_display_egl_get_size;
dpy_class->get_size_mm = gst_vaapi_display_egl_get_size_mm;
dpy_class->get_visual_id = gst_vaapi_display_egl_get_visual_id;
dpy_class->create_window = gst_vaapi_display_egl_create_window;
dpy_class->create_texture = gst_vaapi_display_egl_create_texture;
dpy_class->get_texture_map = gst_vaapi_display_egl_get_texture_map;
}
/**
* gst_vaapi_display_egl_new:
* @display: a #GstVaapiDisplay, or %NULL to pick any one
* @gles_version: the OpenGL ES version API to use
*
* Creates a new #GstVaapiDisplay object suitable in EGL context. If
* the native @display is %NULL, then any type of display is picked,
* i.e. one that can be successfully opened. The @gles_version will
* further ensure the OpenGL ES API to use, or zero to indicate
* "desktop" OpenGL.
*
* Return value: a newly allocated #GstVaapiDisplay object
*/
GstVaapiDisplay *
gst_vaapi_display_egl_new (GstVaapiDisplay * display, guint gles_version)
{
GstVaapiDisplay *wrapper_display;
InitParams params = {
.gles_version = gles_version,
};
if (display) {
params.display = display;
params.display_type = GST_VAAPI_DISPLAY_VADISPLAY_TYPE (display);
}
wrapper_display = g_object_new (GST_TYPE_VAAPI_DISPLAY_EGL, NULL);
return gst_vaapi_display_config (wrapper_display,
GST_VAAPI_DISPLAY_INIT_FROM_NATIVE_DISPLAY, &params);
}
/**
* gst_vaapi_display_egl_new_with_native_display:
* @native_display: an EGLDisplay object
* @display_type: the display type of @native_display
* @gles_version: the OpenGL ES version API to use
*
* Creates a #GstVaapiDisplay based on the native display supplied in
* as @native_display. The caller still owns the display and must call
* native display close function when all #GstVaapiDisplay references
* are released. Doing so too early can yield undefined behaviour.
*
* The @gles_version will further ensure the OpenGL ES API to use, or
* zero to indicate "desktop" OpenGL.
*
* Return value: a newly allocated #GstVaapiDisplay object
*/
GstVaapiDisplay *
gst_vaapi_display_egl_new_with_native_display (gpointer native_display,
GstVaapiDisplayType display_type, guint gles_version)
{
GstVaapiDisplay *display;
InitParams params = {
.display_type = display_type,
.gl_display = native_display,
.gles_version = gles_version,
};
g_return_val_if_fail (native_display != NULL, NULL);
display = g_object_new (GST_TYPE_VAAPI_DISPLAY_EGL, NULL);
return gst_vaapi_display_config (display,
GST_VAAPI_DISPLAY_INIT_FROM_NATIVE_DISPLAY, &params);
}
EglContext *
gst_vaapi_display_egl_get_context (GstVaapiDisplayEGL * display)
{
return ensure_context (display) ? display->egl_context : NULL;
}
EGLDisplay
gst_vaapi_display_egl_get_gl_display (GstVaapiDisplayEGL * display)
{
g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_EGL (display), EGL_NO_DISPLAY);
return display->egl_display->base.handle.p;
}
EGLContext
gst_vaapi_display_egl_get_gl_context (GstVaapiDisplayEGL * display)
{
g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_EGL (display), EGL_NO_CONTEXT);
return ensure_context (display) ? display->egl_context->base.handle.p :
EGL_NO_CONTEXT;
}
gboolean
gst_vaapi_display_egl_set_gl_context (GstVaapiDisplayEGL * display,
EGLContext gl_context)
{
g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_EGL (display), FALSE);
return ensure_context_is_wrapped (display, gl_context);
}
gboolean
gst_vaapi_display_egl_set_current_display (GstVaapiDisplayEGL * display)
{
EglDisplay *egl_display;
g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_EGL (display), FALSE);
if (G_UNLIKELY (eglGetCurrentDisplay () == EGL_NO_DISPLAY))
return TRUE;
if (G_LIKELY (display->egl_display->base.handle.p == eglGetCurrentDisplay ()))
return TRUE;
egl_display = egl_display_new_wrapped (eglGetCurrentDisplay ());
if (!egl_display)
return FALSE;
egl_object_replace (&display->egl_display, egl_display);
egl_object_unref (egl_display);
if (!gst_vaapi_display_egl_set_gl_context (display, eglGetCurrentContext ()))
return FALSE;
return TRUE;
}

View file

@ -0,0 +1,64 @@
/*
* gstvaapidisplay_egl.h - VA/EGL display abstraction
*
* Copyright (C) 2014 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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) egl later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT EGL 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_VAAPI_DISPLAY_EGL_H
#define GST_VAAPI_DISPLAY_EGL_H
#include <EGL/egl.h>
#include <gst/vaapi/gstvaapidisplay.h>
G_BEGIN_DECLS
typedef struct _GstVaapiDisplayEGL GstVaapiDisplayEGL;
#define GST_TYPE_VAAPI_DISPLAY_EGL (gst_vaapi_display_egl_get_type ())
#define GST_VAAPI_DISPLAY_EGL(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_DISPLAY_EGL, GstVaapiDisplayEGL))
GstVaapiDisplay *
gst_vaapi_display_egl_new (GstVaapiDisplay * display, guint gles_version);
GstVaapiDisplay *
gst_vaapi_display_egl_new_with_native_display (gpointer native_display,
GstVaapiDisplayType display_type, guint gles_version);
EGLDisplay
gst_vaapi_display_egl_get_gl_display (GstVaapiDisplayEGL * display);
EGLContext
gst_vaapi_display_egl_get_gl_context (GstVaapiDisplayEGL * display);
gboolean
gst_vaapi_display_egl_set_gl_context (GstVaapiDisplayEGL * display,
EGLContext gl_context);
gboolean
gst_vaapi_display_egl_set_current_display (GstVaapiDisplayEGL * display);
GType
gst_vaapi_display_egl_get_type (void) G_GNUC_CONST;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiDisplayEGL, gst_object_unref)
G_END_DECLS
#endif /* GST_VAAPI_DISPLAY_EGL_H */

View file

@ -0,0 +1,105 @@
/*
* gstvaapidisplay_egl_priv.h - Internal VA/EGL interface
*
* Copyright (C) 2014 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DISPLAY_EGL_PRIV_H
#define GST_VAAPI_DISPLAY_EGL_PRIV_H
#include <gst/vaapi/gstvaapiwindow.h>
#include <gst/vaapi/gstvaapitexturemap.h>
#include "gstvaapidisplay_egl.h"
#include "gstvaapidisplay_priv.h"
#include "gstvaapiutils_egl.h"
G_BEGIN_DECLS
#define GST_VAAPI_IS_DISPLAY_EGL(display) \
(G_TYPE_CHECK_INSTANCE_TYPE ((display), GST_TYPE_VAAPI_DISPLAY_EGL))
#define GST_VAAPI_DISPLAY_EGL_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VAAPI_DISPLAY_EGL, GstVaapiDisplayEGLClass))
#define GST_VAAPI_DISPLAY_EGL_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VAAPI_DISPLAY_EGL, GstVaapiDisplayEGLClass))
#define GST_VAAPI_DISPLAY_EGL_CAST(obj) \
((GstVaapiDisplayEGL *)(obj))
/**
* GST_VAAPI_DISPLAY_EGL_DISPLAY:
* @display: a #GstVaapiDisplay
*
* Macro that evaluates to #EglDisplay wrapper for @display.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_DISPLAY_EGL_DISPLAY
#define GST_VAAPI_DISPLAY_EGL_DISPLAY(display) \
(GST_VAAPI_DISPLAY_EGL_CAST (display)->egl_display)
/**
* GST_VAAPI_DISPLAY_EGL_CONTEXT:
* @display: a #GstVaapiDisplay
*
* Macro that evaluates to #EglContext wrapper for @display.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_DISPLAY_EGL_CONTEXT
#define GST_VAAPI_DISPLAY_EGL_CONTEXT(display) \
gst_vaapi_display_egl_get_context (GST_VAAPI_DISPLAY_EGL (display))
typedef struct _GstVaapiDisplayEGLClass GstVaapiDisplayEGLClass;
/**
* GstVaapiDisplayEGL:
*
* VA/EGL display wrapper.
*/
struct _GstVaapiDisplayEGL
{
/*< private >*/
GstVaapiDisplay parent_instance;
gpointer loader;
GstVaapiDisplay *display;
EglDisplay *egl_display;
EglContext *egl_context;
guint gles_version;
GstVaapiTextureMap *texture_map;
};
/**
* GstVaapiDisplayEGLClass:
*
* VA/EGL display wrapper clas.
*/
struct _GstVaapiDisplayEGLClass
{
/*< private >*/
GstVaapiDisplayClass parent_class;
};
G_GNUC_INTERNAL
EglContext *
gst_vaapi_display_egl_get_context (GstVaapiDisplayEGL * display);
G_END_DECLS
#endif /* GST_VAAPI_DISPLAY_EGL_PRIV_H */

View file

@ -0,0 +1,159 @@
/*
* gstvaapidisplay_glx.c - VA/GLX display abstraction
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
* Copyright (C) 2011-2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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:gstvaapidisplay_glx
* @short_description: VA/GLX display abstraction
*/
#include "sysdeps.h"
#include "gstvaapicompat.h"
#include "gstvaapiutils.h"
#include "gstvaapiutils_glx.h"
#include "gstvaapidisplay_priv.h"
#include "gstvaapidisplay_x11_priv.h"
#include "gstvaapidisplay_glx.h"
#include "gstvaapidisplay_glx_priv.h"
#include "gstvaapiwindow_glx.h"
#include "gstvaapitexture_glx.h"
#define DEBUG_VAAPI_DISPLAY 1
#include "gstvaapidebug.h"
G_DEFINE_TYPE (GstVaapiDisplayGLX, gst_vaapi_display_glx,
GST_TYPE_VAAPI_DISPLAY_X11);
static GstVaapiWindow *
gst_vaapi_display_glx_create_window (GstVaapiDisplay * display, GstVaapiID id,
guint width, guint height)
{
return id != GST_VAAPI_ID_INVALID ?
gst_vaapi_window_glx_new_with_xid (display, id) :
gst_vaapi_window_glx_new (display, width, height);
}
static void
ensure_texture_map (GstVaapiDisplayGLX * display)
{
if (!display->texture_map)
display->texture_map = gst_vaapi_texture_map_new ();
}
static GstVaapiTexture *
gst_vaapi_display_glx_create_texture (GstVaapiDisplay * display, GstVaapiID id,
guint target, guint format, guint width, guint height)
{
GstVaapiTexture *texture;
GstVaapiDisplayGLX *dpy = GST_VAAPI_DISPLAY_GLX (display);
if (id == GST_VAAPI_ID_INVALID)
return gst_vaapi_texture_glx_new (display, target, format, width, height);
ensure_texture_map (dpy);
if (!(texture = gst_vaapi_texture_map_lookup (dpy->texture_map, id))) {
if ((texture =
gst_vaapi_texture_glx_new_wrapped (display, id, target, format))) {
gst_vaapi_texture_map_add (dpy->texture_map, texture, id);
}
}
return texture;
}
static GstVaapiTextureMap *
gst_vaapi_display_glx_get_texture_map (GstVaapiDisplay * display)
{
return GST_VAAPI_DISPLAY_GLX (display)->texture_map;
}
static void
gst_vaapi_display_glx_finalize (GObject * object)
{
GstVaapiDisplayGLX *dpy = GST_VAAPI_DISPLAY_GLX (object);
if (dpy->texture_map)
gst_object_unref (dpy->texture_map);
G_OBJECT_CLASS (gst_vaapi_display_glx_parent_class)->finalize (object);
}
static void
gst_vaapi_display_glx_init (GstVaapiDisplayGLX * display)
{
}
static void
gst_vaapi_display_glx_class_init (GstVaapiDisplayGLXClass * klass)
{
GObjectClass *const object_class = G_OBJECT_CLASS (klass);
GstVaapiDisplayClass *const dpy_class = GST_VAAPI_DISPLAY_CLASS (klass);
object_class->finalize = gst_vaapi_display_glx_finalize;
dpy_class->display_type = GST_VAAPI_DISPLAY_TYPE_GLX;
dpy_class->create_window = gst_vaapi_display_glx_create_window;
dpy_class->create_texture = gst_vaapi_display_glx_create_texture;
dpy_class->get_texture_map = gst_vaapi_display_glx_get_texture_map;
}
/**
* gst_vaapi_display_glx_new:
* @display_name: the X11 display name
*
* Opens an X11 #Display using @display_name and returns a newly
* allocated #GstVaapiDisplay object. The X11 display will be cloed
* when the reference count of the object reaches zero.
*
* Return value: a newly allocated #GstVaapiDisplay object
*/
GstVaapiDisplay *
gst_vaapi_display_glx_new (const gchar * display_name)
{
GstVaapiDisplay *display;
display = g_object_new (GST_TYPE_VAAPI_DISPLAY_GLX, NULL);
return gst_vaapi_display_config (display,
GST_VAAPI_DISPLAY_INIT_FROM_DISPLAY_NAME, (gpointer) display_name);
}
/**
* gst_vaapi_display_glx_new_with_display:
* @x11_display: an X11 #Display
*
* Creates a #GstVaapiDisplay based on the X11 @x11_display
* display. The caller still owns the display and must call
* XCloseDisplay() when all #GstVaapiDisplay references are
* released. Doing so too early can yield undefined behaviour.
*
* Return value: a newly allocated #GstVaapiDisplay object
*/
GstVaapiDisplay *
gst_vaapi_display_glx_new_with_display (Display * x11_display)
{
GstVaapiDisplay *display;
g_return_val_if_fail (x11_display != NULL, NULL);
display = g_object_new (GST_TYPE_VAAPI_DISPLAY_GLX, NULL);
return gst_vaapi_display_config (display,
GST_VAAPI_DISPLAY_INIT_FROM_NATIVE_DISPLAY, x11_display);
}

View file

@ -0,0 +1,51 @@
/*
* gstvaapidisplay_glx.h - VA/GLX display abstraction
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
* Copyright (C) 2012-2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DISPLAY_GLX_H
#define GST_VAAPI_DISPLAY_GLX_H
#include <gst/vaapi/gstvaapidisplay_x11.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_DISPLAY_GLX (gst_vaapi_display_glx_get_type ())
#define GST_VAAPI_DISPLAY_GLX(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_DISPLAY_GLX, GstVaapiDisplayGLX))
typedef struct _GstVaapiDisplayGLX GstVaapiDisplayGLX;
GstVaapiDisplay *
gst_vaapi_display_glx_new (const gchar * display_name);
GstVaapiDisplay *
gst_vaapi_display_glx_new_with_display (Display * x11_display);
GType
gst_vaapi_display_glx_get_type (void) G_GNUC_CONST;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiDisplayGLX, gst_object_unref)
G_END_DECLS
#endif /* GST_VAAPI_DISPLAY_GLX_H */

View file

@ -0,0 +1,72 @@
/*
* gstvaapidisplay_glx_priv.h - Internal VA/GLX interface
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
*
* 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_VAAPI_DISPLAY_GLX_PRIV_H
#define GST_VAAPI_DISPLAY_GLX_PRIV_H
#include <gst/vaapi/gstvaapiutils_glx.h>
#include <gst/vaapi/gstvaapidisplay_glx.h>
#include <gst/vaapi/gstvaapitexturemap.h>
#include "gstvaapidisplay_x11_priv.h"
G_BEGIN_DECLS
#define GST_VAAPI_IS_DISPLAY_GLX(display) \
(G_TYPE_CHECK_INSTANCE_TYPE ((display), GST_TYPE_VAAPI_DISPLAY_GLX))
#define GST_VAAPI_DISPLAY_GLX_CAST(display) \
((GstVaapiDisplayGLX *)(display))
#define GST_VAAPI_DISPLAY_GLX_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VAAPI_DISPLAY_GLX, GstVaapiDisplayGLXClass))
#define GST_VAAPI_DISPLAY_GLX_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VAAPI_DISPLAY_GLX, GstVaapiDisplayGLXClass))
typedef struct _GstVaapiDisplayGLXClass GstVaapiDisplayGLXClass;
/**
* GstVaapiDisplayGLX:
*
* VA/GLX display wrapper.
*/
struct _GstVaapiDisplayGLX
{
/*< private >*/
GstVaapiDisplayX11 parent_instance;
GstVaapiTextureMap *texture_map;
};
/**
* GstVaapiDisplayGLXClass:
*
* VA/GLX display wrapper clas.
*/
struct _GstVaapiDisplayGLXClass
{
/*< private >*/
GstVaapiDisplayX11Class parent_class;
};
G_END_DECLS
#endif /* GST_VAAPI_DISPLAY_GLX_PRIV_H */

View file

@ -0,0 +1,211 @@
/*
* gstvaapidisplay_priv.h - Base VA display (private definitions)
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
* Copyright (C) 2011-2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DISPLAY_PRIV_H
#define GST_VAAPI_DISPLAY_PRIV_H
#include <gst/vaapi/gstvaapidisplay.h>
#include <gst/vaapi/gstvaapiwindow.h>
#include <gst/vaapi/gstvaapitexture.h>
#include <gst/vaapi/gstvaapitexturemap.h>
#include "gstvaapiminiobject.h"
G_BEGIN_DECLS
#define GST_VAAPI_DISPLAY_CAST(display) \
((GstVaapiDisplay *)(display))
#define GST_VAAPI_DISPLAY_GET_PRIVATE(display) \
(GST_VAAPI_DISPLAY_CAST (display)->priv)
#define GST_VAAPI_DISPLAY_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VAAPI_DISPLAY, GstVaapiDisplayClass))
#define GST_VAAPI_IS_DISPLAY_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VAAPI_DISPLAY))
#define GST_VAAPI_DISPLAY_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VAAPI_DISPLAY, GstVaapiDisplayClass))
typedef struct _GstVaapiDisplayPrivate GstVaapiDisplayPrivate;
typedef struct _GstVaapiDisplayClass GstVaapiDisplayClass;
typedef enum _GstVaapiDisplayInitType GstVaapiDisplayInitType;
/**
* GST_VAAPI_DISPLAY_GET_CLASS_TYPE:
* @display: a #GstVaapiDisplay
*
* Returns the #display class type
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_DISPLAY_GET_CLASS_TYPE
#define GST_VAAPI_DISPLAY_GET_CLASS_TYPE(display) \
(GST_VAAPI_DISPLAY_GET_CLASS (display)->display_type)
/**
* GST_VAAPI_DISPLAY_NATIVE:
* @display: a #GstVaapiDisplay
*
* Macro that evaluates to the native display of @display.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_DISPLAY_NATIVE
#define GST_VAAPI_DISPLAY_NATIVE(display) \
(GST_VAAPI_DISPLAY_GET_PRIVATE (display)->native_display)
/**
* GST_VAAPI_DISPLAY_VADISPLAY:
* @display_: a #GstVaapiDisplay
*
* Macro that evaluates to the #VADisplay of @display_.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_DISPLAY_VADISPLAY
#define GST_VAAPI_DISPLAY_VADISPLAY(display_) \
(GST_VAAPI_DISPLAY_GET_PRIVATE (display_)->display)
/**
* GST_VAAPI_DISPLAY_VADISPLAY_TYPE:
* @display: a #GstVaapiDisplay
*
* Returns the underlying VADisplay @display type
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_DISPLAY_VADISPLAY_TYPE
#define GST_VAAPI_DISPLAY_VADISPLAY_TYPE(display) \
(GST_VAAPI_DISPLAY_GET_CLASS (display)->display_type)
/**
* GST_VAAPI_DISPLAY_HAS_VPP:
* @display: a @GstVaapiDisplay
*
* Returns whether the @display supports video processing (VA/VPP)
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_DISPLAY_HAS_VPP
#define GST_VAAPI_DISPLAY_HAS_VPP(display) \
gst_vaapi_display_has_video_processing (GST_VAAPI_DISPLAY_CAST (display))
struct _GstVaapiDisplayPrivate
{
GstVaapiDisplay *parent;
GRecMutex mutex;
gchar *display_name;
VADisplay display;
gpointer native_display;
guint width;
guint height;
guint width_mm;
guint height_mm;
guint par_n;
guint par_d;
GPtrArray *decoders; /* ref element in codecs */
GPtrArray *encoders; /* ref element in codecs */
GArray *codecs;
GArray *image_formats;
GArray *subpicture_formats;
GArray *properties;
gchar *vendor_string;
guint use_foreign_display:1;
guint has_vpp:1;
guint has_profiles:1;
guint got_scrres:1;
guint driver_quirks;
};
/**
* GstVaapiDisplay:
*
* Base class for VA displays.
*/
struct _GstVaapiDisplay
{
/*< private >*/
GstObject parent_instance;
GstVaapiDisplayPrivate *priv;
};
/**
* GstVaapiDisplayClass:
* @open_display: virtual function to open a display
* @close_display: virtual function to close a display
* @lock: (optional) virtual function to lock a display
* @unlock: (optional) virtual function to unlock a display
* @sync: (optional) virtual function to sync a display
* @flush: (optional) virtual function to flush pending requests of a display
* @get_display: virtual function to retrieve the #GstVaapiDisplayInfo
* @get_size: virtual function to retrieve the display dimensions, in pixels
* @get_size_mm: virtual function to retrieve the display dimensions, in millimeters
* @get_visual_id: (optional) virtual function to retrieve the window visual id
* @get_colormap: (optional) virtual function to retrieve the window colormap
* @create_window: (optional) virtual function to create a window
* @create_texture: (optional) virtual function to create a texture
* @get_texture_map: (optional) virtual function to get texture map
*
* Base class for VA displays.
*/
struct _GstVaapiDisplayClass
{
/*< private >*/
GstObjectClass parent_class;
/*< protected >*/
guint display_type;
/*< public >*/
void (*init) (GstVaapiDisplay * display);
gboolean (*bind_display) (GstVaapiDisplay * display, gpointer native_dpy);
gboolean (*open_display) (GstVaapiDisplay * display, const gchar * name);
void (*close_display) (GstVaapiDisplay * display);
void (*lock) (GstVaapiDisplay * display);
void (*unlock) (GstVaapiDisplay * display);
void (*sync) (GstVaapiDisplay * display);
void (*flush) (GstVaapiDisplay * display);
gboolean (*get_display) (GstVaapiDisplay * display, GstVaapiDisplayInfo * info);
void (*get_size) (GstVaapiDisplay * display, guint * pwidth, guint * pheight);
void (*get_size_mm) (GstVaapiDisplay * display, guint * pwidth, guint * pheight);
guintptr (*get_visual_id) (GstVaapiDisplay * display, GstVaapiWindow * window);
guintptr (*get_colormap) (GstVaapiDisplay * display, GstVaapiWindow * window);
GstVaapiWindow *(*create_window) (GstVaapiDisplay * display, GstVaapiID id, guint width, guint height);
GstVaapiTexture *(*create_texture) (GstVaapiDisplay * display, GstVaapiID id, guint target, guint format,
guint width, guint height);
GstVaapiTextureMap *(*get_texture_map) (GstVaapiDisplay * display);
};
/* Initialization types */
enum _GstVaapiDisplayInitType
{
GST_VAAPI_DISPLAY_INIT_FROM_DISPLAY_NAME = 1,
GST_VAAPI_DISPLAY_INIT_FROM_NATIVE_DISPLAY,
GST_VAAPI_DISPLAY_INIT_FROM_VA_DISPLAY
};
GstVaapiDisplay *
gst_vaapi_display_config (GstVaapiDisplay * display,
GstVaapiDisplayInitType init_type, gpointer init_value);
G_END_DECLS
#endif /* GST_VAAPI_DISPLAY_PRIV_H */

View file

@ -0,0 +1,457 @@
/*
* gstvaapidisplay_wayland.c - VA/Wayland display abstraction
*
* Copyright (C) 2012-2013 Intel Corporation
* Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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:gstvaapidisplay_wayland
* @short_description: VA/Wayland display abstraction
*/
#include "sysdeps.h"
#include "gstvaapidisplay_priv.h"
#include "gstvaapidisplay_wayland.h"
#include "gstvaapidisplay_wayland_priv.h"
#include "gstvaapiwindow_wayland.h"
#define DEBUG_VAAPI_DISPLAY 1
#include "gstvaapidebug.h"
G_DEFINE_TYPE_WITH_PRIVATE (GstVaapiDisplayWayland, gst_vaapi_display_wayland,
GST_TYPE_VAAPI_DISPLAY);
static inline const gchar *
get_default_display_name (void)
{
static const gchar *g_display_name;
if (!g_display_name)
g_display_name = getenv ("WAYLAND_DISPLAY");
return g_display_name;
}
/* Mangle display name with our prefix */
static gboolean
set_display_name (GstVaapiDisplay * display, const gchar * display_name)
{
GstVaapiDisplayWaylandPrivate *const priv =
GST_VAAPI_DISPLAY_WAYLAND_GET_PRIVATE (display);
g_free (priv->display_name);
if (!display_name) {
display_name = get_default_display_name ();
if (!display_name)
display_name = "";
}
priv->display_name = g_strdup (display_name);
return priv->display_name != NULL;
}
static void
output_handle_geometry (void *data, struct wl_output *output,
int x, int y, int physical_width, int physical_height,
int subpixel, const char *make, const char *model, int transform)
{
GstVaapiDisplayWaylandPrivate *const priv = data;
priv->phys_width = physical_width;
priv->phys_height = physical_height;
}
static void
output_handle_mode (void *data, struct wl_output *wl_output,
uint32_t flags, int width, int height, int refresh)
{
GstVaapiDisplayWaylandPrivate *const priv = data;
if (flags & WL_OUTPUT_MODE_CURRENT) {
priv->width = width;
priv->height = height;
}
}
static const struct wl_output_listener output_listener = {
output_handle_geometry,
output_handle_mode,
};
static void
handle_xdg_wm_base_ping (void *user_data, struct xdg_wm_base *xdg_wm_base,
uint32_t serial)
{
xdg_wm_base_pong (xdg_wm_base, serial);
}
static const struct xdg_wm_base_listener xdg_wm_base_listener = {
handle_xdg_wm_base_ping
};
static void
dmabuf_format (void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf,
uint32_t format)
{
}
static void
dmabuf_modifier (void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf,
uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo)
{
GstVaapiDisplayWaylandPrivate *const priv = data;
GstDRMFormat drm_format = {
.format = format,
.modifier = (guint64) modifier_hi << 32 | modifier_lo
};
if (gst_vaapi_video_format_from_drm_format (format) ==
GST_VIDEO_FORMAT_UNKNOWN) {
GST_LOG ("ignoring unknown format 0x%x with modifier 0x%" G_GINT64_MODIFIER
"x", format, drm_format.modifier);
return;
}
GST_LOG ("got format 0x%x (%s) with modifier 0x%" G_GINT64_MODIFIER "x",
format, gst_video_format_to_string (gst_vaapi_video_format_from_drm_format
(format)), drm_format.modifier);
g_array_append_val (priv->dmabuf_formats, drm_format);
}
static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = {
dmabuf_format,
dmabuf_modifier,
};
static void
registry_handle_global (void *data,
struct wl_registry *registry,
uint32_t id, const char *interface, uint32_t version)
{
GstVaapiDisplayWaylandPrivate *const priv = data;
if (strcmp (interface, "wl_compositor") == 0)
priv->compositor =
wl_registry_bind (registry, id, &wl_compositor_interface, 1);
else if (strcmp (interface, "wl_subcompositor") == 0)
priv->subcompositor =
wl_registry_bind (registry, id, &wl_subcompositor_interface, 1);
else if (strcmp (interface, "wl_shell") == 0)
priv->wl_shell = wl_registry_bind (registry, id, &wl_shell_interface, 1);
else if (strcmp (interface, "xdg_wm_base") == 0) {
priv->xdg_wm_base =
wl_registry_bind (registry, id, &xdg_wm_base_interface, 1);
xdg_wm_base_add_listener (priv->xdg_wm_base, &xdg_wm_base_listener, priv);
} else if (strcmp (interface, "wl_output") == 0) {
if (!priv->output) {
priv->output = wl_registry_bind (registry, id, &wl_output_interface, 1);
wl_output_add_listener (priv->output, &output_listener, priv);
}
} else if (strcmp (interface, "zwp_linux_dmabuf_v1") == 0) {
priv->dmabuf =
wl_registry_bind (registry, id, &zwp_linux_dmabuf_v1_interface, 3);
zwp_linux_dmabuf_v1_add_listener (priv->dmabuf, &dmabuf_listener, priv);
}
}
static const struct wl_registry_listener registry_listener = {
registry_handle_global,
NULL,
};
static gboolean
gst_vaapi_display_wayland_setup (GstVaapiDisplay * display)
{
GstVaapiDisplayWaylandPrivate *const priv =
GST_VAAPI_DISPLAY_WAYLAND_GET_PRIVATE (display);
wl_display_set_user_data (priv->wl_display, priv);
priv->registry = wl_display_get_registry (priv->wl_display);
wl_registry_add_listener (priv->registry, &registry_listener, priv);
priv->event_fd = wl_display_get_fd (priv->wl_display);
wl_display_roundtrip (priv->wl_display);
if (!priv->width || !priv->height) {
wl_display_roundtrip (priv->wl_display);
if (!priv->width || !priv->height) {
GST_ERROR ("failed to determine the display size");
return FALSE;
}
}
if (!priv->compositor) {
GST_ERROR ("failed to bind compositor interface");
return FALSE;
}
if (priv->xdg_wm_base)
return TRUE;
if (!priv->wl_shell) {
GST_ERROR ("failed to bind wl_shell interface");
return FALSE;
}
return TRUE;
}
static gboolean
gst_vaapi_display_wayland_bind_display (GstVaapiDisplay * display,
gpointer native_display)
{
GstVaapiDisplayWaylandPrivate *const priv =
GST_VAAPI_DISPLAY_WAYLAND_GET_PRIVATE (display);
priv->wl_display = native_display;
priv->use_foreign_display = TRUE;
/* XXX: how to get socket/display name? */
GST_WARNING ("wayland: get display name");
set_display_name (display, NULL);
return gst_vaapi_display_wayland_setup (display);
}
static gboolean
gst_vaapi_display_wayland_open_display (GstVaapiDisplay * display,
const gchar * name)
{
GstVaapiDisplayWaylandPrivate *const priv =
GST_VAAPI_DISPLAY_WAYLAND_GET_PRIVATE (display);
if (!set_display_name (display, name))
return FALSE;
priv->wl_display = wl_display_connect (name);
if (!priv->wl_display)
return FALSE;
priv->use_foreign_display = FALSE;
return gst_vaapi_display_wayland_setup (display);
}
static void
gst_vaapi_display_wayland_close_display (GstVaapiDisplay * display)
{
GstVaapiDisplayWaylandPrivate *const priv =
GST_VAAPI_DISPLAY_WAYLAND_GET_PRIVATE (display);
g_clear_pointer (&priv->output, wl_output_destroy);
g_clear_pointer (&priv->wl_shell, wl_shell_destroy);
g_clear_pointer (&priv->xdg_wm_base, xdg_wm_base_destroy);
g_clear_pointer (&priv->subcompositor, wl_subcompositor_destroy);
g_clear_pointer (&priv->compositor, wl_compositor_destroy);
g_clear_pointer (&priv->registry, wl_registry_destroy);
g_array_unref (priv->dmabuf_formats);
if (priv->wl_display) {
if (!priv->use_foreign_display)
wl_display_disconnect (priv->wl_display);
priv->wl_display = NULL;
}
g_clear_pointer (&priv->display_name, g_free);
}
static gboolean
gst_vaapi_display_wayland_get_display_info (GstVaapiDisplay * display,
GstVaapiDisplayInfo * info)
{
GstVaapiDisplayWaylandPrivate *const priv =
GST_VAAPI_DISPLAY_WAYLAND_GET_PRIVATE (display);
info->native_display = priv->wl_display;
info->display_name = priv->display_name;
if (!info->va_display) {
info->va_display = vaGetDisplayWl (priv->wl_display);
if (!info->va_display)
return FALSE;
}
return TRUE;
}
static void
gst_vaapi_display_wayland_get_size (GstVaapiDisplay * display,
guint * pwidth, guint * pheight)
{
GstVaapiDisplayWaylandPrivate *const priv =
GST_VAAPI_DISPLAY_WAYLAND_GET_PRIVATE (display);
if (!priv->output)
return;
if (pwidth)
*pwidth = priv->width;
if (pheight)
*pheight = priv->height;
}
static void
gst_vaapi_display_wayland_get_size_mm (GstVaapiDisplay * display,
guint * pwidth, guint * pheight)
{
GstVaapiDisplayWaylandPrivate *const priv =
GST_VAAPI_DISPLAY_WAYLAND_GET_PRIVATE (display);
if (!priv->output)
return;
if (pwidth)
*pwidth = priv->phys_width;
if (pheight)
*pheight = priv->phys_height;
}
static GstVaapiWindow *
gst_vaapi_display_wayland_create_window (GstVaapiDisplay * display,
GstVaapiID id, guint width, guint height)
{
if (id != GST_VAAPI_ID_INVALID)
return NULL;
return gst_vaapi_window_wayland_new (display, width, height);
}
static void
gst_vaapi_display_wayland_init (GstVaapiDisplayWayland * display)
{
GstVaapiDisplayWaylandPrivate *const priv =
gst_vaapi_display_wayland_get_instance_private (display);
display->priv = priv;
priv->event_fd = -1;
priv->dmabuf_formats = g_array_new (FALSE, FALSE, sizeof (GstDRMFormat));
}
static void
gst_vaapi_display_wayland_class_init (GstVaapiDisplayWaylandClass * klass)
{
GstVaapiDisplayClass *const dpy_class = GST_VAAPI_DISPLAY_CLASS (klass);
dpy_class->display_type = GST_VAAPI_DISPLAY_TYPE_WAYLAND;
dpy_class->bind_display = gst_vaapi_display_wayland_bind_display;
dpy_class->open_display = gst_vaapi_display_wayland_open_display;
dpy_class->close_display = gst_vaapi_display_wayland_close_display;
dpy_class->get_display = gst_vaapi_display_wayland_get_display_info;
dpy_class->get_size = gst_vaapi_display_wayland_get_size;
dpy_class->get_size_mm = gst_vaapi_display_wayland_get_size_mm;
dpy_class->create_window = gst_vaapi_display_wayland_create_window;
}
/**
* gst_vaapi_display_wayland_new:
* @display_name: the Wayland display name
*
* Opens an Wayland #wl_display using @display_name and returns a
* newly allocated #GstVaapiDisplay object. The Wayland display will
* be cloed when the reference count of the object reaches zero.
*
* Return value: a newly allocated #GstVaapiDisplay object
*/
GstVaapiDisplay *
gst_vaapi_display_wayland_new (const gchar * display_name)
{
GstVaapiDisplay *display;
display = g_object_new (GST_TYPE_VAAPI_DISPLAY_WAYLAND, NULL);
return gst_vaapi_display_config (display,
GST_VAAPI_DISPLAY_INIT_FROM_DISPLAY_NAME, (gpointer) display_name);
}
/**
* gst_vaapi_display_wayland_new_with_display:
* @wl_display: an Wayland #wl_display
*
* Creates a #GstVaapiDisplay based on the Wayland @wl_display
* display. The caller still owns the display and must call
* wl_display_disconnect() when all #GstVaapiDisplay references are
* released. Doing so too early can yield undefined behaviour.
*
* Return value: a newly allocated #GstVaapiDisplay object
*/
GstVaapiDisplay *
gst_vaapi_display_wayland_new_with_display (struct wl_display * wl_display)
{
GstVaapiDisplay *display;
g_return_val_if_fail (wl_display, NULL);
display = g_object_new (GST_TYPE_VAAPI_DISPLAY_WAYLAND, NULL);
return gst_vaapi_display_config (display,
GST_VAAPI_DISPLAY_INIT_FROM_NATIVE_DISPLAY, wl_display);
}
/**
* gst_vaapi_display_wayland_new_with_va_display:
* @va_display: a VADisplay #va_display
* @wl_display: an Wayland #wl_display
*
* Creates a #GstVaapiDisplay based on the VADisplay @va_display and
* the Wayland @wl_display display.
* The caller still owns the display and must call
* wl_display_disconnect() when all #GstVaapiDisplay references are
* released.
*
* Return value: a newly allocated #GstVaapiDisplay object
*/
GstVaapiDisplay *
gst_vaapi_display_wayland_new_with_va_display (VADisplay va_display,
struct wl_display * wl_display)
{
GstVaapiDisplay *display;
GstVaapiDisplayInfo info = {
.va_display = va_display,
.native_display = wl_display,
};
g_return_val_if_fail (wl_display, NULL);
display = g_object_new (GST_TYPE_VAAPI_DISPLAY_WAYLAND, NULL);
if (!gst_vaapi_display_config (display,
GST_VAAPI_DISPLAY_INIT_FROM_VA_DISPLAY, &info)) {
gst_object_unref (display);
return NULL;
}
return display;
}
/**
* gst_vaapi_display_wayland_get_display:
* @display: a #GstVaapiDisplayWayland
*
* Returns the underlying Wayland #wl_display that was created by
* gst_vaapi_display_wayland_new() or that was bound from
* gst_vaapi_display_wayland_new_with_display().
*
* Return value: the Wayland #wl_display attached to @display
*/
struct wl_display *
gst_vaapi_display_wayland_get_display (GstVaapiDisplayWayland * display)
{
g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_WAYLAND (display), NULL);
return GST_VAAPI_DISPLAY_WL_DISPLAY (display);
}

View file

@ -0,0 +1,58 @@
/*
* gstvaapidisplay_wayland.h - VA/Wayland display abstraction
*
* Copyright (C) 2012-2013 Intel Corporation
* Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DISPLAY_WAYLAND_H
#define GST_VAAPI_DISPLAY_WAYLAND_H
#include <va/va_wayland.h>
#include <gst/vaapi/gstvaapidisplay.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_DISPLAY_WAYLAND (gst_vaapi_display_wayland_get_type ())
#define GST_VAAPI_DISPLAY_WAYLAND(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_DISPLAY_WAYLAND, GstVaapiDisplayWayland))
typedef struct _GstVaapiDisplayWayland GstVaapiDisplayWayland;
GstVaapiDisplay *
gst_vaapi_display_wayland_new (const gchar * display_name);
GstVaapiDisplay *
gst_vaapi_display_wayland_new_with_display (struct wl_display * wl_display);
GstVaapiDisplay *
gst_vaapi_display_wayland_new_with_va_display (VADisplay va_display,
struct wl_display * wl_display);
struct wl_display *
gst_vaapi_display_wayland_get_display (GstVaapiDisplayWayland * display);
GType
gst_vaapi_display_wayland_get_type (void) G_GNUC_CONST;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiDisplayWayland, gst_object_unref)
G_END_DECLS
#endif /* GST_VAAPI_DISPLAY_WAYLAND_H */

View file

@ -0,0 +1,114 @@
/*
* gstvaapidisplay_wayland_priv.h - Internal VA/Wayland interface
*
* Copyright (C) 2012-2013 Intel Corporation
* Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DISPLAY_WAYLAND_PRIV_H
#define GST_VAAPI_DISPLAY_WAYLAND_PRIV_H
#include "xdg-shell-client-protocol.h"
#include "linux-dmabuf-unstable-v1-client-protocol.h"
#include <gst/vaapi/gstvaapidisplay_wayland.h>
#include "gstvaapidisplay_priv.h"
G_BEGIN_DECLS
#define GST_VAAPI_IS_DISPLAY_WAYLAND(display) \
(G_TYPE_CHECK_INSTANCE_TYPE ((display), GST_TYPE_VAAPI_DISPLAY_WAYLAND))
#define GST_VAAPI_DISPLAY_WAYLAND_CAST(display) \
((GstVaapiDisplayWayland *)(display))
#define GST_VAAPI_DISPLAY_WAYLAND_GET_PRIVATE(display) \
(GST_VAAPI_DISPLAY_WAYLAND_CAST(display)->priv)
#define GST_VAAPI_DISPLAY_WAYLAND_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VAAPI_DISPLAY_WAYLAND, GstVaapiDisplayWaylandClass))
typedef struct _GstVaapiDisplayWaylandPrivate GstVaapiDisplayWaylandPrivate;
typedef struct _GstVaapiDisplayWaylandClass GstVaapiDisplayWaylandClass;
/**
* GST_VAAPI_DISPLAY_WL_DISPLAY:
* @display: a #GstVaapiDisplay
*
* Macro that evaluates to the underlying Wayland #wl_display object
* of @display
*/
#undef GST_VAAPI_DISPLAY_WL_DISPLAY
#define GST_VAAPI_DISPLAY_WL_DISPLAY(display) \
GST_VAAPI_DISPLAY_WAYLAND_GET_PRIVATE(display)->wl_display
typedef struct _GstDRMFormat GstDRMFormat;
struct _GstDRMFormat {
guint format;
guint64 modifier;
};
struct _GstVaapiDisplayWaylandPrivate
{
gchar *display_name;
struct wl_display *wl_display;
struct wl_compositor *compositor;
struct wl_shell *wl_shell;
struct xdg_wm_base *xdg_wm_base;
struct wl_subcompositor *subcompositor;
struct wl_output *output;
struct zwp_linux_dmabuf_v1 *dmabuf;
struct wl_registry *registry;
GArray *dmabuf_formats;
guint width;
guint height;
guint phys_width;
guint phys_height;
gint event_fd;
guint use_foreign_display:1;
};
/**
* GstVaapiDisplayWayland:
*
* VA/Wayland display wrapper.
*/
struct _GstVaapiDisplayWayland
{
/*< private >*/
GstVaapiDisplay parent_instance;
GstVaapiDisplayWaylandPrivate *priv;
};
/**
* GstVaapiDisplayWaylandClass:
*
* VA/Wayland display wrapper clas.
*/
struct _GstVaapiDisplayWaylandClass
{
/*< private >*/
GstVaapiDisplayClass parent_class;
};
G_END_DECLS
#endif /* GST_VAAPI_DISPLAY_WAYLAND_PRIV_H */

View file

@ -0,0 +1,545 @@
/*
* gstvaapidisplay_x11.c - VA/X11 display abstraction
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
* Copyright (C) 2011-2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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:gstvaapidisplay_x11
* @short_description: VA/X11 display abstraction
*/
#include "sysdeps.h"
#include "gstvaapiutils.h"
#include "gstvaapidisplay_priv.h"
#include "gstvaapidisplay_x11.h"
#include "gstvaapidisplay_x11_priv.h"
#include "gstvaapiwindow_x11.h"
#if HAVE_XRANDR
# include <X11/extensions/Xrandr.h>
#endif
#define DEBUG_VAAPI_DISPLAY 1
#include "gstvaapidebug.h"
G_DEFINE_TYPE_WITH_PRIVATE (GstVaapiDisplayX11, gst_vaapi_display_x11,
GST_TYPE_VAAPI_DISPLAY);
static inline const gchar *
get_default_display_name (void)
{
static const gchar *g_display_name;
if (!g_display_name)
g_display_name = getenv ("DISPLAY");
return g_display_name;
}
/* Reconstruct a display name without our prefix */
static const gchar *
get_display_name (GstVaapiDisplayX11 * display)
{
GstVaapiDisplayX11Private *const priv = display->priv;
const gchar *display_name = priv->display_name;
if (!display_name || *display_name == '\0')
return NULL;
return display_name;
}
/* Mangle display name with our prefix */
static gboolean
set_display_name (GstVaapiDisplayX11 * display, const gchar * display_name)
{
GstVaapiDisplayX11Private *const priv = display->priv;
g_free (priv->display_name);
if (!display_name) {
display_name = get_default_display_name ();
if (!display_name)
display_name = "";
}
priv->display_name = g_strdup (display_name);
return priv->display_name != NULL;
}
/* Set synchronous behavious on the underlying X11 display */
static void
set_synchronous (GstVaapiDisplayX11 * display, gboolean synchronous)
{
GstVaapiDisplayX11Private *const priv = display->priv;
if (priv->synchronous != synchronous) {
priv->synchronous = synchronous;
if (priv->x11_display) {
GST_VAAPI_DISPLAY_LOCK (display);
XSynchronize (priv->x11_display, synchronous);
GST_VAAPI_DISPLAY_UNLOCK (display);
}
}
}
/* Check for display server extensions */
static void
check_extensions (GstVaapiDisplayX11 * display)
{
GstVaapiDisplayX11Private *const priv = display->priv;
int evt_base, err_base;
#if HAVE_XRANDR
priv->use_xrandr = XRRQueryExtension (priv->x11_display,
&evt_base, &err_base);
#endif
}
static gboolean
gst_vaapi_display_x11_bind_display (GstVaapiDisplay * base_display,
gpointer native_display)
{
GstVaapiDisplayX11 *const display = GST_VAAPI_DISPLAY_X11_CAST (base_display);
GstVaapiDisplayX11Private *const priv = display->priv;
priv->x11_display = native_display;
priv->x11_screen = DefaultScreen (native_display);
priv->use_foreign_display = TRUE;
check_extensions (display);
if (!set_display_name (display, XDisplayString (priv->x11_display)))
return FALSE;
return TRUE;
}
static gboolean
gst_vaapi_display_x11_open_display (GstVaapiDisplay * base_display,
const gchar * name)
{
GstVaapiDisplayX11 *const display = GST_VAAPI_DISPLAY_X11_CAST (base_display);
GstVaapiDisplayX11Private *const priv = display->priv;
if (!set_display_name (display, name))
return FALSE;
priv->x11_display = XOpenDisplay (get_display_name (display));
if (!priv->x11_display)
return FALSE;
priv->use_foreign_display = FALSE;
priv->x11_screen = DefaultScreen (priv->x11_display);
check_extensions (display);
return TRUE;
}
static void
gst_vaapi_display_x11_close_display (GstVaapiDisplay * display)
{
GstVaapiDisplayX11Private *const priv =
GST_VAAPI_DISPLAY_X11_PRIVATE (display);
g_clear_pointer (&priv->pixmap_formats, g_array_unref);
if (priv->x11_display) {
if (!priv->use_foreign_display)
XCloseDisplay (priv->x11_display);
priv->x11_display = NULL;
}
g_clear_pointer (&priv->display_name, g_free);
}
static void
gst_vaapi_display_x11_sync (GstVaapiDisplay * display)
{
GstVaapiDisplayX11Private *const priv =
GST_VAAPI_DISPLAY_X11_PRIVATE (display);
if (priv->x11_display) {
GST_VAAPI_DISPLAY_LOCK (display);
XSync (priv->x11_display, False);
GST_VAAPI_DISPLAY_UNLOCK (display);
}
}
static void
gst_vaapi_display_x11_flush (GstVaapiDisplay * display)
{
GstVaapiDisplayX11Private *const priv =
GST_VAAPI_DISPLAY_X11_PRIVATE (display);
if (priv->x11_display) {
GST_VAAPI_DISPLAY_LOCK (display);
XFlush (priv->x11_display);
GST_VAAPI_DISPLAY_UNLOCK (display);
}
}
static gboolean
gst_vaapi_display_x11_get_display_info (GstVaapiDisplay * display,
GstVaapiDisplayInfo * info)
{
GstVaapiDisplayX11Private *const priv =
GST_VAAPI_DISPLAY_X11_PRIVATE (display);
info->native_display = priv->x11_display;
info->display_name = priv->display_name;
if (!info->va_display) {
info->va_display = vaGetDisplay (priv->x11_display);
if (!info->va_display)
return FALSE;
}
return TRUE;
}
static void
gst_vaapi_display_x11_get_size (GstVaapiDisplay * display,
guint * pwidth, guint * pheight)
{
GstVaapiDisplayX11Private *const priv =
GST_VAAPI_DISPLAY_X11_PRIVATE (display);
if (!priv->x11_display)
return;
if (pwidth)
*pwidth = DisplayWidth (priv->x11_display, priv->x11_screen);
if (pheight)
*pheight = DisplayHeight (priv->x11_display, priv->x11_screen);
}
static void
gst_vaapi_display_x11_get_size_mm (GstVaapiDisplay * display,
guint * pwidth, guint * pheight)
{
GstVaapiDisplayX11Private *const priv =
GST_VAAPI_DISPLAY_X11_PRIVATE (display);
guint width_mm, height_mm;
if (!priv->x11_display)
return;
width_mm = DisplayWidthMM (priv->x11_display, priv->x11_screen);
height_mm = DisplayHeightMM (priv->x11_display, priv->x11_screen);
#if HAVE_XRANDR
/* XXX: fix up physical size if the display is rotated */
if (priv->use_xrandr) {
XRRScreenConfiguration *xrr_config = NULL;
XRRScreenSize *xrr_sizes;
Window win;
int num_xrr_sizes, size_id, screen;
Rotation rotation;
do {
win = DefaultRootWindow (priv->x11_display);
screen = XRRRootToScreen (priv->x11_display, win);
xrr_config = XRRGetScreenInfo (priv->x11_display, win);
if (!xrr_config)
break;
size_id = XRRConfigCurrentConfiguration (xrr_config, &rotation);
if (rotation == RR_Rotate_0 || rotation == RR_Rotate_180)
break;
xrr_sizes = XRRSizes (priv->x11_display, screen, &num_xrr_sizes);
if (!xrr_sizes || size_id >= num_xrr_sizes)
break;
width_mm = xrr_sizes[size_id].mheight;
height_mm = xrr_sizes[size_id].mwidth;
} while (0);
if (xrr_config)
XRRFreeScreenConfigInfo (xrr_config);
}
#endif
if (pwidth)
*pwidth = width_mm;
if (pheight)
*pheight = height_mm;
}
static GstVaapiWindow *
gst_vaapi_display_x11_create_window (GstVaapiDisplay * display, GstVaapiID id,
guint width, guint height)
{
return id != GST_VAAPI_ID_INVALID ?
gst_vaapi_window_x11_new_with_xid (display, id) :
gst_vaapi_window_x11_new (display, width, height);
}
void
gst_vaapi_display_x11_class_init (GstVaapiDisplayX11Class * klass)
{
GstVaapiDisplayClass *const dpy_class = GST_VAAPI_DISPLAY_CLASS (klass);
dpy_class->display_type = GST_VAAPI_DISPLAY_TYPE_X11;
dpy_class->bind_display = gst_vaapi_display_x11_bind_display;
dpy_class->open_display = gst_vaapi_display_x11_open_display;
dpy_class->close_display = gst_vaapi_display_x11_close_display;
dpy_class->sync = gst_vaapi_display_x11_sync;
dpy_class->flush = gst_vaapi_display_x11_flush;
dpy_class->get_display = gst_vaapi_display_x11_get_display_info;
dpy_class->get_size = gst_vaapi_display_x11_get_size;
dpy_class->get_size_mm = gst_vaapi_display_x11_get_size_mm;
dpy_class->create_window = gst_vaapi_display_x11_create_window;
}
static void
gst_vaapi_display_x11_init (GstVaapiDisplayX11 * display)
{
GstVaapiDisplayX11Private *const priv =
gst_vaapi_display_x11_get_instance_private (display);
display->priv = priv;
}
/**
* gst_vaapi_display_x11_new:
* @display_name: the X11 display name
*
* Opens an X11 #Display using @display_name and returns a newly
* allocated #GstVaapiDisplay object. The X11 display will be cloed
* when the reference count of the object reaches zero.
*
* Return value: a newly allocated #GstVaapiDisplay object
*/
GstVaapiDisplay *
gst_vaapi_display_x11_new (const gchar * display_name)
{
GstVaapiDisplay *display;
display = g_object_new (GST_TYPE_VAAPI_DISPLAY_X11, NULL);
return gst_vaapi_display_config (display,
GST_VAAPI_DISPLAY_INIT_FROM_DISPLAY_NAME, (gpointer) display_name);
}
/**
* gst_vaapi_display_x11_new_with_display:
* @x11_display: an X11 #Display
*
* Creates a #GstVaapiDisplay based on the X11 @x11_display
* display. The caller still owns the display and must call
* XCloseDisplay() when all #GstVaapiDisplay references are
* released. Doing so too early can yield undefined behaviour.
*
* Return value: a newly allocated #GstVaapiDisplay object
*/
GstVaapiDisplay *
gst_vaapi_display_x11_new_with_display (Display * x11_display)
{
GstVaapiDisplay *display;
g_return_val_if_fail (x11_display, NULL);
display = g_object_new (GST_TYPE_VAAPI_DISPLAY_X11, NULL);
return gst_vaapi_display_config (display,
GST_VAAPI_DISPLAY_INIT_FROM_NATIVE_DISPLAY, x11_display);
}
GstVaapiDisplay *
gst_vaapi_display_x11_new_with_va_display (VADisplay va_display,
Display * x11_display)
{
GstVaapiDisplay *display;
GstVaapiDisplayInfo info = {
.va_display = va_display,
.native_display = x11_display,
};
g_return_val_if_fail (x11_display, NULL);
display = g_object_new (GST_TYPE_VAAPI_DISPLAY_X11, NULL);
return gst_vaapi_display_config (display,
GST_VAAPI_DISPLAY_INIT_FROM_VA_DISPLAY, &info);
}
/**
* gst_vaapi_display_x11_get_display:
* @display: a #GstVaapiDisplayX11
*
* Returns the underlying X11 #Display that was created by
* gst_vaapi_display_x11_new() or that was bound from
* gst_vaapi_display_x11_new_with_display().
*
* Return value: the X11 #Display attached to @display
*/
Display *
gst_vaapi_display_x11_get_display (GstVaapiDisplayX11 * display)
{
g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_X11 (display), NULL);
return GST_VAAPI_DISPLAY_XDISPLAY (display);
}
/**
* gst_vaapi_display_x11_get_screen:
* @display: a #GstVaapiDisplayX11
*
* Returns the default X11 screen that was created by
* gst_vaapi_display_x11_new() or that was bound from
* gst_vaapi_display_x11_new_with_display().
*
* Return value: the X11 #Display attached to @display
*/
int
gst_vaapi_display_x11_get_screen (GstVaapiDisplayX11 * display)
{
g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_X11 (display), -1);
return GST_VAAPI_DISPLAY_XSCREEN (display);
}
/**
* gst_vaapi_display_x11_set_synchronous:
* @display: a #GstVaapiDisplayX11
* @synchronous: boolean value that indicates whether to enable or
* disable synchronization
*
* If @synchronous is %TRUE, gst_vaapi_display_x11_set_synchronous()
* turns on synchronous behaviour on the underlying X11
* display. Otherwise, synchronous behaviour is disabled if
* @synchronous is %FALSE.
*/
void
gst_vaapi_display_x11_set_synchronous (GstVaapiDisplayX11 * display,
gboolean synchronous)
{
g_return_if_fail (GST_VAAPI_IS_DISPLAY_X11 (display));
set_synchronous (display, synchronous);
}
typedef struct _GstVaapiPixmapFormatX11 GstVaapiPixmapFormatX11;
struct _GstVaapiPixmapFormatX11
{
GstVideoFormat format;
gint depth;
gint bpp;
};
static GstVideoFormat
pix_fmt_to_video_format (gint depth, gint bpp)
{
GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
switch (bpp) {
case 16:
if (depth == 15)
format = GST_VIDEO_FORMAT_RGB15;
else if (depth == 16)
format = GST_VIDEO_FORMAT_RGB16;
break;
case 24:
if (depth == 24)
format = GST_VIDEO_FORMAT_RGB;
break;
case 32:
if (depth == 24 || depth == 32)
format = GST_VIDEO_FORMAT_xRGB;
break;
}
return format;
}
static gboolean
ensure_pix_fmts (GstVaapiDisplayX11 * display)
{
GstVaapiDisplayX11Private *const priv =
GST_VAAPI_DISPLAY_X11_PRIVATE (display);
XPixmapFormatValues *pix_fmts;
int i, n, num_pix_fmts;
if (priv->pixmap_formats)
return TRUE;
GST_VAAPI_DISPLAY_LOCK (display);
pix_fmts = XListPixmapFormats (GST_VAAPI_DISPLAY_XDISPLAY (display),
&num_pix_fmts);
GST_VAAPI_DISPLAY_UNLOCK (display);
if (!pix_fmts)
return FALSE;
priv->pixmap_formats = g_array_sized_new (FALSE, FALSE,
sizeof (GstVaapiPixmapFormatX11), num_pix_fmts);
if (!priv->pixmap_formats) {
XFree (pix_fmts);
return FALSE;
}
for (i = 0, n = 0; i < num_pix_fmts; i++) {
GstVaapiPixmapFormatX11 *const pix_fmt =
&g_array_index (priv->pixmap_formats, GstVaapiPixmapFormatX11, n);
pix_fmt->depth = pix_fmts[i].depth;
pix_fmt->bpp = pix_fmts[i].bits_per_pixel;
pix_fmt->format = pix_fmt_to_video_format (pix_fmt->depth, pix_fmt->bpp);
if (pix_fmt->format != GST_VIDEO_FORMAT_UNKNOWN)
n++;
}
priv->pixmap_formats->len = n;
XFree (pix_fmts);
return TRUE;
}
/* Determine the GstVideoFormat based on a supported Pixmap depth */
GstVideoFormat
gst_vaapi_display_x11_get_pixmap_format (GstVaapiDisplayX11 * display,
guint depth)
{
if (ensure_pix_fmts (display)) {
GstVaapiDisplayX11Private *const priv =
GST_VAAPI_DISPLAY_X11_PRIVATE (display);
guint i;
for (i = 0; i < priv->pixmap_formats->len; i++) {
GstVaapiPixmapFormatX11 *const pix_fmt =
&g_array_index (priv->pixmap_formats, GstVaapiPixmapFormatX11, i);
if (pix_fmt->depth == depth)
return pix_fmt->format;
}
}
return GST_VIDEO_FORMAT_UNKNOWN;
}
/* Determine the Pixmap depth based on a GstVideoFormat */
guint
gst_vaapi_display_x11_get_pixmap_depth (GstVaapiDisplayX11 * display,
GstVideoFormat format)
{
if (ensure_pix_fmts (display)) {
GstVaapiDisplayX11Private *const priv =
GST_VAAPI_DISPLAY_X11_PRIVATE (display);
guint i;
for (i = 0; i < priv->pixmap_formats->len; i++) {
GstVaapiPixmapFormatX11 *const pix_fmt =
&g_array_index (priv->pixmap_formats, GstVaapiPixmapFormatX11, i);
if (pix_fmt->format == format)
return pix_fmt->depth;
}
}
return 0;
}

View file

@ -0,0 +1,65 @@
/*
* gstvaapidisplay_x11.h - VA/X11 display abstraction
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
* Copyright (C) 2012-2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DISPLAY_X11_H
#define GST_VAAPI_DISPLAY_X11_H
#include <va/va_x11.h>
#include <gst/vaapi/gstvaapidisplay.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_DISPLAY_X11 (gst_vaapi_display_x11_get_type ())
#define GST_VAAPI_DISPLAY_X11(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_DISPLAY_X11, GstVaapiDisplayX11))
typedef struct _GstVaapiDisplayX11 GstVaapiDisplayX11;
GstVaapiDisplay *
gst_vaapi_display_x11_new (const gchar * display_name);
GstVaapiDisplay *
gst_vaapi_display_x11_new_with_display (Display * x11_display);
GstVaapiDisplay *
gst_vaapi_display_x11_new_with_va_display (VADisplay va_display, Display * x11_display);
Display *
gst_vaapi_display_x11_get_display (GstVaapiDisplayX11 * display);
int
gst_vaapi_display_x11_get_screen (GstVaapiDisplayX11 * display);
void
gst_vaapi_display_x11_set_synchronous (GstVaapiDisplayX11 * display,
gboolean synchronous);
GType
gst_vaapi_display_x11_get_type (void) G_GNUC_CONST;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiDisplayX11, gst_object_unref)
G_END_DECLS
#endif /* GST_VAAPI_DISPLAY_X11_H */

View file

@ -0,0 +1,116 @@
/*
* gstvaapidisplay_x11_priv.h - Internal VA/X11 interface
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
* Copyright (C) 2012-2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_DISPLAY_X11_PRIV_H
#define GST_VAAPI_DISPLAY_X11_PRIV_H
#include <gst/vaapi/gstvaapiutils_x11.h>
#include <gst/vaapi/gstvaapidisplay_x11.h>
#include "gstvaapidisplay_priv.h"
G_BEGIN_DECLS
#define GST_VAAPI_IS_DISPLAY_X11(display) \
(G_TYPE_CHECK_INSTANCE_TYPE ((display), GST_TYPE_VAAPI_DISPLAY_X11))
#define GST_VAAPI_DISPLAY_X11_CAST(display) \
((GstVaapiDisplayX11 *)(display))
#define GST_VAAPI_DISPLAY_X11_PRIVATE(display) \
(GST_VAAPI_DISPLAY_X11_CAST (display)->priv)
#define GST_VAAPI_DISPLAY_X11_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VAAPI_DISPLAY_X11, GstVaapiDisplayX11Class))
typedef struct _GstVaapiDisplayX11Private GstVaapiDisplayX11Private;
typedef struct _GstVaapiDisplayX11Class GstVaapiDisplayX11Class;
/**
* GST_VAAPI_DISPLAY_XDISPLAY:
* @display: a #GstVaapiDisplay
*
* Macro that evaluates to the underlying X11 #Display of @display
*/
#undef GST_VAAPI_DISPLAY_XDISPLAY
#define GST_VAAPI_DISPLAY_XDISPLAY(display) \
GST_VAAPI_DISPLAY_X11_PRIVATE(display)->x11_display
/**
* GST_VAAPI_DISPLAY_XSCREEN:
* @display: a #GstVaapiDisplay
*
* Macro that evaluates to the underlying X11 screen of @display
*/
#undef GST_VAAPI_DISPLAY_XSCREEN
#define GST_VAAPI_DISPLAY_XSCREEN(display) \
GST_VAAPI_DISPLAY_X11_PRIVATE(display)->x11_screen
struct _GstVaapiDisplayX11Private
{
gchar *display_name;
Display *x11_display;
int x11_screen;
GArray *pixmap_formats;
guint use_foreign_display:1; // Foreign native_display?
guint use_xrandr:1;
guint synchronous:1;
};
/**
* GstVaapiDisplayX11:
*
* VA/X11 display wrapper.
*/
struct _GstVaapiDisplayX11
{
/*< private >*/
GstVaapiDisplay parent_instance;
GstVaapiDisplayX11Private *priv;
};
/**
* GstVaapiDisplayX11Class:
*
* VA/X11 display wrapper class.
*/
struct _GstVaapiDisplayX11Class
{
/*< private >*/
GstVaapiDisplayClass parent_class;
};
G_GNUC_INTERNAL
GstVideoFormat
gst_vaapi_display_x11_get_pixmap_format (GstVaapiDisplayX11 * display,
guint depth);
G_GNUC_INTERNAL
guint
gst_vaapi_display_x11_get_pixmap_depth (GstVaapiDisplayX11 * display,
GstVideoFormat format);
G_END_DECLS
#endif /* GST_VAAPI_DISPLAY_X11_PRIV_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,202 @@
/*
* gstvaapiencoder.h - VA encoder abstraction
*
* Copyright (C) 2013-2014 Intel Corporation
* Author: Wind Yuan <feng.yuan@intel.com>
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_ENCODER_H
#define GST_VAAPI_ENCODER_H
#include <gst/video/gstvideoutils.h>
#include <gst/vaapi/gstvaapicodedbufferproxy.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_ENCODER \
(gst_vaapi_encoder_get_type ())
#define GST_VAAPI_ENCODER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_ENCODER, GstVaapiEncoder))
#define GST_VAAPI_IS_ENCODER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_ENCODER))
typedef struct _GstVaapiEncoder GstVaapiEncoder;
GType
gst_vaapi_encoder_get_type (void) G_GNUC_CONST;
/**
* GST_VAAPI_PARAM_ENCODER_EXPOSURE: (value 65536)
*
* This user defined flag is added when the internal encoder class
* wants to expose its property gparam spec to the according encode
* class. */
#define GST_VAAPI_PARAM_ENCODER_EXPOSURE GST_PARAM_USER_SHIFT
/**
* GstVaapiEncoderStatus:
* @GST_VAAPI_ENCODER_STATUS_SUCCESS: Success.
* @GST_VAAPI_ENCODER_STATUS_NO_SURFACE: No surface left to encode.
* @GST_VAAPI_ENCODER_STATUS_NO_BUFFER: No coded buffer left to hold
* the encoded picture.
* @GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN: Unknown error.
* @GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED: No memory left.
* @GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED: The requested
* operation failed to execute properly. e.g. invalid point in time to
* execute the operation.
* @GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_RATE_CONTROL:
* Unsupported rate control value.
* @GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE: Unsupported profile.
* @GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER: Invalid parameter.
* @GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_BUFFER: Invalid buffer.
* @GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_SURFACE: Invalid surface.
* @GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_HEADER: Invalid header.
*
* Set of #GstVaapiEncoder status codes.
*/
typedef enum
{
GST_VAAPI_ENCODER_STATUS_SUCCESS = 0,
GST_VAAPI_ENCODER_STATUS_NO_SURFACE = 1,
GST_VAAPI_ENCODER_STATUS_NO_BUFFER = 2,
GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN = -1,
GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED = -2,
GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED = -3,
GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_RATE_CONTROL = -4,
GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE = -5,
GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER = -100,
GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_BUFFER = -101,
GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_SURFACE = -102,
GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_HEADER = -103,
} GstVaapiEncoderStatus;
/**
* GstVaapiEncoderTune:
* @GST_VAAPI_ENCODER_TUNE_NONE: No tuning option set.
* @GST_VAAPI_ENCODER_TUNE_HIGH_COMPRESSION: Tune for higher compression
* ratios, at the expense of lower compatibility at decoding time.
* @GST_VAAPI_ENCODER_TUNE_LOW_LATENCY: Tune for low latency decoding.
* @GST_VAAPI_ENCODER_TUNE_LOW_POWER: Tune encoder for low power /
* resources conditions. This can affect compression ratio or visual
* quality to match low power conditions.
*
* The set of tuning options for a #GstVaapiEncoder. By default,
* maximum compatibility for decoding is preferred, so the lowest
* coding tools are enabled.
*/
typedef enum {
GST_VAAPI_ENCODER_TUNE_NONE = 0,
GST_VAAPI_ENCODER_TUNE_HIGH_COMPRESSION,
GST_VAAPI_ENCODER_TUNE_LOW_LATENCY,
GST_VAAPI_ENCODER_TUNE_LOW_POWER,
} GstVaapiEncoderTune;
/**
* GstVaapiEncoderMbbrc:
* @GST_VAAPI_ENCODER_MBBRC_AUTO: bitrate control auto
* @GST_VAAPI_ENCODER_MBBRC_ON: bitrate control on
* @GST_VAAPI_ENCODER_MBBRC_OFF: bitrate control off
*
* Values for the macroblock level bitrate control.
*
* This property values are only available for H264 and H265 (HEVC)
* encoders, when rate control is not Constant QP.
**/
typedef enum {
GST_VAAPI_ENCODER_MBBRC_AUTO = 0,
GST_VAAPI_ENCODER_MBBRC_ON = 1,
GST_VAAPI_ENCODER_MBBRC_OFF = 2,
} GstVaapiEncoderMbbrc;
GType
gst_vaapi_encoder_tune_get_type (void) G_GNUC_CONST;
GType
gst_vaapi_encoder_mbbrc_get_type (void) G_GNUC_CONST;
void
gst_vaapi_encoder_replace (GstVaapiEncoder ** old_encoder_ptr,
GstVaapiEncoder * new_encoder);
GstVaapiEncoderStatus
gst_vaapi_encoder_get_codec_data (GstVaapiEncoder * encoder,
GstBuffer ** out_codec_data_ptr);
GstVaapiEncoderStatus
gst_vaapi_encoder_set_codec_state (GstVaapiEncoder * encoder,
GstVideoCodecState * state);
GstVaapiEncoderStatus
gst_vaapi_encoder_set_rate_control (GstVaapiEncoder * encoder,
GstVaapiRateControl rate_control);
GstVaapiEncoderStatus
gst_vaapi_encoder_set_bitrate (GstVaapiEncoder * encoder, guint bitrate);
GstVaapiEncoderStatus
gst_vaapi_encoder_set_target_percentage (GstVaapiEncoder * encoder,
guint target_percentage);
GstVaapiEncoderStatus
gst_vaapi_encoder_put_frame (GstVaapiEncoder * encoder,
GstVideoCodecFrame * frame);
GstVaapiEncoderStatus
gst_vaapi_encoder_set_keyframe_period (GstVaapiEncoder * encoder,
guint keyframe_period);
GstVaapiEncoderStatus
gst_vaapi_encoder_set_tuning (GstVaapiEncoder * encoder,
GstVaapiEncoderTune tuning);
GstVaapiEncoderStatus
gst_vaapi_encoder_set_quality_level (GstVaapiEncoder * encoder,
guint quality_level);
GstVaapiEncoderStatus
gst_vaapi_encoder_set_trellis (GstVaapiEncoder * encoder, gboolean trellis);
GstVaapiEncoderStatus
gst_vaapi_encoder_get_buffer_with_timeout (GstVaapiEncoder * encoder,
GstVaapiCodedBufferProxy ** out_codedbuf_proxy_ptr, guint64 timeout);
GstVaapiEncoderStatus
gst_vaapi_encoder_flush (GstVaapiEncoder * encoder);
GArray *
gst_vaapi_encoder_get_surface_attributes (GstVaapiEncoder * encoder,
GArray * profiles, gint * min_width, gint * min_height,
gint * max_width, gint * max_height, guint * mem_types);
GstVaapiProfile
gst_vaapi_encoder_get_profile (GstVaapiEncoder * encoder);
GstVaapiEntrypoint
gst_vaapi_encoder_get_entrypoint (GstVaapiEncoder * encoder,
GstVaapiProfile profile);
GArray *
gst_vaapi_encoder_get_available_profiles (GstVaapiEncoder * encoder);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiEncoder, gst_object_unref)
G_END_DECLS
#endif /* GST_VAAPI_ENCODER_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,63 @@
/*
* gstvaapiencoder_h264.h - H.264 encoder
*
* Copyright (C) 2011-2014 Intel Corporation
* Author: Wind Yuan <feng.yuan@intel.com>
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_ENCODER_H264_H
#define GST_VAAPI_ENCODER_H264_H
#include <gst/vaapi/gstvaapiencoder.h>
#include <gst/vaapi/gstvaapiutils_h264.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_ENCODER_H264 \
(gst_vaapi_encoder_h264_get_type ())
#define GST_VAAPI_ENCODER_H264(encoder) \
(G_TYPE_CHECK_INSTANCE_CAST ((encoder), GST_TYPE_VAAPI_ENCODER_H264, GstVaapiEncoderH264))
#define GST_IS_VAAPI_ENCODER_H264(encoder) \
(G_TYPE_CHECK_INSTANCE_TYPE ((encoder), GST_TYPE_VAAPI_ENCODER_H264))
typedef struct _GstVaapiEncoderH264 GstVaapiEncoderH264;
typedef struct _GstVaapiEncoderH264Class GstVaapiEncoderH264Class;
GType
gst_vaapi_encoder_h264_get_type (void) G_GNUC_CONST;
GstVaapiEncoder *
gst_vaapi_encoder_h264_new (GstVaapiDisplay * display);
gboolean
gst_vaapi_encoder_h264_set_max_profile (GstVaapiEncoderH264 * encoder,
GstVaapiProfile profile);
gboolean
gst_vaapi_encoder_h264_get_profile_and_level (GstVaapiEncoderH264 * encoder,
GstVaapiProfile * out_profile_ptr, GstVaapiLevelH264 * out_level_ptr);
gboolean
gst_vaapi_encoder_h264_supports_avc (GstVaapiEncoderH264 * encoder);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiEncoderH264, gst_object_unref)
G_END_DECLS
#endif /*GST_VAAPI_ENCODER_H264_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,59 @@
/*
* gstvaapiencoder_h265.h - H.265 encoder
*
* Copyright (C) 2015 Intel Corporation
* Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
*
* 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_VAAPI_ENCODER_H265_H
#define GST_VAAPI_ENCODER_H265_H
#include <gst/vaapi/gstvaapiencoder.h>
#include <gst/vaapi/gstvaapiutils_h265.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_ENCODER_H265 \
(gst_vaapi_encoder_h265_get_type ())
#define GST_VAAPI_ENCODER_H265(encoder) \
(G_TYPE_CHECK_INSTANCE_CAST ((encoder), GST_TYPE_VAAPI_ENCODER_H265, GstVaapiEncoderH265))
#define GST_IS_VAAPI_ENCODER_H265(encoder) \
(G_TYPE_CHECK_INSTANCE_TYPE ((encoder), GST_TYPE_VAAPI_ENCODER_H265))
typedef struct _GstVaapiEncoderH265 GstVaapiEncoderH265;
typedef struct _GstVaapiEncoderH265Class GstVaapiEncoderH265Class;
GType
gst_vaapi_encoder_h265_get_type (void) G_GNUC_CONST;
GstVaapiEncoder *
gst_vaapi_encoder_h265_new (GstVaapiDisplay * display);
gboolean
gst_vaapi_encoder_h265_set_allowed_profiles (GstVaapiEncoderH265 * encoder,
GArray * profiles);
gboolean
gst_vaapi_encoder_h265_get_profile_tier_level (GstVaapiEncoderH265 * encoder,
GstVaapiProfile * out_profile_ptr, GstVaapiTierH265 *out_tier_ptr, GstVaapiLevelH265 * out_level_ptr);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiEncoderH265, gst_object_unref)
G_END_DECLS
#endif /*GST_VAAPI_ENCODER_H265_H */

View file

@ -0,0 +1,914 @@
/*
* gstvaapiencoder_jpeg.c - JPEG encoder
*
* Copyright (C) 2015 Intel Corporation
* Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
*
* 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 "sysdeps.h"
#include <gst/base/gstbitwriter.h>
#include <gst/codecparsers/gstjpegparser.h>
#include "gstvaapicompat.h"
#include "gstvaapiencoder_priv.h"
#include "gstvaapiencoder_jpeg.h"
#include "gstvaapicodedbufferproxy_priv.h"
#include "gstvaapisurface.h"
#define DEBUG 1
#include "gstvaapidebug.h"
/* Define default rate control mode ("constant-qp") */
#define DEFAULT_RATECONTROL GST_VAAPI_RATECONTROL_NONE
/* Supported set of VA rate controls, within this implementation */
#define SUPPORTED_RATECONTROLS \
(GST_VAAPI_RATECONTROL_MASK (NONE))
/* Supported set of tuning options, within this implementation */
#define SUPPORTED_TUNE_OPTIONS \
(GST_VAAPI_ENCODER_TUNE_MASK (NONE))
/* Supported set of VA packed headers, within this implementation */
#define SUPPORTED_PACKED_HEADERS \
(VA_ENC_PACKED_HEADER_RAW_DATA)
#define NUM_DC_RUN_SIZE_BITS 16
#define NUM_AC_RUN_SIZE_BITS 16
#define NUM_AC_CODE_WORDS_HUFFVAL 162
#define NUM_DC_CODE_WORDS_HUFFVAL 12
/* ------------------------------------------------------------------------- */
/* --- JPEG Encoder --- */
/* ------------------------------------------------------------------------- */
struct _GstVaapiEncoderJpeg
{
GstVaapiEncoder parent_instance;
GstVaapiProfile profile;
guint quality;
GstJpegQuantTables quant_tables;
GstJpegQuantTables scaled_quant_tables;
gboolean has_quant_tables;
GstJpegHuffmanTables huff_tables;
gboolean has_huff_tables;
gint cwidth[GST_VIDEO_MAX_COMPONENTS];
gint cheight[GST_VIDEO_MAX_COMPONENTS];
gint h_samp[GST_VIDEO_MAX_COMPONENTS];
gint v_samp[GST_VIDEO_MAX_COMPONENTS];
gint h_max_samp;
gint v_max_samp;
guint n_components;
};
/* based on upstream gst-plugins-good jpegencoder */
static void
generate_sampling_factors (GstVaapiEncoderJpeg * encoder)
{
GstVideoInfo *vinfo;
gint i;
vinfo = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
if (GST_VIDEO_INFO_FORMAT (vinfo) == GST_VIDEO_FORMAT_ENCODED) {
/* Use native I420 format */
encoder->n_components = 3;
for (i = 0; i < encoder->n_components; ++i) {
if (i == 0)
encoder->h_samp[i] = encoder->v_samp[i] = 2;
else
encoder->h_samp[i] = encoder->v_samp[i] = 1;
GST_DEBUG ("sampling factors: %d %d", encoder->h_samp[i],
encoder->v_samp[i]);
}
return;
}
encoder->n_components = GST_VIDEO_INFO_N_COMPONENTS (vinfo);
encoder->h_max_samp = 0;
encoder->v_max_samp = 0;
for (i = 0; i < encoder->n_components; ++i) {
encoder->cwidth[i] = GST_VIDEO_INFO_COMP_WIDTH (vinfo, i);
encoder->cheight[i] = GST_VIDEO_INFO_COMP_HEIGHT (vinfo, i);
encoder->h_samp[i] =
GST_ROUND_UP_4 (GST_VIDEO_INFO_WIDTH (vinfo)) / encoder->cwidth[i];
encoder->h_max_samp = MAX (encoder->h_max_samp, encoder->h_samp[i]);
encoder->v_samp[i] =
GST_ROUND_UP_4 (GST_VIDEO_INFO_HEIGHT (vinfo)) / encoder->cheight[i];
encoder->v_max_samp = MAX (encoder->v_max_samp, encoder->v_samp[i]);
}
/* samp should only be 1, 2 or 4 */
g_assert (encoder->h_max_samp <= 4);
g_assert (encoder->v_max_samp <= 4);
/* now invert */
/* maximum is invariant, as one of the components should have samp 1 */
for (i = 0; i < encoder->n_components; ++i) {
encoder->h_samp[i] = encoder->h_max_samp / encoder->h_samp[i];
encoder->v_samp[i] = encoder->v_max_samp / encoder->v_samp[i];
GST_DEBUG ("sampling factors: %d %d", encoder->h_samp[i],
encoder->v_samp[i]);
}
}
/* Derives the profile that suits best to the configuration */
static GstVaapiEncoderStatus
ensure_profile (GstVaapiEncoderJpeg * encoder)
{
/* Always start from "simple" profile for maximum compatibility */
encoder->profile = GST_VAAPI_PROFILE_JPEG_BASELINE;
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
}
/* Derives the profile supported by the underlying hardware */
static gboolean
ensure_hw_profile (GstVaapiEncoderJpeg * encoder)
{
GstVaapiDisplay *const display = GST_VAAPI_ENCODER_DISPLAY (encoder);
GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_PICTURE_ENCODE;
GstVaapiProfile profile, profiles[2];
guint i, num_profiles = 0;
profiles[num_profiles++] = encoder->profile;
profile = GST_VAAPI_PROFILE_UNKNOWN;
for (i = 0; i < num_profiles; i++) {
if (gst_vaapi_display_has_encoder (display, profiles[i], entrypoint)) {
profile = profiles[i];
break;
}
}
if (profile == GST_VAAPI_PROFILE_UNKNOWN)
goto error_unsupported_profile;
GST_VAAPI_ENCODER_CAST (encoder)->profile = profile;
return TRUE;
/* ERRORS */
error_unsupported_profile:
{
GST_ERROR ("unsupported HW profile %s",
gst_vaapi_profile_get_va_name (encoder->profile));
return FALSE;
}
}
static GstVaapiEncoderStatus
set_context_info (GstVaapiEncoder * base_encoder)
{
GstVaapiEncoderJpeg *encoder = GST_VAAPI_ENCODER_JPEG (base_encoder);
GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
/* Maximum sizes for common headers (in bytes) */
enum
{
MAX_APP_HDR_SIZE = 20,
MAX_FRAME_HDR_SIZE = 19,
MAX_QUANT_TABLE_SIZE = 138,
MAX_HUFFMAN_TABLE_SIZE = 432,
MAX_SCAN_HDR_SIZE = 14
};
if (!ensure_hw_profile (encoder))
return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
base_encoder->num_ref_frames = 0;
/* Only YUV 4:2:0 formats are supported for now. */
base_encoder->codedbuf_size = GST_ROUND_UP_16 (vip->width) *
GST_ROUND_UP_16 (vip->height) * 3 / 2;
base_encoder->codedbuf_size += MAX_APP_HDR_SIZE + MAX_FRAME_HDR_SIZE +
MAX_QUANT_TABLE_SIZE + MAX_HUFFMAN_TABLE_SIZE + MAX_SCAN_HDR_SIZE;
base_encoder->context_info.profile = base_encoder->profile;
base_encoder->context_info.entrypoint = GST_VAAPI_ENTRYPOINT_PICTURE_ENCODE;
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
}
static gboolean
fill_picture (GstVaapiEncoderJpeg * encoder,
GstVaapiEncPicture * picture,
GstVaapiCodedBuffer * codedbuf, GstVaapiSurfaceProxy * surface)
{
guint i;
VAEncPictureParameterBufferJPEG *const pic_param = picture->param;
memset (pic_param, 0, sizeof (VAEncPictureParameterBufferJPEG));
pic_param->reconstructed_picture =
GST_VAAPI_SURFACE_PROXY_SURFACE_ID (surface);
pic_param->picture_width = GST_VAAPI_ENCODER_WIDTH (encoder);
pic_param->picture_height = GST_VAAPI_ENCODER_HEIGHT (encoder);
pic_param->coded_buf = GST_VAAPI_CODED_BUFFER_ID (codedbuf);
pic_param->pic_flags.bits.profile = 0; /* Profile = Baseline */
pic_param->pic_flags.bits.progressive = 0; /* Sequential encoding */
pic_param->pic_flags.bits.huffman = 1; /* Uses Huffman coding */
pic_param->pic_flags.bits.interleaved = 0; /* Input format is non interleaved (YUV) */
pic_param->pic_flags.bits.differential = 0; /* non-Differential Encoding */
pic_param->sample_bit_depth = 8;
pic_param->num_scan = 1;
pic_param->num_components = encoder->n_components;
pic_param->quality = encoder->quality;
for (i = 0; i < pic_param->num_components; i++) {
pic_param->component_id[i] = i + 1;
if (i != 0)
pic_param->quantiser_table_selector[i] = 1;
}
return TRUE;
}
static gboolean
ensure_picture (GstVaapiEncoderJpeg * encoder, GstVaapiEncPicture * picture,
GstVaapiCodedBufferProxy * codedbuf_proxy, GstVaapiSurfaceProxy * surface)
{
GstVaapiCodedBuffer *const codedbuf =
GST_VAAPI_CODED_BUFFER_PROXY_BUFFER (codedbuf_proxy);
if (!fill_picture (encoder, picture, codedbuf, surface))
return FALSE;
return TRUE;
}
/* This is a work-around: Normalize the quality factor and scale QM
* values similar to what VA-Intel driver is doing. Otherwise the
* generated packed headers will be wrong, since the driver itself
* is scaling the QM values using the normalized quality factor */
static void
generate_scaled_qm (GstJpegQuantTables * quant_tables,
GstJpegQuantTables * scaled_quant_tables, guint quality, guint shift)
{
guint qt_val, nm_quality, i;
nm_quality = quality == 0 ? 1 : quality;
nm_quality =
(nm_quality < 50) ? (5000 / nm_quality) : (200 - (nm_quality * 2));
g_assert (quant_tables != NULL);
g_assert (scaled_quant_tables != NULL);
for (i = 0; i < GST_JPEG_MAX_QUANT_ELEMENTS; i++) {
/* Luma QM */
qt_val =
(quant_tables->quant_tables[0].quant_table[i] * nm_quality +
shift) / 100;
scaled_quant_tables->quant_tables[0].quant_table[i] =
CLAMP (qt_val, 1, 255);
/* Chroma QM */
qt_val =
(quant_tables->quant_tables[1].quant_table[i] * nm_quality +
shift) / 100;
scaled_quant_tables->quant_tables[1].quant_table[i] =
CLAMP (qt_val, 1, 255);
}
}
static gboolean
fill_quantization_table (GstVaapiEncoderJpeg * encoder,
GstVaapiEncPicture * picture)
{
VAQMatrixBufferJPEG *q_matrix;
int i;
g_assert (picture);
picture->q_matrix = GST_VAAPI_ENC_Q_MATRIX_NEW (JPEG, encoder);
if (!picture->q_matrix) {
GST_ERROR ("failed to allocate quantiser table");
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
}
q_matrix = picture->q_matrix->param;
if (!encoder->has_quant_tables) {
GstVaapiDisplay *const display = GST_VAAPI_ENCODER_DISPLAY (encoder);
guint shift = 0;
if (gst_vaapi_display_has_driver_quirks (display,
GST_VAAPI_DRIVER_QUIRK_JPEG_ENC_SHIFT_VALUE_BY_50))
shift = 50;
gst_jpeg_get_default_quantization_tables (&encoder->quant_tables);
encoder->has_quant_tables = TRUE;
generate_scaled_qm (&encoder->quant_tables, &encoder->scaled_quant_tables,
encoder->quality, shift);
}
q_matrix->load_lum_quantiser_matrix = 1;
for (i = 0; i < GST_JPEG_MAX_QUANT_ELEMENTS; i++) {
q_matrix->lum_quantiser_matrix[i] =
encoder->quant_tables.quant_tables[0].quant_table[i];
}
q_matrix->load_chroma_quantiser_matrix = 1;
for (i = 0; i < GST_JPEG_MAX_QUANT_ELEMENTS; i++) {
q_matrix->chroma_quantiser_matrix[i] =
encoder->quant_tables.quant_tables[1].quant_table[i];
}
return TRUE;
}
static gboolean
ensure_quantization_table (GstVaapiEncoderJpeg * encoder,
GstVaapiEncPicture * picture)
{
g_assert (picture);
if (!fill_quantization_table (encoder, picture))
return FALSE;
return TRUE;
}
static gboolean
fill_huffman_table (GstVaapiEncoderJpeg * encoder, GstVaapiEncPicture * picture)
{
VAHuffmanTableBufferJPEGBaseline *huffman_table;
guint i, num_tables;
g_assert (picture);
picture->huf_table = GST_VAAPI_ENC_HUFFMAN_TABLE_NEW (JPEGBaseline, encoder);
if (!picture->huf_table) {
GST_ERROR ("failed to allocate Huffman tables");
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
}
huffman_table = picture->huf_table->param;
num_tables = MIN (G_N_ELEMENTS (huffman_table->huffman_table),
GST_JPEG_MAX_SCAN_COMPONENTS);
if (!encoder->has_huff_tables) {
gst_jpeg_get_default_huffman_tables (&encoder->huff_tables);
encoder->has_huff_tables = TRUE;
}
for (i = 0; i < num_tables; i++) {
huffman_table->load_huffman_table[i] =
encoder->huff_tables.dc_tables[i].valid
&& encoder->huff_tables.ac_tables[i].valid;
if (!huffman_table->load_huffman_table[i])
continue;
memcpy (huffman_table->huffman_table[i].num_dc_codes,
encoder->huff_tables.dc_tables[i].huf_bits,
sizeof (huffman_table->huffman_table[i].num_dc_codes));
memcpy (huffman_table->huffman_table[i].dc_values,
encoder->huff_tables.dc_tables[i].huf_values,
sizeof (huffman_table->huffman_table[i].dc_values));
memcpy (huffman_table->huffman_table[i].num_ac_codes,
encoder->huff_tables.ac_tables[i].huf_bits,
sizeof (huffman_table->huffman_table[i].num_ac_codes));
memcpy (huffman_table->huffman_table[i].ac_values,
encoder->huff_tables.ac_tables[i].huf_values,
sizeof (huffman_table->huffman_table[i].ac_values));
memset (huffman_table->huffman_table[i].pad,
0, sizeof (huffman_table->huffman_table[i].pad));
}
return TRUE;
}
static gboolean
ensure_huffman_table (GstVaapiEncoderJpeg * encoder,
GstVaapiEncPicture * picture)
{
g_assert (picture);
if (!fill_huffman_table (encoder, picture))
return FALSE;
return TRUE;
}
static gboolean
fill_slices (GstVaapiEncoderJpeg * encoder, GstVaapiEncPicture * picture)
{
VAEncSliceParameterBufferJPEG *slice_param;
GstVaapiEncSlice *slice;
VAEncPictureParameterBufferJPEG *const pic_param = picture->param;
slice = GST_VAAPI_ENC_SLICE_NEW (JPEG, encoder);
g_assert (slice && slice->param_id != VA_INVALID_ID);
slice_param = slice->param;
memset (slice_param, 0, sizeof (VAEncSliceParameterBufferJPEG));
slice_param->restart_interval = 0;
slice_param->num_components = pic_param->num_components;
slice_param->components[0].component_selector = 1;
slice_param->components[0].dc_table_selector = 0;
slice_param->components[0].ac_table_selector = 0;
slice_param->components[1].component_selector = 2;
slice_param->components[1].dc_table_selector = 1;
slice_param->components[1].ac_table_selector = 1;
slice_param->components[2].component_selector = 3;
slice_param->components[2].dc_table_selector = 1;
slice_param->components[2].ac_table_selector = 1;
gst_vaapi_enc_picture_add_slice (picture, slice);
gst_vaapi_codec_object_replace (&slice, NULL);
return TRUE;
}
static gboolean
ensure_slices (GstVaapiEncoderJpeg * encoder, GstVaapiEncPicture * picture)
{
g_assert (picture);
if (!fill_slices (encoder, picture))
return FALSE;
return TRUE;
}
static void
generate_frame_hdr (GstJpegFrameHdr * frame_hdr, GstVaapiEncoderJpeg * encoder,
GstVaapiEncPicture * picture)
{
VAEncPictureParameterBufferJPEG *const pic_param = picture->param;
guint i;
memset (frame_hdr, 0, sizeof (GstJpegFrameHdr));
frame_hdr->sample_precision = 8;
frame_hdr->width = pic_param->picture_width;
frame_hdr->height = pic_param->picture_height;
frame_hdr->num_components = pic_param->num_components;
for (i = 0; i < frame_hdr->num_components; i++) {
frame_hdr->components[i].identifier = pic_param->component_id[i];
frame_hdr->components[i].horizontal_factor = encoder->h_samp[i];
frame_hdr->components[i].vertical_factor = encoder->v_samp[i];
frame_hdr->components[i].quant_table_selector =
pic_param->quantiser_table_selector[i];
}
}
static void
generate_scan_hdr (GstJpegScanHdr * scan_hdr, GstVaapiEncPicture * picture)
{
VAEncPictureParameterBufferJPEG *const pic_param = picture->param;
memset (scan_hdr, 0, sizeof (GstJpegScanHdr));
scan_hdr->num_components = pic_param->num_components;
//Y Component
scan_hdr->components[0].component_selector = 1;
scan_hdr->components[0].dc_selector = 0;
scan_hdr->components[0].ac_selector = 0;
//U Component
scan_hdr->components[1].component_selector = 2;
scan_hdr->components[1].dc_selector = 1;
scan_hdr->components[1].ac_selector = 1;
//V Component
scan_hdr->components[2].component_selector = 3;
scan_hdr->components[2].dc_selector = 1;
scan_hdr->components[2].ac_selector = 1;
}
static gboolean
bs_write_jpeg_header (GstBitWriter * bs, GstVaapiEncoderJpeg * encoder,
GstVaapiEncPicture * picture)
{
GstJpegFrameHdr frame_hdr;
GstJpegScanHdr scan_hdr;
guint i, j;
gst_bit_writer_put_bits_uint8 (bs, 0xFF, 8);
gst_bit_writer_put_bits_uint8 (bs, GST_JPEG_MARKER_SOI, 8);
gst_bit_writer_put_bits_uint8 (bs, 0xFF, 8);
gst_bit_writer_put_bits_uint8 (bs, GST_JPEG_MARKER_APP_MIN, 8);
gst_bit_writer_put_bits_uint16 (bs, 16, 16);
gst_bit_writer_put_bits_uint8 (bs, 0x4A, 8); //J
gst_bit_writer_put_bits_uint8 (bs, 0x46, 8); //F
gst_bit_writer_put_bits_uint8 (bs, 0x49, 8); //I
gst_bit_writer_put_bits_uint8 (bs, 0x46, 8); //F
gst_bit_writer_put_bits_uint8 (bs, 0x00, 8); //0
gst_bit_writer_put_bits_uint8 (bs, 1, 8); //Major Version
gst_bit_writer_put_bits_uint8 (bs, 1, 8); //Minor Version
gst_bit_writer_put_bits_uint8 (bs, 0, 8); //Density units 0:no units, 1:pixels per inch, 2: pixels per cm
gst_bit_writer_put_bits_uint16 (bs, 1, 16); //X density (pixel-aspect-ratio)
gst_bit_writer_put_bits_uint16 (bs, 1, 16); //Y density (pixel-aspect-ratio)
gst_bit_writer_put_bits_uint8 (bs, 0, 8); //Thumbnail width
gst_bit_writer_put_bits_uint8 (bs, 0, 8); //Thumbnail height
/* Add quantization table */
if (!encoder->has_quant_tables) {
GstVaapiDisplay *const display = GST_VAAPI_ENCODER_DISPLAY (encoder);
guint shift = 0;
if (gst_vaapi_display_has_driver_quirks (display,
GST_VAAPI_DRIVER_QUIRK_JPEG_ENC_SHIFT_VALUE_BY_50))
shift = 50;
gst_jpeg_get_default_quantization_tables (&encoder->quant_tables);
generate_scaled_qm (&encoder->quant_tables, &encoder->scaled_quant_tables,
encoder->quality, shift);
encoder->has_quant_tables = TRUE;
}
gst_bit_writer_put_bits_uint8 (bs, 0xFF, 8);
gst_bit_writer_put_bits_uint8 (bs, GST_JPEG_MARKER_DQT, 8);
gst_bit_writer_put_bits_uint16 (bs, 3 + GST_JPEG_MAX_QUANT_ELEMENTS, 16); //Lq
gst_bit_writer_put_bits_uint8 (bs, encoder->quant_tables.quant_tables[0].quant_precision, 4); //Pq
gst_bit_writer_put_bits_uint8 (bs, 0, 4); //Tq
for (i = 0; i < GST_JPEG_MAX_QUANT_ELEMENTS; i++) {
gst_bit_writer_put_bits_uint16 (bs,
encoder->scaled_quant_tables.quant_tables[0].quant_table[i], 8);
}
gst_bit_writer_put_bits_uint8 (bs, 0xFF, 8);
gst_bit_writer_put_bits_uint8 (bs, GST_JPEG_MARKER_DQT, 8);
gst_bit_writer_put_bits_uint16 (bs, 3 + GST_JPEG_MAX_QUANT_ELEMENTS, 16); //Lq
gst_bit_writer_put_bits_uint8 (bs, encoder->quant_tables.quant_tables[1].quant_precision, 4); //Pq
gst_bit_writer_put_bits_uint8 (bs, 1, 4); //Tq
for (i = 0; i < GST_JPEG_MAX_QUANT_ELEMENTS; i++) {
gst_bit_writer_put_bits_uint16 (bs,
encoder->scaled_quant_tables.quant_tables[1].quant_table[i], 8);
}
/*Add frame header */
generate_frame_hdr (&frame_hdr, encoder, picture);
gst_bit_writer_put_bits_uint8 (bs, 0xFF, 8);
gst_bit_writer_put_bits_uint8 (bs, GST_JPEG_MARKER_SOF_MIN, 8);
gst_bit_writer_put_bits_uint16 (bs, 8 + (3 * 3), 16); //lf, Size of FrameHeader in bytes without the Marker SOF
gst_bit_writer_put_bits_uint8 (bs, frame_hdr.sample_precision, 8);
gst_bit_writer_put_bits_uint16 (bs, frame_hdr.height, 16);
gst_bit_writer_put_bits_uint16 (bs, frame_hdr.width, 16);
gst_bit_writer_put_bits_uint8 (bs, frame_hdr.num_components, 8);
for (i = 0; i < frame_hdr.num_components; i++) {
gst_bit_writer_put_bits_uint8 (bs, frame_hdr.components[i].identifier, 8);
gst_bit_writer_put_bits_uint8 (bs,
frame_hdr.components[i].horizontal_factor, 4);
gst_bit_writer_put_bits_uint8 (bs, frame_hdr.components[i].vertical_factor,
4);
gst_bit_writer_put_bits_uint8 (bs,
frame_hdr.components[i].quant_table_selector, 8);
}
/* Add Huffman table */
if (!encoder->has_huff_tables) {
gst_jpeg_get_default_huffman_tables (&encoder->huff_tables);
encoder->has_huff_tables = TRUE;
}
for (i = 0; i < 2; i++) {
gst_bit_writer_put_bits_uint8 (bs, 0xFF, 8);
gst_bit_writer_put_bits_uint8 (bs, GST_JPEG_MARKER_DHT, 8);
gst_bit_writer_put_bits_uint16 (bs, 0x1F, 16); //length of table
gst_bit_writer_put_bits_uint8 (bs, 0, 4);
gst_bit_writer_put_bits_uint8 (bs, i, 4);
for (j = 0; j < NUM_DC_RUN_SIZE_BITS; j++) {
gst_bit_writer_put_bits_uint8 (bs,
encoder->huff_tables.dc_tables[i].huf_bits[j], 8);
}
for (j = 0; j < NUM_DC_CODE_WORDS_HUFFVAL; j++) {
gst_bit_writer_put_bits_uint8 (bs,
encoder->huff_tables.dc_tables[i].huf_values[j], 8);
}
gst_bit_writer_put_bits_uint8 (bs, 0xFF, 8);
gst_bit_writer_put_bits_uint8 (bs, GST_JPEG_MARKER_DHT, 8);
gst_bit_writer_put_bits_uint16 (bs, 0xB5, 16); //length of table
gst_bit_writer_put_bits_uint8 (bs, 1, 4);
gst_bit_writer_put_bits_uint8 (bs, i, 4);
for (j = 0; j < NUM_AC_RUN_SIZE_BITS; j++) {
gst_bit_writer_put_bits_uint8 (bs,
encoder->huff_tables.ac_tables[i].huf_bits[j], 8);
}
for (j = 0; j < NUM_AC_CODE_WORDS_HUFFVAL; j++) {
gst_bit_writer_put_bits_uint8 (bs,
encoder->huff_tables.ac_tables[i].huf_values[j], 8);
}
}
/* Add ScanHeader */
generate_scan_hdr (&scan_hdr, picture);
gst_bit_writer_put_bits_uint8 (bs, 0xFF, 8);
gst_bit_writer_put_bits_uint8 (bs, GST_JPEG_MARKER_SOS, 8);
gst_bit_writer_put_bits_uint16 (bs, 12, 16); //Length of Scan
gst_bit_writer_put_bits_uint8 (bs, scan_hdr.num_components, 8);
for (i = 0; i < scan_hdr.num_components; i++) {
gst_bit_writer_put_bits_uint8 (bs,
scan_hdr.components[i].component_selector, 8);
gst_bit_writer_put_bits_uint8 (bs, scan_hdr.components[i].dc_selector, 4);
gst_bit_writer_put_bits_uint8 (bs, scan_hdr.components[i].ac_selector, 4);
}
gst_bit_writer_put_bits_uint8 (bs, 0, 8); //0 for Baseline
gst_bit_writer_put_bits_uint8 (bs, 63, 8); //63 for Baseline
gst_bit_writer_put_bits_uint8 (bs, 0, 4); //0 for Baseline
gst_bit_writer_put_bits_uint8 (bs, 0, 4); //0 for Baseline
return TRUE;
}
static gboolean
add_packed_header (GstVaapiEncoderJpeg * encoder, GstVaapiEncPicture * picture)
{
GstVaapiEncPackedHeader *packed_raw_data_hdr;
GstBitWriter bs;
VAEncPackedHeaderParameterBuffer packed_raw_data_hdr_param = { 0 };
guint32 data_bit_size;
guint8 *data;
gst_bit_writer_init_with_size (&bs, 128, FALSE);
bs_write_jpeg_header (&bs, encoder, picture);
data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
data = GST_BIT_WRITER_DATA (&bs);
packed_raw_data_hdr_param.type = VAEncPackedHeaderRawData;
packed_raw_data_hdr_param.bit_length = data_bit_size;
packed_raw_data_hdr_param.has_emulation_bytes = 0;
packed_raw_data_hdr =
gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
&packed_raw_data_hdr_param, sizeof (packed_raw_data_hdr_param), data,
(data_bit_size + 7) / 8);
g_assert (packed_raw_data_hdr);
gst_vaapi_enc_picture_add_packed_header (picture, packed_raw_data_hdr);
gst_vaapi_codec_object_replace (&packed_raw_data_hdr, NULL);
gst_bit_writer_reset (&bs);
return TRUE;
}
static gboolean
ensure_packed_headers (GstVaapiEncoderJpeg * encoder,
GstVaapiEncPicture * picture)
{
g_assert (picture);
if ((GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
VA_ENC_PACKED_HEADER_RAW_DATA)
&& !add_packed_header (encoder, picture))
goto error_create_packed_hdr;
return TRUE;
/* ERRORS */
error_create_packed_hdr:
{
GST_ERROR ("failed to create packed raw data header buffer");
return FALSE;
}
}
static GstVaapiEncoderStatus
gst_vaapi_encoder_jpeg_encode (GstVaapiEncoder * base_encoder,
GstVaapiEncPicture * picture, GstVaapiCodedBufferProxy * codedbuf)
{
GstVaapiEncoderJpeg *const encoder = GST_VAAPI_ENCODER_JPEG (base_encoder);
GstVaapiEncoderStatus ret = GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
GstVaapiSurfaceProxy *reconstruct = NULL;
reconstruct = gst_vaapi_encoder_create_surface (base_encoder);
g_assert (GST_VAAPI_SURFACE_PROXY_SURFACE (reconstruct));
if (!ensure_picture (encoder, picture, codedbuf, reconstruct))
goto error;
if (!ensure_quantization_table (encoder, picture))
goto error;
if (!ensure_huffman_table (encoder, picture))
goto error;
if (!ensure_slices (encoder, picture))
goto error;
if (!ensure_packed_headers (encoder, picture))
goto error;
if (!gst_vaapi_enc_picture_encode (picture))
goto error;
if (reconstruct)
gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder),
reconstruct);
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
/* ERRORS */
error:
{
if (reconstruct)
gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder),
reconstruct);
return ret;
}
}
static GstVaapiEncoderStatus
gst_vaapi_encoder_jpeg_flush (GstVaapiEncoder * base_encoder)
{
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
}
static GstVaapiEncoderStatus
gst_vaapi_encoder_jpeg_reordering (GstVaapiEncoder * base_encoder,
GstVideoCodecFrame * frame, GstVaapiEncPicture ** output)
{
GstVaapiEncoderJpeg *const encoder = GST_VAAPI_ENCODER_JPEG (base_encoder);
GstVaapiEncPicture *picture = NULL;
GstVaapiEncoderStatus status = GST_VAAPI_ENCODER_STATUS_SUCCESS;
if (!frame)
return GST_VAAPI_ENCODER_STATUS_NO_SURFACE;
picture = GST_VAAPI_ENC_PICTURE_NEW (JPEG, encoder, frame);
if (!picture) {
GST_WARNING ("create JPEG picture failed, frame timestamp:%"
GST_TIME_FORMAT, GST_TIME_ARGS (frame->pts));
return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
}
*output = picture;
return status;
}
static GstVaapiEncoderStatus
gst_vaapi_encoder_jpeg_reconfigure (GstVaapiEncoder * base_encoder)
{
GstVaapiEncoderJpeg *const encoder = GST_VAAPI_ENCODER_JPEG (base_encoder);
GstVaapiEncoderStatus status;
status = ensure_profile (encoder);
if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
return status;
/* generate sampling factors (A.1.1) */
generate_sampling_factors (encoder);
return set_context_info (base_encoder);
}
struct _GstVaapiEncoderJpegClass
{
GstVaapiEncoderClass parent_class;
};
G_DEFINE_TYPE (GstVaapiEncoderJpeg, gst_vaapi_encoder_jpeg,
GST_TYPE_VAAPI_ENCODER);
static void
gst_vaapi_encoder_jpeg_init (GstVaapiEncoderJpeg * encoder)
{
encoder->has_quant_tables = FALSE;
memset (&encoder->quant_tables, 0, sizeof (encoder->quant_tables));
memset (&encoder->scaled_quant_tables, 0,
sizeof (encoder->scaled_quant_tables));
encoder->has_huff_tables = FALSE;
memset (&encoder->huff_tables, 0, sizeof (encoder->huff_tables));
}
/**
* @ENCODER_JPEG_PROP_RATECONTROL: Rate control (#GstVaapiRateControl).
* @ENCODER_JPEG_PROP_TUNE: The tuning options (#GstVaapiEncoderTune).
* @ENCODER_JPEG_PROP_QUALITY: Quality Factor value (uint).
*
* The set of JPEG encoder specific configurable properties.
*/
enum
{
ENCODER_JPEG_PROP_RATECONTROL = 1,
ENCODER_JPEG_PROP_TUNE,
ENCODER_JPEG_PROP_QUALITY,
ENCODER_JPEG_N_PROPERTIES
};
static GParamSpec *properties[ENCODER_JPEG_N_PROPERTIES];
static void
gst_vaapi_encoder_jpeg_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER (object);
GstVaapiEncoderJpeg *const encoder = GST_VAAPI_ENCODER_JPEG (object);
if (base_encoder->num_codedbuf_queued > 0) {
GST_ERROR_OBJECT (object,
"failed to set any property after encoding started");
return;
}
switch (prop_id) {
case ENCODER_JPEG_PROP_RATECONTROL:
gst_vaapi_encoder_set_rate_control (base_encoder,
g_value_get_enum (value));
break;
case ENCODER_JPEG_PROP_TUNE:
gst_vaapi_encoder_set_tuning (base_encoder, g_value_get_enum (value));
break;
case ENCODER_JPEG_PROP_QUALITY:
encoder->quality = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
gst_vaapi_encoder_jpeg_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstVaapiEncoderJpeg *const encoder = GST_VAAPI_ENCODER_JPEG (object);
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER (object);
switch (prop_id) {
case ENCODER_JPEG_PROP_RATECONTROL:
g_value_set_enum (value, base_encoder->rate_control);
break;
case ENCODER_JPEG_PROP_TUNE:
g_value_set_enum (value, base_encoder->tune);
break;
case ENCODER_JPEG_PROP_QUALITY:
g_value_set_uint (value, encoder->quality);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
GST_VAAPI_ENCODER_DEFINE_CLASS_DATA (JPEG);
static void
gst_vaapi_encoder_jpeg_class_init (GstVaapiEncoderJpegClass * klass)
{
GObjectClass *const object_class = G_OBJECT_CLASS (klass);
GstVaapiEncoderClass *const encoder_class = GST_VAAPI_ENCODER_CLASS (klass);
encoder_class->class_data = &g_class_data;
encoder_class->reconfigure = gst_vaapi_encoder_jpeg_reconfigure;
encoder_class->reordering = gst_vaapi_encoder_jpeg_reordering;
encoder_class->encode = gst_vaapi_encoder_jpeg_encode;
encoder_class->flush = gst_vaapi_encoder_jpeg_flush;
object_class->set_property = gst_vaapi_encoder_jpeg_set_property;
object_class->get_property = gst_vaapi_encoder_jpeg_get_property;
properties[ENCODER_JPEG_PROP_RATECONTROL] =
g_param_spec_enum ("rate-control",
"Rate Control", "Rate control mode",
g_class_data.rate_control_get_type (),
g_class_data.default_rate_control,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
GST_VAAPI_PARAM_ENCODER_EXPOSURE);
properties[ENCODER_JPEG_PROP_TUNE] =
g_param_spec_enum ("tune",
"Encoder Tuning",
"Encoder tuning option",
g_class_data.encoder_tune_get_type (),
g_class_data.default_encoder_tune,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
GST_VAAPI_PARAM_ENCODER_EXPOSURE);
properties[ENCODER_JPEG_PROP_QUALITY] =
g_param_spec_uint ("quality",
"Quality factor",
"Quality factor", 0, 100, 50,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
GST_VAAPI_PARAM_ENCODER_EXPOSURE);
g_object_class_install_properties (object_class, ENCODER_JPEG_N_PROPERTIES,
properties);
gst_type_mark_as_plugin_api (g_class_data.rate_control_get_type (), 0);
gst_type_mark_as_plugin_api (g_class_data.encoder_tune_get_type (), 0);
}
/**
* gst_vaapi_encoder_jpeg_new:
* @display: a #GstVaapiDisplay
*
* Creates a new #GstVaapiEncoder for JPEG encoding.
*
* Return value: the newly allocated #GstVaapiEncoder object
*/
GstVaapiEncoder *
gst_vaapi_encoder_jpeg_new (GstVaapiDisplay * display)
{
return g_object_new (GST_TYPE_VAAPI_ENCODER_JPEG, "display", display, NULL);
}

View file

@ -0,0 +1,50 @@
/*
* gstvaapiencoder_jpeg.h JPEGG encoder
*
* Copyright (C) 2015 Intel Corporation
* Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
*
* 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_VAAPI_ENCODER_JPEG_H
#define GST_VAAPI_ENCODER_JPEG_H
#include <gst/vaapi/gstvaapiencoder.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_ENCODER_JPEG \
(gst_vaapi_encoder_jpeg_get_type ())
#define GST_VAAPI_ENCODER_JPEG(encoder) \
(G_TYPE_CHECK_INSTANCE_CAST ((encoder), GST_TYPE_VAAPI_ENCODER_JPEG, GstVaapiEncoderJpeg))
#define GST_IS_VAAPI_ENCODER_JPEG(encoder) \
(G_TYPE_CHECK_INSTANCE_TYPE ((encoder), GST_TYPE_VAAPI_ENCODER_JPEG))
typedef struct _GstVaapiEncoderJpeg GstVaapiEncoderJpeg;
typedef struct _GstVaapiEncoderJpegClass GstVaapiEncoderJpegClass;
GType
gst_vaapi_encoder_jpeg_get_type (void) G_GNUC_CONST;
GstVaapiEncoder *
gst_vaapi_encoder_jpeg_new (GstVaapiDisplay * display);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiEncoderJpeg, gst_object_unref)
G_END_DECLS
#endif /*GST_VAAPI_ENCODER_JPEG_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,51 @@
/*
* gstvaapiencoder_mpeg2.h - MPEG-2 encoder
*
* Copyright (C) 2011-2014 Intel Corporation
* Author: Guangxin Xu <guangxin.xu@intel.com>
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_ENCODER_MPEG2_H
#define GST_VAAPI_ENCODER_MPEG2_H
#include <gst/vaapi/gstvaapiencoder.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_ENCODER_MPEG2 \
(gst_vaapi_encoder_mpeg2_get_type ())
#define GST_VAAPI_ENCODER_MPEG2(encoder) \
(G_TYPE_CHECK_INSTANCE_CAST ((encoder), GST_TYPE_VAAPI_ENCODER_MPEG2, GstVaapiEncoderMpeg2))
#define GST_IS_VAAPI_ENCODER_MPEG2(encoder) \
(G_TYPE_CHECK_INSTANCE_TYPE ((encoder), GST_TYPE_VAAPI_ENCODER_MPEG2))
typedef struct _GstVaapiEncoderMpeg2 GstVaapiEncoderMpeg2;
typedef struct _GstVaapiEncoderMpeg2Class GstVaapiEncoderMpeg2Class;
GType
gst_vaapi_encoder_mpeg2_get_type (void) G_GNUC_CONST;
GstVaapiEncoder *
gst_vaapi_encoder_mpeg2_new (GstVaapiDisplay * display);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiEncoderMpeg2, gst_object_unref)
G_END_DECLS
#endif /* GST_VAAPI_ENCODER_MPEG2_H */

View file

@ -0,0 +1,66 @@
/*
* gstvaapiencoder_mpeg2_priv.h - MPEG-2 encoder (private definitions)
*
* Copyright (C) 2013-2014 Intel Corporation
* Author: Guangxin Xu <guangxin.xu@intel.com>
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_ENCODER_MPEG2_PRIV_H
#define GST_VAAPI_ENCODER_MPEG2_PRIV_H
#include "gstvaapiencoder_priv.h"
#include "gstvaapiutils_mpeg2.h"
G_BEGIN_DECLS
#define GST_VAAPI_ENCODER_MPEG2_CAST(encoder) \
((GstVaapiEncoderMpeg2 *) (encoder))
#define START_CODE_PICUTRE 0x00000100
#define START_CODE_SLICE 0x00000101
#define START_CODE_USER 0x000001B2
#define START_CODE_SEQ 0x000001B3
#define START_CODE_EXT 0x000001B5
#define START_CODE_GOP 0x000001B8
struct _GstVaapiEncoderMpeg2
{
GstVaapiEncoder parent_instance;
GstVaapiProfile profile;
GstVaapiLevelMPEG2 level;
guint8 profile_idc;
guint8 level_idc;
guint32 cqp; /* quantizer value for CQP mode */
guint32 ip_period;
/* re-ordering */
GQueue b_frames;
gboolean dump_frames;
gboolean new_gop;
/* reference list */
GstVaapiSurfaceProxy *forward;
GstVaapiSurfaceProxy *backward;
guint32 frame_num; /* same value picture header, but it's not mod by 1024 */
};
G_END_DECLS
#endif /* GST_VAAPI_ENCODER_MPEG2_PRIV_H */

View file

@ -0,0 +1,583 @@
/*
* gstvaapiencoder_objects.c - VA encoder objects abstraction
*
* Copyright (C) 2013-2014 Intel Corporation
* Author: Wind Yuan <feng.yuan@intel.com>
*
* 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 "sysdeps.h"
#include "gstvaapiencoder_objects.h"
#include "gstvaapiencoder_priv.h"
#include "gstvaapisurfaceproxy_priv.h"
#include "gstvaapicompat.h"
#include "gstvaapiutils.h"
#define DEBUG 1
#include "gstvaapidebug.h"
#define GET_ENCODER(obj) GST_VAAPI_ENCODER_CAST((obj)->parent_instance.codec)
#define GET_VA_DISPLAY(obj) GET_ENCODER(obj)->va_display
#define GET_VA_CONTEXT(obj) GET_ENCODER(obj)->va_context
/* ------------------------------------------------------------------------- */
/* --- Encoder Packed Header --- */
/* ------------------------------------------------------------------------- */
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncPackedHeader,
gst_vaapi_enc_packed_header);
void
gst_vaapi_enc_packed_header_destroy (GstVaapiEncPackedHeader * header)
{
vaapi_destroy_buffer (GET_VA_DISPLAY (header), &header->param_id);
vaapi_destroy_buffer (GET_VA_DISPLAY (header), &header->data_id);
header->param = NULL;
header->data = NULL;
}
gboolean
gst_vaapi_enc_packed_header_create (GstVaapiEncPackedHeader * header,
const GstVaapiCodecObjectConstructorArgs * args)
{
gboolean success;
header->param_id = VA_INVALID_ID;
header->data_id = VA_INVALID_ID;
success = vaapi_create_buffer (GET_VA_DISPLAY (header),
GET_VA_CONTEXT (header),
VAEncPackedHeaderParameterBufferType,
args->param_size, args->param, &header->param_id, &header->param);
if (!success)
return FALSE;
if (!args->data_size)
return TRUE;
success = vaapi_create_buffer (GET_VA_DISPLAY (header),
GET_VA_CONTEXT (header),
VAEncPackedHeaderDataBufferType,
args->data_size, args->data, &header->data_id, &header->data);
if (!success)
return FALSE;
return TRUE;
}
GstVaapiEncPackedHeader *
gst_vaapi_enc_packed_header_new (GstVaapiEncoder * encoder,
gconstpointer param, guint param_size, gconstpointer data, guint data_size)
{
GstVaapiCodecObject *object;
object = gst_vaapi_codec_object_new (&GstVaapiEncPackedHeaderClass,
GST_VAAPI_CODEC_BASE (encoder), param, param_size, data, data_size, 0);
return GST_VAAPI_ENC_PACKED_HEADER (object);
}
gboolean
gst_vaapi_enc_packed_header_set_data (GstVaapiEncPackedHeader * header,
gconstpointer data, guint data_size)
{
gboolean success;
vaapi_destroy_buffer (GET_VA_DISPLAY (header), &header->data_id);
header->data = NULL;
success = vaapi_create_buffer (GET_VA_DISPLAY (header),
GET_VA_CONTEXT (header),
VAEncPackedHeaderDataBufferType,
data_size, data, &header->data_id, &header->data);
if (!success)
return FALSE;
return TRUE;
}
/* ------------------------------------------------------------------------- */
/* --- Encoder Sequence --- */
/* ------------------------------------------------------------------------- */
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncSequence, gst_vaapi_enc_sequence);
void
gst_vaapi_enc_sequence_destroy (GstVaapiEncSequence * sequence)
{
vaapi_destroy_buffer (GET_VA_DISPLAY (sequence), &sequence->param_id);
sequence->param = NULL;
}
gboolean
gst_vaapi_enc_sequence_create (GstVaapiEncSequence * sequence,
const GstVaapiCodecObjectConstructorArgs * args)
{
gboolean success;
sequence->param_id = VA_INVALID_ID;
success = vaapi_create_buffer (GET_VA_DISPLAY (sequence),
GET_VA_CONTEXT (sequence),
VAEncSequenceParameterBufferType,
args->param_size, args->param, &sequence->param_id, &sequence->param);
if (!success)
return FALSE;
return TRUE;
}
GstVaapiEncSequence *
gst_vaapi_enc_sequence_new (GstVaapiEncoder * encoder,
gconstpointer param, guint param_size)
{
GstVaapiCodecObject *object;
object = gst_vaapi_codec_object_new (&GstVaapiEncSequenceClass,
GST_VAAPI_CODEC_BASE (encoder), param, param_size, NULL, 0, 0);
return GST_VAAPI_ENC_SEQUENCE (object);
}
/* ------------------------------------------------------------------------- */
/* --- Encoder Slice --- */
/* ------------------------------------------------------------------------- */
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncSlice, gst_vaapi_enc_slice);
void
gst_vaapi_enc_slice_destroy (GstVaapiEncSlice * slice)
{
if (slice->packed_headers) {
g_ptr_array_unref (slice->packed_headers);
slice->packed_headers = NULL;
}
vaapi_destroy_buffer (GET_VA_DISPLAY (slice), &slice->param_id);
slice->param = NULL;
}
gboolean
gst_vaapi_enc_slice_create (GstVaapiEncSlice * slice,
const GstVaapiCodecObjectConstructorArgs * args)
{
gboolean success;
slice->param_id = VA_INVALID_ID;
success = vaapi_create_buffer (GET_VA_DISPLAY (slice),
GET_VA_CONTEXT (slice),
VAEncSliceParameterBufferType,
args->param_size, args->param, &slice->param_id, &slice->param);
if (!success)
return FALSE;
slice->packed_headers = g_ptr_array_new_with_free_func ((GDestroyNotify)
gst_vaapi_mini_object_unref);
if (!slice->packed_headers)
return FALSE;
return TRUE;
}
GstVaapiEncSlice *
gst_vaapi_enc_slice_new (GstVaapiEncoder * encoder,
gconstpointer param, guint param_size)
{
GstVaapiCodecObject *object;
object = gst_vaapi_codec_object_new (&GstVaapiEncSliceClass,
GST_VAAPI_CODEC_BASE (encoder), param, param_size, NULL, 0, 0);
return GST_VAAPI_ENC_SLICE (object);
}
/* ------------------------------------------------------------------------- */
/* --- Encoder Misc Parameter Buffer --- */
/* ------------------------------------------------------------------------- */
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncMiscParam, gst_vaapi_enc_misc_param);
void
gst_vaapi_enc_misc_param_destroy (GstVaapiEncMiscParam * misc)
{
vaapi_destroy_buffer (GET_VA_DISPLAY (misc), &misc->param_id);
misc->param = NULL;
misc->data = NULL;
}
gboolean
gst_vaapi_enc_misc_param_create (GstVaapiEncMiscParam * misc,
const GstVaapiCodecObjectConstructorArgs * args)
{
gboolean success;
misc->param_id = VA_INVALID_ID;
success = vaapi_create_buffer (GET_VA_DISPLAY (misc),
GET_VA_CONTEXT (misc),
VAEncMiscParameterBufferType,
args->param_size, args->param, &misc->param_id, &misc->param);
if (!success)
return FALSE;
return TRUE;
}
GstVaapiEncMiscParam *
gst_vaapi_enc_misc_param_new (GstVaapiEncoder * encoder,
VAEncMiscParameterType type, guint data_size)
{
GstVaapiCodecObject *object;
GstVaapiEncMiscParam *misc;
VAEncMiscParameterBuffer *va_misc;
object = gst_vaapi_codec_object_new (&GstVaapiEncMiscParamClass,
GST_VAAPI_CODEC_BASE (encoder),
NULL, sizeof (VAEncMiscParameterBuffer) + data_size, NULL, 0, 0);
if (!object)
return NULL;
misc = GST_VAAPI_ENC_MISC_PARAM (object);
va_misc = misc->param;
va_misc->type = type;
misc->data = va_misc->data;
return misc;
}
/* ------------------------------------------------------------------------- */
/* --- Quantization Matrices --- */
/* ------------------------------------------------------------------------- */
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncQMatrix, gst_vaapi_enc_q_matrix);
void
gst_vaapi_enc_q_matrix_destroy (GstVaapiEncQMatrix * q_matrix)
{
vaapi_destroy_buffer (GET_VA_DISPLAY (q_matrix), &q_matrix->param_id);
q_matrix->param = NULL;
}
gboolean
gst_vaapi_enc_q_matrix_create (GstVaapiEncQMatrix * q_matrix,
const GstVaapiCodecObjectConstructorArgs * args)
{
q_matrix->param_id = VA_INVALID_ID;
return vaapi_create_buffer (GET_VA_DISPLAY (q_matrix),
GET_VA_CONTEXT (q_matrix), VAQMatrixBufferType,
args->param_size, args->param, &q_matrix->param_id, &q_matrix->param);
}
GstVaapiEncQMatrix *
gst_vaapi_enc_q_matrix_new (GstVaapiEncoder * encoder,
gconstpointer param, guint param_size)
{
GstVaapiCodecObject *object;
object = gst_vaapi_codec_object_new (&GstVaapiEncQMatrixClass,
GST_VAAPI_CODEC_BASE (encoder), param, param_size, NULL, 0, 0);
if (!object)
return NULL;
return GST_VAAPI_ENC_Q_MATRIX_CAST (object);
}
/* ------------------------------------------------------------------------- */
/* --- JPEG Huffman Tables --- */
/* ------------------------------------------------------------------------- */
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncHuffmanTable,
gst_vaapi_enc_huffman_table);
void
gst_vaapi_enc_huffman_table_destroy (GstVaapiEncHuffmanTable * huf_table)
{
vaapi_destroy_buffer (GET_VA_DISPLAY (huf_table), &huf_table->param_id);
huf_table->param = NULL;
}
gboolean
gst_vaapi_enc_huffman_table_create (GstVaapiEncHuffmanTable * huf_table,
const GstVaapiCodecObjectConstructorArgs * args)
{
huf_table->param_id = VA_INVALID_ID;
return vaapi_create_buffer (GET_VA_DISPLAY (huf_table),
GET_VA_CONTEXT (huf_table), VAHuffmanTableBufferType, args->param_size,
args->param, &huf_table->param_id, (void **) &huf_table->param);
}
GstVaapiEncHuffmanTable *
gst_vaapi_enc_huffman_table_new (GstVaapiEncoder * encoder,
guint8 * data, guint data_size)
{
GstVaapiCodecObject *object;
object = gst_vaapi_codec_object_new (&GstVaapiEncHuffmanTableClass,
GST_VAAPI_CODEC_BASE (encoder), data, data_size, NULL, 0, 0);
if (!object)
return NULL;
return GST_VAAPI_ENC_HUFFMAN_TABLE_CAST (object);
}
/* ------------------------------------------------------------------------- */
/* --- Encoder Picture --- */
/* ------------------------------------------------------------------------- */
GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiEncPicture, gst_vaapi_enc_picture);
void
gst_vaapi_enc_picture_destroy (GstVaapiEncPicture * picture)
{
if (picture->packed_headers) {
g_ptr_array_unref (picture->packed_headers);
picture->packed_headers = NULL;
}
if (picture->misc_params) {
g_ptr_array_unref (picture->misc_params);
picture->misc_params = NULL;
}
if (picture->slices) {
g_ptr_array_unref (picture->slices);
picture->slices = NULL;
}
gst_vaapi_codec_object_replace (&picture->q_matrix, NULL);
gst_vaapi_codec_object_replace (&picture->huf_table, NULL);
gst_vaapi_codec_object_replace (&picture->sequence, NULL);
gst_vaapi_surface_proxy_replace (&picture->proxy, NULL);
picture->surface_id = VA_INVALID_ID;
picture->surface = NULL;
vaapi_destroy_buffer (GET_VA_DISPLAY (picture), &picture->param_id);
picture->param = NULL;
if (picture->frame) {
gst_video_codec_frame_unref (picture->frame);
picture->frame = NULL;
}
}
gboolean
gst_vaapi_enc_picture_create (GstVaapiEncPicture * picture,
const GstVaapiCodecObjectConstructorArgs * args)
{
GstVideoCodecFrame *const frame = (GstVideoCodecFrame *) args->data;
gboolean success;
picture->proxy = gst_video_codec_frame_get_user_data (frame);
if (!gst_vaapi_surface_proxy_ref (picture->proxy))
return FALSE;
picture->surface = GST_VAAPI_SURFACE_PROXY_SURFACE (picture->proxy);
if (!picture->surface)
return FALSE;
picture->surface_id = GST_VAAPI_SURFACE_ID (picture->surface);
if (picture->surface_id == VA_INVALID_ID)
return FALSE;
picture->type = GST_VAAPI_PICTURE_TYPE_NONE;
picture->pts = GST_CLOCK_TIME_NONE;
picture->frame_num = 0;
picture->poc = 0;
picture->param_id = VA_INVALID_ID;
picture->param_size = args->param_size;
success = vaapi_create_buffer (GET_VA_DISPLAY (picture),
GET_VA_CONTEXT (picture),
VAEncPictureParameterBufferType,
args->param_size, args->param, &picture->param_id, &picture->param);
if (!success)
return FALSE;
picture->param_size = args->param_size;
picture->packed_headers = g_ptr_array_new_with_free_func ((GDestroyNotify)
gst_vaapi_mini_object_unref);
if (!picture->packed_headers)
return FALSE;
picture->misc_params = g_ptr_array_new_with_free_func ((GDestroyNotify)
gst_vaapi_mini_object_unref);
if (!picture->misc_params)
return FALSE;
picture->slices = g_ptr_array_new_with_free_func ((GDestroyNotify)
gst_vaapi_mini_object_unref);
if (!picture->slices)
return FALSE;
picture->frame = gst_video_codec_frame_ref (frame);
return TRUE;
}
GstVaapiEncPicture *
gst_vaapi_enc_picture_new (GstVaapiEncoder * encoder,
gconstpointer param, guint param_size, GstVideoCodecFrame * frame)
{
GstVaapiCodecObject *object;
g_return_val_if_fail (frame != NULL, NULL);
object = gst_vaapi_codec_object_new (&GstVaapiEncPictureClass,
GST_VAAPI_CODEC_BASE (encoder), param, param_size, frame, 0, 0);
return GST_VAAPI_ENC_PICTURE (object);
}
void
gst_vaapi_enc_picture_set_sequence (GstVaapiEncPicture * picture,
GstVaapiEncSequence * sequence)
{
g_return_if_fail (picture != NULL);
g_return_if_fail (sequence != NULL);
gst_vaapi_codec_object_replace (&picture->sequence, sequence);
}
void
gst_vaapi_enc_picture_add_packed_header (GstVaapiEncPicture * picture,
GstVaapiEncPackedHeader * header)
{
g_return_if_fail (picture != NULL);
g_return_if_fail (header != NULL);
g_ptr_array_add (picture->packed_headers,
gst_vaapi_codec_object_ref (header));
}
void
gst_vaapi_enc_picture_add_misc_param (GstVaapiEncPicture * picture,
GstVaapiEncMiscParam * misc)
{
g_return_if_fail (picture != NULL);
g_return_if_fail (misc != NULL);
g_ptr_array_add (picture->misc_params, gst_vaapi_codec_object_ref (misc));
}
void
gst_vaapi_enc_picture_add_slice (GstVaapiEncPicture * picture,
GstVaapiEncSlice * slice)
{
g_return_if_fail (picture != NULL);
g_return_if_fail (slice != NULL);
g_ptr_array_add (picture->slices, gst_vaapi_codec_object_ref (slice));
}
void
gst_vaapi_enc_slice_add_packed_header (GstVaapiEncSlice * slice,
GstVaapiEncPackedHeader * header)
{
g_return_if_fail (slice != NULL);
g_return_if_fail (header != NULL);
g_ptr_array_add (slice->packed_headers, gst_vaapi_codec_object_ref (header));
}
static gboolean
do_encode (VADisplay dpy, VAContextID ctx, VABufferID * buf_id, void **buf_ptr)
{
VAStatus status;
vaapi_unmap_buffer (dpy, *buf_id, buf_ptr);
status = vaRenderPicture (dpy, ctx, buf_id, 1);
if (!vaapi_check_status (status, "vaRenderPicture()"))
return FALSE;
/* XXX: vaRenderPicture() is meant to destroy the VA buffer implicitly */
vaapi_destroy_buffer (dpy, buf_id);
return TRUE;
}
gboolean
gst_vaapi_enc_picture_encode (GstVaapiEncPicture * picture)
{
GstVaapiEncSequence *sequence;
GstVaapiEncQMatrix *q_matrix;
GstVaapiEncHuffmanTable *huf_table;
VADisplay va_display;
VAContextID va_context;
VAStatus status;
guint i;
g_return_val_if_fail (picture != NULL, FALSE);
g_return_val_if_fail (picture->surface_id != VA_INVALID_SURFACE, FALSE);
va_display = GET_VA_DISPLAY (picture);
va_context = GET_VA_CONTEXT (picture);
GST_DEBUG ("encode picture 0x%08x", picture->surface_id);
status = vaBeginPicture (va_display, va_context, picture->surface_id);
if (!vaapi_check_status (status, "vaBeginPicture()"))
return FALSE;
/* Submit Sequence parameter */
sequence = picture->sequence;
if (sequence && !do_encode (va_display, va_context,
&sequence->param_id, &sequence->param))
return FALSE;
/* Submit Quantization matrix */
q_matrix = picture->q_matrix;
if (q_matrix && !do_encode (va_display, va_context,
&q_matrix->param_id, &q_matrix->param))
return FALSE;
/* Submit huffman table */
huf_table = picture->huf_table;
if (huf_table && !do_encode (va_display, va_context,
&huf_table->param_id, (void **) &huf_table->param))
return FALSE;
/* Submit Packed Headers */
for (i = 0; i < picture->packed_headers->len; i++) {
GstVaapiEncPackedHeader *const header =
g_ptr_array_index (picture->packed_headers, i);
if (!do_encode (va_display, va_context,
&header->param_id, &header->param) ||
!do_encode (va_display, va_context, &header->data_id, &header->data))
return FALSE;
}
/* Submit Picture parameter */
if (!do_encode (va_display, va_context, &picture->param_id, &picture->param))
return FALSE;
/* Submit Misc Params */
for (i = 0; i < picture->misc_params->len; i++) {
GstVaapiEncMiscParam *const misc =
g_ptr_array_index (picture->misc_params, i);
if (!do_encode (va_display, va_context, &misc->param_id, &misc->param))
return FALSE;
}
/* Submit Slice parameters */
for (i = 0; i < picture->slices->len; i++) {
GstVaapiEncSlice *const slice = g_ptr_array_index (picture->slices, i);
guint j;
/* Submit packed_slice_header and packed_raw_data */
for (j = 0; j < slice->packed_headers->len; j++) {
GstVaapiEncPackedHeader *const header =
g_ptr_array_index (slice->packed_headers, j);
if (!do_encode (va_display, va_context,
&header->param_id, &header->param) ||
!do_encode (va_display, va_context, &header->data_id, &header->data))
return FALSE;
}
if (!do_encode (va_display, va_context, &slice->param_id, &slice->param))
return FALSE;
}
status = vaEndPicture (va_display, va_context);
if (!vaapi_check_status (status, "vaEndPicture()"))
return FALSE;
return TRUE;
}

View file

@ -0,0 +1,362 @@
/*
* gstvaapiencoder_objects.h - VA encoder objects abstraction
*
* Copyright (C) 2013-2014 Intel Corporation
* Author: Wind Yuan <feng.yuan@intel.com>
*
* 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_VAAPI_ENCODER_OBJECTS_H
#define GST_VAAPI_ENCODER_OBJECTS_H
#include <gst/vaapi/gstvaapicodec_objects.h>
#include <gst/vaapi/gstvaapidecoder_objects.h>
#include <gst/vaapi/gstvaapiencoder.h>
G_BEGIN_DECLS
typedef struct _GstVaapiEncPicture GstVaapiEncPicture;
typedef struct _GstVaapiEncSequence GstVaapiEncSequence;
typedef struct _GstVaapiEncMiscParam GstVaapiEncMiscParam;
typedef struct _GstVaapiEncSlice GstVaapiEncSlice;
typedef struct _GstVaapiEncQMatrix GstVaapiEncQMatrix;
typedef struct _GstVaapiEncHuffmanTable GstVaapiEncHuffmanTable;
typedef struct _GstVaapiEncPackedHeader GstVaapiEncPackedHeader;
/* ------------------------------------------------------------------------- */
/* --- Encoder Packed Header --- */
/* ------------------------------------------------------------------------- */
#define GST_VAAPI_ENC_PACKED_HEADER(obj) \
((GstVaapiEncPackedHeader *) (obj))
/**
* GstVaapiEncPackedHeader:
*
* A #GstVaapiCodecObject holding a packed header (param/data) for the
* encoder.
*/
struct _GstVaapiEncPackedHeader
{
/*< private >*/
GstVaapiCodecObject parent_instance;
/*< public >*/
VABufferID param_id;
gpointer param;
VABufferID data_id;
gpointer data;
};
G_GNUC_INTERNAL
GstVaapiEncPackedHeader *
gst_vaapi_enc_packed_header_new (GstVaapiEncoder * encoder,
gconstpointer param, guint param_size, gconstpointer data, guint data_size);
G_GNUC_INTERNAL
gboolean
gst_vaapi_enc_packed_header_set_data (GstVaapiEncPackedHeader * header,
gconstpointer data, guint data_size);
/* ------------------------------------------------------------------------- */
/* --- Encoder Sequence --- */
/* ------------------------------------------------------------------------- */
#define GST_VAAPI_ENC_SEQUENCE(obj) \
((GstVaapiEncSequence *) (obj))
/**
* GstVaapiEncSequence:
*
* A #GstVaapiCodecObject holding a sequence parameter for encoding.
*/
struct _GstVaapiEncSequence
{
/*< private >*/
GstVaapiCodecObject parent_instance;
/*< public >*/
VABufferID param_id;
gpointer param;
};
G_GNUC_INTERNAL
GstVaapiEncSequence *
gst_vaapi_enc_sequence_new (GstVaapiEncoder * encoder,
gconstpointer param, guint param_size);
/* ------------------------------------------------------------------------- */
/* --- Encoder Slice --- */
/* ------------------------------------------------------------------------- */
#define GST_VAAPI_ENC_SLICE(obj) \
((GstVaapiEncSlice *) (obj))
/**
* GstVaapiEncSlice:
*
* A #GstVaapiCodecObject holding a slice parameter used for encoding.
*/
struct _GstVaapiEncSlice
{
/*< private >*/
GstVaapiCodecObject parent_instance;
/*< public >*/
VABufferID param_id;
gpointer param;
GPtrArray *packed_headers;
};
G_GNUC_INTERNAL
GstVaapiEncSlice *
gst_vaapi_enc_slice_new (GstVaapiEncoder * encoder,
gconstpointer param, guint param_size);
/* ------------------------------------------------------------------------- */
/* --- Encoder Misc Parameter Buffer --- */
/* ------------------------------------------------------------------------- */
#define GST_VAAPI_ENC_MISC_PARAM(obj) \
((GstVaapiEncMiscParam *) (obj))
/**
* GstVaapiEncMiscParam:
*
* A #GstVaapiCodecObject holding a misc parameter and associated data
* used for controlling the encoder dynamically.
*/
struct _GstVaapiEncMiscParam
{
/*< private >*/
GstVaapiCodecObject parent_instance;
gpointer param;
/*< public >*/
VABufferID param_id;
gpointer data;
};
G_GNUC_INTERNAL
GstVaapiEncMiscParam *
gst_vaapi_enc_misc_param_new (GstVaapiEncoder * encoder,
VAEncMiscParameterType type, guint data_size);
/* ------------------------------------------------------------------------- */
/* --- Quantization Matrices --- */
/* ------------------------------------------------------------------------- */
#define GST_VAAPI_ENC_Q_MATRIX_CAST(obj) \
((GstVaapiEncQMatrix *) (obj))
/**
* GstVaapiEncQMatrix:
*
* A #GstVaapiCodecObject holding a quantization matrix parameter.
*/
struct _GstVaapiEncQMatrix
{
/*< private >*/
GstVaapiCodecObject parent_instance;
VABufferID param_id;
/*< public >*/
gpointer param;
};
G_GNUC_INTERNAL
GstVaapiEncQMatrix *
gst_vaapi_enc_q_matrix_new (GstVaapiEncoder * encoder, gconstpointer param,
guint param_size);
/* ------------------------------------------------------------------------- */
/* --- JPEG Huffman Tables --- */
/* ------------------------------------------------------------------------- */
#define GST_VAAPI_ENC_HUFFMAN_TABLE_CAST(obj) \
((GstVaapiEncHuffmanTable *) (obj))
/**
* GstVaapiEncHuffmanTable:
*
* A #GstVaapiCodecObject holding huffman table.
*/
struct _GstVaapiEncHuffmanTable
{
/*< private >*/
GstVaapiCodecObject parent_instance;
VABufferID param_id;
/*< public >*/
gpointer param;
};
G_GNUC_INTERNAL
GstVaapiEncHuffmanTable *
gst_vaapi_enc_huffman_table_new (GstVaapiEncoder * encoder, guint8 * data,
guint data_size);
/* ------------------------------------------------------------------------- */
/* --- Encoder Picture --- */
/* ------------------------------------------------------------------------- */
#define GST_VAAPI_ENC_PICTURE(obj) \
((GstVaapiEncPicture *) (obj))
typedef enum
{
GST_VAAPI_ENC_PICTURE_FLAG_IDR = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 0),
GST_VAAPI_ENC_PICTURE_FLAG_REFERENCE = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 1),
GST_VAAPI_ENC_PICTURE_FLAG_LAST = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 2),
} GstVaapiEncPictureFlags;
#define GST_VAAPI_ENC_PICTURE_FLAGS GST_VAAPI_MINI_OBJECT_FLAGS
#define GST_VAAPI_ENC_PICTURE_FLAG_IS_SET GST_VAAPI_MINI_OBJECT_FLAG_IS_SET
#define GST_VAAPI_ENC_PICTURE_FLAG_SET GST_VAAPI_MINI_OBJECT_FLAG_SET
#define GST_VAAPI_ENC_PICTURE_FLAG_UNSET GST_VAAPI_MINI_OBJECT_FLAG_UNSET
#define GST_VAAPI_ENC_PICTURE_IS_IDR(picture) \
GST_VAAPI_ENC_PICTURE_FLAG_IS_SET(picture, GST_VAAPI_ENC_PICTURE_FLAG_IDR)
#define GST_VAAPI_ENC_PICTURE_IS_REFRENCE(picture) \
GST_VAAPI_ENC_PICTURE_FLAG_IS_SET(picture, GST_VAAPI_ENC_PICTURE_FLAG_REFERENCE)
/**
* GstVaapiEncPicture:
*
* A #GstVaapiCodecObject holding a picture parameter for encoding.
*/
struct _GstVaapiEncPicture
{
/*< private >*/
GstVaapiCodecObject parent_instance;
GstVideoCodecFrame *frame;
GstVaapiSurfaceProxy *proxy;
GstVaapiSurface *surface;
VABufferID param_id;
guint param_size;
/* Additional data to pass down */
GstVaapiEncSequence *sequence;
GPtrArray *packed_headers;
GPtrArray *misc_params;
/*< public >*/
GstVaapiPictureType type;
VASurfaceID surface_id;
gpointer param;
GPtrArray *slices;
GstVaapiEncQMatrix *q_matrix;
GstVaapiEncHuffmanTable *huf_table;
GstClockTime pts;
guint frame_num;
guint poc;
guint temporal_id;
gboolean has_roi;
};
G_GNUC_INTERNAL
GstVaapiEncPicture *
gst_vaapi_enc_picture_new (GstVaapiEncoder * encoder,
gconstpointer param, guint param_size, GstVideoCodecFrame * frame);
G_GNUC_INTERNAL
void
gst_vaapi_enc_picture_set_sequence (GstVaapiEncPicture * picture,
GstVaapiEncSequence * sequence);
G_GNUC_INTERNAL
void
gst_vaapi_enc_picture_add_packed_header (GstVaapiEncPicture * picture,
GstVaapiEncPackedHeader * header);
G_GNUC_INTERNAL
void
gst_vaapi_enc_picture_add_misc_param (GstVaapiEncPicture * picture,
GstVaapiEncMiscParam * misc);
G_GNUC_INTERNAL
void
gst_vaapi_enc_picture_add_slice (GstVaapiEncPicture * picture,
GstVaapiEncSlice * slice);
G_GNUC_INTERNAL
void
gst_vaapi_enc_slice_add_packed_header (GstVaapiEncSlice *slice,
GstVaapiEncPackedHeader * header);
G_GNUC_INTERNAL
gboolean
gst_vaapi_enc_picture_encode (GstVaapiEncPicture * picture);
#define gst_vaapi_enc_picture_ref(picture) \
gst_vaapi_codec_object_ref (picture)
#define gst_vaapi_enc_picture_unref(picture) \
gst_vaapi_codec_object_unref (picture)
#define gst_vaapi_enc_picture_replace(old_picture_ptr, new_picture) \
gst_vaapi_codec_object_replace (old_picture_ptr, new_picture)
/* ------------------------------------------------------------------------- */
/* --- Helpers to create codec-dependent objects --- */
/* ------------------------------------------------------------------------- */
/* GstVaapiEncSequence */
#define GST_VAAPI_ENC_SEQUENCE_NEW(codec, encoder) \
gst_vaapi_enc_sequence_new (GST_VAAPI_ENCODER_CAST (encoder), \
NULL, sizeof (G_PASTE (VAEncSequenceParameterBuffer, codec)))
/* GstVaapiEncMiscParam */
#define GST_VAAPI_ENC_MISC_PARAM_NEW(type, encoder) \
gst_vaapi_enc_misc_param_new (GST_VAAPI_ENCODER_CAST (encoder), \
G_PASTE (VAEncMiscParameterType, type), \
sizeof (G_PASTE (VAEncMiscParameter, type)))
/* GstVaapiEncQualityLevelMiscParam */
#define GST_VAAPI_ENC_QUALITY_LEVEL_MISC_PARAM_NEW(encoder) \
gst_vaapi_enc_misc_param_new (GST_VAAPI_ENCODER_CAST (encoder), \
VAEncMiscParameterTypeQualityLevel, \
sizeof (VAEncMiscParameterBufferQualityLevel))
/* GstVaapiEncQuantizationMiscParam */
#define GST_VAAPI_ENC_QUANTIZATION_MISC_PARAM_NEW(encoder) \
gst_vaapi_enc_misc_param_new (GST_VAAPI_ENCODER_CAST (encoder), \
VAEncMiscParameterTypeQuantization, \
sizeof (VAEncMiscParameterQuantization))
/* GstVaapiEncPicture */
#define GST_VAAPI_ENC_PICTURE_NEW(codec, encoder, frame) \
gst_vaapi_enc_picture_new (GST_VAAPI_ENCODER_CAST (encoder), \
NULL, sizeof (G_PASTE (VAEncPictureParameterBuffer, codec)), frame)
/* GstVaapiEncSlice */
#define GST_VAAPI_ENC_SLICE_NEW(codec, encoder) \
gst_vaapi_enc_slice_new (GST_VAAPI_ENCODER_CAST (encoder), \
NULL, sizeof(G_PASTE (VAEncSliceParameterBuffer, codec)))
/* GstVaapiEncQuantMatrix */
#define GST_VAAPI_ENC_Q_MATRIX_NEW(codec, encoder) \
gst_vaapi_enc_q_matrix_new (GST_VAAPI_ENCODER_CAST (encoder), \
NULL, sizeof (G_PASTE (VAQMatrixBuffer, codec)))
/* GstVaapiEncHuffmanTable */
#define GST_VAAPI_ENC_HUFFMAN_TABLE_NEW(codec, encoder) \
gst_vaapi_enc_huffman_table_new (GST_VAAPI_ENCODER_CAST (encoder), \
NULL, sizeof (G_PASTE (VAHuffmanTableBuffer, codec)))
G_END_DECLS
#endif /* GST_VAAPI_ENCODER_OBJECTS_H */

View file

@ -0,0 +1,394 @@
/*
* gstvaapiencoder_priv.h - VA encoder abstraction (private definitions)
*
* Copyright (C) 2013-2014 Intel Corporation
* Author: Wind Yuan <feng.yuan@intel.com>
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_ENCODER_PRIV_H
#define GST_VAAPI_ENCODER_PRIV_H
#include <gst/vaapi/gstvaapiencoder.h>
#include <gst/vaapi/gstvaapiencoder_objects.h>
#include <gst/vaapi/gstvaapicontext.h>
#include <gst/vaapi/gstvaapivideopool.h>
#include <gst/video/gstvideoutils.h>
#include <gst/vaapi/gstvaapivalue.h>
G_BEGIN_DECLS
#define GST_VAAPI_ENCODER_CAST(encoder) \
((GstVaapiEncoder *)(encoder))
#define GST_VAAPI_ENCODER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VAAPI_ENCODER, GstVaapiEncoderClass))
#define GST_VAAPI_ENCODER_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VAAPI_ENCODER, GstVaapiEncoderClass))
/**
* GST_VAAPI_ENCODER_PACKED_HEADERS:
* @encoder: a #GstVaapiEncoder
*
* Macro that evaluates to the required set of VA packed headers that
* need to be submitted along with the corresponding param buffers.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_ENCODER_PACKED_HEADERS
#define GST_VAAPI_ENCODER_PACKED_HEADERS(encoder) \
GST_VAAPI_ENCODER_CAST(encoder)->packed_headers
/**
* GST_VAAPI_ENCODER_DISPLAY:
* @encoder: a #GstVaapiEncoder
*
* Macro that evaluates to the #GstVaapiDisplay of @encoder.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_ENCODER_DISPLAY
#define GST_VAAPI_ENCODER_DISPLAY(encoder) \
GST_VAAPI_ENCODER_CAST(encoder)->display
/**
* GST_VAAPI_ENCODER_CONTEXT:
* @encoder: a #GstVaapiEncoder
*
* Macro that evaluates to the #GstVaapiContext of @encoder.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_ENCODER_CONTEXT
#define GST_VAAPI_ENCODER_CONTEXT(encoder) \
GST_VAAPI_ENCODER_CAST(encoder)->context
/**
* GST_VAAPI_ENCODER_VIDEO_INFO:
* @encoder: a #GstVaapiEncoder
*
* Macro that evaluates to the #GstVideoInfo of @encoder.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_ENCODER_VIDEO_INFO
#define GST_VAAPI_ENCODER_VIDEO_INFO(encoder) \
(&GST_VAAPI_ENCODER_CAST (encoder)->video_info)
/**
* GST_VAAPI_ENCODER_WIDTH:
* @encoder: a #GstVaapiEncoder
*
* Macro that evaluates to the coded width of the picture.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_ENCODER_WIDTH
#define GST_VAAPI_ENCODER_WIDTH(encoder) \
(GST_VAAPI_ENCODER_VIDEO_INFO (encoder)->width)
/**
* GST_VAAPI_ENCODER_HEIGHT:
* @encoder: a #GstVaapiEncoder
*
* Macro that evaluates to the coded height of the picture.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_ENCODER_HEIGHT
#define GST_VAAPI_ENCODER_HEIGHT(encoder) \
(GST_VAAPI_ENCODER_VIDEO_INFO (encoder)->height)
/**
* GST_VAAPI_ENCODER_FPS_N:
* @encoder: a #GstVaapiEncoder
*
* Macro that evaluates to the coded framerate numerator.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_ENCODER_FPS_N
#define GST_VAAPI_ENCODER_FPS_N(encoder) \
(GST_VAAPI_ENCODER_VIDEO_INFO (encoder)->fps_n)
/**
* GST_VAAPI_ENCODER_FPS_D:
* @encoder: a #GstVaapiEncoder
*
* Macro that evaluates to the coded framerate denominator.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_ENCODER_FPS_D
#define GST_VAAPI_ENCODER_FPS_D(encoder) \
(GST_VAAPI_ENCODER_VIDEO_INFO (encoder)->fps_d)
/**
* GST_VAAPI_ENCODER_RATE_CONTROL:
* @encoder: a #GstVaapiEncoder
*
* Macro that evaluates to the rate control.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_ENCODER_RATE_CONTROL
#define GST_VAAPI_ENCODER_RATE_CONTROL(encoder) \
(GST_VAAPI_ENCODER_CAST (encoder)->rate_control)
/**
* GST_VAAPI_ENCODER_KEYFRAME_PERIOD:
* @encoder: a #GstVaapiEncoder
*
* Macro that evaluates to the keyframe period.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_ENCODER_KEYFRAME_PERIOD
#define GST_VAAPI_ENCODER_KEYFRAME_PERIOD(encoder) \
(GST_VAAPI_ENCODER_CAST (encoder)->keyframe_period)
/**
* GST_VAAPI_ENCODER_TUNE:
* @encoder: a #GstVaapiEncoder
*
* Macro that evaluates to the tuning option.
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_ENCODER_TUNE
#define GST_VAAPI_ENCODER_TUNE(encoder) \
(GST_VAAPI_ENCODER_CAST (encoder)->tune)
/**
* GST_VAAPI_ENCODER_QUALITY_LEVEL:
* @encoder: a #GstVaapiEncoder
*
* Macro that evaluates to the quality level
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_ENCODER_QUALITY_LEVEL
#define GST_VAAPI_ENCODER_QUALITY_LEVEL(encoder) \
(GST_VAAPI_ENCODER_CAST (encoder)->va_quality_level.quality_level)
/**
* GST_VAAPI_ENCODER_VA_RATE_CONTROL:
* @encoder: a #GstVaapiEncoder
*
* Macro that evaluates to #VAEncMiscParameterRateControl
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_ENCODER_VA_RATE_CONTROL
#define GST_VAAPI_ENCODER_VA_RATE_CONTROL(encoder) \
(GST_VAAPI_ENCODER_CAST (encoder)->va_ratecontrol)
/**
* GST_VAAPI_ENCODER_VA_FRAME_RATE:
* @encoder: a #GstVaapiEncoder
*
* Macro that evaluates to #VAEncMiscParameterFrameRate
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_ENCODER_VA_FRAME_RATE
#define GST_VAAPI_ENCODER_VA_FRAME_RATE(encoder) \
(GST_VAAPI_ENCODER_CAST (encoder)->va_framerate)
/**
* GST_VAAPI_ENCODER_VA_HRD:
* @encoder: a #GstVaapiEncoder
*
* Macro that evaluates to #VAEncMiscParameterHRD
* This is an internal macro that does not do any run-time type check.
*/
#undef GST_VAAPI_ENCODER_VA_HRD
#define GST_VAAPI_ENCODER_VA_HRD(encoder) \
(GST_VAAPI_ENCODER_CAST (encoder)->va_hrd)
/* Generate a mask for the supplied tuning option (internal) */
#define GST_VAAPI_ENCODER_TUNE_MASK(TUNE) \
(1U << G_PASTE (GST_VAAPI_ENCODER_TUNE_, TUNE))
#define GST_VAAPI_TYPE_ENCODER_TUNE \
(gst_vaapi_encoder_tune_get_type ())
#define GST_VAAPI_TYPE_ENCODER_MBBRC \
(gst_vaapi_encoder_mbbrc_get_type ())
typedef struct _GstVaapiEncoderClass GstVaapiEncoderClass;
typedef struct _GstVaapiEncoderClassData GstVaapiEncoderClassData;
struct _GstVaapiEncoder
{
/*< private >*/
GstObject parent_instance;
GPtrArray *properties;
GstVaapiDisplay *display;
GstVaapiContext *context;
GstVaapiContextInfo context_info;
GstVaapiEncoderTune tune;
guint packed_headers;
VADisplay va_display;
VAContextID va_context;
GstVideoInfo video_info;
GstVaapiProfile profile;
guint num_ref_frames;
GstVaapiRateControl rate_control;
guint32 rate_control_mask;
guint bitrate; /* kbps */
guint target_percentage;
guint keyframe_period;
/* Maximum number of reference frames supported
* for the reference picture list 0 and list 2 */
guint max_num_ref_frames_0;
guint max_num_ref_frames_1;
/* parameters */
VAEncMiscParameterBufferQualityLevel va_quality_level;
GMutex mutex;
GCond surface_free;
GCond codedbuf_free;
guint codedbuf_size;
GstVaapiVideoPool *codedbuf_pool;
GAsyncQueue *codedbuf_queue;
guint32 num_codedbuf_queued;
guint got_packed_headers:1;
guint got_rate_control_mask:1;
/* miscellaneous buffer parameters */
VAEncMiscParameterRateControl va_ratecontrol;
VAEncMiscParameterFrameRate va_framerate;
VAEncMiscParameterHRD va_hrd;
gint8 default_roi_value;
/* trellis quantization */
gboolean trellis;
};
struct _GstVaapiEncoderClassData
{
/*< private >*/
GstVaapiCodec codec;
guint32 packed_headers;
GType (*rate_control_get_type)(void);
GstVaapiRateControl default_rate_control;
guint32 rate_control_mask;
GType (*encoder_tune_get_type)(void);
GstVaapiEncoderTune default_encoder_tune;
guint32 encoder_tune_mask;
};
#define GST_VAAPI_ENCODER_DEFINE_CLASS_DATA(CODEC) \
GST_VAAPI_TYPE_DEFINE_ENUM_SUBSET_FROM_MASK( \
G_PASTE (GstVaapiRateControl, CODEC), \
G_PASTE (gst_vaapi_rate_control_, CODEC), \
GST_VAAPI_TYPE_RATE_CONTROL, SUPPORTED_RATECONTROLS); \
\
GST_VAAPI_TYPE_DEFINE_ENUM_SUBSET_FROM_MASK( \
G_PASTE (GstVaapiEncoderTune, CODEC), \
G_PASTE (gst_vaapi_encoder_tune_, CODEC), \
GST_VAAPI_TYPE_ENCODER_TUNE, SUPPORTED_TUNE_OPTIONS); \
\
static const GstVaapiEncoderClassData g_class_data = { \
.codec = G_PASTE (GST_VAAPI_CODEC_, CODEC), \
.packed_headers = SUPPORTED_PACKED_HEADERS, \
.rate_control_get_type = \
G_PASTE (G_PASTE (gst_vaapi_rate_control_, CODEC), _get_type), \
.default_rate_control = DEFAULT_RATECONTROL, \
.rate_control_mask = SUPPORTED_RATECONTROLS, \
.encoder_tune_get_type = \
G_PASTE (G_PASTE (gst_vaapi_encoder_tune_, CODEC), _get_type), \
.default_encoder_tune = GST_VAAPI_ENCODER_TUNE_NONE, \
.encoder_tune_mask = SUPPORTED_TUNE_OPTIONS, \
}
struct _GstVaapiEncoderClass
{
/*< private >*/
GstObjectClass parent_class;
const GstVaapiEncoderClassData *class_data;
GstVaapiEncoderStatus (*reconfigure) (GstVaapiEncoder * encoder);
GstVaapiEncoderStatus (*reordering) (GstVaapiEncoder * encoder,
GstVideoCodecFrame * in,
GstVaapiEncPicture ** out);
GstVaapiEncoderStatus (*encode) (GstVaapiEncoder * encoder,
GstVaapiEncPicture * picture,
GstVaapiCodedBufferProxy * codedbuf);
GstVaapiEncoderStatus (*flush) (GstVaapiEncoder * encoder);
/* get_codec_data can be NULL */
GstVaapiEncoderStatus (*get_codec_data) (GstVaapiEncoder * encoder,
GstBuffer ** codec_data);
/* Iterator that retrieves the pending pictures in the reordered
* list */
gboolean (*get_pending_reordered) (GstVaapiEncoder * encoder,
GstVaapiEncPicture ** picture,
gpointer * state);
};
G_GNUC_INTERNAL
GstVaapiSurfaceProxy *
gst_vaapi_encoder_create_surface (GstVaapiEncoder *
encoder);
static inline void
gst_vaapi_encoder_release_surface (GstVaapiEncoder * encoder,
GstVaapiSurfaceProxy * proxy)
{
gst_vaapi_surface_proxy_unref (proxy);
}
G_GNUC_INTERNAL
gboolean
gst_vaapi_encoder_ensure_param_quality_level (GstVaapiEncoder * encoder,
GstVaapiEncPicture * picture);
G_GNUC_INTERNAL
gboolean
gst_vaapi_encoder_ensure_param_control_rate (GstVaapiEncoder * encoder,
GstVaapiEncPicture * picture);
G_GNUC_INTERNAL
gboolean
gst_vaapi_encoder_ensure_param_roi_regions (GstVaapiEncoder * encoder,
GstVaapiEncPicture * picture);
G_GNUC_INTERNAL
gboolean
gst_vaapi_encoder_ensure_param_trellis (GstVaapiEncoder * encoder,
GstVaapiEncPicture * picture);
G_GNUC_INTERNAL
gboolean
gst_vaapi_encoder_ensure_num_slices (GstVaapiEncoder * encoder,
GstVaapiProfile profile, GstVaapiEntrypoint entrypoint,
guint media_max_slices, guint * num_slices);
G_GNUC_INTERNAL
gboolean
gst_vaapi_encoder_ensure_max_num_ref_frames (GstVaapiEncoder * encoder,
GstVaapiProfile profile, GstVaapiEntrypoint entrypoint);
G_GNUC_INTERNAL
gboolean
gst_vaapi_encoder_ensure_tile_support (GstVaapiEncoder * encoder,
GstVaapiProfile profile, GstVaapiEntrypoint entrypoint);
G_END_DECLS
#endif /* GST_VAAPI_ENCODER_PRIV_H */

View file

@ -0,0 +1,701 @@
/*
* gstvaapiencoder_vp8.c - VP8 encoder
*
* Copyright (C) 2015 Intel Corporation
* Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
*
* 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 "sysdeps.h"
#include <gst/base/gstbitwriter.h>
#include <gst/codecparsers/gstvp8parser.h>
#include "gstvaapicompat.h"
#include "gstvaapiencoder_priv.h"
#include "gstvaapiencoder_vp8.h"
#include "gstvaapicodedbufferproxy_priv.h"
#include "gstvaapisurface.h"
#define DEBUG 1
#include "gstvaapidebug.h"
/* Define default rate control mode ("constant-qp") */
#define DEFAULT_RATECONTROL GST_VAAPI_RATECONTROL_CQP
/* Supported set of VA rate controls, within this implementation */
#define SUPPORTED_RATECONTROLS \
(GST_VAAPI_RATECONTROL_MASK (CQP) | \
GST_VAAPI_RATECONTROL_MASK (CBR) | \
GST_VAAPI_RATECONTROL_MASK (VBR))
/* Supported set of tuning options, within this implementation */
#define SUPPORTED_TUNE_OPTIONS \
(GST_VAAPI_ENCODER_TUNE_MASK (NONE))
/* Supported set of VA packed headers, within this implementation */
#define SUPPORTED_PACKED_HEADERS \
(VA_ENC_PACKED_HEADER_NONE)
#define DEFAULT_LOOP_FILTER_LEVEL 0
#define DEFAULT_SHARPNESS_LEVEL 0
#define DEFAULT_YAC_QI 40
/* ------------------------------------------------------------------------- */
/* --- VP8 Encoder --- */
/* ------------------------------------------------------------------------- */
struct _GstVaapiEncoderVP8
{
GstVaapiEncoder parent_instance;
GstVaapiProfile profile;
guint loop_filter_level;
guint sharpness_level;
guint yac_qi;
guint frame_num;
/* reference list */
GstVaapiSurfaceProxy *last_ref;
GstVaapiSurfaceProxy *golden_ref;
GstVaapiSurfaceProxy *alt_ref;
};
/* Derives the profile that suits best to the configuration */
static GstVaapiEncoderStatus
ensure_profile (GstVaapiEncoderVP8 * encoder)
{
/* Always start from "simple" profile for maximum compatibility */
encoder->profile = GST_VAAPI_PROFILE_VP8;
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
}
/* Derives the profile supported by the underlying hardware */
static gboolean
ensure_hw_profile (GstVaapiEncoderVP8 * encoder)
{
GstVaapiDisplay *const display = GST_VAAPI_ENCODER_DISPLAY (encoder);
GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_SLICE_ENCODE;
GstVaapiProfile profile, profiles[2];
guint i, num_profiles = 0;
profiles[num_profiles++] = encoder->profile;
profile = GST_VAAPI_PROFILE_UNKNOWN;
for (i = 0; i < num_profiles; i++) {
if (gst_vaapi_display_has_encoder (display, profiles[i], entrypoint)) {
profile = profiles[i];
break;
}
}
if (profile == GST_VAAPI_PROFILE_UNKNOWN)
goto error_unsupported_profile;
GST_VAAPI_ENCODER_CAST (encoder)->profile = profile;
return TRUE;
/* ERRORS */
error_unsupported_profile:
{
GST_ERROR ("unsupported HW profile %s",
gst_vaapi_profile_get_va_name (encoder->profile));
return FALSE;
}
}
static gboolean
ensure_bitrate (GstVaapiEncoderVP8 * encoder)
{
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
/* Default compression: 64 bits per macroblock */
switch (GST_VAAPI_ENCODER_RATE_CONTROL (encoder)) {
case GST_VAAPI_RATECONTROL_CBR:
case GST_VAAPI_RATECONTROL_VBR:
if (!base_encoder->bitrate) {
base_encoder->bitrate =
gst_util_uint64_scale (GST_VAAPI_ENCODER_WIDTH (encoder) *
GST_VAAPI_ENCODER_HEIGHT (encoder),
GST_VAAPI_ENCODER_FPS_N (encoder),
GST_VAAPI_ENCODER_FPS_D (encoder)) / (4 * 1000);
}
break;
default:
base_encoder->bitrate = 0;
break;
}
return TRUE;
}
static GstVaapiEncoderStatus
set_context_info (GstVaapiEncoder * base_encoder)
{
GstVaapiEncoderVP8 *encoder = GST_VAAPI_ENCODER_VP8 (base_encoder);
GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
/* Maximum sizes for common headers (in bytes) */
enum
{
MAX_FRAME_TAG_SIZE = 10,
MAX_UPDATE_SEGMENTATION_SIZE = 13,
MAX_MB_LF_ADJUSTMENTS_SIZE = 9,
MAX_QUANT_INDICES_SIZE = 5,
MAX_TOKEN_PROB_UPDATE_SIZE = 1188,
MAX_MV_PROBE_UPDATE_SIZE = 38,
MAX_REST_OF_FRAME_HDR_SIZE = 15
};
if (!ensure_hw_profile (encoder))
return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
base_encoder->num_ref_frames = 3;
/* Only YUV 4:2:0 formats are supported for now. */
/* Assumig 4 times compression ratio */
base_encoder->codedbuf_size = GST_ROUND_UP_16 (vip->width) *
GST_ROUND_UP_16 (vip->height) * 12 / 4;
base_encoder->codedbuf_size +=
MAX_FRAME_TAG_SIZE + MAX_UPDATE_SEGMENTATION_SIZE +
MAX_MB_LF_ADJUSTMENTS_SIZE + MAX_QUANT_INDICES_SIZE +
MAX_TOKEN_PROB_UPDATE_SIZE + MAX_MV_PROBE_UPDATE_SIZE +
MAX_REST_OF_FRAME_HDR_SIZE;
base_encoder->context_info.profile = base_encoder->profile;
base_encoder->context_info.entrypoint = GST_VAAPI_ENTRYPOINT_SLICE_ENCODE;
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
}
static void
clear_ref (GstVaapiEncoderVP8 * encoder, GstVaapiSurfaceProxy ** ref)
{
if (*ref) {
gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder), *ref);
*ref = NULL;
}
}
static void
clear_references (GstVaapiEncoderVP8 * encoder)
{
clear_ref (encoder, &encoder->last_ref);
clear_ref (encoder, &encoder->golden_ref);
clear_ref (encoder, &encoder->alt_ref);
}
static void
push_reference (GstVaapiEncoderVP8 * encoder, GstVaapiSurfaceProxy * ref)
{
if (encoder->last_ref == NULL) {
encoder->golden_ref = gst_vaapi_surface_proxy_ref (ref);
encoder->alt_ref = gst_vaapi_surface_proxy_ref (ref);
} else {
clear_ref (encoder, &encoder->alt_ref);
encoder->alt_ref = encoder->golden_ref;
encoder->golden_ref = encoder->last_ref;
}
encoder->last_ref = ref;
}
static gboolean
fill_sequence (GstVaapiEncoderVP8 * encoder, GstVaapiEncSequence * sequence)
{
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
VAEncSequenceParameterBufferVP8 *const seq_param = sequence->param;
memset (seq_param, 0, sizeof (VAEncSequenceParameterBufferVP8));
seq_param->frame_width = GST_VAAPI_ENCODER_WIDTH (encoder);
seq_param->frame_height = GST_VAAPI_ENCODER_HEIGHT (encoder);
if (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CBR ||
GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_VBR)
seq_param->bits_per_second = base_encoder->bitrate * 1000;
seq_param->intra_period = base_encoder->keyframe_period;
return TRUE;
}
static gboolean
ensure_sequence (GstVaapiEncoderVP8 * encoder, GstVaapiEncPicture * picture)
{
GstVaapiEncSequence *sequence;
g_assert (picture);
if (picture->type != GST_VAAPI_PICTURE_TYPE_I)
return TRUE;
sequence = GST_VAAPI_ENC_SEQUENCE_NEW (VP8, encoder);
if (!sequence)
goto error;
if (!fill_sequence (encoder, sequence))
goto error;
gst_vaapi_enc_picture_set_sequence (picture, sequence);
gst_vaapi_codec_object_replace (&sequence, NULL);
return TRUE;
/* ERRORS */
error:
{
gst_vaapi_codec_object_replace (&sequence, NULL);
return FALSE;
}
}
static gboolean
ensure_control_rate_params (GstVaapiEncoderVP8 * encoder)
{
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
if (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CQP)
return TRUE;
/* RateControl params */
GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).initial_qp = encoder->yac_qi;
GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).min_qp = 1;
/* *INDENT-OFF* */
/* HRD params */
GST_VAAPI_ENCODER_VA_HRD (encoder) = (VAEncMiscParameterHRD) {
.buffer_size = base_encoder->bitrate * 1000 * 2,
.initial_buffer_fullness = base_encoder->bitrate * 1000,
};
/* *INDENT-ON* */
return TRUE;
}
static gboolean
ensure_misc_params (GstVaapiEncoderVP8 * encoder, GstVaapiEncPicture * picture)
{
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
if (!gst_vaapi_encoder_ensure_param_quality_level (base_encoder, picture))
return FALSE;
if (!gst_vaapi_encoder_ensure_param_control_rate (base_encoder, picture))
return FALSE;
return TRUE;
}
static gboolean
fill_picture (GstVaapiEncoderVP8 * encoder,
GstVaapiEncPicture * picture,
GstVaapiCodedBuffer * codedbuf, GstVaapiSurfaceProxy * surface)
{
VAEncPictureParameterBufferVP8 *const pic_param = picture->param;
int i;
memset (pic_param, 0, sizeof (VAEncPictureParameterBufferVP8));
pic_param->reconstructed_frame = GST_VAAPI_SURFACE_PROXY_SURFACE_ID (surface);
pic_param->coded_buf = GST_VAAPI_CODED_BUFFER_ID (codedbuf);
if (picture->type == GST_VAAPI_PICTURE_TYPE_P) {
pic_param->pic_flags.bits.frame_type = 1;
pic_param->ref_arf_frame =
GST_VAAPI_SURFACE_PROXY_SURFACE_ID (encoder->alt_ref);
pic_param->ref_gf_frame =
GST_VAAPI_SURFACE_PROXY_SURFACE_ID (encoder->golden_ref);
pic_param->ref_last_frame =
GST_VAAPI_SURFACE_PROXY_SURFACE_ID (encoder->last_ref);
pic_param->pic_flags.bits.refresh_last = 1;
pic_param->pic_flags.bits.refresh_golden_frame = 0;
pic_param->pic_flags.bits.copy_buffer_to_golden = 1;
pic_param->pic_flags.bits.refresh_alternate_frame = 0;
pic_param->pic_flags.bits.copy_buffer_to_alternate = 2;
} else {
pic_param->ref_last_frame = VA_INVALID_SURFACE;
pic_param->ref_gf_frame = VA_INVALID_SURFACE;
pic_param->ref_arf_frame = VA_INVALID_SURFACE;
pic_param->pic_flags.bits.refresh_last = 1;
pic_param->pic_flags.bits.refresh_golden_frame = 1;
pic_param->pic_flags.bits.refresh_alternate_frame = 1;
}
pic_param->pic_flags.bits.show_frame = 1;
if (encoder->loop_filter_level) {
pic_param->pic_flags.bits.version = 1;
pic_param->pic_flags.bits.loop_filter_type = 1; /* Enable simple loop filter */
/* Disabled segmentation, so what matters is only loop_filter_level[0] */
for (i = 0; i < 4; i++)
pic_param->loop_filter_level[i] = encoder->loop_filter_level;
}
pic_param->sharpness_level = encoder->sharpness_level;
/* Used for CBR */
pic_param->clamp_qindex_low = 0;
pic_param->clamp_qindex_high = 127;
return TRUE;
}
static gboolean
ensure_picture (GstVaapiEncoderVP8 * encoder, GstVaapiEncPicture * picture,
GstVaapiCodedBufferProxy * codedbuf_proxy, GstVaapiSurfaceProxy * surface)
{
GstVaapiCodedBuffer *const codedbuf =
GST_VAAPI_CODED_BUFFER_PROXY_BUFFER (codedbuf_proxy);
if (!fill_picture (encoder, picture, codedbuf, surface))
return FALSE;
return TRUE;
}
static gboolean
fill_quantization_table (GstVaapiEncoderVP8 * encoder,
GstVaapiEncPicture * picture, GstVaapiEncQMatrix * q_matrix)
{
VAQMatrixBufferVP8 *const qmatrix_param = q_matrix->param;
int i;
memset (qmatrix_param, 0, sizeof (VAQMatrixBufferVP8));
/* DefaultYacQantVal = 8 for I frame, which is ac_qlookup[4] and
* DefaultYacQantVAl = 44 for P frame, which is ac_qllookup[40] */
for (i = 0; i < 4; i++) {
if (encoder->yac_qi == DEFAULT_YAC_QI) {
if (picture->type == GST_VAAPI_PICTURE_TYPE_I)
qmatrix_param->quantization_index[i] = 4;
else
qmatrix_param->quantization_index[i] = 40;
} else
qmatrix_param->quantization_index[i] = encoder->yac_qi;
}
return TRUE;
}
static gboolean
ensure_quantization_table (GstVaapiEncoderVP8 * encoder,
GstVaapiEncPicture * picture)
{
g_assert (picture);
picture->q_matrix = GST_VAAPI_ENC_Q_MATRIX_NEW (VP8, encoder);
if (!picture->q_matrix) {
GST_ERROR ("failed to allocate quantiser table");
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
}
if (!fill_quantization_table (encoder, picture, picture->q_matrix))
return FALSE;
return TRUE;
}
static GstVaapiEncoderStatus
gst_vaapi_encoder_vp8_encode (GstVaapiEncoder * base_encoder,
GstVaapiEncPicture * picture, GstVaapiCodedBufferProxy * codedbuf)
{
GstVaapiEncoderVP8 *const encoder = GST_VAAPI_ENCODER_VP8 (base_encoder);
GstVaapiEncoderStatus ret = GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
GstVaapiSurfaceProxy *reconstruct = NULL;
reconstruct = gst_vaapi_encoder_create_surface (base_encoder);
g_assert (GST_VAAPI_SURFACE_PROXY_SURFACE (reconstruct));
if (!ensure_sequence (encoder, picture))
goto error;
if (!ensure_misc_params (encoder, picture))
goto error;
if (!ensure_picture (encoder, picture, codedbuf, reconstruct))
goto error;
if (!ensure_quantization_table (encoder, picture))
goto error;
if (!gst_vaapi_enc_picture_encode (picture))
goto error;
if (reconstruct) {
if (picture->type == GST_VAAPI_PICTURE_TYPE_I)
clear_references (encoder);
push_reference (encoder, reconstruct);
}
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
/* ERRORS */
error:
{
if (reconstruct)
gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder),
reconstruct);
return ret;
}
}
static GstVaapiEncoderStatus
gst_vaapi_encoder_vp8_flush (GstVaapiEncoder * base_encoder)
{
GstVaapiEncoderVP8 *const encoder = GST_VAAPI_ENCODER_VP8 (base_encoder);
encoder->frame_num = 0;
clear_references (encoder);
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
}
static GstVaapiEncoderStatus
gst_vaapi_encoder_vp8_reordering (GstVaapiEncoder * base_encoder,
GstVideoCodecFrame * frame, GstVaapiEncPicture ** output)
{
GstVaapiEncoderVP8 *const encoder = GST_VAAPI_ENCODER_VP8 (base_encoder);
GstVaapiEncPicture *picture = NULL;
GstVaapiEncoderStatus status = GST_VAAPI_ENCODER_STATUS_SUCCESS;
if (!frame)
return GST_VAAPI_ENCODER_STATUS_NO_SURFACE;
picture = GST_VAAPI_ENC_PICTURE_NEW (VP8, encoder, frame);
if (!picture) {
GST_WARNING ("create VP8 picture failed, frame timestamp:%"
GST_TIME_FORMAT, GST_TIME_ARGS (frame->pts));
return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
}
if (encoder->frame_num >= base_encoder->keyframe_period) {
encoder->frame_num = 0;
clear_references (encoder);
}
if (encoder->frame_num == 0) {
picture->type = GST_VAAPI_PICTURE_TYPE_I;
GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
} else {
picture->type = GST_VAAPI_PICTURE_TYPE_P;
}
encoder->frame_num++;
*output = picture;
return status;
}
static GstVaapiEncoderStatus
gst_vaapi_encoder_vp8_reconfigure (GstVaapiEncoder * base_encoder)
{
GstVaapiEncoderVP8 *const encoder = GST_VAAPI_ENCODER_VP8 (base_encoder);
GstVaapiEncoderStatus status;
status = ensure_profile (encoder);
if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
return status;
if (!ensure_bitrate (encoder))
goto error;
ensure_control_rate_params (encoder);
return set_context_info (base_encoder);
/* ERRORS */
error:
{
return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
}
}
struct _GstVaapiEncoderVP8Class
{
GstVaapiEncoderClass parent_class;
};
G_DEFINE_TYPE (GstVaapiEncoderVP8, gst_vaapi_encoder_vp8,
GST_TYPE_VAAPI_ENCODER);
static void
gst_vaapi_encoder_vp8_init (GstVaapiEncoderVP8 * encoder)
{
encoder->frame_num = 0;
encoder->last_ref = NULL;
encoder->golden_ref = NULL;
encoder->alt_ref = NULL;
}
static void
gst_vaapi_encoder_vp8_finalize (GObject * object)
{
GstVaapiEncoderVP8 *const encoder = GST_VAAPI_ENCODER_VP8 (object);
clear_references (encoder);
G_OBJECT_CLASS (gst_vaapi_encoder_vp8_parent_class)->finalize (object);
}
/**
* @ENCODER_VP8_PROP_RATECONTROL: Rate control (#GstVaapiRateControl).
* @ENCODER_VP8_PROP_TUNE: The tuning options (#GstVaapiEncoderTune).
* @ENCODER_VP8_PROP_LOOP_FILTER_LEVEL: Loop Filter Level(uint).
* @ENCODER_VP8_PROP_LOOP_SHARPNESS_LEVEL: Sharpness Level(uint).
* @ENCODER_VP8_PROP_YAC_Q_INDEX: Quantization table index for luma AC(uint).
*
* The set of VP8 encoder specific configurable properties.
*/
enum
{
ENCODER_VP8_PROP_RATECONTROL = 1,
ENCODER_VP8_PROP_TUNE,
ENCODER_VP8_PROP_LOOP_FILTER_LEVEL,
ENCODER_VP8_PROP_SHARPNESS_LEVEL,
ENCODER_VP8_PROP_YAC_Q_INDEX,
ENCODER_VP8_N_PROPERTIES
};
static GParamSpec *properties[ENCODER_VP8_N_PROPERTIES];
static void
gst_vaapi_encoder_vp8_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER (object);
GstVaapiEncoderVP8 *const encoder = GST_VAAPI_ENCODER_VP8 (object);
if (base_encoder->num_codedbuf_queued > 0) {
GST_ERROR_OBJECT (object,
"failed to set any property after encoding started");
return;
}
switch (prop_id) {
case ENCODER_VP8_PROP_RATECONTROL:
gst_vaapi_encoder_set_rate_control (base_encoder,
g_value_get_enum (value));
break;
case ENCODER_VP8_PROP_TUNE:
gst_vaapi_encoder_set_tuning (base_encoder, g_value_get_enum (value));
break;
case ENCODER_VP8_PROP_LOOP_FILTER_LEVEL:
encoder->loop_filter_level = g_value_get_uint (value);
break;
case ENCODER_VP8_PROP_SHARPNESS_LEVEL:
encoder->sharpness_level = g_value_get_uint (value);
break;
case ENCODER_VP8_PROP_YAC_Q_INDEX:
encoder->yac_qi = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
gst_vaapi_encoder_vp8_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstVaapiEncoderVP8 *const encoder = GST_VAAPI_ENCODER_VP8 (object);
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER (object);
switch (prop_id) {
case ENCODER_VP8_PROP_RATECONTROL:
g_value_set_enum (value, base_encoder->rate_control);
break;
case ENCODER_VP8_PROP_TUNE:
g_value_set_enum (value, base_encoder->tune);
break;
case ENCODER_VP8_PROP_LOOP_FILTER_LEVEL:
g_value_set_uint (value, encoder->loop_filter_level);
break;
case ENCODER_VP8_PROP_SHARPNESS_LEVEL:
g_value_set_uint (value, encoder->sharpness_level);
break;
case ENCODER_VP8_PROP_YAC_Q_INDEX:
g_value_set_uint (value, encoder->yac_qi);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
GST_VAAPI_ENCODER_DEFINE_CLASS_DATA (VP8);
static void
gst_vaapi_encoder_vp8_class_init (GstVaapiEncoderVP8Class * klass)
{
GObjectClass *const object_class = G_OBJECT_CLASS (klass);
GstVaapiEncoderClass *const encoder_class = GST_VAAPI_ENCODER_CLASS (klass);
encoder_class->class_data = &g_class_data;
encoder_class->reconfigure = gst_vaapi_encoder_vp8_reconfigure;
encoder_class->reordering = gst_vaapi_encoder_vp8_reordering;
encoder_class->encode = gst_vaapi_encoder_vp8_encode;
encoder_class->flush = gst_vaapi_encoder_vp8_flush;
object_class->set_property = gst_vaapi_encoder_vp8_set_property;
object_class->get_property = gst_vaapi_encoder_vp8_get_property;
object_class->finalize = gst_vaapi_encoder_vp8_finalize;
properties[ENCODER_VP8_PROP_RATECONTROL] =
g_param_spec_enum ("rate-control",
"Rate Control", "Rate control mode",
g_class_data.rate_control_get_type (),
g_class_data.default_rate_control,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
GST_VAAPI_PARAM_ENCODER_EXPOSURE);
properties[ENCODER_VP8_PROP_TUNE] =
g_param_spec_enum ("tune", "Encoder Tuning", "Encoder tuning option",
g_class_data.encoder_tune_get_type (),
g_class_data.default_encoder_tune,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
GST_VAAPI_PARAM_ENCODER_EXPOSURE);
properties[ENCODER_VP8_PROP_LOOP_FILTER_LEVEL] =
g_param_spec_uint ("loop-filter-level", "Loop Filter Level",
"Controls the deblocking filter strength", 0, 63,
DEFAULT_LOOP_FILTER_LEVEL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
GST_VAAPI_PARAM_ENCODER_EXPOSURE);
properties[ENCODER_VP8_PROP_SHARPNESS_LEVEL] =
g_param_spec_uint ("sharpness-level", "Sharpness Level",
"Controls the deblocking filter sensitivity", 0, 7,
DEFAULT_SHARPNESS_LEVEL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
GST_VAAPI_PARAM_ENCODER_EXPOSURE);
properties[ENCODER_VP8_PROP_YAC_Q_INDEX] =
g_param_spec_uint ("yac-qi",
"Luma AC Quant Table index",
"Quantization Table index for Luma AC Coefficients,"
" (in default case, yac_qi=4 for key frames and yac_qi=40"
" for P frames)",
0, 127, DEFAULT_YAC_QI,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
GST_VAAPI_PARAM_ENCODER_EXPOSURE);
g_object_class_install_properties (object_class, ENCODER_VP8_N_PROPERTIES,
properties);
gst_type_mark_as_plugin_api (g_class_data.rate_control_get_type (), 0);
gst_type_mark_as_plugin_api (g_class_data.encoder_tune_get_type (), 0);
}
/**
* gst_vaapi_encoder_vp8_new:
* @display: a #GstVaapiDisplay
*
* Creates a new #GstVaapiEncoder for VP8 encoding.
*
* Return value: the newly allocated #GstVaapiEncoder object
*/
GstVaapiEncoder *
gst_vaapi_encoder_vp8_new (GstVaapiDisplay * display)
{
return g_object_new (GST_TYPE_VAAPI_ENCODER_VP8, "display", display, NULL);
}

View file

@ -0,0 +1,49 @@
/*
* gstvaapiencoder_vp8.h VP8G encoder
*
* Copyright (C) 2015 Intel Corporation
* Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
*
* 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_VAAPI_ENCODER_VP8_H
#define GST_VAAPI_ENCODER_VP8_H
#include <gst/vaapi/gstvaapiencoder.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_ENCODER_VP8 \
(gst_vaapi_encoder_vp8_get_type ())
#define GST_VAAPI_ENCODER_VP8(encoder) \
(G_TYPE_CHECK_INSTANCE_CAST ((encoder), GST_TYPE_VAAPI_ENCODER_VP8, GstVaapiEncoderVP8))
#define GST_IS_VAAPI_ENCODER_VP8(encoder) \
(G_TYPE_CHECK_INSTANCE_TYPE ((encoder), GST_TYPE_VAAPI_ENCODER_VP8))
typedef struct _GstVaapiEncoderVP8 GstVaapiEncoderVP8;
typedef struct _GstVaapiEncoderVP8Class GstVaapiEncoderVP8Class;
GType
gst_vaapi_encoder_vp8_get_type (void) G_GNUC_CONST;
GstVaapiEncoder *
gst_vaapi_encoder_vp8_new (GstVaapiDisplay * display);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiEncoderVP8, gst_object_unref)
G_END_DECLS
#endif /*GST_VAAPI_ENCODER_VP8_H */

View file

@ -0,0 +1,824 @@
/*
* gstvaapiencoder_vp9.c - VP9 encoder
*
* Copyright (C) 2016 Intel Corporation
* Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
*
* 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 "sysdeps.h"
#include <gst/base/gstbitwriter.h>
#include <gst/codecparsers/gstvp9parser.h>
#include "gstvaapicompat.h"
#include "gstvaapiencoder_priv.h"
#include "gstvaapiencoder_vp9.h"
#include "gstvaapicodedbufferproxy_priv.h"
#include "gstvaapisurface.h"
#include "gstvaapiutils_vpx.h"
#define DEBUG 1
#include "gstvaapidebug.h"
#define MAX_TILE_WIDTH_B64 64
/* Define default rate control mode ("constant-qp") */
#define DEFAULT_RATECONTROL GST_VAAPI_RATECONTROL_CQP
/* Supported set of VA rate controls, within this implementation */
#define SUPPORTED_RATECONTROLS \
(GST_VAAPI_RATECONTROL_MASK (CQP) | \
GST_VAAPI_RATECONTROL_MASK (CBR) | \
GST_VAAPI_RATECONTROL_MASK (VBR))
/* Supported set of tuning options, within this implementation */
#define SUPPORTED_TUNE_OPTIONS \
(GST_VAAPI_ENCODER_TUNE_MASK (NONE) | \
GST_VAAPI_ENCODER_TUNE_MASK (LOW_POWER))
/* Supported set of VA packed headers, within this implementation */
#define SUPPORTED_PACKED_HEADERS \
(VA_ENC_PACKED_HEADER_NONE)
#define DEFAULT_LOOP_FILTER_LEVEL 10
#define DEFAULT_SHARPNESS_LEVEL 0
#define DEFAULT_YAC_QINDEX 60
#define MAX_FRAME_WIDTH 4096
#define MAX_FRAME_HEIGHT 4096
/* Default CPB length (in milliseconds) */
#define DEFAULT_CPB_LENGTH 1500
typedef enum
{
GST_VAAPI_ENCODER_VP9_REF_PIC_MODE_0 = 0,
GST_VAAPI_ENCODER_VP9_REF_PIC_MODE_1 = 1
} GstVaapiEnoderVP9RefPicMode;
static GType
gst_vaapi_encoder_vp9_ref_pic_mode_type (void)
{
static GType gtype = 0;
if (gtype == 0) {
static const GEnumValue values[] = {
{GST_VAAPI_ENCODER_VP9_REF_PIC_MODE_0,
"Use Keyframe(Alt & Gold) and Previousframe(Last) for prediction ",
"mode-0"},
{GST_VAAPI_ENCODER_VP9_REF_PIC_MODE_1,
"Use last three frames for prediction (n:Last n-1:Gold n-2:Alt)",
"mode-1"},
{0, NULL, NULL},
};
gtype = g_enum_register_static ("GstVaapiEncoderVP9RefPicMode", values);
}
return gtype;
}
/* ------------------------------------------------------------------------- */
/* --- VP9 Encoder --- */
/* ------------------------------------------------------------------------- */
struct _GstVaapiEncoderVP9
{
GstVaapiEncoder parent_instance;
GstVaapiProfile profile;
guint loop_filter_level;
guint sharpness_level;
guint yac_qi;
guint ref_pic_mode;
guint frame_num;
GstVaapiSurfaceProxy *ref_list[GST_VP9_REF_FRAMES]; /* reference list */
guint ref_list_idx; /* next free slot in ref_list */
GstVaapiEntrypoint entrypoint;
GArray *allowed_profiles;
/* Bitrate contral parameters, CPB = Coded Picture Buffer */
guint bitrate_bits; /* bitrate (bits) */
guint cpb_length; /* length of CPB buffer (ms) */
};
/* Estimates a good enough bitrate if none was supplied */
static void
ensure_bitrate (GstVaapiEncoderVP9 * encoder)
{
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
guint bitrate;
switch (GST_VAAPI_ENCODER_RATE_CONTROL (encoder)) {
case GST_VAAPI_RATECONTROL_CBR:
case GST_VAAPI_RATECONTROL_VBR:
if (!base_encoder->bitrate) {
/* FIXME: Provide better estimation */
/* Using a 1/6 compression ratio */
/* 12 bits per pixel fro yuv420 */
base_encoder->bitrate =
(GST_VAAPI_ENCODER_WIDTH (encoder) *
GST_VAAPI_ENCODER_HEIGHT (encoder) * 12 / 6) *
GST_VAAPI_ENCODER_FPS_N (encoder) /
GST_VAAPI_ENCODER_FPS_D (encoder) / 1000;
GST_INFO ("target bitrate computed to %u kbps", base_encoder->bitrate);
}
bitrate = (base_encoder->bitrate * 1000);
if (bitrate != encoder->bitrate_bits) {
GST_DEBUG ("HRD bitrate: %u bits/sec", bitrate);
encoder->bitrate_bits = bitrate;
}
break;
default:
base_encoder->bitrate = 0;
break;
}
}
static gboolean
is_profile_allowed (GstVaapiEncoderVP9 * encoder, GstVaapiProfile profile)
{
guint i;
if (encoder->allowed_profiles == NULL)
return TRUE;
for (i = 0; i < encoder->allowed_profiles->len; i++)
if (profile ==
g_array_index (encoder->allowed_profiles, GstVaapiProfile, i))
return TRUE;
return FALSE;
}
/* Derives the profile that suits best to the configuration */
static GstVaapiEncoderStatus
ensure_profile (GstVaapiEncoderVP9 * encoder)
{
const GstVideoFormat format =
GST_VIDEO_INFO_FORMAT (GST_VAAPI_ENCODER_VIDEO_INFO (encoder));
guint depth, chrome;
if (!GST_VIDEO_FORMAT_INFO_IS_YUV (gst_video_format_get_info (format)))
return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
depth = GST_VIDEO_FORMAT_INFO_DEPTH (gst_video_format_get_info (format), 0);
chrome = gst_vaapi_utils_vp9_get_chroma_format_idc
(gst_vaapi_video_format_get_chroma_type
(GST_VIDEO_INFO_FORMAT (GST_VAAPI_ENCODER_VIDEO_INFO (encoder))));
encoder->profile = GST_VAAPI_PROFILE_UNKNOWN;
/*
Profile Color | Depth Chroma | Subsampling
0 | 8 bit/sample | 4:2:0
1 | 8 bit | 4:2:2, 4:4:4
2 | 10 or 12 bit | 4:2:0
3 | 10 or 12 bit | 4:2:2, 4:4:4 */
if (chrome == 3 || chrome == 2) {
/* 4:4:4 and 4:2:2 */
if (depth == 8) {
encoder->profile = GST_VAAPI_PROFILE_VP9_1;
} else if (depth == 10 || depth == 12) {
encoder->profile = GST_VAAPI_PROFILE_VP9_3;
}
} else if (chrome == 1) {
/* 4:2:0 */
if (depth == 8) {
encoder->profile = GST_VAAPI_PROFILE_VP9_0;
} else if (depth == 10 || depth == 12) {
encoder->profile = GST_VAAPI_PROFILE_VP9_2;
}
}
if (encoder->profile == GST_VAAPI_PROFILE_UNKNOWN) {
GST_WARNING ("Failed to decide VP9 profile");
return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
}
if (!is_profile_allowed (encoder, encoder->profile)) {
GST_WARNING ("Failed to find an allowed VP9 profile");
return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
}
/* Ensure bitrate if not set already */
ensure_bitrate (encoder);
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
}
static GstVaapiEncoderStatus
set_context_info (GstVaapiEncoder * base_encoder)
{
GstVaapiEncoderVP9 *encoder = GST_VAAPI_ENCODER_VP9 (base_encoder);
GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
const guint DEFAULT_SURFACES_COUNT = 2;
/* FIXME: Maximum sizes for common headers (in bytes) */
GST_VAAPI_ENCODER_CAST (encoder)->profile = encoder->profile;
base_encoder->num_ref_frames = 3 + DEFAULT_SURFACES_COUNT;
/* Only YUV 4:2:0 formats are supported for now. */
base_encoder->codedbuf_size = GST_ROUND_UP_16 (vip->width) *
GST_ROUND_UP_16 (vip->height) * 3 / 2;
base_encoder->context_info.profile = base_encoder->profile;
base_encoder->context_info.entrypoint = encoder->entrypoint;
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
}
static gboolean
fill_sequence (GstVaapiEncoderVP9 * encoder, GstVaapiEncSequence * sequence)
{
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
VAEncSequenceParameterBufferVP9 *const seq_param = sequence->param;
memset (seq_param, 0, sizeof (VAEncSequenceParameterBufferVP9));
seq_param->max_frame_width = MAX_FRAME_WIDTH;
seq_param->max_frame_height = MAX_FRAME_HEIGHT;
/* keyframe minimum interval */
seq_param->kf_min_dist = 1;
/* keyframe maximum interval */
seq_param->kf_max_dist = base_encoder->keyframe_period;
seq_param->intra_period = base_encoder->keyframe_period;
seq_param->bits_per_second = encoder->bitrate_bits;
return TRUE;
}
static gboolean
ensure_sequence (GstVaapiEncoderVP9 * encoder, GstVaapiEncPicture * picture)
{
GstVaapiEncSequence *sequence;
g_assert (picture);
if (picture->type != GST_VAAPI_PICTURE_TYPE_I)
return TRUE;
sequence = GST_VAAPI_ENC_SEQUENCE_NEW (VP9, encoder);
if (!sequence)
goto error;
if (!fill_sequence (encoder, sequence))
goto error;
gst_vaapi_enc_picture_set_sequence (picture, sequence);
gst_vaapi_codec_object_replace (&sequence, NULL);
return TRUE;
/* ERRORS */
error:
{
gst_vaapi_codec_object_replace (&sequence, NULL);
return FALSE;
}
}
static gboolean
ensure_control_rate_params (GstVaapiEncoderVP9 * encoder)
{
if (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CQP)
return TRUE;
/* RateControl params */
GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).bits_per_second =
encoder->bitrate_bits;
GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).window_size = encoder->cpb_length;
/* *INDENT-OFF* */
/* HRD params */
GST_VAAPI_ENCODER_VA_HRD (encoder) = (VAEncMiscParameterHRD) {
.buffer_size = encoder->bitrate_bits * 2,
.initial_buffer_fullness = encoder->bitrate_bits,
};
/* *INDENT-ON* */
return TRUE;
}
static gboolean
ensure_misc_params (GstVaapiEncoderVP9 * encoder, GstVaapiEncPicture * picture)
{
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
if (!gst_vaapi_encoder_ensure_param_quality_level (base_encoder, picture))
return FALSE;
if (!gst_vaapi_encoder_ensure_param_control_rate (base_encoder, picture))
return FALSE;
return TRUE;
}
static void
get_ref_indices (guint ref_pic_mode, guint ref_list_idx, guint * last_idx,
guint * gf_idx, guint * arf_idx, guint8 * refresh_frame_flags)
{
if (ref_pic_mode == GST_VAAPI_ENCODER_VP9_REF_PIC_MODE_0) {
*last_idx = ref_list_idx - 1;
*gf_idx = 1;
*arf_idx = 2;
*refresh_frame_flags = 0x01;
} else if (ref_pic_mode == GST_VAAPI_ENCODER_VP9_REF_PIC_MODE_1) {
gint last_filled_idx = (ref_list_idx - 1) & (GST_VP9_REF_FRAMES - 1);
*last_idx = last_filled_idx;
*gf_idx = (last_filled_idx - 1) & (GST_VP9_REF_FRAMES - 1);
*arf_idx = (last_filled_idx - 2) & (GST_VP9_REF_FRAMES - 1);
*refresh_frame_flags = 1 << ((*last_idx + 1) % GST_VP9_REF_FRAMES);
}
GST_LOG
("last_ref_idx:%d gold_ref_idx:%d alt_reff_idx:%d refesh_frame_flag:%x",
*last_idx, *gf_idx, *arf_idx, *refresh_frame_flags);
}
static gboolean
fill_picture (GstVaapiEncoderVP9 * encoder,
GstVaapiEncPicture * picture,
GstVaapiCodedBuffer * codedbuf, GstVaapiSurfaceProxy * surface)
{
VAEncPictureParameterBufferVP9 *const pic_param = picture->param;
guint i, last_idx = 0, gf_idx = 0, arf_idx = 0;
guint8 refresh_frame_flags = 0;
gint sb_cols = 0, min_log2_tile_columns = 0;
memset (pic_param, 0, sizeof (VAEncPictureParameterBufferVP9));
pic_param->reconstructed_frame = GST_VAAPI_SURFACE_PROXY_SURFACE_ID (surface);
pic_param->coded_buf = GST_VAAPI_CODED_BUFFER_ID (codedbuf);
/* Update Reference Frame list */
if (picture->type == GST_VAAPI_PICTURE_TYPE_I)
memset (pic_param->reference_frames, 0xFF,
sizeof (pic_param->reference_frames));
else {
for (i = 0; i < G_N_ELEMENTS (pic_param->reference_frames); i++) {
pic_param->reference_frames[i] =
GST_VAAPI_SURFACE_PROXY_SURFACE_ID (encoder->ref_list[i]);
}
}
/* It is possible to have dynamic scaling with gpu by providing
* src and destination resoltuion. For now we are just using
* default encoder width and height */
pic_param->frame_width_src = GST_VAAPI_ENCODER_WIDTH (encoder);
pic_param->frame_height_src = GST_VAAPI_ENCODER_HEIGHT (encoder);
pic_param->frame_width_dst = GST_VAAPI_ENCODER_WIDTH (encoder);
pic_param->frame_height_dst = GST_VAAPI_ENCODER_HEIGHT (encoder);
pic_param->pic_flags.bits.show_frame = 1;
if (picture->type == GST_VAAPI_PICTURE_TYPE_P) {
pic_param->pic_flags.bits.frame_type = GST_VP9_INTER_FRAME;
/* use three of the reference frames (last, golden and altref)
* for prediction */
pic_param->ref_flags.bits.ref_frame_ctrl_l0 = 0x7;
get_ref_indices (encoder->ref_pic_mode, encoder->ref_list_idx, &last_idx,
&gf_idx, &arf_idx, &refresh_frame_flags);
pic_param->ref_flags.bits.ref_last_idx = last_idx;
pic_param->ref_flags.bits.ref_gf_idx = gf_idx;
pic_param->ref_flags.bits.ref_arf_idx = arf_idx;
pic_param->refresh_frame_flags = refresh_frame_flags;
}
/* Maximum width of a tile in units of superblocks is MAX_TILE_WIDTH_B64(64).
* When the width is enough to partition more than MAX_TILE_WIDTH_B64(64) superblocks,
* we need multi tiles to handle it.*/
sb_cols = (pic_param->frame_width_src + 63) / 64;
while ((MAX_TILE_WIDTH_B64 << min_log2_tile_columns) < sb_cols)
++min_log2_tile_columns;
pic_param->log2_tile_columns = min_log2_tile_columns;
pic_param->luma_ac_qindex = encoder->yac_qi;
pic_param->luma_dc_qindex_delta = 1;
pic_param->chroma_ac_qindex_delta = 1;
pic_param->chroma_dc_qindex_delta = 1;
pic_param->filter_level = encoder->loop_filter_level;
pic_param->sharpness_level = encoder->sharpness_level;
return TRUE;
}
static gboolean
ensure_picture (GstVaapiEncoderVP9 * encoder, GstVaapiEncPicture * picture,
GstVaapiCodedBufferProxy * codedbuf_proxy, GstVaapiSurfaceProxy * surface)
{
GstVaapiCodedBuffer *const codedbuf =
GST_VAAPI_CODED_BUFFER_PROXY_BUFFER (codedbuf_proxy);
if (!fill_picture (encoder, picture, codedbuf, surface))
return FALSE;
return TRUE;
}
static void
update_ref_list (GstVaapiEncoderVP9 * encoder, GstVaapiEncPicture * picture,
GstVaapiSurfaceProxy * ref)
{
guint i;
if (picture->type == GST_VAAPI_PICTURE_TYPE_I) {
for (i = 0; i < G_N_ELEMENTS (encoder->ref_list); i++)
gst_vaapi_surface_proxy_replace (&encoder->ref_list[i], ref);
gst_vaapi_surface_proxy_unref (ref);
/* set next free slot index */
encoder->ref_list_idx = 1;
return;
}
switch (encoder->ref_pic_mode) {
case GST_VAAPI_ENCODER_VP9_REF_PIC_MODE_0:
gst_vaapi_surface_proxy_replace (&encoder->ref_list[0], ref);
gst_vaapi_surface_proxy_unref (ref);
break;
case GST_VAAPI_ENCODER_VP9_REF_PIC_MODE_1:
i = encoder->ref_list_idx;
gst_vaapi_surface_proxy_replace (&encoder->ref_list[i], ref);
gst_vaapi_surface_proxy_unref (ref);
encoder->ref_list_idx = (encoder->ref_list_idx + 1) % GST_VP9_REF_FRAMES;
break;
default:
g_assert ("Code shouldn't reach here");
break;
}
}
static GstVaapiEncoderStatus
gst_vaapi_encoder_vp9_encode (GstVaapiEncoder * base_encoder,
GstVaapiEncPicture * picture, GstVaapiCodedBufferProxy * codedbuf)
{
GstVaapiEncoderVP9 *const encoder = GST_VAAPI_ENCODER_VP9 (base_encoder);
GstVaapiEncoderStatus ret = GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
GstVaapiSurfaceProxy *reconstruct = NULL;
reconstruct = gst_vaapi_encoder_create_surface (base_encoder);
g_assert (GST_VAAPI_SURFACE_PROXY_SURFACE (reconstruct));
if (!ensure_sequence (encoder, picture))
goto error;
if (!ensure_misc_params (encoder, picture))
goto error;
if (!ensure_picture (encoder, picture, codedbuf, reconstruct))
goto error;
if (!gst_vaapi_enc_picture_encode (picture))
goto error;
update_ref_list (encoder, picture, reconstruct);
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
/* ERRORS */
error:
{
if (reconstruct)
gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder),
reconstruct);
return ret;
}
}
static GstVaapiEncoderStatus
gst_vaapi_encoder_vp9_flush (GstVaapiEncoder * base_encoder)
{
GstVaapiEncoderVP9 *const encoder = GST_VAAPI_ENCODER_VP9 (base_encoder);
encoder->frame_num = 0;
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
}
static GstVaapiEncoderStatus
gst_vaapi_encoder_vp9_reordering (GstVaapiEncoder * base_encoder,
GstVideoCodecFrame * frame, GstVaapiEncPicture ** output)
{
GstVaapiEncoderVP9 *const encoder = GST_VAAPI_ENCODER_VP9 (base_encoder);
GstVaapiEncPicture *picture = NULL;
GstVaapiEncoderStatus status = GST_VAAPI_ENCODER_STATUS_SUCCESS;
if (!frame)
return GST_VAAPI_ENCODER_STATUS_NO_SURFACE;
picture = GST_VAAPI_ENC_PICTURE_NEW (VP9, encoder, frame);
if (!picture) {
GST_WARNING ("create VP9 picture failed, frame timestamp:%"
GST_TIME_FORMAT, GST_TIME_ARGS (frame->pts));
return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
}
if (encoder->frame_num >= base_encoder->keyframe_period) {
encoder->frame_num = 0;
}
if (encoder->frame_num == 0) {
picture->type = GST_VAAPI_PICTURE_TYPE_I;
GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
} else {
picture->type = GST_VAAPI_PICTURE_TYPE_P;
}
encoder->frame_num++;
*output = picture;
return status;
}
static GstVaapiEncoderStatus
gst_vaapi_encoder_vp9_reconfigure (GstVaapiEncoder * base_encoder)
{
GstVaapiEncoderVP9 *const encoder = GST_VAAPI_ENCODER_VP9 (base_encoder);
GstVaapiEncoderStatus status;
status = ensure_profile (encoder);
if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
return status;
encoder->entrypoint =
gst_vaapi_encoder_get_entrypoint (base_encoder, encoder->profile);
if (encoder->entrypoint == GST_VAAPI_ENTRYPOINT_INVALID) {
GST_WARNING ("Cannot find valid profile/entrypoint pair");
return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
}
ensure_control_rate_params (encoder);
return set_context_info (base_encoder);
}
struct _GstVaapiEncoderVP9Class
{
GstVaapiEncoderClass parent_class;
};
G_DEFINE_TYPE (GstVaapiEncoderVP9, gst_vaapi_encoder_vp9,
GST_TYPE_VAAPI_ENCODER);
static void
gst_vaapi_encoder_vp9_init (GstVaapiEncoderVP9 * encoder)
{
encoder->frame_num = 0;
encoder->loop_filter_level = DEFAULT_LOOP_FILTER_LEVEL;
encoder->sharpness_level = DEFAULT_SHARPNESS_LEVEL;
encoder->yac_qi = DEFAULT_YAC_QINDEX;
encoder->cpb_length = DEFAULT_CPB_LENGTH;
encoder->entrypoint = GST_VAAPI_ENTRYPOINT_SLICE_ENCODE;
memset (encoder->ref_list, 0,
G_N_ELEMENTS (encoder->ref_list) * sizeof (encoder->ref_list[0]));
encoder->ref_list_idx = 0;
encoder->allowed_profiles = NULL;
}
static void
gst_vaapi_encoder_vp9_finalize (GObject * object)
{
GstVaapiEncoderVP9 *const encoder = GST_VAAPI_ENCODER_VP9 (object);
if (encoder->allowed_profiles)
g_array_unref (encoder->allowed_profiles);
G_OBJECT_CLASS (gst_vaapi_encoder_vp9_parent_class)->finalize (object);
}
/**
* @ENCODER_VP9_PROP_RATECONTROL: Rate control (#GstVaapiRateControl).
* @ENCODER_VP9_PROP_TUNE: The tuning options (#GstVaapiEncoderTune).
* @ENCODER_VP9_PROP_LOOP_FILTER_LEVEL: Loop Filter Level(uint).
* @ENCODER_VP9_PROP_LOOP_SHARPNESS_LEVEL: Sharpness Level(uint).
* @ENCODER_VP9_PROP_YAC_Q_INDEX: Quantization table index for luma AC
* @ENCODER_VP9_PROP_REF_PIC_MODE: Reference picute selection modes
* @ENCODER_VP9_PROP_CPB_LENGTH:Length of CPB buffer in milliseconds
*
* The set of VP9 encoder specific configurable properties.
*/
enum
{
ENCODER_VP9_PROP_RATECONTROL = 1,
ENCODER_VP9_PROP_TUNE,
ENCODER_VP9_PROP_LOOP_FILTER_LEVEL,
ENCODER_VP9_PROP_SHARPNESS_LEVEL,
ENCODER_VP9_PROP_YAC_Q_INDEX,
ENCODER_VP9_PROP_REF_PIC_MODE,
ENCODER_VP9_PROP_CPB_LENGTH,
ENCODER_VP9_N_PROPERTIES
};
static GParamSpec *properties[ENCODER_VP9_N_PROPERTIES];
static void
gst_vaapi_encoder_vp9_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER (object);
GstVaapiEncoderVP9 *const encoder = GST_VAAPI_ENCODER_VP9 (object);
if (base_encoder->num_codedbuf_queued > 0) {
GST_ERROR_OBJECT (object,
"failed to set any property after encoding started");
return;
}
switch (prop_id) {
case ENCODER_VP9_PROP_RATECONTROL:
gst_vaapi_encoder_set_rate_control (base_encoder,
g_value_get_enum (value));
break;
case ENCODER_VP9_PROP_TUNE:
gst_vaapi_encoder_set_tuning (base_encoder, g_value_get_enum (value));
break;
case ENCODER_VP9_PROP_LOOP_FILTER_LEVEL:
encoder->loop_filter_level = g_value_get_uint (value);
break;
case ENCODER_VP9_PROP_SHARPNESS_LEVEL:
encoder->sharpness_level = g_value_get_uint (value);
break;
case ENCODER_VP9_PROP_YAC_Q_INDEX:
encoder->yac_qi = g_value_get_uint (value);
break;
case ENCODER_VP9_PROP_REF_PIC_MODE:
encoder->ref_pic_mode = g_value_get_enum (value);
break;
case ENCODER_VP9_PROP_CPB_LENGTH:
encoder->cpb_length = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
gst_vaapi_encoder_vp9_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstVaapiEncoderVP9 *const encoder = GST_VAAPI_ENCODER_VP9 (object);
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER (object);
switch (prop_id) {
case ENCODER_VP9_PROP_RATECONTROL:
g_value_set_enum (value, base_encoder->rate_control);
break;
case ENCODER_VP9_PROP_TUNE:
g_value_set_enum (value, base_encoder->tune);
break;
case ENCODER_VP9_PROP_LOOP_FILTER_LEVEL:
g_value_set_uint (value, encoder->loop_filter_level);
break;
case ENCODER_VP9_PROP_SHARPNESS_LEVEL:
g_value_set_uint (value, encoder->sharpness_level);
break;
case ENCODER_VP9_PROP_YAC_Q_INDEX:
g_value_set_uint (value, encoder->yac_qi);
break;
case ENCODER_VP9_PROP_REF_PIC_MODE:
g_value_set_enum (value, encoder->ref_pic_mode);
break;
case ENCODER_VP9_PROP_CPB_LENGTH:
g_value_set_uint (value, encoder->cpb_length);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
GST_VAAPI_ENCODER_DEFINE_CLASS_DATA (VP9);
static void
gst_vaapi_encoder_vp9_class_init (GstVaapiEncoderVP9Class * klass)
{
GObjectClass *const object_class = G_OBJECT_CLASS (klass);
GstVaapiEncoderClass *const encoder_class = GST_VAAPI_ENCODER_CLASS (klass);
encoder_class->class_data = &g_class_data;
encoder_class->reconfigure = gst_vaapi_encoder_vp9_reconfigure;
encoder_class->reordering = gst_vaapi_encoder_vp9_reordering;
encoder_class->encode = gst_vaapi_encoder_vp9_encode;
encoder_class->flush = gst_vaapi_encoder_vp9_flush;
object_class->set_property = gst_vaapi_encoder_vp9_set_property;
object_class->get_property = gst_vaapi_encoder_vp9_get_property;
object_class->finalize = gst_vaapi_encoder_vp9_finalize;
properties[ENCODER_VP9_PROP_RATECONTROL] =
g_param_spec_enum ("rate-control",
"Rate Control", "Rate control mode",
g_class_data.rate_control_get_type (),
g_class_data.default_rate_control,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
GST_VAAPI_PARAM_ENCODER_EXPOSURE);
properties[ENCODER_VP9_PROP_TUNE] =
g_param_spec_enum ("tune",
"Encoder Tuning",
"Encoder tuning option",
g_class_data.encoder_tune_get_type (),
g_class_data.default_encoder_tune,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
GST_VAAPI_PARAM_ENCODER_EXPOSURE);
properties[ENCODER_VP9_PROP_LOOP_FILTER_LEVEL] =
g_param_spec_uint ("loop-filter-level",
"Loop Filter Level",
"Controls the deblocking filter strength",
0, 63, DEFAULT_LOOP_FILTER_LEVEL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
GST_VAAPI_PARAM_ENCODER_EXPOSURE);
properties[ENCODER_VP9_PROP_SHARPNESS_LEVEL] =
g_param_spec_uint ("sharpness-level",
"Sharpness Level",
"Controls the deblocking filter sensitivity",
0, 7, DEFAULT_SHARPNESS_LEVEL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
GST_VAAPI_PARAM_ENCODER_EXPOSURE);
properties[ENCODER_VP9_PROP_YAC_Q_INDEX] =
g_param_spec_uint ("yac-qi",
"Luma AC Quant Table index",
"Quantization Table index for Luma AC Coefficients",
0, 255, DEFAULT_YAC_QINDEX,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
GST_VAAPI_PARAM_ENCODER_EXPOSURE);
properties[ENCODER_VP9_PROP_REF_PIC_MODE] =
g_param_spec_enum ("ref-pic-mode",
"RefPic Selection",
"Reference Picture Selection Modes",
gst_vaapi_encoder_vp9_ref_pic_mode_type (),
GST_VAAPI_ENCODER_VP9_REF_PIC_MODE_0,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
GST_VAAPI_PARAM_ENCODER_EXPOSURE);
/**
* GstVaapiEncoderVP9:cpb-length:
*
* The size of the Coded Picture Buffer , which means
* the window size in milliseconds.
*
*/
properties[ENCODER_VP9_PROP_CPB_LENGTH] =
g_param_spec_uint ("cpb-length",
"CPB Length", "Length of the CPB_buffer/window_size in milliseconds",
1, 10000, DEFAULT_CPB_LENGTH,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
GST_VAAPI_PARAM_ENCODER_EXPOSURE);
g_object_class_install_properties (object_class, ENCODER_VP9_N_PROPERTIES,
properties);
gst_type_mark_as_plugin_api (g_class_data.rate_control_get_type (), 0);
gst_type_mark_as_plugin_api (g_class_data.encoder_tune_get_type (), 0);
}
/**
* gst_vaapi_encoder_vp9_new:
* @display: a #GstVaapiDisplay
*
* Creates a new #GstVaapiEncoder for VP9 encoding.
*
* Return value: the newly allocated #GstVaapiEncoder object
*/
GstVaapiEncoder *
gst_vaapi_encoder_vp9_new (GstVaapiDisplay * display)
{
return g_object_new (GST_TYPE_VAAPI_ENCODER_VP9, "display", display, NULL);
}
/**
* gst_vaapi_encoder_vp9_set_allowed_profiles:
* @encoder: a #GstVaapiEncoderVP9
* @profiles: a #GArray of all allowed #GstVaapiProfile.
*
* Set the all allowed profiles for the encoder.
*
* Return value: %TRUE on success
*/
gboolean
gst_vaapi_encoder_vp9_set_allowed_profiles (GstVaapiEncoderVP9 * encoder,
GArray * profiles)
{
g_return_val_if_fail (profiles != 0, FALSE);
encoder->allowed_profiles = g_array_ref (profiles);
return TRUE;
}

View file

@ -0,0 +1,53 @@
/*
* gstvaapiencoder_vp9.h VP9 encoder
*
* Copyright (C) 2016 Intel Corporation
* Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
*
* 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_VAAPI_ENCODER_VP9_H
#define GST_VAAPI_ENCODER_VP9_H
#include <gst/vaapi/gstvaapiencoder.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_ENCODER_VP9 \
(gst_vaapi_encoder_vp9_get_type ())
#define GST_VAAPI_ENCODER_VP9(encoder) \
(G_TYPE_CHECK_INSTANCE_CAST ((encoder), GST_TYPE_VAAPI_ENCODER_VP9, GstVaapiEncoderVP9))
#define GST_IS_VAAPI_ENCODER_VP9(encoder) \
(G_TYPE_CHECK_INSTANCE_TYPE ((encoder), GST_TYPE_VAAPI_ENCODER_VP9))
typedef struct _GstVaapiEncoderVP9 GstVaapiEncoderVP9;
typedef struct _GstVaapiEncoderVP9Class GstVaapiEncoderVP9Class;
GType
gst_vaapi_encoder_vp9_get_type (void) G_GNUC_CONST;
GstVaapiEncoder *
gst_vaapi_encoder_vp9_new (GstVaapiDisplay * display);
gboolean
gst_vaapi_encoder_vp9_set_allowed_profiles (GstVaapiEncoderVP9 * encoder,
GArray * profiles);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiEncoderVP9, gst_object_unref)
G_END_DECLS
#endif /*GST_VAAPI_ENCODER_VP9_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,325 @@
/*
* gstvaapifilter.h - Video processing abstraction
*
* Copyright (C) 2013 Intel Corporation
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
*
* 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_VAAPI_FILTER_H
#define GST_VAAPI_FILTER_H
#include <gst/vaapi/gstvaapisurface.h>
#include <gst/vaapi/video-format.h>
G_BEGIN_DECLS
#define GST_TYPE_VAAPI_FILTER \
(gst_vaapi_filter_get_type ())
#define GST_VAAPI_FILTER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VAAPI_FILTER, GstVaapiFilter))
#define GST_VAAPI_IS_FILTER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_FILTER))
typedef struct _GstVaapiFilter GstVaapiFilter;
typedef struct _GstVaapiFilterOpInfo GstVaapiFilterOpInfo;
/**
* @GST_VAAPI_FILTER_OP_FORMAT: Force output pixel format (#GstVideoFormat).
* @GST_VAAPI_FILTER_OP_CROP: Crop source surface (#GstVaapiRectangle).
* @GST_VAAPI_FILTER_OP_DENOISE: Noise reduction (float).
* @GST_VAAPI_FILTER_OP_SHARPEN: Sharpening (float).
* @GST_VAAPI_FILTER_OP_HUE: Change color hue (float).
* @GST_VAAPI_FILTER_OP_SATURATION: Change saturation (float).
* @GST_VAAPI_FILTER_OP_BRIGHTNESS: Change brightness (float).
* @GST_VAAPI_FILTER_OP_CONTRAST: Change contrast (float).
* @GST_VAAPI_FILTER_OP_SCALING: Change scaling method (#GstVaapiScaleMethod).
* @GST_VAAPI_FILTER_OP_VIDEO_DIRECTION: Change video direction
* (#GstVideoOrientationMethod).
* @GST_VAAPI_FILTER_OP_HDR_TONE_MAP: HDR tone mapping (bool).
* @GST_VAAPI_FILTER_OP_SKINTONE: Skin tone enhancement (bool).
* @GST_VAAPI_FILTER_OP_SKINTONE_LEVEL: Skin tone enhancement (uint).
*
* The set of operations that could be applied to the filter.
*/
typedef enum {
GST_VAAPI_FILTER_OP_FORMAT = 1,
GST_VAAPI_FILTER_OP_CROP,
GST_VAAPI_FILTER_OP_DENOISE,
GST_VAAPI_FILTER_OP_SHARPEN,
GST_VAAPI_FILTER_OP_HUE,
GST_VAAPI_FILTER_OP_SATURATION,
GST_VAAPI_FILTER_OP_BRIGHTNESS,
GST_VAAPI_FILTER_OP_CONTRAST,
GST_VAAPI_FILTER_OP_DEINTERLACING,
GST_VAAPI_FILTER_OP_SCALING,
GST_VAAPI_FILTER_OP_VIDEO_DIRECTION,
GST_VAAPI_FILTER_OP_HDR_TONE_MAP,
#ifndef GST_REMOVE_DEPRECATED
GST_VAAPI_FILTER_OP_SKINTONE,
#endif
GST_VAAPI_FILTER_OP_SKINTONE_LEVEL,
} GstVaapiFilterOp;
/**
* GstVaapiFilterOpInfo:
* @operation: the #GstVaapiFilterOp
* @pspec: the #GParamSpec describing the associated configurable value
*
* A #GstVaapiFilterOp descriptor.
*/
struct _GstVaapiFilterOpInfo
{
const GstVaapiFilterOp op;
GParamSpec *const pspec;
};
/**
* GstVaapiFilterStatus:
* @GST_VAAPI_FILTER_STATUS_SUCCESS: Success.
* @GST_VAAPI_FILTER_STATUS_ERROR_ALLOCATION_FAILED: No memory left.
* @GST_VAAPI_FILTER_STATUS_ERROR_OPERATION_FAILED: Operation failed.
* @GST_VAAPI_FILTER_STATUS_ERROR_INVALID_PARAMETER: Invalid parameter.
* @GST_VAAPI_FILTER_STATUS_ERROR_UNSUPPORTED_OPERATION: Unsupported operation.
* @GST_VAAPI_FILTER_STATUS_ERROR_UNSUPPORTED_FORMAT: Unsupported target format.
*
* Video processing status for gst_vaapi_filter_process().
*/
typedef enum {
GST_VAAPI_FILTER_STATUS_SUCCESS = 0,
GST_VAAPI_FILTER_STATUS_ERROR_ALLOCATION_FAILED,
GST_VAAPI_FILTER_STATUS_ERROR_OPERATION_FAILED,
GST_VAAPI_FILTER_STATUS_ERROR_INVALID_PARAMETER,
GST_VAAPI_FILTER_STATUS_ERROR_UNSUPPORTED_OPERATION,
GST_VAAPI_FILTER_STATUS_ERROR_UNSUPPORTED_FORMAT,
} GstVaapiFilterStatus;
/**
* GstVaapiScaleMethod:
* @GST_VAAPI_SCALE_METHOD_DEFAULT: Default scaling mode.
* @GST_VAAPI_SCALE_METHOD_FAST: Fast scaling mode, at the expense of quality.
* @GST_VAAPI_SCALE_METHOD_HQ: High quality scaling mode, at the
* expense of speed.
*
* Scaling algorithms.
*/
typedef enum {
GST_VAAPI_SCALE_METHOD_DEFAULT,
GST_VAAPI_SCALE_METHOD_FAST,
GST_VAAPI_SCALE_METHOD_HQ,
} GstVaapiScaleMethod;
/**
* GstVaapiDeinterlaceMethod:
* @GST_VAAPI_DEINTERLACE_METHOD_NONE: No deinterlacing.
* @GST_VAAPI_DEINTERLACE_METHOD_BOB: Basic bob deinterlacing algorithm.
* @GST_VAAPI_DEINTERLACE_METHOD_WEAVE: Weave deinterlacing algorithm.
* @GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE: Motion adaptive
* deinterlacing algorithm.
* @GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED: Motion compensated
* deinterlacing algorithm.
*
* Deinterlacing algorithms.
*/
typedef enum {
GST_VAAPI_DEINTERLACE_METHOD_NONE,
GST_VAAPI_DEINTERLACE_METHOD_BOB,
GST_VAAPI_DEINTERLACE_METHOD_WEAVE,
GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE,
GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED,
} GstVaapiDeinterlaceMethod;
/**
* GstVaapiDeinterlaceFlags:
* @GST_VAAPI_DEINTERLACE_FLAG_TFF: Top-field first. If this flag is
* not set, then bottom-field first order is assumed. Note: this
* only affects the way reference frames are organized for advanced
* deinterlacing modes.
* @GST_VAAPI_DEINTERLACE_FLAG_ONEFIELD: The input frame represents a
* single field. If this flag is not set, then the whole frame holds
* two interleaved fields.
* @GST_VAAPI_DEINTERLACE_FLAG_TOPFIELD: The top field of the input
* frame is to be used for deinterlacing. Otherwise, if this flag is
* not set, then the bottom field of the input frame will be used
* for deinterlacing.
*
* The set of gst_vaapi_filter_set_deinterlacing() flags.
*/
typedef enum {
GST_VAAPI_DEINTERLACE_FLAG_TFF = 1 << 31,
GST_VAAPI_DEINTERLACE_FLAG_ONEFIELD = 1 << 30,
GST_VAAPI_DEINTERLACE_FLAG_TOPFIELD = 1 << 29,
} GstVaapiDeinterlaceFlags;
#define GST_VAAPI_TYPE_SCALE_METHOD \
gst_vaapi_scale_method_get_type()
#define GST_VAAPI_TYPE_DEINTERLACE_METHOD \
gst_vaapi_deinterlace_method_get_type()
#define GST_VAAPI_TYPE_DEINTERLACE_FLAGS \
gst_vaapi_deinterlace_flags_get_type()
GType
gst_vaapiscale_method_get_type (void) G_GNUC_CONST;
GType
gst_vaapi_deinterlace_method_get_type (void) G_GNUC_CONST;
GType
gst_vaapi_deinterlace_flags_get_type (void) G_GNUC_CONST;
GType
gst_vaapi_filter_get_type (void) G_GNUC_CONST;
GstVaapiFilter *
gst_vaapi_filter_new (GstVaapiDisplay * display);
void
gst_vaapi_filter_replace (GstVaapiFilter ** old_filter_ptr,
GstVaapiFilter * new_filter);
GPtrArray *
gst_vaapi_filter_get_operations (GstVaapiFilter * filter);
gboolean
gst_vaapi_filter_has_operation (GstVaapiFilter * filter, GstVaapiFilterOp op);
gboolean
gst_vaapi_filter_use_operation (GstVaapiFilter * filter, GstVaapiFilterOp op);
gboolean
gst_vaapi_filter_set_operation (GstVaapiFilter * filter, GstVaapiFilterOp op,
const GValue * value);
GstVaapiFilterStatus
gst_vaapi_filter_process (GstVaapiFilter * filter,
GstVaapiSurface * src_surface, GstVaapiSurface * dst_surface, guint flags);
GArray *
gst_vaapi_filter_get_formats (GstVaapiFilter * filter);
gboolean
gst_vaapi_filter_set_format (GstVaapiFilter * filter, GstVideoFormat format);
gboolean
gst_vaapi_filter_append_caps (GstVaapiFilter * filter, GstStructure * structure);
guint
gst_vaapi_filter_get_memory_types (GstVaapiFilter * filter);
gboolean
gst_vaapi_filter_set_cropping_rectangle (GstVaapiFilter * filter,
const GstVaapiRectangle * rect);
gboolean
gst_vaapi_filter_set_target_rectangle (GstVaapiFilter * filter,
const GstVaapiRectangle * rect);
gboolean
gst_vaapi_filter_set_denoising_level (GstVaapiFilter * filter, gfloat level);
gboolean
gst_vaapi_filter_set_sharpening_level (GstVaapiFilter * filter, gfloat level);
gboolean
gst_vaapi_filter_set_hue (GstVaapiFilter * filter, gfloat value);
gboolean
gst_vaapi_filter_set_saturation (GstVaapiFilter * filter, gfloat value);
gboolean
gst_vaapi_filter_set_brightness (GstVaapiFilter * filter, gfloat value);
gboolean
gst_vaapi_filter_set_contrast (GstVaapiFilter * filter, gfloat value);
gboolean
gst_vaapi_filter_set_deinterlacing (GstVaapiFilter * filter,
GstVaapiDeinterlaceMethod method, guint flags);
gboolean
gst_vaapi_filter_set_deinterlacing_references (GstVaapiFilter * filter,
GstVaapiSurface ** forward_references, guint num_forward_references,
GstVaapiSurface ** backward_references, guint num_backward_references);
gboolean
gst_vaapi_filter_set_scaling (GstVaapiFilter * filter,
GstVaapiScaleMethod method);
gboolean
gst_vaapi_filter_set_video_direction (GstVaapiFilter * filter,
GstVideoOrientationMethod method);
GstVideoOrientationMethod
gst_vaapi_filter_get_video_direction (GstVaapiFilter * filter);
gboolean
gst_vaapi_filter_set_hdr_tone_map (GstVaapiFilter * filter, gboolean value);
gboolean
gst_vaapi_filter_set_hdr_tone_map_meta (GstVaapiFilter * filter,
GstVideoMasteringDisplayInfo * minfo, GstVideoContentLightLevel * linfo);
#ifndef GST_REMOVE_DEPRECATED
gboolean
gst_vaapi_filter_set_skintone (GstVaapiFilter * filter,
gboolean enhance);
#endif
gboolean
gst_vaapi_filter_set_skintone_level (GstVaapiFilter * filter, guint value);
gfloat
gst_vaapi_filter_get_denoising_level_default (GstVaapiFilter * filter);
gfloat
gst_vaapi_filter_get_sharpening_level_default (GstVaapiFilter * filter);
gfloat
gst_vaapi_filter_get_hue_default (GstVaapiFilter * filter);
gfloat
gst_vaapi_filter_get_saturation_default (GstVaapiFilter * filter);
gfloat
gst_vaapi_filter_get_brightness_default (GstVaapiFilter * filter);
gfloat
gst_vaapi_filter_get_contrast_default (GstVaapiFilter * filter);
GstVaapiScaleMethod
gst_vaapi_filter_get_scaling_default (GstVaapiFilter * filter);
GstVideoOrientationMethod
gst_vaapi_filter_get_video_direction_default (GstVaapiFilter * filter);
#ifndef GST_REMOVE_DEPRECATED
gboolean
gst_vaapi_filter_get_skintone_default (GstVaapiFilter * filter);
#endif
guint
gst_vaapi_filter_get_skintone_level_default (GstVaapiFilter * filter);
gboolean
gst_vaapi_filter_set_colorimetry (GstVaapiFilter * filter,
GstVideoColorimetry * input, GstVideoColorimetry * output);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiFilter, gst_object_unref)
#endif /* GST_VAAPI_FILTER_H */

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more