summaryrefslogtreecommitdiff
path: root/subprojects/gst-omx
diff options
context:
space:
mode:
authorThibault Saunier <tsaunier@igalia.com>2021-09-24 16:15:01 -0300
committerThibault Saunier <tsaunier@igalia.com>2021-09-24 16:15:01 -0300
commitb7d9115a055a9e8411281322ec2f12e1c9f4b6b5 (patch)
tree9808ea97ec723b989cf0ae480a9e9ab41103a75d /subprojects/gst-omx
parentf627a5c2ed50f8638d83e8ecd3fc29251af29f0a (diff)
downloadgstreamer-b7d9115a055a9e8411281322ec2f12e1c9f4b6b5.tar.gz
Move files from gst-omx into the "subprojects/gst-omx/" subdir
Diffstat (limited to 'subprojects/gst-omx')
-rw-r--r--subprojects/gst-omx/.gitignore3
-rw-r--r--subprojects/gst-omx/.gitlab-ci.yml1
-rw-r--r--subprojects/gst-omx/AUTHORS2
-rw-r--r--subprojects/gst-omx/COPYING502
-rw-r--r--subprojects/gst-omx/ChangeLog8029
-rw-r--r--subprojects/gst-omx/NEWS299
-rw-r--r--subprojects/gst-omx/README17
-rw-r--r--subprojects/gst-omx/RELEASE96
-rw-r--r--subprojects/gst-omx/config/bellagio/gstomx.conf60
-rw-r--r--subprojects/gst-omx/config/bellagio/meson.build1
-rw-r--r--subprojects/gst-omx/config/meson.build20
-rw-r--r--subprojects/gst-omx/config/rpi/gstomx.conf102
-rw-r--r--subprojects/gst-omx/config/rpi/meson.build1
-rw-r--r--subprojects/gst-omx/config/tizonia/gstomx.conf.in49
-rw-r--r--subprojects/gst-omx/config/tizonia/meson.build5
-rw-r--r--subprojects/gst-omx/config/zynqultrascaleplus/gstomx.conf35
-rw-r--r--subprojects/gst-omx/config/zynqultrascaleplus/meson.build1
-rw-r--r--subprojects/gst-omx/docs/gst_plugins_cache.json13
-rw-r--r--subprojects/gst-omx/docs/index.md3
-rw-r--r--subprojects/gst-omx/docs/meson.build62
-rw-r--r--subprojects/gst-omx/docs/sitemap.txt1
-rw-r--r--subprojects/gst-omx/examples/egl/cube_texture_and_coords.h100
-rw-r--r--subprojects/gst-omx/examples/egl/meson.build31
-rw-r--r--subprojects/gst-omx/examples/egl/testegl.c1611
-rw-r--r--subprojects/gst-omx/examples/meson.build3
-rw-r--r--subprojects/gst-omx/gst-omx.doap332
-rwxr-xr-xsubprojects/gst-omx/hooks/pre-commit.hook83
-rw-r--r--subprojects/gst-omx/meson.build432
-rw-r--r--subprojects/gst-omx/meson_options.txt14
-rw-r--r--subprojects/gst-omx/omx/gstomx.c4179
-rw-r--r--subprojects/gst-omx/omx/gstomx.h493
-rw-r--r--subprojects/gst-omx/omx/gstomxaacdec.c296
-rw-r--r--subprojects/gst-omx/omx/gstomxaacdec.h60
-rw-r--r--subprojects/gst-omx/omx/gstomxaacenc.c511
-rw-r--r--subprojects/gst-omx/omx/gstomxaacenc.h65
-rw-r--r--subprojects/gst-omx/omx/gstomxallocator.c554
-rw-r--r--subprojects/gst-omx/omx/gstomxallocator.h114
-rw-r--r--subprojects/gst-omx/omx/gstomxamrdec.c220
-rw-r--r--subprojects/gst-omx/omx/gstomxamrdec.h61
-rw-r--r--subprojects/gst-omx/omx/gstomxanalogaudiosink.c64
-rw-r--r--subprojects/gst-omx/omx/gstomxanalogaudiosink.h61
-rw-r--r--subprojects/gst-omx/omx/gstomxaudiodec.c1404
-rw-r--r--subprojects/gst-omx/omx/gstomxaudiodec.h100
-rw-r--r--subprojects/gst-omx/omx/gstomxaudioenc.c1181
-rw-r--r--subprojects/gst-omx/omx/gstomxaudioenc.h87
-rw-r--r--subprojects/gst-omx/omx/gstomxaudiosink.c1228
-rw-r--r--subprojects/gst-omx/omx/gstomxaudiosink.h103
-rw-r--r--subprojects/gst-omx/omx/gstomxbufferpool.c674
-rw-r--r--subprojects/gst-omx/omx/gstomxbufferpool.h101
-rw-r--r--subprojects/gst-omx/omx/gstomxh263dec.c99
-rw-r--r--subprojects/gst-omx/omx/gstomxh263dec.h60
-rw-r--r--subprojects/gst-omx/omx/gstomxh263enc.c302
-rw-r--r--subprojects/gst-omx/omx/gstomxh263enc.h60
-rw-r--r--subprojects/gst-omx/omx/gstomxh264dec.c216
-rw-r--r--subprojects/gst-omx/omx/gstomxh264dec.h60
-rw-r--r--subprojects/gst-omx/omx/gstomxh264enc.c894
-rw-r--r--subprojects/gst-omx/omx/gstomxh264enc.h73
-rw-r--r--subprojects/gst-omx/omx/gstomxh264utils.c131
-rw-r--r--subprojects/gst-omx/omx/gstomxh264utils.h36
-rw-r--r--subprojects/gst-omx/omx/gstomxh265dec.c224
-rw-r--r--subprojects/gst-omx/omx/gstomxh265dec.h61
-rw-r--r--subprojects/gst-omx/omx/gstomxh265enc.c748
-rw-r--r--subprojects/gst-omx/omx/gstomxh265enc.h72
-rw-r--r--subprojects/gst-omx/omx/gstomxh265utils.c138
-rw-r--r--subprojects/gst-omx/omx/gstomxh265utils.h37
-rw-r--r--subprojects/gst-omx/omx/gstomxhdmiaudiosink.c66
-rw-r--r--subprojects/gst-omx/omx/gstomxhdmiaudiosink.h61
-rw-r--r--subprojects/gst-omx/omx/gstomxmjpegdec.c98
-rw-r--r--subprojects/gst-omx/omx/gstomxmjpegdec.h60
-rw-r--r--subprojects/gst-omx/omx/gstomxmp3dec.c246
-rw-r--r--subprojects/gst-omx/omx/gstomxmp3dec.h60
-rw-r--r--subprojects/gst-omx/omx/gstomxmp3enc.c278
-rw-r--r--subprojects/gst-omx/omx/gstomxmp3enc.h65
-rw-r--r--subprojects/gst-omx/omx/gstomxmpeg2videodec.c101
-rw-r--r--subprojects/gst-omx/omx/gstomxmpeg2videodec.h59
-rw-r--r--subprojects/gst-omx/omx/gstomxmpeg4videodec.c102
-rw-r--r--subprojects/gst-omx/omx/gstomxmpeg4videodec.h60
-rw-r--r--subprojects/gst-omx/omx/gstomxmpeg4videoenc.c336
-rw-r--r--subprojects/gst-omx/omx/gstomxmpeg4videoenc.h60
-rw-r--r--subprojects/gst-omx/omx/gstomxtheoradec.c157
-rw-r--r--subprojects/gst-omx/omx/gstomxtheoradec.h61
-rw-r--r--subprojects/gst-omx/omx/gstomxvideo.c356
-rw-r--r--subprojects/gst-omx/omx/gstomxvideo.h74
-rw-r--r--subprojects/gst-omx/omx/gstomxvideodec.c3524
-rw-r--r--subprojects/gst-omx/omx/gstomxvideodec.h119
-rw-r--r--subprojects/gst-omx/omx/gstomxvideoenc.c3732
-rw-r--r--subprojects/gst-omx/omx/gstomxvideoenc.h133
-rw-r--r--subprojects/gst-omx/omx/gstomxvp8dec.c99
-rw-r--r--subprojects/gst-omx/omx/gstomxvp8dec.h60
-rw-r--r--subprojects/gst-omx/omx/gstomxwmvdec.c98
-rw-r--r--subprojects/gst-omx/omx/gstomxwmvdec.h60
-rw-r--r--subprojects/gst-omx/omx/meson.build63
-rw-r--r--subprojects/gst-omx/omx/openmax/OMX_Audio.h1311
-rw-r--r--subprojects/gst-omx/omx/openmax/OMX_Component.h579
-rw-r--r--subprojects/gst-omx/omx/openmax/OMX_ComponentExt.h61
-rw-r--r--subprojects/gst-omx/omx/openmax/OMX_ContentPipe.h195
-rw-r--r--subprojects/gst-omx/omx/openmax/OMX_Core.h1431
-rw-r--r--subprojects/gst-omx/omx/openmax/OMX_CoreExt.h73
-rw-r--r--subprojects/gst-omx/omx/openmax/OMX_IVCommon.h920
-rw-r--r--subprojects/gst-omx/omx/openmax/OMX_Image.h328
-rw-r--r--subprojects/gst-omx/omx/openmax/OMX_Index.h258
-rw-r--r--subprojects/gst-omx/omx/openmax/OMX_IndexExt.h87
-rw-r--r--subprojects/gst-omx/omx/openmax/OMX_Other.h337
-rw-r--r--subprojects/gst-omx/omx/openmax/OMX_Types.h359
-rw-r--r--subprojects/gst-omx/omx/openmax/OMX_Video.h1060
-rw-r--r--subprojects/gst-omx/omx/openmax/OMX_VideoExt.h69
-rwxr-xr-xsubprojects/gst-omx/scripts/extract-release-date-from-doap-file.py45
-rw-r--r--subprojects/gst-omx/tests/check/generic/states.c225
-rw-r--r--subprojects/gst-omx/tests/check/meson.build56
-rw-r--r--subprojects/gst-omx/tests/meson.build4
-rw-r--r--subprojects/gst-omx/tools/listcomponents.c169
-rw-r--r--subprojects/gst-omx/tools/meson.build8
112 files changed, 44438 insertions, 0 deletions
diff --git a/subprojects/gst-omx/.gitignore b/subprojects/gst-omx/.gitignore
new file mode 100644
index 0000000000..d4cb069593
--- /dev/null
+++ b/subprojects/gst-omx/.gitignore
@@ -0,0 +1,3 @@
+*~
+*.bak
+*.swp
diff --git a/subprojects/gst-omx/.gitlab-ci.yml b/subprojects/gst-omx/.gitlab-ci.yml
new file mode 100644
index 0000000000..c61aa7a529
--- /dev/null
+++ b/subprojects/gst-omx/.gitlab-ci.yml
@@ -0,0 +1 @@
+include: "https://gitlab.freedesktop.org/gstreamer/gst-ci/raw/master/gitlab/ci_template.yml"
diff --git a/subprojects/gst-omx/AUTHORS b/subprojects/gst-omx/AUTHORS
new file mode 100644
index 0000000000..3d3e8d7e9c
--- /dev/null
+++ b/subprojects/gst-omx/AUTHORS
@@ -0,0 +1,2 @@
+Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
diff --git a/subprojects/gst-omx/COPYING b/subprojects/gst-omx/COPYING
new file mode 100644
index 0000000000..4362b49151
--- /dev/null
+++ b/subprojects/gst-omx/COPYING
@@ -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!
diff --git a/subprojects/gst-omx/ChangeLog b/subprojects/gst-omx/ChangeLog
new file mode 100644
index 0000000000..43c8c6adba
--- /dev/null
+++ b/subprojects/gst-omx/ChangeLog
@@ -0,0 +1,8029 @@
+=== release 1.19.2 ===
+
+2021-09-23 01:36:02 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * gst-omx.doap:
+ * meson.build:
+ Release 1.19.2
+
+2021-07-09 15:14:15 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: fix OMX flags on header buffer
+ The header (SPS/PPS) buffer should have the CODECONFIG flag
+ Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-omx/-/merge_requests/49>
+
+2021-07-09 14:52:59 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: allow to start decoder on HEADER buffer
+ If the headers are sent in their own buffer
+ it won't have the SYNC_FRAME flag but we still
+ do want to start decoding rather than dropping it.
+ Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-omx/-/merge_requests/49>
+
+2018-09-06 21:56:57 +0000 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * omx/gstomx.c:
+ * omx/gstomxh264dec.c:
+ * omx/gstomxh265dec.c:
+ * omx/gstomxvideodec.c:
+ omxh26xdec: videodecoder support subframe
+ Use of subframe API from videodecoder base class.
+ This subframe allows to decode subframe instead of
+ waiting for a whole frame.
+ The subframe uses the same frame over the whole
+ subframe passing process and will wait
+ for a signal to know the last subframe.
+ In this implementation it will use
+ GST_VIDEO_BUFFER_FLAG_MARKER as the
+ end of batch of subframes.
+ This implement subframe mode negotation for the Zynq based on caps
+ negotation. This mode can be combined with low-latency mode, in order to
+ reach the lowest possible latency (assuming the stream is within the
+ low-latency constraints for the HW).
+ ... ! video/x-h264,alignment=nal ! omxh264dec ! ...
+ Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-omx/-/merge_requests/49>
+
+2021-06-01 15:29:18 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * meson.build:
+ Back to development
+
+=== release 1.19.1 ===
+
+2021-06-01 00:16:41 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * gst-omx.doap:
+ * meson.build:
+ Release 1.19.1
+
+2020-11-04 18:48:13 +0530 Nirbheek Chauhan <nirbheek@centricular.com>
+
+ * meson.build:
+ meson: Enable some MSVC warnings for parity with GCC/Clang
+ This makes it easier to do development with MSVC by making it warn
+ on common issues that GCC/Clang error out for in our CI configuration.
+ Continuation from https://gitlab.freedesktop.org/gstreamer/gst-build/-/merge_requests/223
+ Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-omx/-/merge_requests/75>
+
+2020-10-16 12:45:09 +0200 Stéphane Cerveau <scerveau@collabora.com>
+
+ * examples/egl/testegl.c:
+ * meson.build:
+ meson: update glib minimum version to 2.56
+ In order to support the symbol g_enum_to_string in various
+ project using GStreamer ( gst-validate etc.), the glib minimum
+ version should be 2.56.0.
+ Remove compat code as glib requirement
+ is now > 2.56
+ Version used by Ubuntu 18.04 LTS
+ Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-omx/-/merge_requests/74>
+
+2020-10-05 12:32:10 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: support interlace-mode=interleaved input
+ interlace-mode=alternate is a special case of interlace-mode=interleaved
+ where the fields are split using two different buffers.
+ The Zynq decoder always produces alternate content and we
+ used to assume that upstream will set interlace-mode=alternate in its
+ caps as well.
+ This is no longer the case as h265parse is now setting
+ alternate-mode=interleaved on alternate content to not break compat with
+ elements not supporting alternate.
+ As a result the decoder now accept both 'interleaved' and 'alternate' on
+ its input and ensures that its ouput has interlace-mode=alternate.
+ Needed to fix https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/issues/825
+ Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-omx/-/merge_requests/72>
+
+2020-09-08 17:31:06 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * .gitlab-ci.yml:
+ ci: include template from gst-ci master branch again
+
+2020-09-08 16:59:09 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * meson.build:
+ Back to development
+
+=== release 1.18.0 ===
+
+2020-09-08 00:10:02 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * .gitlab-ci.yml:
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * gst-omx.doap:
+ * meson.build:
+ Release 1.18.0
+
+2020-08-27 17:19:44 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * config/tizonia/meson.build:
+ meson: fix Tizonia build
+ Was failing for release versions with
+ meson.build:414:10: ERROR: Can not set values on configuration object that has been used.
+ Caused by !69, but CI didn't notice at the time because it was set to a git version.
+
+=== release 1.17.90 ===
+
+2020-08-20 16:16:35 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * gst-omx.doap:
+ * meson.build:
+ Release 1.17.90
+
+2020-07-08 17:39:20 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * gst-omx.doap:
+ * meson.build:
+ * scripts/extract-release-date-from-doap-file.py:
+ meson: set release date from .doap file for releases
+ Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-omx/-/merge_requests/69>
+
+2020-07-03 02:04:16 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * meson.build:
+ Back to development
+
+=== release 1.17.2 ===
+
+2020-07-03 00:37:06 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * gst-omx.doap:
+ * meson.build:
+ Release 1.17.2
+
+2020-06-20 00:28:37 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * meson.build:
+ Back to development
+
+=== release 1.17.1 ===
+
+2020-06-19 19:27:38 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * gst-omx.doap:
+ * meson.build:
+ Release 1.17.1
+
+2020-06-16 01:20:27 +0530 Nirbheek Chauhan <nirbheek@centricular.com>
+
+ * docs/gst_plugins_cache.json:
+ docs: Update plugin cache json
+ https://gitlab.freedesktop.org/alatiera/gst-ci/-/jobs/3109574
+ Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-omx/-/merge_requests/68>
+
+2020-06-03 22:24:09 -0400 Thibault Saunier <tsaunier@igalia.com>
+
+ * docs/gst_plugins_cache.json:
+ docs: Update documentation cache
+
+2019-12-23 18:23:55 -0800 Dylan Yip <dylan.yip@xilinx.com>
+
+ * omx/gstomx.c:
+ omx: Add latest OMX_ALG_Index's to omx_index_type_to_str
+ Add following indexes to omx_index_type_to_str:
+ OMX_ALG_IndexParamVideoAccessUnitDelimiter
+ OMX_ALG_IndexParamVideoBufferingPeriodSEI
+ OMX_ALG_IndexParamVideoPictureTimingSEI
+ OMX_ALG_IndexParamVideoRecoveryPointSEI
+ OMX_ALG_IndexParamVideoMasteringDisplayColourVolumeSEI
+ OMX_ALG_IndexParamVideoContentLightLevelSEI
+ OMX_ALG_IndexConfigVideoRegionOfInterestByValue
+ OMX_ALG_IndexConfigVideoColorPrimaries
+
+2020-05-20 17:05:33 +0200 Stéphane Cerveau <scerveau@collabora.com>
+
+ * omx/gstomx.c:
+ zynq: change API to use public 2020.01 from vcu-omx-il
+ This new release 2020.01 fixes an API typo
+ Change to OMX_ALG_IndexConfigVideoHighDynamicRangeSEI
+ instead of OMX_ALG_IndexConfigVideoHighDynamicRangeSEIs
+ among others.
+
+2017-12-27 17:18:54 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: factor out gst_omx_video_enc_allocate_out_buffers()
+ No semantic change.
+ Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-omx/-/merge_requests/66>
+
+2020-04-10 11:47:03 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxh265enc.c:
+ * omx/gstomxvideo.c:
+ * omx/gstomxvideo.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: remove unsupported formats from caps template
+ Our encoder implementation actually supports a small subset of the
+ formats supported by the decoder. Those are the formats for which we
+ have a copy path in gst_omx_video_enc_fill_buffer() and which are not
+ filtered out in filter_supported_formats().
+
+2020-04-10 09:59:02 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideo.h:
+ video: remove BGR from supported format
+ It's not supported by either decoder or encoder and is even not listed in
+ gst_omx_video_get_format_from_omx() so it can't work.
+
+2020-04-10 10:21:16 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: add GRAY8 support
+ It's supported by Zynq encoder and was already in the sink caps
+ template.
+
+2020-04-10 11:18:49 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: factor out gst_omx_video_enc_copy_plane()
+ No semantic change, I'm going to use it to copy GRAY8 buffers which is
+ actually a single plane 8-bits format.
+
+2020-04-10 10:58:34 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: use gst_video_meta_get_plane_height() to compute slice height
+ This new API saves us from doing manual computation and actually work
+ with single planar formats, such as GRAY8.
+
+2020-04-07 19:59:12 +0200 Stéphane Cerveau <scerveau@collabora.com>
+
+ * omx/gstomxh264enc.c:
+ * omx/gstomxh265enc.c:
+ * omx/gstomxvideo.c:
+ * omx/gstomxvideoenc.c:
+ omxh26xenc: fix coverity with frame test
+ Coverity was complaining with:
+ Null pointer dereferences (REVERSE_INULL) Null-checking "frame"
+ suggests that it may be null, but it has already been
+ dereferenced on all paths leading to the check.
+ The frame == NULL has been removed as 'frame' is actively used
+ in the code above without any change of dereferencing and setting
+ its value to NULL before the test.
+ CID: 1461287
+
+2020-03-19 16:23:41 +0100 Stéphane Cerveau <scerveau@collabora.com>
+
+ * omx/gstomxvideoenc.c:
+ gstomxvideoenc: fix subframe output_buffer
+ Using more than 1 subframes was failing with
+ frame->output_buffer = NULL
+
+2020-02-06 10:21:49 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: add support of alternate interlace mode on zynq
+
+2020-02-06 10:11:13 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxh265enc.c:
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: add support of alternate interlace mode on zynq
+ It's only supported by the Zynq HEVC encoder for now.
+
+2020-02-06 10:12:50 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomx.c:
+ omx: add alternate flags to buffer_flags_map
+ Zynq specific flags used to tag top/bottom fields in alternate mode.
+
+2020-02-06 09:57:48 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideo.c:
+ * omx/gstomxvideoenc.c:
+ omxvideo(enc): use GST_VIDEO_INFO_FIELD_RATE_N()
+ Does not change anything for now but will be needed when we'll support
+ interlace-mode=alternate as the field rate will be twice the frame rate.
+ Made the code safe from division by 0 while I was on it.
+
+2020-02-06 09:36:20 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omxvideo{enc,dec}: use GST_VIDEO_INFO_FIELD_HEIGHT()
+ Does not change anything for now but will be needed when we'll support
+ interlace-mode=alternate as the fields will have half the frame height.
+
+2020-02-25 10:45:47 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomx.c:
+ omx: don't log error when failing to load conf file with generic target
+ The generic target is meant to only test building gst-omx. It doesn't
+ provide any configuration file and so is not supposed to register any
+ element.
+ I'm not aware of any user building gst-omx with this target and
+ providing their own conf file to actually register elements. But best to
+ not break this use case anyway so let's just downgrade the log message.
+ Fix GST_ERROR in the 'check fedora' CI job.
+
+2020-01-27 11:56:53 +0100 Stéphane Cerveau <scerveau@collabora.com>
+
+ * meson.build:
+ meson: add glib project fallback
+ Add a fallback from glib project to provide glib, gio and
+ gmodule dependencies.
+
+2020-01-15 11:06:12 +0000 Stéphane Cerveau <scerveau@collabora.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: fix warning
+ Fix warning test when OMX_BUFFERFLAG_ENDOFFRAME
+ is not set.
+
+2018-08-28 13:03:14 -0700 Varunkumar Allagadapa <varunkum@xilinx.com>
+
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: Add look-ahead property to ZYNQ_USCALE_PLUS encoder
+ This patch adds look-ahead property to encoder
+ The value indicates look ahead size in frames,
+ the number of frames processed ahead of second pass encoding.
+ Dual pass encoding is disabled if look-ahead
+ value is less than 2.
+
+2018-08-06 13:02:41 -0700 Varunkumar Allagadapa <varunkum@xilinx.com>
+
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: Add long-term-ref support to ZYNQ_USCALE_PLUS encoder
+ Custom API that upstream elements can use to notify encoders about
+ marking longterm ref. pictures or using longterm ref. pictures in
+ encoding process.
+ This patch adds below properties:
+ long-term-ref: Enable/Disable dynamically marking long-term
+ reference pictures in encoding process
+ long-term-freq: Periodicity of long-term reference picture
+ marking in encoding process.
+ If a picture is marked as long-term reference picture then it remains
+ in the DPB list for ever unless it overrides with new long-term pitcure with
+ same index. Encoder can use this long-term picture as refence for
+ encoding.
+ This feature is mostly useful to avoid visual artifacts propagation in streaming use cases
+ when packet loss happens. Instead of requesting for IDR, client can request for use long-term
+ reference picture for encoding.
+
+2020-01-07 10:24:19 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * meson.build:
+ meson: display OMX target when configuring
+ I'm adding more gst-omx CI (
+ https://gitlab.freedesktop.org/gstreamer/gst-ci/issues/20 ) having the
+ OMX targets displayed in the logs makes things clearer.
+
+2019-08-30 10:27:32 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomx.c:
+ omx: remove useless double negations
+ flush and port->flushing are both gboolean.
+
+2019-12-20 22:19:06 -0800 Julien Isorce <jisorce@oblong.com>
+
+ * meson.build:
+ meson: fix tizonia build
+ meson.build was both using path to gst-omx/openmax/OMX*
+ headers and path to OMX headers provided by tizilheaders.pc
+ so this patch makes sure we only use the later.
+ Also bump tizonia minimum version to 0.19.0 which
+ is the latest release.
+
+2019-05-16 10:50:18 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxh265enc.c:
+ * omx/gstomxh265enc.h:
+ omxh265enc: handle CODECCONFIG buffers
+ Exact same code as omxh264enc.
+
+2019-05-16 10:38:49 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: send codec data downstream
+ We are operating in stream-format=byte-stream so the codec data buffer
+ is meant to be part of the buffer flow.
+ The base class will push it when a key frame is requested (as we stored
+ it with gst_video_encoder_set_headers()) but we still have to push it
+ right away as part of the normal buffer flow.
+ Also set the HEADER flag on this buffer.
+
+2019-05-16 10:38:49 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: no need to check if codeconfig has startcode
+ We currently only support stream-format=byte-stream so there is no point
+ re-checking for it when handling CODECCONFIG buffer.
+
+2018-09-04 20:12:17 +0000 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * omx/gstomxh264enc.c:
+ * omx/gstomxh265enc.c:
+ omxh26xenc: Negotiate subframe mode
+ We now negotiate subframe mode through the caps. To enabled subframe
+ mode, the caps need to specify alignment=nal:
+ ... ! omxh264enc ! video/x-h264,alignment=nal ! ...
+ ... ! omxh265enc ! video/x-h265,alignment=nal ! ...
+
+2018-08-31 12:24:34 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: use subframe base class API
+ Use subframe base class support.
+
+2018-09-04 19:34:59 +0000 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: Add helper to enable/disable/read subframe mode
+
+2019-12-19 13:51:17 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomx.c:
+ zynq: add mapping for latest custom indexes
+ Fix warning when building using version 2019.2 of OMX headers.
+
+2019-09-12 16:29:59 -0700 Varunkumar Allagadapa <varunkumar.allagadapa@xilinx.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: update qp-mode settings
+ Adds load-qp-absolute and load-qp-relative qp-modes
+
+2019-12-10 18:34:25 +0900 Shinya Saito <ssaito@igel.co.jp>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Add stride check for input buffer extraction
+ Stride of input buffer may be different from
+ that of omx input port even if both sizes are the same.
+
+2019-05-15 14:04:47 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: pass padding requirements to ALLOCATION query
+ By passing the expected video buffer layout, the upstream producer
+ may be able to produce buffers fitting those requierements allowing
+ gst-omx to use dynamic buffer mode rather than having to copy each input
+ buffer.
+ This is particularly useful with v4l2src as it can request the capture
+ driver to produce buffers with the required paddings.
+
+2019-07-09 13:07:32 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxbufferpool.c:
+ * omx/gstomxvideo.c:
+ * omx/gstomxvideo.h:
+ omxbufferpool: use gst_video_meta_set_alignment()
+ Tell buffer consumer about our paddings.
+ v4l2src can now uses these paddings information when trying to import
+ buffers to configure the v4l2 driver accordingly.
+
+2019-05-30 11:11:34 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: fix buffer size in debug log
+ Use the actual OMX buffer size rather than the info.size as OMX
+ may require larger buffer if the port requires some padding.
+
+2019-10-14 00:48:32 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * .gitignore:
+ * .gitmodules:
+ * Makefile.am:
+ * autogen.sh:
+ * common:
+ * config/Makefile.am:
+ * config/bellagio/Makefile.am:
+ * config/rpi/Makefile.am:
+ * config/tizonia/Makefile.am:
+ * config/zynqultrascaleplus/Makefile.am:
+ * configure.ac:
+ * examples/Makefile.am:
+ * examples/egl/Makefile.am:
+ * m4/Makefile.am:
+ * omx/Makefile.am:
+ * tests/Makefile.am:
+ * tests/check/.gitignore:
+ * tests/check/Makefile.am:
+ * tests/check/generic/.gitignore:
+ * tools/Makefile.am:
+ Remove autotools build
+
+2019-10-07 16:59:10 +0000 Stéphane Cerveau <scerveau@collabora.com>
+
+ * omx/gstomxallocator.c:
+ omxallocator: fix leak with a proper chaining finalize
+
+2019-09-20 15:02:24 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: revert draining on ALLOCATION and DRAIN query
+ My latest patch introduces some regressions which I have no time to
+ debug properly at the moment so just revert it for now.
+
+2019-09-17 13:02:54 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: let encoder base class handle ALLOCATION query
+ Fixing a regression introduced in my previous patch
+ (7c40a91c31aa4bcbb191f7c6a5d222edf9dfd9d1).
+ The ALLOCATION query needs to be handled by GstVideoEncoder (to call
+ propose_allocation()) so chain up the query handling rather than early
+ returning.
+
+2019-08-29 12:20:56 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: drain encoder on ALLOCATION and DRAIN queries
+ Ensure that the encoder releases all its input buffers when requested by
+ upstream. Encoder input buffers may be shared with downstreaming (when
+ using dmabuf), upstream may then request the encoder to
+ drain when reconfiguring before destroying its buffers.
+ Also drain on ALLOCATION query as we already do in kmssink as that
+ notify of a format change.
+ Fix "decoder ! encoder" pipeline when decoding a file with different
+ resolutions on Zynq.
+
+2019-08-28 15:52:41 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomx.c:
+ omx: log the number of pending buffers when port is EOS
+
+2019-08-28 15:49:00 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomx.c:
+ omx: log when an output port is eos
+
+2019-08-27 15:47:28 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: log the full input format
+ Make it easier to debug dynamic format changes.
+
+2019-08-21 12:25:40 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: fix dmabuf import
+ When importing dmabuf, UseBuffer() has to be called with the fd as
+ pBuffer rather than the mapped address of the buffer.
+
+2019-08-21 12:48:25 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxbufferpool.c:
+ omxbufferpool: fix dmabuf import
+ When importing dmabuf from downstream, we want the allocator to be in
+ OTHER_POOL mode despite output_mode being DMABUF.
+ So check first if other_pool is set before checking for pool's
+ output_mode.
+
+2019-08-22 17:55:54 +0900 Shinya Saito <ssaito@igel.co.jp>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Remove unnecessary gst_video_frame_unmap()
+
+2019-07-25 16:30:13 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: log supported caps by the decoder
+ Can be useful when debugging to check the caps supported by the decoder
+ before filtering.
+
+2019-07-11 12:03:46 +0900 Shinya Saito <ssaito@igel.co.jp>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Unref frame of codec config buffer
+ After handling codec config, codec frame should be unreffed.
+
+2019-06-14 16:27:37 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideo.c:
+ omxvideo: check difference between frame and requested ts
+ This has proven to be very useful when debugging to detect bugs where we
+ match the wrong gst frame with an output OMX buffer.
+
+2019-06-14 10:57:29 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideo.c:
+ * omx/gstomxvideo.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omxvideo: add debug infos to find_nearest_frame()
+ Those debug infos have proved to be very helpful when debugging
+ timestamp issues. They are often linked to gst-omx picking the wrong
+ frame when trying to map from OMX.
+
+2019-03-05 16:57:40 +0900 Shinya Saito <ssaito@igel.co.jp>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Deactivate negotiated pool when output own buffer
+ If decoder outputs internal buffer and not use OMX_UseBuffer,
+ downstream bufferpool should be stopped.
+
+2019-06-03 12:21:05 +0900 Shinya Saito <ssaito@igel.co.jp>
+
+ * omx/gstomxh264enc.c:
+ * omx/gstomxh264enc.h:
+ omxh264enc: Add 'ref-frames' property
+ Add a property to control the number of frames for reference.
+ Min and max value is based on OpenMAX IL 1.2.0 Specification.
+
+2019-06-03 07:57:02 +0200 Niels De Graef <niels.degraef@barco.com>
+
+ * configure.ac:
+ * meson.build:
+ meson: Bump minimal GLib version to 2.44
+ This means we can use some newer features and get rid of some
+ boilerplate code using the G_DECLARE_* macros.
+ As discussed on IRC, 2.44 is old enough by now to start depending on it.
+
+2019-04-19 12:38:54 -0400 Thibault Saunier <tsaunier@igalia.com>
+
+ * docs/gst_plugins_cache.json:
+ * docs/index.md:
+ * docs/meson.build:
+ * docs/sitemap.txt:
+ * meson.build:
+ * meson_options.txt:
+ * omx/meson.build:
+ doc: Build documentation of hotdoc
+
+2019-03-26 12:26:03 +0200 George Kiagiadakis <george.kiagiadakis@collabora.com>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ gstomx: remove gst_omx_buffer_set_omx_buf/get_omx_buf
+ They are no longer used anywhere
+
+2019-03-22 12:11:13 +0200 George Kiagiadakis <george.kiagiadakis@collabora.com>
+
+ * omx/Makefile.am:
+ * omx/gstomxallocator.c:
+ * omx/gstomxallocator.h:
+ * omx/gstomxbufferpool.c:
+ * omx/gstomxbufferpool.h:
+ * omx/gstomxvideoenc.c:
+ * omx/meson.build:
+ omxbufferpool: refactor to allow memory sharing
+ One big restriction of the OMX buffer pool has always been
+ that the GstMemory objects were flagged with NO_SHARE.
+ This was because the buffer pool needed to be sure that when
+ a buffer returned to the pool, it would be safe to release the
+ OMX buffer back to OpenMAX.
+ With this change, this is no longer a restriction. What this
+ commit introduces is a new allocator that allows us to track
+ the GstMemory objects independently. Now, when a buffer returns
+ to the pool, it is not necessary for the memory to be released
+ as well. We simply track the memory's ref count in the allocator
+ and we return the OMX buffer back when the memory's ref count
+ drops to 0.
+ The reason for doing this is to allow implementing zero-copy
+ transfers in situations where we may need to copy or map a
+ certain region of the buffer. For instance, omxh264enc ! h264parse
+ should be possible to be zero-copy by using an OMX buffer pool
+ between them.
+
+2019-04-23 15:13:23 +0530 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxbufferpool.c:
+ omxbufferpool: fix memory mapping with offset
+ gst_memory_map() is already adding the offset to the mapped pointer.
+ Doing it in the memory implementation was resulting in the offset being
+ accounted twice.
+ It doesn't matter yet as we are only creating memory without offset for
+ now but it will once we'll start sharing OMX memories.
+
+2019-04-19 10:43:58 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * RELEASE:
+ * configure.ac:
+ * meson.build:
+ Back to development
+
+=== release 1.16.0 ===
+
+2019-04-19 00:38:44 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * configure.ac:
+ * gst-omx.doap:
+ * meson.build:
+ Release 1.16.0
+
+2019-04-16 12:23:10 -0700 Julien Isorce <jisorce@oblong.com>
+
+ * omx/gstomx.c:
+ Fixes build with omx >= 1.2.0
+ gstomx.c:1405:10: error: ‘OMX_IndexParamCustomContentPipe’ undeclared (first use in this function)
+ case OMX_IndexParamCustomContentPipe
+ Some enums have been deprecated in 1.2.0
+ https://gitlab.freedesktop.org/gstreamer/gst-omx/issues/27
+
+2018-05-18 10:55:21 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * configure.ac:
+ * examples/egl/Makefile.am:
+ * examples/egl/meson.build:
+ testegl: properly detect and use rpi specific libs
+ Use pkg-config to detect and configure rpi specific libs used in testegl
+ rather than hardcoding their flags.
+
+2018-05-18 10:53:34 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * examples/egl/testegl.c:
+ testelg: include eglext.h
+ Neded for the declaration of eglSaneChooseConfigBRCM().
+
+2018-05-18 10:38:33 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * examples/egl/testegl.c:
+ testegl: move up pi specific macros
+ We need to define __VCCOREVER__ and disable redundant-decls before
+ including the egl.h from the pi.
+
+=== release 1.15.90 ===
+
+2019-04-11 00:40:52 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * configure.ac:
+ * gst-omx.doap:
+ * meson.build:
+ Release 1.15.90
+
+2019-04-10 00:19:55 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * meson.build:
+ meson: add -Wundef as additional warning flag
+
+2019-04-10 00:16:27 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * omx/gstomxvideoenc.c:
+ omx: fix autotools build for generic target
+ gstomxvideoenc.c:2874:7: error: "USE_OMX_TARGET_ZYNQ_USCALE_PLUS" is not defined, evaluates to 0 [-Werror=undef]
+ #elif USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ Works on meson because it doesn't use -Wundef
+
+2018-11-12 12:51:28 +0200 Jordan Petridis <jordan@centricular.com>
+
+ * .gitlab-ci.yml:
+ Add Gitlab CI configuration
+ This commit adds a .gitlab-ci.yml file, which uses a feature
+ to fetch the config from a centralized repository. The intent is
+ to have all the gstreamer modules use the same configuration.
+ The configuration is currently hosted at the gst-ci repository
+ under the gitlab/ci_template.yml path.
+ Part of https://gitlab.freedesktop.org/gstreamer/gstreamer-project/issues/29
+
+2019-03-25 16:30:11 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomx.c:
+ omx: disable OMX_API_TRACE code if gst debug is disabled
+ No need to create debug structs which won't be used as DEBUG macros are
+ no-op.
+
+2018-10-11 10:55:04 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: log Get/SetParameter/Config calls
+ Extend OMX_API_TRACE by logging component configuration calls.
+
+2019-02-06 14:57:05 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxbufferpool.c:
+ omxbufferpool: don't use CAT_PERFORMANCE if pool will copy
+ This was the single place where this category was used in gst-omx so
+ most users, including me, are generally not turning it and were missing this
+ important information from logs.
+ The copying code uses gst_video_frame_copy() which is already logging
+ with CAT_PERFORMANCE so we can still have this information when using
+ only this debug category.
+
+2019-02-06 14:50:44 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: add debug if proposed pool can't provide enough buffers
+ We were silently ignoring the pool which was pretty confusing when
+ debugging.
+
+2019-03-26 12:17:26 +0000 Charlie Turner <cturner@igalia.com>
+
+ * omx/gstomxaacdec.c:
+ * omx/gstomxaacenc.c:
+ * omx/gstomxamrdec.c:
+ * omx/gstomxh263dec.c:
+ * omx/gstomxh263enc.c:
+ * omx/gstomxh264dec.c:
+ * omx/gstomxh264enc.c:
+ * omx/gstomxh265dec.c:
+ * omx/gstomxh265enc.c:
+ * omx/gstomxmjpegdec.c:
+ * omx/gstomxmp3dec.c:
+ * omx/gstomxmp3enc.c:
+ * omx/gstomxmpeg2videodec.c:
+ * omx/gstomxmpeg4videodec.c:
+ * omx/gstomxmpeg4videoenc.c:
+ * omx/gstomxtheoradec.c:
+ * omx/gstomxvp8dec.c:
+ * omx/gstomxwmvdec.c:
+ omx: Add hardware classifiers to encoders/decoders
+
+2019-03-25 16:01:48 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * meson.build:
+ meson: sync warnings flags with -good
+ Add more warnings flags and disabled unused variable warnings if gst
+ debug system is disabled.
+ Copied from gst-plugins-good/meson.build
+
+2019-03-04 09:16:40 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * NEWS:
+ * RELEASE:
+ * configure.ac:
+ * meson.build:
+ Back to development
+
+=== release 1.15.2 ===
+
+2019-02-26 12:02:23 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * configure.ac:
+ * gst-omx.doap:
+ * meson.build:
+ Release 1.15.2
+
+2019-02-14 23:57:09 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * meson.build:
+ * meson_options.txt:
+ meson: add options to disable examples, tests and tools and bump meson requirement
+
+2019-01-04 10:11:38 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomxvideo.c:
+ * omx/gstomxvideo.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omxvideo: use GST_VIDEO_CAPS_MAKE() for template caps
+ Simplify the code and so we advertise the formats actually supported by
+ gst-omx.
+
+2018-06-04 12:20:03 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: validate cpb-size and initial-delay
+ cpb-size cannot be smaller than initial-delay.
+
+2018-10-02 10:47:06 -0400 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Remove duplicated QoS code
+ The 'finish' function do the exact same check / drop, there is no
+ need to duplicate this here.
+
+2018-09-20 14:44:09 -0400 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: Remove dead code
+ The omxvideodec base class have a totally unused prepare_frame() vritual
+ function, remove it.
+
+2018-07-11 17:38:22 -0700 Varunkumar Allagadapa <varunkum@xilinx.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: add adaptive gop-mode option
+ Added adaptive gop-mode option to ZYNQ_USCALE_PLUS encoder properties
+
+2018-02-13 18:25:51 +0000 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Add dynamic framerate support
+ Instead of going through a full reset, try and change the framerate
+ config on the encoder when only the framerate have change.
+
+=== release 1.15.1 ===
+
+2019-01-17 02:38:28 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * configure.ac:
+ * gst-omx.doap:
+ * meson.build:
+ Release 1.15.1
+
+2018-02-20 10:57:42 -0800 Varunkumar Allagadapa <varunkum@xilinx.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Add dynamic IDR insertion support on zynq
+ As the pi, the zynq has its own API to request keyframe.
+
+2019-01-07 13:29:37 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxbufferpool.c:
+ omxbufferpool: fix race when releasing input buffers
+ If buffers were released from the pool while
+ gst_omx_video_enc_handle_frame() was waiting for new buffers,
+ gst_omx_port_acquire_buffer() was never awaken as the buffers weren't
+ released through OMX's messaging system.
+ GQueue isn't thread safe so also protect it with the lock mutex.
+
+2018-11-15 11:17:59 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxbufferpool.c:
+ * omx/gstomxbufferpool.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omxbufferpool: fix early input buffer release
+ We used to track the 'allocating' status on the pool. It is used while
+ allocating so output buffers aren't passed right away to OMX and input
+ ones are not re-added to the pending queue.
+ This was causing a bug when exporting buffers to v4l2src. On start
+ v4l2src acquires a buffer, read its stride and release it right away.
+ As no buffer was received by the encoder element at this point, 'allocating'
+ was still on TRUE and so the the buffer wasn't put back to the pending
+ queue and, as result, no longer available to the pool.
+ Fix this by checking the active status of the pool instead of manually
+ tracking it down. The pool is considered as active at the very end of
+ the activation process so we're good when buffers are released during
+ the activation.
+
+2018-12-05 17:24:48 -0300 Thibault Saunier <tsaunier@igalia.com>
+
+ * common:
+ Automatic update of common submodule
+ From ed78bee to 59cb678
+
+2018-11-23 12:57:15 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.com>
+
+ * omx/gstomx.c:
+ omx: fix OMX_EventBufferFlag OMX_API_TRACE struct
+ The GType was missing from the second field of the struct.
+
+2018-11-05 05:43:43 +0000 Matthew Waters <matthew@centricular.com>
+
+ * .gitmodules:
+ * gst-omx.doap:
+ Update git locations to gitlab
+
+2018-09-18 16:50:11 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: rename OMX_PERFORMANCE debug cat to OMX_API_TRACE
+ This debug category can now be used to track more OMX calls and events
+ so best to rename it to something more generic.
+ https://bugzilla.gnome.org/show_bug.cgi?id=797171
+
+2018-08-21 17:35:04 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: log OMX commands with OMX_PERFORMANCE debug category
+ It has been useful to have a clear raw and structured view of the gst
+ <-> OMX exchanges when debugging.
+ https://bugzilla.gnome.org/show_bug.cgi?id=797171
+
+2018-08-21 16:50:38 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: factor out gst_omx_component_send_command()
+ No semantic change. I'm going to add extra debug in this function.
+ https://bugzilla.gnome.org/show_bug.cgi?id=797171
+
+2018-08-21 15:14:09 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: log OMX events with OMX_PERFORMANCE debug category
+ It has been useful to have a clear raw and structured view of the gst
+ <-> OMX exchanges when debugging.
+ https://bugzilla.gnome.org/show_bug.cgi?id=797171
+
+2018-08-22 12:51:30 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: rename log_omx_performance() to log_omx_performance_buffer()
+ I'm about to log more things under this category
+ https://bugzilla.gnome.org/show_bug.cgi?id=797171
+
+2018-09-07 22:57:30 -0400 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Remove spurious locking
+ The method we call in the context of pushing a buffer are all thread
+ safe. Holding a lock would prevent input buffers from being queued while
+ pushing.
+ https://bugzilla.gnome.org/show_bug.cgi?id=715192
+
+2018-09-07 23:09:29 -0400 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Remove unneeded size check
+ We only enter this branch if nFilledLen > 0, there is not need
+ to check again.
+ https://bugzilla.gnome.org/show_bug.cgi?id=715192
+
+2018-09-07 22:55:41 -0400 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Remove spurious unlock in error case
+ This was forgotton in previous patch. We no long hold the lock when goto
+ invalid_buffer is called.
+ https://bugzilla.gnome.org/show_bug.cgi?id=715192
+
+2018-08-31 17:28:03 -0400 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: don't hold the stream lock when trying to push a frame
+ The base class methods will lock this properly when needed, there seems
+ to be no need to lock it explicitly.
+ This allows the patch in gstvideodec for unlocking the stream lock
+ when pushing buffers out to work.
+ https://bugzilla.gnome.org/show_bug.cgi?id=715192
+
+2018-07-31 13:22:31 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: don't import OMX buffers from downstream
+ We already have code configuring the encoder stride and slice height
+ when receiving the first buffer from upstream.
+ We don't have an equivalent when the encoder is exporting its buffers to the
+ decoder.
+ There is no point adding it and making the code even more
+ complex as we wouldn't gain anything by exporting from the encoder to
+ the decoder. The dynamic buffer mode already ensures 0-copy between OMX
+ components.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796918
+
+2018-05-15 11:59:26 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxbufferpool.c:
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: implement dmabuf export on input buffers
+ Propose pool upstream so input buffers can be allocated by the port and
+ exported as dmabuf.
+ The actual OMX buffers are allocated when the pool is activated, so we
+ don't end up doing useless allocations if the pool isn't used.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796918
+
+2018-08-13 15:10:37 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxaudiodec.c:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxaudiosink.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: allow gst_omx_port_acquire_buffer() to not wait for buffers
+ Will be needed to implement GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796918
+
+2018-07-31 15:04:33 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: don't import non-dmabuf when dec is in dmabuf mode
+ Fix 'omxh264dec ! videocrop' pipeline.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796918
+
+2018-08-02 11:29:12 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: factor out gst_omx_try_importing_buffer()
+ No semantic change, just make the code clearer and improve debug output.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796918
+
+2018-07-26 16:30:08 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: fix gst_video_info_from_caps() caps assertion
+ The "use buffers" code path uses gst_video_info_from_caps() which is
+ asserting if caps is NULL (because pool was rejected).
+ https://bugzilla.gnome.org/show_bug.cgi?id=796918
+
+2018-07-26 16:22:50 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: fix pool caps reference stealing
+ gst_buffer_pool_config_get_params() doesn't ref the returning caps;
+ so gst_caps_replace() was unreffing the reference owned by the pool.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796918
+
+2018-07-25 09:57:20 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: prevent timeout when shutting down because of pending out buffers
+ The OMX transition state to Loaded won't be complete until all buffers
+ have been freed. There is no point waiting, and timeout, if we know that
+ output buffers haven't been freed yet.
+ The typical scenario is output buffers being still used downstream
+ and being freed later when released back to the pool.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796918
+
+2018-07-24 15:14:31 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxbufferpool.c:
+ omxbufferpool: reference the OMX component
+ Now that the pool is responsible of freeing the OMX buffers, we need to
+ ensure that the OMX component stay alive while the pool is as we rely on
+ the component to free the buffers.
+ The GstOMXPort is owned by the component so no need to ref this one.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796918
+
+2018-07-24 15:06:01 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxaudiodec.c:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxaudiosink.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ turn GstOMXComponent to a GstMiniObject
+ Will use it for refcounting.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796918
+
+2018-05-28 12:20:45 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxbufferpool.c:
+ * omx/gstomxvideodec.c:
+ omxbufferpool: deallocate OMX buffers when stopping
+ The pool is stopped when all the buffers have been released. Deallocate
+ when stopping so we are sure that the buffers aren't still used by
+ another element.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796918
+
+2018-05-24 16:28:21 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: call gst_omx_buffer_unmap() when handling BUFFER_DONE
+ When using a input buffer pool, the buffer may be released to the pool when
+ gst_omx_buffer_unmap() is called. We need to have buf->used unset at
+ this point as the pool may use it to check the status of the pool.
+ {Empty,Fill}BufferDone is called from OMX internal threads while
+ messages are handled from gst elements' thread. Best to do all this
+ when handling the message so we don't mess with OMX threads and keep
+ the original thread/logic split.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796918
+
+2018-05-25 14:44:16 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omxvideo{enc,dec}: stop calling shutdown() in change_state
+ This is no longer needed since we implemented close() vfuncs as the
+ encoder/decoder base class already take care of calling close() (which
+ is calling shutdown()) in its own change_state implementation.
+ We also move the shut down of the component from PAUSED_TO_READY to READY_TO_NULL.
+ By doing so upstream will have already deactivated the pool from the
+ encoder and so won't be preventing the OMX state change as the buffers
+ will all be released.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796918
+
+2018-05-15 16:21:26 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxbufferpool.c:
+ omx: factor out gst_omx_buffer_get/set_omx_buf()
+ Move the qdata code to helper functions as I'm going to need them in
+ omxvideoenc to implement dmabuf export.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796918
+
+2018-05-15 11:01:13 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: factor out gst_omx_video_enc_set_to_idle()
+ No semantic change. We'll have to use this when the input pool is
+ activated so we can allocate buffers.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796918
+
+2018-05-15 09:56:10 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: factor out gst_omx_video_enc_deallocate_in_buffers()
+ Will add extra code when adding input buffer pool.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796918
+
+2018-05-14 15:16:38 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: add pBuffer to OMX_PERFORMANCE logs
+ Can be useful to check the fd being passed when using dmabuf.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796918
+
+2018-03-21 12:43:33 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: factor out gst_omx_port_set_dmabuf()
+ No semantic change. I also made the debug message a bit clearer.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796918
+
+2018-08-22 15:56:18 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: wait for flush complete and buffers being released when flushing
+ When flusing we should wait for OMX to send the flush command complete event
+ AND all ports being released.
+ We were stopping as soon as one of those condition was met.
+ Fix a race between FillThisBufferDone/EmptyBufferDone and the flush
+ EventCmdComplete messages. The OMX implementation is supposed to release
+ its buffers before posting the EventCmdComplete event but the ordering
+ isn't guaranteed as the FillThisBufferDone/EmptyBufferDone and
+ EventHandler callbacks can be called from different threads (cf 2.7
+ 'Thread Safety' in the spec).
+ Only wait for buffers currently used by OMX as some buffers may not be
+ in the pending queue because they are held downstream.
+ https://bugzilla.gnome.org/show_bug.cgi?id=789475
+
+2018-08-22 15:52:23 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: factor out should_wait_until_flushed()
+ No semantic change. Makes the code easier to understand and I'm about to
+ change the waiting condition.
+ https://bugzilla.gnome.org/show_bug.cgi?id=789475
+
+2018-08-28 13:10:35 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: pause component when flushing
+ As stated in the spec ("6.1.3 Seek Event Sequence") we should pause
+ before flushing.
+ We were pausing the decoder but not the encoder so I just aligned the
+ two code paths.
+ https://bugzilla.gnome.org/show_bug.cgi?id=797038
+
+2018-07-12 12:41:18 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: fix vertical padding in NV16 formats
+ My previous patch to calculate the vertical padding was always halfing
+ the height of the chroma plane which is incorrect for NV16 formats.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796749
+
+2018-07-05 15:13:47 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: include vertical padding in nFilledLen when copying
+ According to the OMX spec (3.1.3.7.1) nFilledLen is meant to include any
+ padding. We use to include the horizontal one (stride) but not the
+ vertical one if nSliceHeight is bigger than the actual height.
+ The calculated nFilledLen was wrong as it didn't include the padding
+ between planes.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796749
+
+2018-04-26 12:30:47 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: implement decide_allocation
+ Increase the number of output buffers by the number of buffers requested
+ downstream.
+ Prevent buffers starvation if downstream is going to use dynamic buffer
+ mode on its input.
+ https://bugzilla.gnome.org/show_bug.cgi?id=795746
+
+2018-04-26 12:29:16 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: implement propose_allocation
+ Tell upstream about how many buffer we plan to use so they can adjust
+ their own number of buffers accordingly if needed.
+ Same logic as the existing gst_omx_video_enc_propose_allocation().
+ https://bugzilla.gnome.org/show_bug.cgi?id=795746
+
+2018-05-17 09:54:11 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: always signal drain cond when stopping streaming loop
+ Similar change as the one I just did in omxvideodec.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796207
+
+2018-05-16 17:06:29 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: always signal drain cond when stopping streaming loop
+ If for some reason something goes wrong and we stop the streaming loop
+ we may end up with other threads still waiting on the drain cond.
+ No more buffers will be produced by the component so they were waiting
+ forever.
+ Fix this by always signalling this cond when stopping the streaming
+ loop.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796207
+
+2018-05-16 17:02:01 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideoenc: factor out gst_omx_video_enc_pause_loop()
+ No semantic change. I'm going to use it in more failure cases.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796207
+
+2018-05-17 14:24:52 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * config/zynqultrascaleplus/gstomx.conf:
+ zynqultrascaleplus: enable 'ensure-buffer-count-actual' hack
+ https://bugzilla.gnome.org/show_bug.cgi?id=791211
+
+2018-04-27 16:26:36 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omxvideodec/enc: add hack updating nBufferCountActual before allocating
+ The OMX specs states that the nBufferCountActual of a port has to default
+ to its nBufferCountMin. If we don't change nBufferCountActual we purely rely
+ on this default. But in some cases, OMX may change nBufferCountMin before we
+ allocate buffers. Like for example when configuring the input ports with the
+ actual format, it may decrease the number of minimal buffers required.
+ This method checks this and update nBufferCountActual if needed so we'll use
+ less buffers than the worst case in such scenarios.
+ SetParameter() needs to be called when the port is either disabled or
+ the component in the Loaded state.
+ Don't do this for the decoder output as
+ gst_omx_video_dec_allocate_output_buffers() already check
+ nBufferCountMin when computing the number of output buffers.
+ On some platform, like rpi, the default nBufferCountActual is much
+ higher than nBufferCountMin so only enable this using a specific gst-omx
+ hack.
+ https://bugzilla.gnome.org/show_bug.cgi?id=791211
+
+2018-05-28 15:02:13 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omxvidee{enc,dec}: refresh input port definition after setting format
+ Setting the input format and the associated encoder/decoder settings
+ may also affect the nBufferCountMin of the input port.
+ Refresh the input port so we'll use up to date values in propose/decide
+ allocation.
+ https://bugzilla.gnome.org/show_bug.cgi?id=796445
+
+2018-05-07 11:59:08 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: always consider component in 'invalid' state when an error occured
+ gst_omx_component_get_state() used to early return if there was no
+ pending state change. So if the component raised an error it wasn't
+ considered in the invalid state until the next requested state change.
+ Fix this by checking first if we received an error.
+ https://bugzilla.gnome.org/show_bug.cgi?id=795874
+
+2018-05-25 01:35:58 +1000 Matthew Waters <matthew@centricular.com>
+
+ * meson.build:
+ * meson_options.txt:
+ meson: Update option names to omit 'with_omx' prefixes
+ Companion commit to:
+ https://cgit.freedesktop.org/gstreamer/gstreamer/commit/?id=4fb02fc85b70be631f5331b2547e5dc61ef7a43a
+ https://cgit.freedesktop.org/gstreamer/gst-plugins-base/commit/?id=1e1a5d658e4a031535c44823fd398d3052ca2000
+ etc...
+
+2018-03-21 13:52:23 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: pass a GstOMXBufferMode to gst_omx_buffer_pool_new()
+ The output_mode is supposed to be a GstOMXBufferMode, not a boolean.
+
+2018-05-03 09:27:15 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * config/zynqultrascaleplus/gstomx.conf:
+ zynq: remove 'no-disable-outport' hack
+ No longer needed with newer version of the OMX stack.
+
+2018-03-13 16:15:30 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh264enc.c:
+ * omx/gstomxh265enc.c:
+ omxh26{4,5}enc: don't pick default 10-bit profile
+ The OMX stack of the zynqultrascaleplus (the only one supporting
+ NV12_10LE32 and NV16_10LE32) will now pick the proper profile if none
+ has been requested. Best to rely on its default than hardcoding a
+ specific one in gst-omx.
+ https://bugzilla.gnome.org/show_bug.cgi?id=794319
+
+2018-03-06 14:16:56 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh264utils.c:
+ omxh264: sync with supported profiles on zynqultrascaleplus
+ Add extra supported AVC profiles and remove extended and 4:4:4 profiles
+ which are actually not implemented.
+ https://bugzilla.gnome.org/show_bug.cgi?id=794177
+
+2018-03-06 10:45:14 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh264enc.c:
+ * omx/gstomxh264utils.c:
+ * omx/gstomxh264utils.h:
+ omxh264: factor out gst_omx_h264_utils_get_profile_from_enum()
+ Move the profile <-> enum mapping to one place. Make changes easier as
+ I'm about to add extra profiles.
+ No semantic change.
+ https://bugzilla.gnome.org/show_bug.cgi?id=794177
+
+2018-03-06 11:02:44 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh265utils.c:
+ omxh265: add format range extension profiles on zynqultrascaleplus
+ The zynqultrascaleplus OMX gained support for more format range
+ extensions profiles (A.3.5).
+ https://bugzilla.gnome.org/show_bug.cgi?id=794177
+
+2018-03-06 10:45:14 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh265enc.c:
+ * omx/gstomxh265utils.c:
+ * omx/gstomxh265utils.h:
+ omxh265: factor out gst_omx_h265_utils_get_profile_from_enum()
+ Move the profile <-> enum mapping to one place. Make changes easier as
+ I'm about to add some profiles.
+ No semantic change.
+ https://bugzilla.gnome.org/show_bug.cgi?id=794177
+
+2018-03-08 12:22:26 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: add NV16 support
+ NV16 format wasn't supported on encoder input while it was on decoder
+ output.
+ https://bugzilla.gnome.org/show_bug.cgi?id=794175
+
+2018-03-08 12:09:38 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideo.c:
+ omxvideo: display port number when listing supported formats
+ More convenient when debugging.
+ https://bugzilla.gnome.org/show_bug.cgi?id=794175
+
+2018-03-29 16:42:40 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.h:
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: restore OMX default target-bitrate if requested by user
+ 0xffffffff is the magic number in gst-omx meaning 'the default value
+ defined in OMX'. This works fine with OMX parameters which are only set
+ once when starting the component but not with configs which can be
+ changed while PLAYING.
+ Save the actual OMX default bitrate so we can restore it later if user
+ sets back 0xffffffff on the property.
+ Added GST_OMX_PROP_OMX_DEFAULT so we stop hardcoding magic numbers
+ everywhere.
+ https://bugzilla.gnome.org/show_bug.cgi?id=794998
+
+2018-03-29 11:36:00 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: use gst_omx_video_enc_set_bitrate() when setting bitrate in set_format
+ We weren't using the usual pattern when re-setting the bitrate:
+ - get parameters from OMX
+ - update only the fields different from 0xffffffff (OMX defaults)
+ - set parameters
+ Also added a comment explaining why we re-set this param.
+ https://bugzilla.gnome.org/show_bug.cgi?id=794998
+
+2018-03-29 11:26:04 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: factor out gst_omx_video_enc_set_bitrate()
+ No semantic change, I'm about to re-use this function in set_format().
+ https://bugzilla.gnome.org/show_bug.cgi?id=794998
+
+2018-04-20 11:54:14 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * meson.build:
+ meson: fix miscellaneous meson warnings
+ cc.has_header*() doesn't have a 'required:' kwarg.
+
+2018-04-18 12:42:55 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omxvideoenc/dec: fix handling of component enabling failing
+ - Report the error from OMX if any (OMX_EventError)
+ - If not report the failing to the application (GST_ELEMENT_ERROR)
+ - return GST_FLOW_ERROR rather than FALSE
+ - don't leak @frame
+ https://bugzilla.gnome.org/show_bug.cgi?id=795352
+
+2018-04-16 10:53:41 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * common:
+ Automatic update of common submodule
+ From 3fa2c9e to ed78bee
+
+2018-03-14 14:53:50 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ log_omx_performance: convert pointers to strings
+ G_TYPE_POINTER are not serialized in logs.
+ https://bugzilla.gnome.org/show_bug.cgi?id=794331
+
+2018-04-02 15:14:51 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: remove duplicated debug message
+ We already have the exact same message at the beginning of
+ gst_omx_video_enc_handle_frame(). Having it twice is confusing when
+ reading/grepping logs.
+ I kept the earlier one to keep the symetry with
+ gst_omx_video_dec_handle_frame().
+ https://bugzilla.gnome.org/show_bug.cgi?id=794897
+
+2018-02-22 11:27:03 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: add 'roi' qp-mode on zynqultrascaleplus
+ New QP mode used to handle ROI metadata.
+ https://bugzilla.gnome.org/show_bug.cgi?id=793696
+
+2018-03-20 10:31:10 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * NEWS:
+ * RELEASE:
+ * configure.ac:
+ * meson.build:
+ Back to development
+
+=== release 1.14.0 ===
+
+2018-03-19 20:31:02 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * configure.ac:
+ * gst-omx.doap:
+ * meson.build:
+ Release 1.14.0
+
+=== release 1.13.91 ===
+
+2018-03-13 19:32:39 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * configure.ac:
+ * gst-omx.doap:
+ * meson.build:
+ Release 1.13.91
+
+2018-03-09 12:02:29 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * meson.build:
+ meson: fix typo in package name define
+
+2018-02-27 15:42:53 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh265enc.c:
+ * omx/gstomxh265utils.c:
+ omxh265: update 422 profile names
+ h265parse is gaining support for the format range extension profile
+ (bgo#793876).
+ Use the profile names defined in h265parse.
+ https://bugzilla.gnome.org/show_bug.cgi?id=793928
+
+2018-03-05 13:49:18 -0500 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Don't drop the frame on empty payload
+ This otherwise may lead to "No reference frame found" warning.
+
+2018-03-01 15:16:55 -0500 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Don't drop the frame on empty payload
+ This otherwise may lead to "No reference frame found" warning.
+
+2018-03-02 15:36:06 -0500 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * omx/gstomx.c:
+ omx: Free empty buffers list in use_dynamic_buffers
+ To indicate we are doing dynamic buffers importation, we pass
+ a list of NULL pointers, but we forgot to free that list.
+
+2018-03-01 15:16:32 -0500 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Fix CodecState leak
+
+=== release 1.13.90 ===
+
+2018-03-03 23:00:59 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * configure.ac:
+ * gst-omx.doap:
+ * meson.build:
+ Release 1.13.90
+
+2018-03-03 20:21:06 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * config/Makefile.am:
+ config: dist tizonia config files
+
+2018-03-02 11:06:08 -0500 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * omx/gstomx.c:
+ Revert "omx: wait for flush complete and buffers being released when flushing"
+ This reverts commit 4211e4c29a262f110cb92ddf9c06b403ced233ef.
+
+2018-02-21 12:50:42 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ videoenc: don't set stride padding to 0 when copying frames
+ Padding can be left undefined there is no point filling it with 0.
+ https://bugzilla.gnome.org/show_bug.cgi?id=793694
+
+2018-02-16 11:50:35 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxbufferpool.c:
+ * omx/gstomxh264enc.c:
+ * omx/gstomxh265enc.c:
+ * omx/gstomxvideo.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ add support for NV12_10LE32 and NV16_10LE32 on zynqultrascaleplus
+ The encoder and decoder on zynqultrascaleplus support these new 10 bits
+ format.
+ https://bugzilla.gnome.org/show_bug.cgi?id=793694
+
+2018-02-16 11:46:47 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: factor out gst_omx_video_enc_nv12_manual_copy()
+ No semantic change, I'm going to re-use it to copy the NV12_10LE32
+ format.
+ https://bugzilla.gnome.org/show_bug.cgi?id=793694
+
+2018-01-17 10:40:49 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: display the computed buffer size when configuring input
+ https://bugzilla.gnome.org/show_bug.cgi?id=793694
+
+2018-02-06 14:25:57 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ videoenc: implement ROI on zynqultrascaleplus
+ Check input buffers for ROI meta and pass them to the encoder by using
+ zynqultrascaleplus's custom OMX extension. Also add a new
+ "default-roi-quality" in order to tell the encoder what quality level
+ should be applied to ROI by default.
+ https://bugzilla.gnome.org/show_bug.cgi?id=793696
+
+2018-02-14 17:23:39 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: remove GST_PARAM_MUTABLE_PLAYING from 'max-bitrate' property
+ This property isn't actually mutable in the PLAYING state.
+ https://bugzilla.gnome.org/show_bug.cgi?id=793458
+
+2018-02-14 17:20:02 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: protect target_bitrate with the object lock
+ The 'target-bitrate' property can be changed while PLAYING
+ (GST_PARAM_MUTABLE_PLAYING). Make it thread-safe to prevent concurrent
+ accesses between the application and streaming thread.
+ https://bugzilla.gnome.org/show_bug.cgi?id=793458
+
+2018-02-20 11:46:49 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxbufferpool.c:
+ omxbufferpool: add PERFORMANCE DEBUG message when copying output frames
+ I spent quiet some time figuring out why performance of my pipeline were
+ terrible. Turned out it was because of output frames being copied
+ because of stride/offset mismatch.
+ Add a PERFORMANCE DEBUG message to make it easier to spot and debug from logs.
+ https://bugzilla.gnome.org/show_bug.cgi?id=793637
+
+2018-02-15 19:44:37 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * configure.ac:
+ * meson.build:
+ Back to development
+
+=== release 1.13.1 ===
+
+2018-02-15 17:50:14 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * Makefile.am:
+ * NEWS:
+ * configure.ac:
+ * gst-omx.doap:
+ * meson.build:
+ Release 1.13.1
+
+2017-06-30 15:15:06 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh265enc.c:
+ omxh265enc: fix typo in "periodicty-idr" property name
+ Also fix the 'nick' of the property.
+ omxh265enc is based on the code from omxh264enc and suffers the same
+ typo as we fixed in https://bugzilla.gnome.org/show_bug.cgi?id=784370
+ This element isn't part of a stable release yet so it's not an API
+ break.
+ https://bugzilla.gnome.org/show_bug.cgi?id=793390
+
+2018-02-08 19:18:59 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * meson.build:
+ meson: make version numbers ints and fix int/string comparison
+ WARNING: Trying to compare values of different types (str, int).
+ The result of this is undefined and will become a hard error
+ in a future Meson release.
+ Also remove unused libversion/soversion.
+
+2017-12-12 16:50:00 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * configure.ac:
+ * meson.build:
+ * omx/gstomx.h:
+ include all OMX extension headers if present
+ The OMX specs defines 8 headers that implementations can use to define
+ their custom extensions. We were checking and including 3 and ignoring
+ the other ones.
+ https://bugzilla.gnome.org/show_bug.cgi?id=792043
+
+2018-01-30 10:31:03 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * meson.build:
+ * omx/meson.build:
+ * tools/meson.build:
+ meson: simplify OMX extensions detection
+ We are now always checking which files are present or not, even when using our
+ internal copy of OMX, rather than hardcoding the ones present in it.
+ https://bugzilla.gnome.org/show_bug.cgi?id=792043
+
+2018-01-30 11:54:24 +0000 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * meson.build:
+ * omx/meson.build:
+ * tools/meson.build:
+ Revert "meson: use include_directories() with external OMX headers path"
+ This reverts commit 9d37a92a615e54e8ee12f8c65bcfe386ec9de2d0.
+
+2017-11-27 14:52:10 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh265enc.c:
+ * omx/gstomxh265enc.h:
+ omxh265enc: add some encoding properties
+ constrained-intra-prediction and loop-filter-mode.
+ Those map standard OMX settings.
+ https://bugzilla.gnome.org/show_bug.cgi?id=792528
+
+2017-11-23 15:54:15 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh264enc.c:
+ * omx/gstomxh264enc.h:
+ omxh264enc: add some encoding properties
+ entropy-mode, constrained-intra-prediction and loop-filter-mode.
+ Those map standard OMX settings.
+ https://bugzilla.gnome.org/show_bug.cgi?id=792528
+
+2017-06-08 12:31:21 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: add zynqultrascaleplus specific properties
+ https://bugzilla.gnome.org/show_bug.cgi?id=792528
+
+2017-10-31 12:24:39 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: document unit of target-bitrate property
+ nTargetBitrate and nEncodeBitrate are defined in bits per second in the
+ OMX spec.
+ https://bugzilla.gnome.org/show_bug.cgi?id=792528
+
+2017-07-06 10:18:48 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: add internal-entropy-buffers property on zynqultrascaleplus
+ Custom property to control the number of internal buffers used in the
+ decoder to smooth out entropy decoding performance.
+ https://bugzilla.gnome.org/show_bug.cgi?id=792528
+
+2018-01-30 10:31:03 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * meson.build:
+ * omx/meson.build:
+ * tools/meson.build:
+ meson: use include_directories() with external OMX headers path
+ It seems cleaner to use the proper meson tools to include this path
+ rather than manually tweak the build flags.
+ This also allows us to simplify the OMX extensions detection code. We
+ are now always checking which files are present, even when using our
+ internal copy of OMX, rather than hardcoding the ones present in it.
+ https://bugzilla.gnome.org/show_bug.cgi?id=792043
+
+2017-11-07 15:09:35 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: expose chroma format and bit depth in output caps
+ As we added in the parser (bgo#792039) expose the chroma and bit
+ depth information in output caps.
+ https://bugzilla.gnome.org/show_bug.cgi?id=792040
+
+2017-11-07 14:30:45 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: factor out get_output_caps()
+ No semantic change so far.
+ https://bugzilla.gnome.org/show_bug.cgi?id=792040
+
+2017-12-29 11:59:36 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * config/zynqultrascaleplus/gstomx.conf:
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideodec.c:
+ omxvideodec: add hack to pass color format from caps to OMX decoder
+ This hack tries to pass as much information as possible from caps to the
+ decoder before it receives any buffer. These information can be used by
+ the OMX decoder to, for example, pre-allocate its internal buffers
+ before starting to decode and so reduce its initial latency.
+ This mechanism is currently supported by the zynqultrascaleplus decoder.
+ https://bugzilla.gnome.org/show_bug.cgi?id=792040
+
+2017-12-01 12:43:19 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ log failing OMX calls as errors
+ I find it confusing when debugging that OMX calls returning an error
+ where not logged as GST_LEVEL_ERROR making them harder to spot.
+ Fix this by introducing simple log macros checking the return value of
+ the OMX call and logging failures as errors.
+ https://bugzilla.gnome.org/show_bug.cgi?id=791069
+
+2017-10-30 11:59:19 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ add OMX_PERFORMANCE debug category
+ Can be used to log buffers exchange between OMX and gst-omx to profile
+ performances of the OMX component.
+ Ideally this should be done using tracer hooks but it's currently not
+ possible to define custom hooks outside of core.
+ Use GST_DEBUG="OMX_PERFORMANCE:8" to enable it.
+ See also
+ https://github.com/gdesmott/gst-log-parser/blob/master/src/bin/omx-perf.rs
+ as a simple program consuming those logs to generate gnuplot files and
+ stats.
+ https://bugzilla.gnome.org/show_bug.cgi?id=791093
+
+2017-07-27 11:21:59 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: implement dmabuf import on zynqultrascaleplus
+ The Zynq UltraScale+ encoder implements a custom OMX extension to
+ directly import dmabuf saving the need of mapping input buffers.
+ This can be use with either 'v4l2src io-mode=dmabuf' or an OMX video
+ decoder upstream.
+ https://bugzilla.gnome.org/show_bug.cgi?id=792361
+
+2017-09-22 16:02:40 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: drop late input frames if QoS is enabled
+ Make use of the new GstVideoEncoder QoS API to drop late input frames. This may
+ help a live pipeline to catch up if it's being late and all frames end up
+ being dropped at the sink.
+ https://bugzilla.gnome.org/show_bug.cgi?id=792783
+
+2018-01-19 15:18:23 +0530 Ashish Kumar <kr.ashish@samsung.com>
+
+ * examples/egl/testegl.c:
+ TestEgl: Removed redundant/unused code
+ https://bugzilla.gnome.org/show_bug.cgi?id=788550
+
+2018-01-03 16:07:18 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: early return in fill_buffer() if something goes wrong
+ If something goes wrong while trying to manually copy the input buffer,
+ the 'break' was moving us out of the 'for' loop but not out of the switch block.
+ So we ended up calling gst_video_frame_unmap() a second time (raising
+ assertions) and returning TRUE rather than FALSE.
+ Reproduced with a WIP zynqultrascaleplus OMX branch reporting wrong
+ buffer sizes and so triggering this bug.
+ https://bugzilla.gnome.org/show_bug.cgi?id=792167
+
+2017-12-19 16:09:41 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * meson.build:
+ meson: gl: the winsys and platform list in the .pc file is space-separated
+
+2017-12-19 16:08:58 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * meson.build:
+ meson: fix subproject fallback for gstreamer-gl-1.0
+ It's now in -base.
+
+2017-12-12 17:30:27 +0000 Julien Isorce <jisorce@oblong.com>
+
+ * omx/gstomxvideo.c:
+ * omx/gstomxvideo.h:
+ * omx/gstomxvideodec.c:
+ omxvideodec: ignore very little variations of the framerate
+ If less than 1%.
+ The dynamic format change should not happen when the
+ resolution does not change and when only the framerate
+ changes but very slightly, i.e. from 50000/1677=29.81
+ to 89/3=29.66 so a "percentage change" of less than 1%
+ (i.e. 100*(29.81-29.66)/29.66 = 0.50 < 1 ). In that case
+ just ignore it to avoid unnecessary renegotiation.
+ https://bugzilla.gnome.org/show_bug.cgi?id=759043
+
+2017-08-09 12:07:33 -0400 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: use dynamic buffer mode on input if possible
+ Prevent from copying the input buffers between GStreamer and OMX.
+ Tested on zynqultrascaleplus and rpi (without dynamic buffers).
+ https://bugzilla.gnome.org/show_bug.cgi?id=787093
+
+2017-07-20 16:35:31 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: use dynamic buffer mode on input if possible
+ If the OMX component supports dynamic buffer mode and the input buffers
+ are properly aligned avoid copying each input frame between OMX and
+ GStreamer.
+ Tested on zynqultrascaleplus and rpi (without dynamic buffers).
+ https://bugzilla.gnome.org/show_bug.cgi?id=787093
+
+2017-07-20 12:56:37 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omxvideoenc/dec: factor out input buffer allocation
+ No semantic change so far. I'm going to add an alternate way to allocate
+ input buffers.
+ https://bugzilla.gnome.org/show_bug.cgi?id=787093
+
+2017-07-20 16:31:54 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: add API to implement dynamic buffers support
+ OMX 1.2.0 introduced a third way to manage buffers by allowing
+ components to only allocate buffers header during their initialization
+ and change their pBuffer pointer at runtime.
+ This new feature can save us a copy between GStreamer and OMX for each
+ input buffer.
+ This patch adds API to allocate and use such buffers.
+ https://bugzilla.gnome.org/show_bug.cgi?id=787093
+
+2017-12-14 14:53:17 +1100 Matthew Waters <matthew@centricular.com>
+
+ * common:
+ Automatic update of common submodule
+ From e8c7a71 to 3fa2c9e
+
+2017-12-13 12:06:40 +0000 Julien Isorce <jisorce@oblong.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: consolidate the decision to try UseBuffer
+ The tee element can call gst_query_add_allocation_pool with pool as NULL.
+ Checking nth > 0 is not enough so we need to verify if there is a pool.
+ https://bugzilla.gnome.org/show_bug.cgi?id=730758
+ https://bugzilla.gnome.org/show_bug.cgi?id=784069
+
+2017-12-12 14:45:30 +0000 Julien Isorce <jisorce@oblong.com>
+
+ * omx/gstomxvideo.c:
+ * omx/gstomxvideo.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ gstomxvideodec: fix framerate overflow
+ Some live streams can set the framerate to 50000/1677 (=29.81).
+ GstVideoInfo.fps_n << 16 is wrong if the fps_n is 50000
+ (i.e. greater than 32767).
+ https://bugzilla.gnome.org/show_bug.cgi?id=759043
+
+2017-08-22 13:48:26 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * configure.ac:
+ * examples/egl/Makefile.am:
+ * examples/egl/meson.build:
+ * examples/egl/testegl.c:
+ * meson.build:
+ example: port testegl.c to desktop
+ Will be easier to maintain.
+ Also uniformize autotool build with meson build which is
+ already retrieving the gl libs.
+ https://bugzilla.gnome.org/show_bug.cgi?id=781606
+
+2017-12-11 15:55:44 +0000 Julien Isorce <jisorce@oblong.com>
+
+ * meson.build:
+ meson: move omx features check after target selection
+ And uses gst_omx_args instead of add_global_arguments.
+ Similar to c69232852120d064c689caef07b3c68ad8fe6288
+ which was only for configure.ac
+ Useful to get omxvp8dec with meson too:
+ meson . buildtmp -D with_omx_target=tizonia
+ https://bugzilla.gnome.org/show_bug.cgi?id=782800
+
+2017-12-04 17:11:04 +0000 Julien Isorce <jisorce@oblong.com>
+
+ * config/tizonia/gstomx.conf.in:
+ config: add OMX.Aratelia.audio_decoder.aac to Tizonia config
+ Useful mostly for testing/debugging purpose as this is a software
+ based decoder (libfaad) for which GStreamer provides a direct
+ wrapper.
+ https://bugzilla.gnome.org/show_bug.cgi?id=791482
+
+2017-11-29 14:18:41 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: retrieve OMX_IndexParamVideoPortFormat before setting it
+ The usual pattern when setting OMX params is to first get the struct
+ param, override the values we want to set and then set the updated
+ param.
+ We were not doing this with OMX_IndexParamVideoPortFormat and so were
+ resetting some fields such as OMX_VIDEO_PARAM_PORTFORMATTYPE.xFramerate
+ https://bugzilla.gnome.org/show_bug.cgi?id=790979
+
+2017-05-21 17:34:51 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * omx/gstomxaacenc.c:
+ omxaacenc: also set 'profile' if mpegversion is 4
+ Like done by gst_codec_utils_aac_caps_set_level_and_profile
+ which is called by avenc_aac, ffaac and voaacenc.
+ https://bugzilla.gnome.org/show_bug.cgi?id=735208
+
+2017-10-24 12:19:50 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: wait for flush complete and buffers being released when flushing
+ As stated in the existing comment, when flusing we should wait for OMX
+ to send the flush command complete event AND all ports being released.
+ We were stopping as soon as one of those condition was met.
+ Fix a race between FillThisBufferDone/EmptyBufferDone and the flush
+ EventCmdComplete messages. The OMX implementation is supposed to release
+ its buffers before posting the EventCmdComplete event but the ordering
+ isn't guaranteed as the FillThisBufferDone/EmptyBufferDone and
+ EventHandler callbacks can be called from different threads (cf 2.7
+ 'Thread Safety' in the spec).
+ https://bugzilla.gnome.org/show_bug.cgi?id=789475
+
+2017-10-24 11:45:20 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ gst_omx_port_set_flushing: simplify waiting loop
+ No semantic change so far, I just made the 'while' end condition easier
+ to understand as a first step before changing it.
+ - move error/time out checks inside the loop to make it clearer on what
+ we are actually waiting for.
+ - group port->buffers checks together with parenthesis as they are part
+ of the same conceptual check: waiting for all buffers to be released.
+ https://bugzilla.gnome.org/show_bug.cgi?id=789475
+
+2017-11-27 20:17:17 +1100 Matthew Waters <matthew@centricular.com>
+
+ * common:
+ Automatic update of common submodule
+ From 3f4aa96 to e8c7a71
+
+2017-11-23 15:03:48 +0100 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh264enc.c:
+ * omx/gstomxh264utils.c:
+ zynqultrascaleplus: add support for extra AVC levels
+ The Zynqultrascaleplus has support for extra AVC levels not defined in
+ the OMX spec as a customer extension.
+ https://bugzilla.gnome.org/show_bug.cgi?id=790758
+
+2017-10-16 14:47:07 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * .gitignore:
+ * Makefile.am:
+ * config/meson.build:
+ * configure.ac:
+ * meson.build:
+ * tests/Makefile.am:
+ * tests/check/.gitignore:
+ * tests/check/Makefile.am:
+ * tests/check/generic/.gitignore:
+ * tests/check/generic/states.c:
+ * tests/check/meson.build:
+ * tests/meson.build:
+ add test support
+ Most of the boilerplate and the states test has been copied from
+ gst-plugins-good.
+ https://bugzilla.gnome.org/show_bug.cgi?id=789094
+
+2017-10-17 13:07:05 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * meson.build:
+ * tools/meson.build:
+ meson: add tools support
+ Looks like the tools directory was left out during the initial port to
+ meson.
+ https://bugzilla.gnome.org/show_bug.cgi?id=789090
+
+2017-10-16 14:24:50 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: fix build on rpi
+ The nTimeStamp field is a OMX_TICKS struct on the rpi so use the proper
+ macro to set it.
+ Fix build on the build which has been broken by
+ b3173144b7c1b12c9e1b7571f78659be45d813f6
+ https://bugzilla.gnome.org/show_bug.cgi?id=789052
+
+2017-10-17 12:11:04 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * configure.ac:
+ * meson.build:
+ check if Allegro headers are present when building zynqultrascaleplus
+ The Zynq UltraScale+ uses a custom version of OMX implementing several
+ 3rd party extensions. Make sure those are present when building this
+ target.
+ https://bugzilla.gnome.org/show_bug.cgi?id=788064
+
+2017-10-16 12:42:44 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: remove redundant debug message
+ We have already a debug message right after.
+ https://bugzilla.gnome.org/show_bug.cgi?id=789058
+
+2017-10-16 13:26:38 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh265enc.c:
+ * omx/gstomxh265utils.c:
+ omxh265: fix enum casting when using Allegro HEVC extensions
+ Allegro's HEVC implementation defines a superset of the profiles and
+ enums from the Android implementation.
+ Properly cast to fix -Wenum-conversion warnings from clang.
+ https://bugzilla.gnome.org/show_bug.cgi?id=789057
+
+2017-10-16 13:08:12 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh265enc.c:
+ * omx/gstomxvp8dec.c:
+ properly cast extension enums
+ OMX's allow 3rds party to define extensions using their own enums
+ (like OMX_VIDEO_CODINGEXTTYPE) and to be used as the general
+ ones (like OMX_VIDEO_CODINGTYPE).
+ Properly cast those to fix -Wenum-conversion warnings from some
+ compilers such as clang.
+ https://bugzilla.gnome.org/show_bug.cgi?id=789057
+
+2017-10-09 13:12:35 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: also reset nTimeStamp when re-using buffers
+ Some OMX implementations may check if the timestamp of the output buffers
+ they receive is actually not set.
+ https://bugzilla.gnome.org/show_bug.cgi?id=788711
+
+2017-10-04 17:11:55 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: factor out gst_omx_buffer_reset()
+ https://bugzilla.gnome.org/show_bug.cgi?id=788711
+
+2017-10-09 17:27:22 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ add gst_omx_buffer_flags_to_string()
+ Make debug logs more readable so users don't have to manually figure out
+ the meaning of flags.
+ https://bugzilla.gnome.org/show_bug.cgi?id=788767
+
+2017-09-27 19:47:29 +0530 Ponnam Srinivas <p.srinivas@samsung.com>
+
+ * omx/gstomxh263enc.c:
+ h263enc: fix caps leak in error code path
+ https://bugzilla.gnome.org/show_bug.cgi?id=788245
+
+2017-09-21 15:21:36 +0530 Ponnam Srinivas <p.srinivas@samsung.com>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: fix caps leak
+ https://bugzilla.gnome.org/show_bug.cgi?id=787711
+
+2017-09-21 11:36:46 +0530 Ponnam Srinivas <p.srinivas@samsung.com>
+
+ * omx/gstomxh265enc.c:
+ omxh265enc: fix caps leak
+ https://bugzilla.gnome.org/show_bug.cgi?id=787714
+
+2017-09-13 15:32:51 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: log info about frame before releasing it
+ gst_video_decoder_release_frame() takes ownership of the frame and will
+ destroy it. So we should no longer use it after calling it.
+ https://bugzilla.gnome.org/show_bug.cgi?id=787628
+
+2017-08-20 20:19:33 +0530 Gurkirpal Singh <gurkirpal204@gmail.com>
+
+ * configure.ac:
+ configure: Show tizonia target in help
+ https://bugzilla.gnome.org/show_bug.cgi?id=786544
+
+2017-07-12 14:35:10 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * config/zynqultrascaleplus/gstomx.conf:
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomxh265dec.c:
+ * omx/gstomxh265dec.h:
+ * omx/meson.build:
+ omxh265dec: add H265 decoder
+ Add HEVC decoder for the zynqultrascaleplus platform.
+ I used the H264 decoder code as a template.
+ https://bugzilla.gnome.org/show_bug.cgi?id=785434
+
+2017-07-12 11:01:15 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * config/zynqultrascaleplus/gstomx.conf:
+ * configure.ac:
+ * meson.build:
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomxh265enc.c:
+ * omx/gstomxh265enc.h:
+ * omx/gstomxh265utils.c:
+ * omx/gstomxh265utils.h:
+ * omx/meson.build:
+ omxh265enc: add H265 encoder
+ The OMX spec doesn't support HEVC but the OMX stack of the
+ zynqultrascaleplus adds it as a custom extension.
+ It uses the same API as the one of Android's OMX stack.
+ I used the H264 encoder code as a template.
+ https://bugzilla.gnome.org/show_bug.cgi?id=785434
+
+2017-08-28 13:56:22 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: use caps from query in propose_allocation
+ Prevent crash by not deferencing a NULL pointer if self->input_state
+ isn't defined when propose_allocation() is called.
+ https://bugzilla.gnome.org/show_bug.cgi?id=786442
+
+2017-09-04 09:34:03 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: display states as string if changing failed
+ Improve the error message by displaying the states in their string
+ representation rather than their numerical value.
+ https://bugzilla.gnome.org/show_bug.cgi?id=787235
+
+2017-08-22 10:22:45 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: EGLDisplay is not indirectly defined by gstgl headers inclusion
+ Just use gpointer as done in GstGL to not include
+ EGL/egl.h just for EGLDisplay.
+ https://bugzilla.gnome.org/show_bug.cgi?id=784779
+
+2017-07-14 16:34:04 +0530 Gurkirpal Singh <gurkirpal204@gmail.com>
+
+ * config/tizonia/gstomx.conf.in:
+ config: expose OMX.mesa h264 decoder and encoder in Tizonia config
+ https://bugzilla.gnome.org/show_bug.cgi?id=783976
+
+2017-08-11 07:48:37 -0700 Julien Isorce <jisorce@oblong.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: remove wrong SettingsChanged ack
+ Partially revert 1b7d0b8:
+ omxvideodec: handle IL 1.2 behavior for OMX_SetParameter
+ It turned out it was a problem in the decoder which was
+ not updating some local variables upon SetParameter.
+ https://bugzilla.gnome.org/show_bug.cgi?id=783976
+
+2017-07-20 09:43:19 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * omx/gstomxaudiodec.c:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx{audio,video}{dec,enc}: sequentially disable ports because buffers are not shared
+ For the history, the parallel disable port has been introduced by:
+ "00be69f omxvideodec: Disable output port when setting a new format"
+ and then replicated to videoenc, audiodec and audioenc.
+ This is only required to do 'parallel' if buffers are shared between ports.
+ But for decoders and encoders the input and output buffer are of different
+ nature by definition (bitstream vs images). So they cannot be shared.
+ Also starting from IL 1.2.0 it is written in the spec that the parallel
+ disable is not allowed and will return an error. Except when buffers are
+ shared.
+ Again here we know in advance that they are not shared so let's always
+ do a sequential disable.
+ Tested on Desktop, rpi and zynqultrascaleplus.
+ https://bugzilla.gnome.org/show_bug.cgi?id=786348
+
+2017-08-17 12:26:05 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * common:
+ Automatic update of common submodule
+ From 48a5d85 to 3f4aa96
+
+2017-08-10 12:16:53 -0400 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: use the decoder API to set latency
+ https://bugzilla.gnome.org/show_bug.cgi?id=785125
+
+2017-07-06 14:19:19 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omxvideoenc/dec: declare latency on zynqultrascaleplus
+ The OMX specification doesn't provide any API to expose the latency
+ introduced by encoders and decoders. We implemented this as a custom
+ extension as declaring the latency is needed for live pipelines like
+ video conferencing.
+ https://bugzilla.gnome.org/show_bug.cgi?id=785125
+
+2017-08-07 13:16:01 -0400 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: adjust stride and slice height from input
+ Use the stride and slice height information from the first buffer meta
+ data to adjust the settings of the input port.
+ This will ensure that the OMX input buffers match the GStreamer ones
+ and so will save us from having to copy line-by-line each one.
+ This is also the first step to allow the OMX encoder to receive dmabuf.
+ Tested on rpi and zynqultrascaleplus.
+ https://bugzilla.gnome.org/show_bug.cgi?id=785967
+
+2017-08-07 11:45:29 -0400 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: delay buffer configuration until component is enabled
+ No significant change for now. Just delay the input port configuration
+ of the buffer size related fields (stride, slice height, buffer size)
+ until the component is activated.
+ This will allow us to use the actual stride/height of the first input
+ and so avoid the buffer copying code path in most cases.
+ Tested on rpi and zynqultrascaleplus.
+ https://bugzilla.gnome.org/show_bug.cgi?id=785967
+
+2017-07-24 13:52:35 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omxvideodec/enc: delay allocation after the allocation query
+ Allocating OMX components buffers in set_format() is too early.
+ Doing it when receiving the first buffers will allow the element to use
+ the information from the allocation query and/or the first incoming
+ buffer to pick to best allocation mode.
+ Tested on raspberry pi with dynamic resolution changes on decoder and
+ encoder input.
+ https://bugzilla.gnome.org/show_bug.cgi?id=785967
+
+2017-07-25 14:27:45 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: start src thread in handle_frame()
+ Makes the code simpler as we no longer need to restart the thread in
+ gst_omx_video_enc_flush() and It's more symetric which the omxvideodec
+ implementation.
+ I'm also going to move the enabling of the OMX component in
+ handle_frame() and the src pad thread needs to be started after it.
+ https://bugzilla.gnome.org/show_bug.cgi?id=785967
+
+2017-07-25 14:07:30 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: earlier return if downstream_flow_ret is not OK
+ There is no point to (re)start the src thread if, for example, we are
+ flushing.
+ https://bugzilla.gnome.org/show_bug.cgi?id=785967
+
+2017-07-24 12:31:37 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: factor out enable and disable code
+ No semantic change, just factor out the code enabling and disabling the
+ component to their own functions.
+ Makes the code easier to read as the set_format() method was already
+ pretty big. Will also allow us to easily change the enabling logic.
+ https://bugzilla.gnome.org/show_bug.cgi?id=785967
+
+2017-07-24 12:31:37 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: factor out enable and disable code
+ No semantic change, just factor out the code enabling and disabling the
+ component to their own functions.
+ Makes the code easier to read as the set_format() method was already
+ pretty big. Will also allow us to easily change the enabling logic.
+ https://bugzilla.gnome.org/show_bug.cgi?id=785967
+
+2017-07-27 12:12:01 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: also reset nFilledLen before calling OMX_FillThisBuffer()
+ The spec states that the buffer passed to OMX_FillThisBuffer() needs to be
+ empty. Some implementation may check it actually is by checking its
+ nFilledLen field, so best to reset it as well.
+ https://bugzilla.gnome.org/show_bug.cgi?id=785623
+
+2017-07-17 21:06:47 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: make generic the OMX_UseEGLImage code path
+ Will be easier to maintain and to make enhancements.
+ Tested with Tizonia on Desktop.
+ Also tested with Bellagio to make sure it does not crash when
+ calling OMX_UseEGLImage and indeed it returns NotImplemented.
+ Then gst-omx fallback to OMX_UseBuffer if it can and so on.
+ Also tested on rpi to make sure there is no regression.
+ https://bugzilla.gnome.org/show_bug.cgi?id=784365
+
+2017-07-21 11:52:00 -0400 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Fix segment seek
+ On segment seek, unlike EOS, we drain, but we cannot expect a flush
+ later to reset the decoder state. As a side effect, the decoder would
+ remain in EOS state and ignore any new incoming buffers.
+ To fix this, we call _flush() inside the _drain() function, and
+ _finish() becomes what _drain() was before. This way, for _finish() (the
+ eos case) we only drain, for _drain() triggered by segment seek or new
+ caps, we also reset the decoder state so it's ready to accept buffers.
+ https://bugzilla.gnome.org/show_bug.cgi?id=785237
+
+2017-07-10 15:00:58 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: ensure enough buffers are allocated in the pool
+ Handle allocation query and ensure enough buffers are allocated in
+ the negotiated pool. This help preventing buffer starvation in the pipeline.
+ https://bugzilla.gnome.org/show_bug.cgi?id=785122
+
+2017-07-04 12:16:39 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * configure.ac:
+ * meson.build:
+ * omx/Makefile.am:
+ * omx/gstomxbufferpool.c:
+ * omx/gstomxbufferpool.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ * omx/meson.build:
+ omxvideodec: add dmabuf support for output
+ The zynqultrascaleplus OMX implementation has a custom extension
+ allowing decoders to output dmabuf and so avoid buffers copy between OMX
+ and GStreamer.
+ Make use of this extension when built on the zynqultrascaleplus. The
+ buffer pool code should be re-usable for other platforms as well.
+ https://bugzilla.gnome.org/show_bug.cgi?id=784847
+
+2017-06-20 00:13:33 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * config/tizonia/gstomx.conf.in:
+ config: add OMX.Aratelia.video_decoder.vp8 to Tizonia config
+ Useful mostly for testing/debugging purpose as this is a software
+ based encoder (libvpxdec) for which GStreamer provides a direct
+ wrapper.
+ https://bugzilla.gnome.org/show_bug.cgi?id=783976
+
+2017-06-19 23:56:02 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: handle IL 1.2 behavior for OMX_SetParameter
+ It triggers SettingsChanged on the other port and it is up to
+ the client to decide if it should lead to a port reconfiguration.
+ Settings are propagated to the other port for fields they have
+ in common. But this event is only triggered on the other port
+ if it actually change a setting.
+ https://bugzilla.gnome.org/show_bug.cgi?id=783976
+
+2017-07-18 23:41:17 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * config/tizonia/gstomx.conf.in:
+ config: set rank to 0 for Tizonia's mp3 decoder
+ Should have been 0 from the initial commit
+ eed49b4231a063639f90279c8044404c2149902a
+
+2017-07-17 21:03:55 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: fix file permissions
+ Introduced by ebc9b4903cbdac2793c24b05a1bb7acc3b67fae5
+
+2017-06-29 23:17:26 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: fix buffer leak when eglimage setup fails
+ Can happen if gst_buffer_pool_acquire_buffer succeeds but
+ gst_buffer_n_memory (buffer) is not exactly 1.
+ In theory this should not happen because the decoder requests
+ EGLImage(RGBA) but better to fix any leak on corner cases.
+ https://bugzilla.gnome.org/show_bug.cgi?id=784365
+
+2017-07-17 18:36:36 +0530 Satya Prakash Gupta <sp.gupta@samsung.com>
+
+ * omx/gstomx.c:
+ omx: Possible Memory leak in gst_caps_from_string
+ https://bugzilla.gnome.org/show_bug.cgi?id=784978
+
+2017-07-17 15:48:44 +0530 Satya Prakash Gupta <sp.gupta@samsung.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Fix deadlock in error case when draining
+ https://bugzilla.gnome.org/show_bug.cgi?id=784972
+
+2017-07-17 13:44:54 +0530 Satya Prakash Gupta <sp.gupta@samsung.com>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Fix deadlock in error case when draining
+ https://bugzilla.gnome.org/show_bug.cgi?id=784967
+
+2017-06-02 12:36:30 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * configure.ac:
+ * meson.build:
+ * omx/gstomx.h:
+ build: include OMX_IndexExt and OMX_ComponentExt if present
+ These files may be used by OMX implementation to define custom extensions.
+ Include them if present as we are already doing with OMX_VideoExt.h
+ https://bugzilla.gnome.org/show_bug.cgi?id=784847
+
+2017-07-13 16:40:26 +1000 Jan Schmidt <jan@centricular.com>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: Re-add periodicty-idr property for backward compat
+ Retain backwards compatibility by adding a duplicate
+ property for periodicty-idr
+ https://bugzilla.gnome.org/show_bug.cgi?id=784370
+
+2017-06-30 15:15:06 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: fix typo in "periodicty-idr" property name
+ Also fix the 'nick' of the property.
+ https://bugzilla.gnome.org/show_bug.cgi?id=784370
+
+2017-06-29 22:48:47 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: use OMX_UseBuffer
+ For example this allows the omx decoder to directly fill the
+ pixmaps coming from the video sink.
+ It only avoids a buffer copy when the decoder uses a pool provided
+ by a downstream element. So let's restrict this usage to situations
+ where the decoder decides to use a downstream buffer pool.
+ Tested with Tizonia/OMX.Aratelia.video_decoder.vp8
+ and with Bellagio/OMX.mesa.video_decoder.avc.
+ If it fails to setup buffers with OMX_UseBuffer the decoders
+ fallbacks to usual OMX_AllocateBuffer.
+ Also it allows to test on desktop the GstOMXBufferPool->other_pool
+ management which was previously only used in the OMX_UseEGLImage
+ case, i.e. on Rpi.
+ https://bugzilla.gnome.org/show_bug.cgi?id=784069
+
+2017-07-12 10:29:16 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * omx/gstomx.c:
+ omx: do not always print an error if OMX_{UseBuffer,EGLImage} fails
+ Let the caller decide to print an error. Because it can be part of
+ a normal trial path.
+ https://bugzilla.gnome.org/show_bug.cgi?id=784069
+
+2017-07-12 16:00:53 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/meson.build:
+ meson: add gstomxmp3enc
+ Commit 02d493e85921596f7cac7ef4af02fde500e9a5d8 didn't add
+ gstomxmp3enc.c to meson.
+ https://bugzilla.gnome.org/show_bug.cgi?id=784848
+
+2017-05-23 10:32:58 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * config/tizonia/gstomx.conf.in:
+ config: add OMX.Aratelia.audio_encoder.mp3 to Tizonia config
+ Useful mostly for testing/debugging purpose as this is a software
+ based encoder (libmp3lame) for which GStreamer provides a direct
+ wrapper.
+ https://bugzilla.gnome.org/show_bug.cgi?id=782988
+
+2017-05-23 10:32:06 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomxmp3enc.c:
+ * omx/gstomxmp3enc.h:
+ omx: add gstomxmp3enc
+ Initial support and only tested with the software based
+ encoder OMX.Aratelia.audio_encoder.mp3 from Tizonia which
+ internally uses libmp3lame.
+ https://bugzilla.gnome.org/show_bug.cgi?id=782988
+
+2017-03-28 16:27:10 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * config/zynqultrascaleplus/gstomx.conf:
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxh264dec.c:
+ h264dec: add hack to pass profile and level to OMX
+ This information can be useful to zynqultrascaleplus decoders. They may
+ use this information to reduce startup latency by configuring itself
+ before receiving the first frames.
+ We also have a custom OMX extension allowing the decoder to report the
+ latency. The profile/level information helps it reporting a more
+ accurate latency earlier.
+ https://bugzilla.gnome.org/show_bug.cgi?id=783114
+
+2017-07-03 13:17:11 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/Makefile.am:
+ * omx/gstomxh264enc.c:
+ * omx/gstomxh264utils.c:
+ * omx/gstomxh264utils.h:
+ * omx/meson.build:
+ omxh264enc: move profile and level parsing functions to their own files
+ Will allow to re-use them in the decoder element.
+ https://bugzilla.gnome.org/show_bug.cgi?id=783114
+
+2017-07-04 03:15:00 +0530 Gurkirpal Singh <gurkirpal204@gmail.com>
+
+ * config/meson.build:
+ * config/tizonia/meson.build:
+ * meson.build:
+ * meson_options.txt:
+ meson: Add tizonia option
+ https://bugzilla.gnome.org/show_bug.cgi?id=782800
+
+2017-04-29 02:56:59 +0530 Gurkirpal Singh <gurkirpal204@gmail.com>
+
+ * .gitignore:
+ * config/tizonia/Makefile.am:
+ * config/tizonia/gstomx.conf.in:
+ * config/tizonia/meson.build:
+ * configure.ac:
+ config: add omxmp3dec config for tizonia
+ GST_OMX_CONFIG_DIR=$HOME/gst/master/gst-omx/config/tizonia/ \
+ gst-launch-1.0 filesrc location=mpthreetest.mp3 ! id3demux ! \
+ mpegaudioparse ! omxmp3dec ! audioconvert ! pulsesink
+ v2: [Nicolas] Use template to create gstomx.conf using pkg-config
+ v3: [Nicolas] Ignore only config/tizonia/gstomx.conf
+ v4: [Nicolas] Add "/" for single occurence
+ https://bugzilla.gnome.org/show_bug.cgi?id=782800
+
+2017-05-07 20:09:54 +0530 Gurkirpal Singh <gurkirpal204@gmail.com>
+
+ * omx/gstomx.c:
+ omx: always ignore OMX_ErrorPortUnpopulated
+ It is safe to ignore it always. Tizonia notifies this error to pass
+ some khronos conformance tests. Problem is that gst-omx saves this
+ error in comp->last_error and then gst_omx_port_set_enabled early
+ error out which fails the pipeline.
+ https://bugzilla.gnome.org/show_bug.cgi?id=782800
+
+2017-04-29 02:53:26 +0530 Gurkirpal Singh <gurkirpal204@gmail.com>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: guard some omx enums with IL version
+ Some enums that existed in 1.1.2 just do not exit in 1.2.0
+ See https://www.khronos.org/registry/OpenMAX-IL/specs/OpenMAX_IL_1_2_0_Specification_redline.pdf
+ https://bugzilla.gnome.org/show_bug.cgi?id=782800
+
+2017-04-29 01:56:01 +0530 Gurkirpal Singh <gurkirpal204@gmail.com>
+
+ * configure.ac:
+ configure.ac: add tizonia target for --with-omx-target flag.
+ This will check for tizilheaders.pc which adds path to omx-il
+ headers its cflags. Can be installed all together with the 1.2 headers
+ with package tizilheaders if not building from sources:
+ https://github.com/tizonia/tizonia-openmax-il
+ It is also adviced to remove libomxil-bellagio-dev package because
+ it installs headers /usr/include directly, ex: /usr/include/OMX_Video.h.
+ https://bugzilla.gnome.org/show_bug.cgi?id=782800
+
+2017-07-05 10:47:41 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: update local port_def after reopening the component
+ gst_omx_audio_enc_open will only update GstOMXAudioEnc->port->port_def.
+ Note that the component is reopen only if the flag
+ GST_OMX_HACK_NO_COMPONENT_RECONFIGURE is set.
+ https://bugzilla.gnome.org/show_bug.cgi?id=782418
+
+2017-07-05 10:48:52 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: update local port_def after reopening the component
+ gst_omx_video_enc_open will only update GstOMXVideoEnc->port->port_def.
+ Note that the component is reopen only if the flag
+ GST_OMX_HACK_NO_COMPONENT_RECONFIGURE is set.
+ https://bugzilla.gnome.org/show_bug.cgi?id=782418
+
+2017-05-10 12:38:39 +0900 Sejun Park <sejun79.park@samsung.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: update local port_def after reopening the component
+ gst_omx_video_dec_open will only update GstOMXVideoDec->port->port_def.
+ Note that the component is reopen only if the flag
+ GST_OMX_HACK_NO_COMPONENT_RECONFIGURE is set.
+ https://bugzilla.gnome.org/show_bug.cgi?id=782418
+
+2017-07-03 16:33:06 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: increase the minimum number of allocated buffers
+ Ensure that enough buffers are allocated by adding up component's own
+ minimal plus the number of buffers requested by downstream.
+ This should prevent buffers starvation problem if downstream elements
+ are holding some of the buffers they required.
+ Also simplify the check on the maximum on buffers. What we actually care
+ about is to make sure the pool can hold the minimum of required buffers.
+ https://bugzilla.gnome.org/show_bug.cgi?id=784479
+
+2017-07-03 10:54:50 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: raise a warning if AVCIntraPeriod is not supported
+ Some platforms may not implement OMX_IndexConfigVideoAVCIntraPeriod and
+ use OMX_IndexParamVideoAvc instead to configure the GOP pattern.
+ So raise a warning instead of an error if this API is not implemented.
+ https://bugzilla.gnome.org/show_bug.cgi?id=784379
+
+2017-06-29 14:16:19 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh264enc.c:
+ * omx/gstomxh264enc.h:
+ omxh264enc: add 'b-frames' property
+ Add a property to control the number of B-frames produced by the
+ encoder using the OMX_VIDEO_PARAM_AVCTYPE OMX API.
+ https://bugzilla.gnome.org/show_bug.cgi?id=784379
+
+2017-06-30 14:18:35 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: fix typo in 'set_avc_intra_period'
+ https://bugzilla.gnome.org/show_bug.cgi?id=784379
+
+2017-05-22 11:23:33 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * config/Makefile.am:
+ * config/meson.build:
+ * config/zynqultrascaleplus/Makefile.am:
+ * config/zynqultrascaleplus/gstomx.conf:
+ * config/zynqultrascaleplus/meson.build:
+ * configure.ac:
+ * meson.build:
+ * meson_options.txt:
+ add 'zynqultrascaleplus' as OMX target
+ Adding support for the 'Zynq UltraScale+' as a new OMX target.
+ See https://www.xilinx.com/products/silicon-devices/soc/zynq-ultrascale-mpsoc.html
+ for details about the platform.
+ https://bugzilla.gnome.org/show_bug.cgi?id=783097
+
+2017-05-21 15:23:09 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * config/bellagio/gstomx.conf:
+ config: add OMX.mesa.video_decoder.{avc,mpeg2} for Bellagio config
+ Install libomxil-bellagio0 and make sure mesa has been built with
+ --enable-omx. Check there is /usr/lib/libomxil-bellagio0/libomx_mesa.so
+ then run omxregister-bellagio to regenerate $XDG_DATA_HOME/.omxregister
+ Then omxh264dec and omxmpeg2dec should load.
+ https://bugzilla.gnome.org/show_bug.cgi?id=782926
+
+2017-05-18 13:50:56 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * configure.ac:
+ configure.ac: move omx features check after target selection
+ Does not change anything, except this will be useful for future commits.
+ Indeed some targets provide a .pc file where to look for the omx headers.
+ https://bugzilla.gnome.org/show_bug.cgi?id=782800
+
+2017-06-29 16:48:07 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh264dec.c:
+ omxh264dec: remove 'parsed=true' from sink pad
+ The decoder only requires to receive one frame per buffer which is
+ already enforced with 'alignment=au'. There is no need to require to
+ have a parser upstream.
+ Allow to run "encode ! decode" pipeline without having a parser.
+ https://bugzilla.gnome.org/show_bug.cgi?id=784344
+
+2017-06-16 13:28:33 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: set profile/level using OMX_VIDEO_PARAM_AVCTYPE as well
+ The OMX specification defines two API to set the AVC profile and level:
+ using OMX_VIDEO_PARAM_PROFILELEVELTYPE and OMX_VIDEO_PARAM_AVCTYPE.
+ We were already supporting the former but not the latter. We are now
+ setting both so implementation don't have to rely on a specific one.
+ https://bugzilla.gnome.org/show_bug.cgi?id=783862
+
+2017-06-16 13:19:33 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: factor out update_param_profile_level()
+ https://bugzilla.gnome.org/show_bug.cgi?id=783862
+
+2017-06-16 12:53:15 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: factor out string to profile/level enum conversion
+ https://bugzilla.gnome.org/show_bug.cgi?id=783862
+
+2017-06-28 15:06:10 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: use OMX_IndexConfigBrcmVideoIntraPeriod on pi
+ The OMX_VIDEO_CONFIG_AVCINTRAPERIOD.nPFrames setting isn't of any use on
+ the raspbery pi. Instead it uses a custom extension to define the I
+ frame period.
+ https://bugzilla.gnome.org/show_bug.cgi?id=783829
+
+2017-06-28 15:03:52 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: factor out set_avc_intra_perdiod()
+ https://bugzilla.gnome.org/show_bug.cgi?id=783829
+
+2017-06-02 12:48:57 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * meson.build:
+ meson: define HAVE_VIDEO_EXT if OMX_VideoExt.h is present
+ Meson build wasn't defining the HAVE_VIDEO_EXT like configure.ac does.
+ https://bugzilla.gnome.org/show_bug.cgi?id=783346
+
+2017-06-11 12:32:01 +0000 Graham Leggett <minfrin@sharp.fm>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Improve debug output when setting codec state due to new codec_data fails
+ https://bugzilla.gnome.org/show_bug.cgi?id=783657
+
+2017-05-20 14:49:20 +0100 Julien Isorce <jisorce@oblong.com>
+
+ * omx/gstomx.c:
+ omx: allow 0 feature
+ Previously the omx plugin was blacklisted if GST_OMX_CONFIG_DIR
+ points to an invalid path or if the gstomx.conf contains 0 valid
+ component.
+ Problem is that once the plugin is blacklisted, a rescan is not
+ triggered upon changes of the env var or the gstomx.conf file
+ despite being setup with gst_plugin_add_dependency.
+ This also makes it more consistent with other plugins that auto
+ generate features. For example gst-{ffmeg,libav}, gstreamer-vaapi,
+ v4l2 video dec.
+ To clarify the diff, the plugin_init func will return TRUE even if
+ g_key_file_get_groups returns 0 element and even if
+ g_key_file_load_from_dirs fails.
+ https://bugzilla.gnome.org/show_bug.cgi?id=782867
+
+2017-04-26 22:52:17 +0530 Gurkirpal Singh <gurkirpal204@gmail.com>
+
+ * config/bellagio/gstomx.conf:
+ config: add OMX.st.audio_decoder.mp3.mad for Bellagio config
+ MP3 Software decoder (libmad based) but useful for testing
+ and to compare with other targets.
+ GST_OMX_CONFIG_DIR=$HOME/gst/master/gst-omx/config/bellagio/ \
+ gst-launch-1.0 filesrc location=mpthreetest.mp3 ! id3demux ! \
+ mpegaudioparse ! omxmp3dec ! audioconvert ! pulsesink
+ Didn't add 'local' in core-name path compared to other components
+ in that same gstomx.conf file because OMX.st.audio_decoder.mp3.mad
+ comes with the Ubuntu package 'libomxil-bellagio0-components-mad'.
+ All other components listed in this gstomx.conf for Bellagio, are
+ not provided by any Ubuntu packages. It could explain the 'local',
+ i.e. requiring to build them from source.
+ dpkg -L libomxil-bellagio0
+ /usr/lib/libomxil-bellagio.so.0
+ https://bugzilla.gnome.org/show_bug.cgi?id=781786
+ Signed-off-by: Gurkirpal Singh <gurkirpal204@gmail.com>
+ Signed-off-by: Julien Isorce <jisorce@oblong.com>
+
+2017-05-16 14:39:04 -0400 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * configure.ac:
+ Remove plugin specific static build option
+ Static and dynamic plugins now have the same interface. The standard
+ --enable-static/--enable-shared toggle are sufficient.
+
+2017-05-10 12:10:10 +0900 Sejun Park <sejun79.park@samsung.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Removed unreachable code
+ https://bugzilla.gnome.org/show_bug.cgi?id=782416
+
+2017-05-09 16:26:44 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/meson.build:
+ meson: add dep on GModule
+ libgstomx uses the GModule API and so needs it in its dependencies list.
+ https://bugzilla.gnome.org/show_bug.cgi?id=782387
+
+2017-05-09 13:27:28 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * meson.build:
+ meson: fix config.h generation
+ "No such input file config.h.meson", but it's not needed anyway.
+ https://bugzilla.gnome.org/show_bug.cgi?id=782382
+
+2017-05-04 18:59:33 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * configure.ac:
+ * meson.build:
+ Back to development
+
+=== release 1.12.0 ===
+
+2017-05-04 15:48:56 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * configure.ac:
+ * gst-omx.doap:
+ * meson.build:
+ Release 1.12.0
+
+=== release 1.11.91 ===
+
+2017-04-27 17:53:50 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * configure.ac:
+ * gst-omx.doap:
+ * meson.build:
+ Release 1.11.91
+
+2017-04-17 17:02:48 +0200 Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ videoenc: use GST_ROUND_UP_N() macro
+ Makes the code much easier to read and understand.
+ https://bugzilla.gnome.org/show_bug.cgi?id=781409
+
+2017-04-24 20:30:21 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * common:
+ Automatic update of common submodule
+ From 60aeef6 to 48a5d85
+
+2017-04-10 23:51:00 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * autogen.sh:
+ * common:
+ Automatic update of common submodule
+ From 39ac2f5 to 60aeef6
+
+=== release 1.11.90 ===
+
+2017-04-07 16:36:45 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * configure.ac:
+ * gst-omx.doap:
+ * meson.build:
+ Release 1.11.90
+
+2017-04-07 14:27:23 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Fix compiler warning
+ gstomxvideoenc.c: In function ‘gst_omx_video_enc_fill_buffer’:
+ CC libgstomx_la-gstomxaacdec.lo
+ gstomxvideoenc.c:1316:27: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 8 has type ‘OMX_U32 {aka long unsigned int}’ [-Wformat=]
+ GST_LOG_OBJECT (self, "Matched strides - direct copy %u bytes",
+ ^
+ outbuf->omx_buf->nFilledLen);
+ ~~~~~~~~~~~~~~~~~~
+
+2017-03-22 17:18:09 +0530 Gurkirpal Singh <gurkirpal204@gmail.com>
+
+ * meson.build:
+ meson: fix logic to set HAVE_THEORA
+ https://bugzilla.gnome.org/show_bug.cgi?id=780392
+
+2017-03-14 03:02:06 +1100 Jan Schmidt <thaytan@noraisin.net>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Add an unimplemented mapping for RGBA formats
+ Add some pixel formats mappings for 2 RGBA formats. Not yet
+ implemented in the buffer input code though, so no effect for now.
+
+2017-03-14 03:00:49 +1100 Jan Schmidt <thaytan@noraisin.net>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Add GST_OMX_HACK_HEIGHT_MULTIPLE_16 for Rpi
+ The Raspberry Pi encoder produces corrupt output unless
+ the input height is a multiple of 16. Add a hack that adds
+ zero padding when needed.
+
+2017-03-14 02:42:15 +1100 Jan Schmidt <thaytan@noraisin.net>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Add a mapping for OMX_COLOR_FormatYUV420PackedSemiPlanar
+ The RaspberryPi
+
+2017-03-14 02:40:24 +1100 Jan Schmidt <thaytan@noraisin.net>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Filter out unimplemented formats
+ Don't announce pixel formats in the caps if they've not been
+ implemented.
+
+2017-03-14 02:34:36 +1100 Jan Schmidt <thaytan@noraisin.net>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: demote ERROR message
+ There's no need to warn about failing to negotiate EGL output
+ - that can be perfectly normal.
+
+2017-02-24 16:00:29 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * meson.build:
+ meson: Update version
+
+2017-02-24 15:38:17 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * configure.ac:
+ Back to development
+
+=== release 1.11.2 ===
+
+2017-02-24 15:10:17 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * configure.ac:
+ * gst-omx.doap:
+ Release 1.11.2
+
+2017-02-15 18:22:53 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * Makefile.am:
+ meson: dist meson build files
+ Ship meson build files in tarballs, so people who use tarballs
+ in their builds can start playing with meson already.
+
+2017-01-13 16:23:12 +0000 Vincent Penquerc'h <vincent.penquerch@collabora.co.uk>
+
+ * omx/gstomxaacenc.c:
+ omxaacenc: let encoder know about incoming rate/channels
+ https://bugzilla.gnome.org/show_bug.cgi?id=777223
+
+2017-01-18 02:43:44 +1100 Matthew Waters <matthew@centricular.com>
+
+ * config/bellagio/meson.build:
+ * config/meson.build:
+ * config/rpi/meson.build:
+ * examples/egl/meson.build:
+ * examples/meson.build:
+ * hooks/pre-commit.hook:
+ * meson.build:
+ * meson_options.txt:
+ * omx/meson.build:
+ build: add meson build definition
+ Currently only been tested on the RPi within gst-build.
+
+2017-01-18 15:21:35 +1100 Matthew Waters <matthew@centricular.com>
+
+ * examples/egl/testegl.c:
+ examples/testegl: update for libgstgl changes
+
+2017-01-12 16:33:09 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * configure.ac:
+ Back to development
+
+=== release 1.11.1 ===
+
+2017-01-12 16:26:55 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * configure.ac:
+ * gst-omx.doap:
+ Release 1.11.1
+
+2017-01-10 15:29:08 +0000 Vincent Penquerc'h <vincent.penquerch@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: set base class format instead of just source pad caps
+
+2016-12-18 19:46:55 +0000 Graham Leggett <minfrin@sharp.fm>
+
+ * omx/gstomxaudiodec.c:
+ * omx/gstomxvideodec.c:
+ omx*dec: Flush before we stop the srcpad loop
+ Flushing could otherwise hang if output port queue of pending buffers was empty
+ https://bugzilla.gnome.org/show_bug.cgi?id=774654
+
+2016-12-14 13:29:08 -0800 Reynaldo H. Verdejo Pinochet <reynaldo@osg.samsung.com>
+
+ * omx/gstomx.c:
+ Fix broken build due to syntax error
+ Problem was introduced by 8716c23e2b0553db2982eb84c437f493c974385e
+
+2016-12-12 11:12:48 +0000 Graham Leggett <minfrin@sharp.fm>
+
+ * omx/gstomx.c:
+ Prevent early EOS by resetting eos flag once GST_OMX_ACQUIRE_BUFFER_EOS is triggered
+ https://bugzilla.gnome.org/show_bug.cgi?id=774600
+
+2016-12-12 11:09:15 +0000 Graham Leggett <minfrin@sharp.fm>
+
+ * omx/gstomx.c:
+ Add clear debug logging on all the paths out of gst_omx_port_acquire_buffer()
+ https://bugzilla.gnome.org/show_bug.cgi?id=774600
+
+2016-12-01 18:23:50 +0100 George Kiagiadakis <george.kiagiadakis@collabora.com>
+
+ * config/rpi/gstomx.conf:
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ Add a signals-premature-eos hack for egl_render
+ egl_render seems to have a bug and signals EOS before it has finished
+ pushing out all data; this hack simply makes acquire_buffer() wait
+ a bit more before signalling EOS, in case egl_render decides to spit
+ out some more data.
+ https://bugzilla.gnome.org/show_bug.cgi?id=741856
+
+2016-12-11 19:52:37 +0000 Graham Leggett <minfrin@sharp.fm>
+
+ * omx/gstomxvideo.c:
+ Add support for OMX_COLOR_FormatYUV420PackedSemiPlanar and OMX_COLOR_Format24bitBGR888
+ https://bugzilla.gnome.org/show_bug.cgi?id=775959
+
+2016-12-03 08:20:46 +0100 Edward Hervey <bilboed@bilboed.com>
+
+ * common:
+ Automatic update of common submodule
+ From ac2f647 to 39ac2f5
+
+2016-11-26 11:27:58 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * .gitmodules:
+ common: use https protocol for common submodule
+ https://bugzilla.gnome.org/show_bug.cgi?id=775110
+
+2016-11-25 23:56:06 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomx.c:
+ omx: Fix compiler warning with latest clang
+ gstomx.c:1376:42: error: implicit conversion from enumeration type 'GstOMXAcquireBufferReturn' to different enumeration type 'OMX_ERRORTYPE'
+ (aka 'enum OMX_ERRORTYPE') [-Werror,-Wenum-conversion]
+ g_return_val_if_fail (!port->tunneled, GST_OMX_ACQUIRE_BUFFER_ERROR);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ https://bugzilla.gnome.org/show_bug.cgi?id=775112
+
+2016-11-17 19:56:35 +1100 Matthew Waters <matthew@centricular.com>
+
+ * omx/gstomxvideodec.c:
+ videodecoder: remove use of EGLImage orientation
+ New code should use GstVideoTransformationMeta
+ (The defaults do the right thing here though).
+
+=== release 1.11.0 ===
+
+2016-11-01 18:53:25 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * configure.ac:
+ Back to development
+
+=== release 1.10.0 ===
+
+2016-11-01 18:20:48 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * configure.ac:
+ * gst-omx.doap:
+ Release 1.10.0
+
+=== release 1.9.90 ===
+
+2016-09-30 13:04:51 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * common:
+ * configure.ac:
+ * gst-omx.doap:
+ Release 1.9.90
+
+2016-09-14 11:33:13 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * configure.ac:
+ configure: Depend on gstreamer 1.9.2.1
+
+2016-09-12 14:09:46 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * configure.ac:
+ * omx/gstomx.c:
+ omx: Also search for gstomx.conf in the autoconf --sysconfdir
+ https://bugzilla.gnome.org/show_bug.cgi?id=770743
+
+2016-09-10 20:52:10 +1000 Jan Schmidt <jan@centricular.com>
+
+ * autogen.sh:
+ * common:
+ Automatic update of common submodule
+ From b18d820 to f980fd9
+
+2016-09-10 09:58:16 +1000 Jan Schmidt <jan@centricular.com>
+
+ * autogen.sh:
+ * common:
+ Automatic update of common submodule
+ From ac2f647 to b18d820
+
+2016-09-01 12:36:09 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * configure.ac:
+ Back to development
+
+=== release 1.9.2 ===
+
+2016-09-01 12:35:58 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * common:
+ * configure.ac:
+ * gst-omx.doap:
+ Release 1.9.2
+
+2016-07-11 21:15:48 +0200 Stefan Sauer <ensonic@users.sf.net>
+
+ * common:
+ Automatic update of common submodule
+ From ac2f647 to f49c55e
+
+2016-07-06 13:51:24 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * configure.ac:
+ Back to development
+
+=== release 1.9.1 ===
+
+2016-07-06 13:48:45 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * common:
+ * configure.ac:
+ * gst-omx.doap:
+ Release 1.9.1
+
+2016-06-29 16:37:43 +0900 Kazunori Kobayashi <kkobayas@igel.co.jp>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Use GST_VIDEO_FRAME_PLANE_STRIDE() to get output buffer's stride
+ GST_VIDEO_FRAME_PLANE_STRIDE() should be used to get the actual buffer stride,
+ as reported in the buffers's GstVideoMeta, when copying data to that buffer.
+ https://bugzilla.gnome.org/show_bug.cgi?id=768173
+
+2016-06-21 11:48:40 -0400 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * common:
+ Automatic update of common submodule
+ From ac2f647 to f363b32
+
+2016-06-21 11:43:13 +0200 Aurélien Zanelli <aurelien.zanelli@parrot.com>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: implement GstPreset interface
+ To allow user to use GstPreset to quickly save and load a set of
+ parameters.
+ https://bugzilla.gnome.org/show_bug.cgi?id=767907
+
+2016-06-21 11:41:15 +0200 Aurélien Zanelli <aurelien.zanelli@parrot.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: implement GstPreset interface
+ To allow user to use GstPreset to quickly save and load a set of
+ parameters.
+ https://bugzilla.gnome.org/show_bug.cgi?id=767907
+
+2016-06-17 12:06:48 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * configure.ac:
+ * omx/gstomx.h:
+ * omx/gstomxaudiodec.c:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideo.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: #define OMX_SKIP64BIT on the RPi as required by their API
+ Also add generic support for OMX_SKIP64BIT to gst-omx, in case other
+ implementations also #define that for whatever reason.
+ https://bugzilla.gnome.org/show_bug.cgi?id=766475
+
+2016-06-17 10:59:45 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Implement ::drain() virtual method
+ https://bugzilla.gnome.org/show_bug.cgi?id=767641
+
+2016-06-04 19:31:45 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * configure.ac:
+ configure: remove AG_GST_PARSE_SUBSYSTEM_DISABLES
+ This would check which subsystems are disabled in core by grepping
+ gstconfig.h. Only problem is: gstconfig.h has moved into libdir now
+ so we've been checking a non-existent file for a while now. The
+ macro would just sets GST_DISABLE_* for use in configure.ac and
+ Makefile.am, but we don't use that anywhere so just get rid of it
+ (the one place where we use GST_DISABLE_GST_DEBUG is in a .c file
+ which gets the define from the gstconfig.h include).
+ https://bugzilla.gnome.org/show_bug.cgi?id=750056
+
+2016-01-20 03:10:38 +0900 Gwang Yoon Hwang <yoon@igalia.com>
+
+ * examples/egl/testegl.c:
+ * omx/gstomxvideodec.c:
+ omxvideodec : Use gstglmemoryegl for the RPi
+ Modified to use gstglmemoryegl to avoid texture creation/copy operations
+ at the glupload.
+ [Matthew Waters]: gst-indent the sources and port testegl to GstGLMemoryEGL
+ https://bugzilla.gnome.org/show_bug.cgi?id=760918
+
+2016-04-14 10:04:32 +0100 Julien Isorce <j.isorce@samsung.com>
+
+ * common:
+ Automatic update of common submodule
+ From 6f2d209 to ac2f647
+
+2016-02-26 12:42:41 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * common:
+ Automatic update of common submodule
+ From b64f03f to 6f2d209
+
+2016-02-17 20:51:03 +1100 Matthew Waters <matthew@centricular.com>
+
+ * examples/egl/testegl.c:
+ examples: update egl example for gstgl API changes
+ https://bugzilla.gnome.org/show_bug.cgi?id=762053
+ https://bugzilla.gnome.org/show_bug.cgi?id=753917
+
+2016-02-05 18:11:06 -0300 Thiago Santos <thiagoss@osg.samsung.com>
+
+ * autogen.sh:
+ * common:
+ Automatic update of common submodule
+ From 86e4663 to b64f03f
+
+2015-12-21 00:43:49 +0100 Koop Mast <kwm@rainbow-runner.nl>
+
+ * configure.ac:
+ configure: Make -Bsymbolic check work with clang.
+ Update the -Bsymbolic check with the version glib has. This version
+ works with clang.
+ https://bugzilla.gnome.org/show_bug.cgi?id=759713
+
+2015-12-07 09:11:32 -0500 Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
+
+ * autogen.sh:
+ * common:
+ Automatic update of common submodule
+ From b319909 to 86e4663
+
+2015-11-18 13:00:28 +0000 Enrique Ocaña González <eocanha@igalia.com>
+
+ * omx/gstomx.c:
+ Remember the last_error after a failed set state call to avoid blocking the next get state call
+ gst_omx_video_dec_flush() blocks forever in
+ http://cgit.freedesktop.org/gstreamer/gst-omx/tree/omx/gstomxvideodec.c?id=9adf0ff82903cad5331e40975ae91ed5d11bc102#n2110
+ when the previous call to gst_omx_component_set_state() fails in
+ http://cgit.freedesktop.org/gstreamer/gst-omx/tree/omx/gstomx.c?id=9adf0ff82903cad5331e40975ae91ed5d11bc102#n827.
+ To mitigate that, I set "last_error" to true, so the code in
+ http://cgit.freedesktop.org/gstreamer/gst-omx/tree/omx/gstomx.c?id=9adf0ff82903cad5331e40975ae91ed5d11bc102#n862
+ exits early and doesn't block.
+ https://bugzilla.gnome.org/show_bug.cgi?id=758274
+
+2015-11-18 12:59:59 +0000 Enrique Ocaña González <eocanha@igalia.com>
+
+ * omx/gstomxaudiodec.c:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ Properly handle drain requests while flushing
+ Without this commit the decoder streaming thread stops without ever attending
+ the drain request, leaving the decoder input thread waiting forever.
+ https://bugzilla.gnome.org/show_bug.cgi?id=758274
+
+2015-11-10 10:42:35 +0100 Nicolas Huet <nicolas.huet@parrot.com>
+
+ * omx/gstomx.c:
+ omx: fix hacks leak on class init
+
+2015-10-21 14:37:13 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * common:
+ Automatic update of common submodule
+ From b99800a to b319909
+
+2015-10-21 14:28:41 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * common:
+ Automatic update of common submodule
+ From 9aed1d7 to b99800a
+
+2015-09-01 16:08:11 -0300 Thiago Santos <thiagoss@osg.samsung.com>
+
+ * omx/gstomxaacdec.c:
+ omxaacdec: Do not accept unknown layouts
+ It was defaulting to RAW when an unknown layout was received but
+ the caps template would actually forbid that on the caps query
+ or accept-caps anyway.
+
+2015-09-01 08:59:54 -0300 Thiago Santos <thiagoss@osg.samsung.com>
+
+ * omx/gstomxaudiodec.c:
+ omxaudiodec: use default pad accept-caps handling
+ Instead of the audiodecoder one. The OMX audioo decoders have their
+ valid input in the template pad, so just check against that to
+ avoid doing a query downstream.
+
+2015-08-28 12:57:33 -0300 Thiago Santos <thiagoss@osg.samsung.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: use default pad accept-caps handling
+ Instead of the videodecoder one. The OMX video decoders have their
+ valid input in the template pad, so just check against that to
+ avoid doing a query downstream.
+
+2015-08-22 15:54:55 +0000 Graham Leggett <minfrin@sharp.fm>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Add keyframe support for the Rpi, using OMX_IndexConfigBrcmVideoRequestIFrame
+ https://bugzilla.gnome.org/show_bug.cgi?id=753085
+
+2015-08-20 17:20:50 +0900 Vineeth TM <vineeth.tm@samsung.com>
+
+ * examples/egl/testegl.c:
+ gst-omx: Fix memory leaks when context parse fails
+ When g_option_context_parse fails, context and error variables are not getting free'd
+ which results in memory leaks. Free'ing the same.
+ And replacing g_error_free with g_clear_error, which checks if the error being passed
+ is not NULL and sets the variable to NULL on free'ing.
+ https://bugzilla.gnome.org/show_bug.cgi?id=753865
+
+2015-08-16 14:53:42 +0200 Philippe Normand <philn@igalia.com>
+
+ * omx/gstomxh264dec.c:
+ omxh264dec: implement is_format_change
+ The omxvideodecoder class only checks some of the caps parameters but if
+ other fields change such as h264 profile and/or level it wouldn't trigger a
+ reconfiguration.
+ https://bugzilla.gnome.org/show_bug.cgi?id=752376
+
+2015-07-03 00:26:48 +0200 Aurélien Zanelli <aurelien.zanelli@darkosphere.fr>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: unref allocator after getting it from allocation query
+ Otherwise a reference will be leaked for each allocator. It only happens
+ when target platform is Raspberry Pi and when we have GL support.
+ https://bugzilla.gnome.org/show_bug.cgi?id=751867
+
+2015-07-03 21:59:54 +0200 Stefan Sauer <ensonic@users.sf.net>
+
+ * common:
+ Automatic update of common submodule
+ From f74b2df to 9aed1d7
+
+2015-06-16 17:50:14 -0400 Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
+
+ * common:
+ Automatic update of common submodule
+ From 6015d26 to f74b2df
+
+2015-06-09 11:30:49 +0200 Edward Hervey <bilboed@bilboed.com>
+
+ * common:
+ Automatic update of common submodule
+ From d9a3353 to 6015d26
+
+2015-06-08 23:08:28 +0200 Stefan Sauer <ensonic@users.sf.net>
+
+ * common:
+ Automatic update of common submodule
+ From d37af32 to d9a3353
+
+2015-06-07 23:07:22 +0200 Stefan Sauer <ensonic@users.sf.net>
+
+ * common:
+ Automatic update of common submodule
+ From 21ba2e5 to d37af32
+
+2015-06-07 17:32:25 +0200 Stefan Sauer <ensonic@users.sf.net>
+
+ * common:
+ Automatic update of common submodule
+ From c408583 to 21ba2e5
+
+2015-06-07 17:16:43 +0200 Stefan Sauer <ensonic@users.sf.net>
+
+ * autogen.sh:
+ * common:
+ Automatic update of common submodule
+ From c8fb372 to c408583
+
+2015-05-19 18:21:40 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxaudiodec.c:
+ * omx/gstomxaudiodec.h:
+ omxaudiodec: Add an output adapter for chunking the output into codec frames
+ Otherwise the base class will be confused.
+ See https://bugzilla.gnome.org/show_bug.cgi?id=685730
+
+2015-04-26 18:24:13 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * Android.mk:
+ * omx/Makefile.am:
+ Remove obsolete Android build cruft
+ This is not needed any longer.
+
+2015-04-22 10:40:22 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * INSTALL:
+ Remove INSTALL file
+ autotools automatically generate this, and when using different versions
+ for autogen.sh there will always be changes to a file tracked by git.
+
+2015-04-08 15:57:59 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * .gitignore:
+ * Makefile.am:
+ * configure.ac:
+ * m4/Makefile.am:
+ Add m4 directory so aclocal doesn't complain in autogen.sh
+ Might come in handy, and these warnings seem to be
+ fatal in some environments.
+ You may need to git clean -x -d -f your tree before
+ git pulling/merging.
+
+2015-04-07 22:25:57 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * INSTALL:
+ * autogen.sh:
+ Update autogen.sh to latest version
+
+2015-04-03 18:58:17 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * common:
+ Automatic update of common submodule
+ From bc76a8b to c8fb372
+
+2015-03-06 12:12:49 +0000 Luis de Bethencourt <luis.bg@samsung.com>
+
+ * omx/gstomxaacdec.c:
+ omxaudiodec: add comment explaining duplicate code path
+
+2015-03-06 12:09:06 +0000 Luis de Bethencourt <luis.bg@samsung.com>
+
+ * omx/gstomxaacdec.c:
+ Revert "omxaudiodec: remove duplicate code path"
+ This reverts commit a8d26ff27a8b43f589424a59294f9057641b2a46.
+
+2015-03-06 12:03:56 +0000 Luis de Bethencourt <luis.bg@samsung.com>
+
+ * omx/gstomx.c:
+ omx: handle both errors in the two steps of update_port_definition
+ Also consider potential errors in the _get_parameter() in the return of the
+ update_port_definition function.
+ CID #1287052
+
+2015-03-06 10:57:53 +0000 Luis de Bethencourt <luis.bg@samsung.com>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: impossible if statement
+ ret is set to GST_STATE_CHANGE_SUCCESS and never touched, so it is impossible
+ for it to be anything else at the if check. Remove the if check.
+ CID #1287053
+
+2015-03-06 10:54:43 +0000 Luis de Bethencourt <luis.bg@samsung.com>
+
+ * omx/gstomxaudiodec.c:
+ omxaudiodec: impossible if statement
+ ret is set to GST_STATE_CHANGE_SUCCESS and never touched, so it is impossible
+ for it to be anything else at the if check. Remove it.
+ CID #1287054
+
+2015-03-06 10:50:30 +0000 Luis de Bethencourt <luis.bg@samsung.com>
+
+ * omx/gstomxaacdec.c:
+ omxaudiodec: remove duplicate code path
+
+2014-12-19 11:19:55 +0200 George Kiagiadakis <george.kiagiadakis@collabora.com>
+
+ * omx/gstomx.c:
+ omx: call handle_messages() only once in acquire_buffer() to avoid potential deadlock
+ There is one rare case where calling handle_messages() more than once can cause a deadlock
+ in the video decoder element:
+ - sink pad thread starts the src pad task (gst_omx_video_dec_loop())
+ - _video_dec_loop() calls gst_omx_port_acquire_buffer() on dec_out_port
+ - blocks in gst_omx_component_wait_message() releasing comp->lock and comp->messages_lock
+ (initially, there are no buffers configured on that port, so it waits for OMX_EventPortSettingsChanged)
+ - the sink pad thread pushes a buffer to the decoder with gst_omx_port_release_buffer()
+ - _release_buffer() grabs comp->lock and sends the buffer to OMX, which consumes it immediately
+ - EmptyBufferDone gets called at this point, which signals _wait_message() to unblock
+ - the message from EmptyBufferDone is processed in gst_omx_component_handle_messages()
+ called from gst_omx_port_release_buffer()
+ - gst_omx_port_release_buffer releases comp->lock
+ - the src pad thread now gets to run, grabbing comp->lock while it exits from _wait_message()
+ - _acquire_buffer() calls the _handle_messages() on the next line after _wait_message(),
+ which does nothing (no pending messages)
+ - then it goes to "retry:" and calls _handle_messages() again, which also does nothing
+ (still no pending messages)
+ - scheduler switches to a videocore thread that calls EventHandler, informing us about the
+ OMX_EventPortSettingsChanged event that just arrived
+ - EventHandler graps comp->messages_lock, but not comp->lock, so it can run in parallel at
+ this point just fine.
+ - scheduler switches back to the src pad thread (which is in the middle of _acquire_buffer())
+ - the next _handle_messages() which is right before if (g_queue_is_empty (&port->pending_buffers))
+ processes the OMX_EventPortSettingsChanged
+ - the buffer queue is still empty, so that thread blocks again in _wait_message()
+ - the sink pad thread tries to acquire the next input port buffer
+ - _acquire_buffer() also blocks this thread in:
+ if (comp->pending_reconfigure_outports) { ... _wait_message() ... }
+ - DEADLOCK. gstreamer is waiting for omx to do something, omx waits for gstreamer to do something.
+ By removing those extra _handle_messages() calls, we can ensure that all the checks of
+ _acquire_buffer() will re-run. In the above case, after the scheduler switches back to
+ the middle of _acquire_buffer(), the code will enter _wait_message(), which will see that
+ there are pending messages and will return immediately, going back to "retry:" and
+ re-doing all the checks properly.
+ https://bugzilla.gnome.org/show_bug.cgi?id=741854
+
+2015-02-26 09:27:44 +0900 Wonchul Lee <chul0812@gmail.com>
+
+ * omx/gstomx.c:
+ omx: cleanup code a bit to remove else statement
+ https://bugzilla.gnome.org/show_bug.cgi?id=745191
+
+2015-01-12 16:13:35 +0100 Stefan Sauer <ensonic@users.sf.net>
+
+ * common:
+ Automatic update of common submodule
+ From f2c6b95 to bc76a8b
+
+2014-12-18 10:56:15 +0100 Sebastian Dröge <sebastian@centricular.com>
+
+ * common:
+ Automatic update of common submodule
+ From ef1ffdc to f2c6b95
+
+2014-11-27 17:12:42 +0100 Edward Hervey <bilboed@bilboed.com>
+
+ * common:
+ Automatic update of common submodule
+ From 7bb2bce to ef1ffdc
+
+2014-11-13 09:55:02 +0900 Jun Ji <jun.ji@lge.com>
+
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomxamrdec.c:
+ * omx/gstomxamrdec.h:
+ omx: Add omxamrdec
+ https://bugzilla.gnome.org/show_bug.cgi?id=739333
+
+2014-10-27 18:00:50 +0100 Sebastian Dröge <sebastian@centricular.com>
+
+ * common:
+ Automatic update of common submodule
+ From 84d06cd to 7bb2bce
+
+2014-10-21 13:03:44 +0100 Tim-Philipp Müller <tim@centricular.com>
+
+ * common:
+ Automatic update of common submodule
+ From a8c8939 to 84d06cd
+
+2014-10-21 13:00:10 +0200 Stefan Sauer <ensonic@users.sf.net>
+
+ * common:
+ Automatic update of common submodule
+ From 1f5d3c3 to a8c8939
+
+2014-09-30 10:47:20 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxaudiodec.c:
+ omxaudiodec: Clean up code a bit to get rid of useless NULL checks
+
+2014-09-30 10:50:07 +0900 junji <jun.ji@lge.com>
+
+ * omx/gstomxaudiodec.c:
+ omxaudiodec: Unmap input buffers after usage
+ https://bugzilla.gnome.org/show_bug.cgi?id=736314
+
+2014-08-31 20:30:13 +0000 Michal Lazo <michal.lazo@mdragon.org>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Setup aspect ratio on RPi
+ Needs firmware from yesterday or newer to work with all possible
+ aspect ratios. Before that it only supported a fixed list.
+ https://bugzilla.gnome.org/show_bug.cgi?id=732533
+
+2014-08-28 10:44:31 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Implement the hack flag GST_OMX_HACK_NO_COMPONENT_RECONFIGURE
+
+2014-08-28 10:43:22 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Use the base class' open/close vfuncs instead of calling them ourselves
+
+2014-08-26 22:13:53 -0500 Peng Liu <pengliu.mail@gmail.com>
+
+ * config/rpi/gstomx.conf:
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Implement the hack flag GST_OMX_HACK_NO_COMPONENT_RECONFIGURE
+ Fix a video encoder stall problem on RPi when changing the aspect ratio.
+ https://bugzilla.gnome.org/show_bug.cgi?id=732533
+
+2014-08-14 17:36:11 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxaudiodec.c:
+ * omx/gstomxaudiodec.h:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxaudioenc.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omx: Let base classes handle EOS
+ https://bugzilla.gnome.org//show_bug.cgi?id=734774
+
+2014-08-14 17:33:07 +0300 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxaudiodec.c:
+ omxaudiodec: Fix flushing logic and make it more similar to the video decoder
+
+=== release 1.2.0 ===
+
+2014-07-23 11:28:12 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * ChangeLog:
+ * NEWS:
+ * RELEASE:
+ * configure.ac:
+ * gst-omx.doap:
+ * omx/Makefile.am:
+ Release 1.2.0
+
+2014-07-22 09:23:00 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * config/bellagio/gstomx.conf:
+ * config/rpi/gstomx.conf:
+ config: Update ranks to PRIMARY+1 to have higher preference than avdec_*
+ See https://bugzilla.gnome.org/show_bug.cgi?id=732161
+
+2014-07-20 17:46:30 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxaudiosink.c:
+ omxaudiosink: Set port to not flushing in prepare() and keep it at flushing in unprepare()
+ https://bugzilla.gnome.org/show_bug.cgi?id=733168
+
+2014-07-13 22:15:18 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxaacdec.c:
+ * omx/gstomxaudiodec.c:
+ * omx/gstomxaudiodec.h:
+ * omx/gstomxmp3dec.c:
+ omxaudiodec: Implement setting of fallback channel positions
+
+2014-07-13 18:22:39 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomxaacdec.c:
+ * omx/gstomxaacdec.h:
+ * omx/gstomxmp3dec.c:
+ omx: Add AAC audio decoder
+
+2014-07-02 09:22:28 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxaudiodec.c:
+ omxaudiodec: Get PCM parameters from the out port, not the in port
+
+2014-05-15 13:24:39 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxaudiodec.c:
+ omxaudiodec: Implement hack for not disabling the output port after set_format until the output format is known
+ Needed on some OMX implementations, e.g. the one from Atmel. It does
+ not send the settings-changed event on the output port if it is
+ disabled.
+
+2014-05-10 23:12:54 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomxaudiodec.c:
+ * omx/gstomxaudiodec.h:
+ * omx/gstomxmp3dec.c:
+ * omx/gstomxmp3dec.h:
+ omx: Add audio decoder base class and a subclass for MP3
+
+2014-07-01 09:38:01 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * configure.ac:
+ * omx/Makefile.am:
+ omx: Link to gmodule-2.0-no-export for being able to use the g_module_*() API
+ https://bugzilla.gnome.org/show_bug.cgi?id=732518
+
+2014-06-30 15:00:54 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * examples/egl/testegl.c:
+ examples: #define GST_USE_UNSTABLE_API for libgstgl
+
+2014-06-29 19:10:19 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxh264enc.c:
+ * omx/gstomxh264enc.h:
+ omxh264enc: Properly accumulate headers and push before the next frame
+ Fixes output of encoding on RPi, where each header buffer (SPS and PPS)
+ is in a separate OMX buffer.
+ https://bugzilla.gnome.org/show_bug.cgi?id=726669
+
+2014-06-29 19:04:54 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Implement flush() instead of the deprecated reset()
+
+2014-06-25 17:14:18 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * config/rpi/gstomx.conf:
+ rpi: It's 44100Hz, not 41400Hz
+
+2014-06-25 11:12:51 +0100 Julien Isorce <julien.isorce@collabora.co.uk>
+
+ * configure.ac:
+ configure.ac: require gstgl >= 1.3.3
+
+2014-04-25 13:25:05 +0100 Julien Isorce <julien.isorce@collabora.co.uk>
+
+ * Makefile.am:
+ * configure.ac:
+ example: enable testegl
+ See https://bugzilla.gnome.org/show_bug.cgi?id=728940
+
+2014-06-25 10:19:54 +0100 Julien Isorce <julien.isorce@collabora.co.uk>
+
+ * examples/egl/testegl.c:
+ testegl: do matrix mutlplication in the shader
+ See https://bugzilla.gnome.org/show_bug.cgi?id=728940
+
+2014-06-25 09:36:38 +0100 Julien Isorce <julien.isorce@collabora.co.uk>
+
+ * examples/egl/testegl.c:
+ testegl: add a comment for the parse command
+ See https://bugzilla.gnome.org/show_bug.cgi?id=728940
+
+2014-04-25 17:32:16 +0100 Julien Isorce <julien.isorce@collabora.co.uk>
+
+ * examples/egl/Makefile.am:
+ * examples/egl/cube_texture_and_coords.h:
+ * examples/egl/testegl.c:
+ testegl: convert code from GLESv1 to GLESv2
+ See https://bugzilla.gnome.org/show_bug.cgi?id=728940
+
+2014-04-25 13:21:59 +0100 Julien Isorce <julien.isorce@collabora.co.uk>
+
+ * examples/egl/Makefile.am:
+ * examples/egl/testegl.c:
+ testegl: port to gstgl API
+ - append a glfilter just before fakesink
+ So that we get gltexture or eglimages
+ - propagate our EGLDisplay to the pipeline
+ see GST_QUERY_CONTEXT
+ - share our EGLContext with the iternal gl context
+ of the pipeline, see GST_QUERY_ALLOCATION
+ - use GstVideoGLTextureUploadMeta to upload
+ the incoming gltexture or eglimage to our gl texture
+ TODO: convert from GLESv1 to GLESv2
+ See https://bugzilla.gnome.org/show_bug.cgi?id=728940
+
+2014-06-24 14:52:58 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxbufferpool.c:
+ * omx/gstomxbufferpool.h:
+ * omx/gstomxvideodec.c:
+ omxbufferpool: Copy buffers if the stride does not match and we can't use video meta
+ https://bugzilla.gnome.org/show_bug.cgi?id=731672
+
+2014-06-24 14:52:43 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * configure.ac:
+ * omx/gstomx.h:
+ * omx/gstomxvp8dec.h:
+ omx: Only include OMX_VideoExt.h conditionally
+ It does not exist on the RPi for example.
+
+2014-06-24 13:59:44 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * configure.ac:
+ configure.ac: Require GStreamer core/base >= 1.2.2
+ Needed at least for gst_video_decoder_release_frame().
+
+2014-06-24 13:02:13 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxbufferpool.c:
+ omxbufferpool: Fix format string compiler warning
+
+2014-06-22 21:11:45 +0000 Michal Lazo <xlazom00@gmail.com>
+
+ * omx/gstomxbufferpool.c:
+ omxbufferpool: Initialize debug category
+
+2014-06-24 12:42:22 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxbufferpool.c:
+ omxbufferpool: Properly convert OMX alignment to GStreamer alignment
+ GStreamer uses a bitmask for the alignment while OMX uses the
+ alignment itself. Let's convert.
+ https://bugzilla.gnome.org/show_bug.cgi?id=710564
+
+2014-06-24 11:11:28 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: Don't let baseclass finish frames for SPS/PPS buffers
+ Otherwise we a) send them twice, and b) finish a frame for something
+ that does not even include a frame.
+ https://bugzilla.gnome.org/show_bug.cgi?id=726669
+
+2014-06-24 10:22:37 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxvideo.h:
+ omxvideo: Include the separate headers too for compatibility with 1.0.x
+
+2014-03-24 16:09:40 +0800 Zhao, Halley <halley.zhao@intel.com>
+
+ * configure.ac:
+ * omx/gstomxvp8dec.h:
+ omxvp8dec: use VP8 definition from OMX_VideoExt.h
+ https://bugzilla.gnome.org/show_bug.cgi?id=726957
+
+2014-03-24 15:33:26 +0800 Zhao, Halley <halley.zhao@intel.com>
+
+ * configure.ac:
+ configure: add --with-omx-header-path option for external omx headers
+ https://bugzilla.gnome.org/show_bug.cgi?id=726957
+
+2014-06-18 23:04:33 +0200 Aurélien Zanelli <aurelien.zanelli@darkosphere.fr>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: fix a query leak
+ Also add a debug message if query fails.
+ https://bugzilla.gnome.org/show_bug.cgi?id=731898
+
+2014-05-30 15:29:15 +0200 Aurélien Zanelli <aurelien.zanelli@parrot.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: release frames with old PTS to avoid memory issue
+ Interlaced stream could make the decoder use two input frames to produce
+ one output frame causing the gstvideodecoder frame list to grow.
+ Assuming the video decoder output frame in display order rather than in
+ decoding order, this commit add a way to release frames with PTS less
+ than current output frame.
+ https://bugzilla.gnome.org/show_bug.cgi?id=730995
+
+2013-06-27 21:59:29 +0900 Kazunori Kobayashi <kkobayas@igel.co.jp>
+
+ * omx/gstomx.c:
+ omx: Fix a missing g_free() in error path
+ This fixes a memory leak with g_strdup() when an error occurs.
+ https://bugzilla.gnome.org/show_bug.cgi?id=731141
+
+2014-06-02 15:34:09 +0200 Aurélien Zanelli <aurelien.zanelli@parrot.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: add missing stream unlock in error path
+
+2014-05-31 15:12:05 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomx.c:
+ omx: Don't handle disabling/enabling ports exactly like flushing
+ Otherwise we might abort a flush operation in another thread when
+ enabling/disabling ports, leading to deadlocks sometimes.
+ https://bugzilla.gnome.org/show_bug.cgi?id=730989
+
+2014-05-26 11:02:10 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Don't leak buffer pool config in error cases
+ CID 1216158
+
+2014-05-21 10:53:43 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * common:
+ Automatic update of common submodule
+ From 211fa5f to 1f5d3c3
+
+2014-05-19 09:10:07 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Don't forget to unref codec state
+ CID 1214603
+
+2014-05-19 09:08:33 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Make output buffer pointer always initialized
+ CID 1214605
+
+2014-05-19 09:06:42 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Check return value of gst_buffer_map()
+ CID 1214599
+
+2014-05-19 09:04:09 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Check return value of gst_omx_port_set_enabled() for errors
+ CID 1214589
+
+2014-05-19 09:01:46 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Check return values of buffer pool config parsing functions
+ CID 1214588
+
+2014-05-19 08:48:50 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomx.c:
+ omx: Remove dead code, buf can never be NULL here as we just check for that the line above
+ CID 1214596
+
+2014-05-19 08:47:36 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomx.c:
+ omx: Fix comparisons in gst_omx_state_to_string() case to actually make sense
+ CID 1214593
+
+2014-05-19 08:45:10 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomx.c:
+ omx: Make sure to compare the error codes as unsigned integers so that comparisons >2**31 actually work
+ CID 1214592
+
+2014-05-19 08:40:23 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomx.c:
+ omx: Fix comparisons in gst_omx_command_to_string() default cause to actually work
+ CID 1214591
+
+2014-05-15 13:22:56 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Implement hack for not disabling the output port after set_format until the output format is known
+ Needed on some OMX implementations, e.g. the one from Atmel. It does
+ not send the settings-changed event on the output port if it is
+ disabled.
+
+2014-05-15 13:21:07 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Implement hack for not disabling the output port after set_format until the output format is known
+ Needed on some OMX implementations, e.g. the one from Atmel. It does
+ not send the settings-changed event on the output port if it is
+ disabled.
+
+2014-05-15 10:58:34 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideodec.c:
+ omx: Add a hack for not disabling the output port after set_format until the output format is known
+ Needed on some OMX implementations, e.g. the one from Atmel. It does
+ not send the settings-changed event on the output port if it is
+ disabled.
+
+2014-05-12 12:33:32 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxaudiosink.c:
+ omxaudiosink: implement _delay only in the RaspberryPI
+ Make code implementation conditionally built for RaspberryPI because
+ OMX_IndexConfigAudioRenderingLatency seems to be a Broadcom extension.
+ On other targets the query position might not be accurate without
+ implementing _delay appropriatelly.
+
+2014-05-12 08:56:15 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Correctly scale nTickCount by OMX_TICKS_PER_SECOND
+
+2014-05-10 22:48:23 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Drain encoder on NULL buffer and don't drain on flushing
+
+2014-05-10 22:47:56 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Set nTickCount based on the buffer's duration instead of something wrong
+
+2014-05-10 22:47:21 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Set nTickCount to the whole duration of the buffer instead of a wrong calculation
+
+2014-05-10 22:46:51 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxaudiosink.c:
+ omxaudiosink: Fix format string compiler warnings
+
+2014-04-04 14:11:58 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * config/rpi/gstomx.conf:
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomxanalogaudiosink.c:
+ * omx/gstomxanalogaudiosink.h:
+ * omx/gstomxaudiosink.c:
+ * omx/gstomxaudiosink.h:
+ * omx/gstomxhdmiaudiosink.c:
+ * omx/gstomxhdmiaudiosink.h:
+ omxaudiosink: Implements OpenMAX based audio sinks
+ Provides omxanalogaudiosink and omxhdmiaudiosink elements on
+ the Raspberry PI.
+ - omxanalogaudiosink is capable to render raw mono or stereo audio
+ through the jack output.
+ - omxhdmiaudiosink is capable to render raw audio up to 8 channels
+ and transmit ac3/dts(IEC 61937) through the HDMI output.
+ - sinks provide a clock derived from rendered samples
+ - sinks support the GstStreamVolume interface by implementing
+ the volume and mute properties.
+ https://bugzilla.gnome.org/show_bug.cgi?id=728962
+
+2014-05-03 10:17:35 +0200 Sebastian Dröge <sebastian@centricular.com>
+
+ * common:
+ Automatic update of common submodule
+ From bcb1518 to 211fa5f
+
+2014-04-29 15:16:16 +0100 Julien Isorce <julien.isorce@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: can negotiate caps with memory:EGLImage feature when using EGLImage allocator
+ Previously when using gst EGLImage allocator the caps was
+ video/x-raw, format=RGBA instead of
+ video/x-raw(memory:EGLImage), format=RGBA
+ Kepp previous behavior in case negotiation fails with caps feature.
+ It means it will still have a chance to use EGLImage even if the
+ feature is not in the caps.
+ https://bugzilla.gnome.org/show_bug.cgi?id=729196
+
+2014-04-23 09:57:48 +0200 Aurélien Zanelli <aurelien.zanelli@parrot.com>
+
+ * omx/gstomxvp8dec.h:
+ omxvp8dec: fix typo in GST_TYPE_OMX_VP8_DEC define
+ https://bugzilla.gnome.org/show_bug.cgi?id=728774
+
+2014-04-16 11:00:55 +0200 Aurélien Zanelli <aurelien.zanelli@parrot.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: don't unref caps before logging field from it
+ https://bugzilla.gnome.org/show_bug.cgi?id=728322
+
+2014-04-15 17:30:13 +0100 Julien Isorce <julien.isorce@collabora.co.uk>
+
+ * Makefile.am:
+ * configure.ac:
+ example: disable testegl since libgstegl has been removed
+ As decided in bug #703343
+ Not compatible with the new libgstgl API.
+ A portage has been started, attachment 272800.
+ https://bugzilla.gnome.org/show_bug.cgi?id=703343
+
+2014-04-15 17:11:08 +0100 Julien Isorce <julien.isorce@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: use new libgstgl API since libgstegl has been removed
+ There is no point to retrieve a ref/unref type
+ instead of an EGLDisplay directly. It's like for EGLImage.
+ https://bugzilla.gnome.org/show_bug.cgi?id=703343
+
+2014-04-15 17:06:38 +0100 Julien Isorce <julien.isorce@collabora.co.uk>
+
+ * configure.ac:
+ * examples/Makefile.am:
+ * omx/Makefile.am:
+ * omx/gstomxvideodec.c:
+ configure.ac: check for libgstgl since libgstegl has been removed
+ https://bugzilla.gnome.org/show_bug.cgi?id=703343
+
+2014-04-09 18:52:16 +0200 Aurélien Zanelli <aurelien.zanelli@parrot.com>
+
+ * omx/gstomxbufferpool.c:
+ * omx/gstomxvideodec.c:
+ omxvideodec: add support of more color format
+ Add support for ABGR, ARGB, RGB16, BGR16, YUY2, UYVY, YVYU, GRAY8 and
+ NV16 color format.
+
+2014-04-09 18:51:57 +0200 Aurélien Zanelli <aurelien.zanelli@parrot.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: simplify color format conversion in fill_buffer function
+
+2014-04-09 18:51:41 +0200 Aurélien Zanelli <aurelien.zanelli@parrot.com>
+
+ * omx/gstomxbufferpool.c:
+ omxbufferpool: make video stride and offset calculation easier
+ It will be easier to support more color format.
+
+2014-04-09 18:51:12 +0200 Aurélien Zanelli <aurelien.zanelli@parrot.com>
+
+ * omx/gstomxvideo.c:
+ * omx/gstomxvideo.h:
+ * omx/gstomxvideodec.c:
+ omx: add an helper to convert OMX color format to GStreamer color format
+
+2014-03-10 17:43:50 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * examples/egl/testegl.c:
+ * omx/gstomxvideodec.c:
+ omxvideodec: Implement pipeline draining to support adaptive scenarios
+ When draining due a format change also drain
+ the pipeline to reclaim back all buffers.
+ https://bugzilla.gnome.org/show_bug.cgi?id=726107
+
+2014-03-27 13:57:32 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * examples/egl/testegl.c:
+ examples: fix several memory leaks in the testegl example
+ Ensure to call to image_data_free in order to release GPU resources.
+ Also ensure to destroy EGLImage and GLTexture from proper
+ thread/context.
+ https://bugzilla.gnome.org/show_bug.cgi?id=726107
+
+2014-03-25 17:16:31 +0000 Julien Isorce <julien.isorce@collabora.co.uk>
+
+ * examples/egl/testegl.c:
+ examples: keep a ref on the buffer instead of the memory
+ Like in eglglessink
+ https://bugzilla.gnome.org/show_bug.cgi?id=726107
+
+2014-03-07 20:08:05 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: fixes race condition during seeks
+ Acording 6.1.3 Seek Event Sequence in the OpenMAX IL 1.1.2 spec
+ document in order to flush the component it needs to be in
+ paused state.
+ https://bugzilla.gnome.org/show_bug.cgi?id=726038
+
+2014-01-29 18:31:26 +0000 Julien Isorce <julien.isorce@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: use flush because reset is deprecated
+ https://bugzilla.gnome.org/show_bug.cgi?id=726038
+
+2014-01-27 17:03:50 +0000 Julien Isorce <julien.isorce@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: populate the most downstream output port on reset
+ Make seeking work when using egl_render component
+ https://bugzilla.gnome.org/show_bug.cgi?id=726038
+
+2014-03-24 17:49:59 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxbufferpool.c:
+ omxbufferpool: return buffers to the pool instead of freeing them
+ We have to return the buffers back to the pool in when stopping to
+ not mess with the GstBufferPool accounting.
+ The OMX buffers will be freed when those won't be in charge of the
+ pool in the chained up call to 'stop'.
+ Fixes segfaults on finalize and pool not being properly deactivated.
+ https://bugzilla.gnome.org/show_bug.cgi?id=726337
+
+2014-03-19 12:12:49 +0100 Christian König <christian.koenig@amd.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: add missing unlock in the error path
+ Signed-off-by: Christian König <christian.koenig@amd.com>
+ https://bugzilla.gnome.org/show_bug.cgi?id=726958
+
+2014-03-18 23:36:59 +0100 Michal Lazo <xlazom00@gmail.com>
+
+ * omx/gstomxh264enc.c:
+ * omx/gstomxh264enc.h:
+ fix filemode
+
+2014-03-17 09:57:11 +0000 Julien Isorce <julien.isorce@collabora.co.uk>
+
+ * omx/gstomxbufferpool.c:
+ omxbufferpool: fix memory leak if used on output port
+ When using GstOMXBufferPool on an output port, it internally uses
+ a GPtrArray to manage the GstBuffers instead of the default queue
+ from the GstBufferPool base class.
+ In this case GstBufferPool::default_free_buffer is not called when
+ the pool is stopped. Because the queue is empty. So explicitely
+ call gst_omx_buffer_pool_free_buffer on each buffer contained in
+ the GPtrArray.
+ https://bugzilla.gnome.org/show_bug.cgi?id=726337
+
+2014-03-16 17:32:05 +0100 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: Fix compiler warnings
+
+2014-03-16 17:19:08 +0100 Michal Lazo <xlazom00@gmail.com>
+
+ * omx/gstomxh264enc.c:
+ * omx/gstomxh264enc.h:
+ omxh264enc: IDR interval, SPS and PPS headers for rpi
+ https://bugzilla.gnome.org/show_bug.cgi?id=720031
+
+2014-03-13 14:26:58 +0100 Christian König <christian.koenig@amd.com>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideo.c:
+ omxvideo: fix debug category initialisation
+ https://bugzilla.gnome.org/show_bug.cgi?id=726024
+
+2014-03-13 19:04:47 +0100 Christian König <christian.koenig@amd.com>
+
+ * omx/gstomxbufferpool.h:
+ omxbufferpool: add proper type definitions
+ https://bugzilla.gnome.org/show_bug.cgi?id=726325
+
+2014-03-02 10:30:04 +0100 Christian König <christian.koenig@amd.com>
+
+ * omx/gstomx.c:
+ omx: consolidate message waiting code
+ Add a wait_message helper function and remove all those duplicated code.
+ https://bugzilla.gnome.org/show_bug.cgi?id=725493
+
+2014-03-12 12:48:12 +0100 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxvideo.c:
+ omx: Copy old copyright notice into the new file
+
+2014-03-12 12:47:34 +0100 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxvideo.c:
+ * omx/gstomxvideo.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Rename function from _4_ to _for_ for clarity
+
+2014-03-03 16:15:24 +0100 Christian König <christian.koenig@amd.com>
+
+ * omx/Makefile.am:
+ * omx/gstomxvideo.c:
+ * omx/gstomxvideo.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omxvideo: start sharing more code between video decoder and encoder
+ Identical functionality spread of two different components.
+ We can't use a common base class because of different inheritance,
+ but let's try to share the code anyway.
+ https://bugzilla.gnome.org/show_bug.cgi?id=726024
+
+2014-03-12 12:43:49 +0100 Sebastian Dröge <sebastian@centricular.com>
+
+ * examples/egl/Makefile.am:
+ examples: Only build RPi EGL example if RPi was chosen as target
+
+2014-03-12 12:42:23 +0100 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxbufferpool.h:
+ omxbufferpool: Fix header include guard
+
+2014-03-05 11:41:02 +0100 Christian König <christian.koenig@amd.com>
+
+ * omx/Makefile.am:
+ * omx/gstomxbufferpool.c:
+ * omx/gstomxbufferpool.h:
+ * omx/gstomxvideodec.c:
+ omxvideodec: separate the buffer pool from the decoder
+ https://bugzilla.gnome.org/show_bug.cgi?id=726025
+
+2014-03-04 17:41:20 +0100 Christian König <christian.koenig@amd.com>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideodec.c:
+ omx: simplify tunnel functions
+ Specifying the component is error prone and unnecessary.
+ https://bugzilla.gnome.org/show_bug.cgi?id=726021
+
+2014-03-07 17:12:24 +0100 Christian König <christian.koenig@amd.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: fix memory leak in gst_omx_video_dec_allocate_output_buffers
+ https://bugzilla.gnome.org/show_bug.cgi?id=725907
+
+2014-03-07 13:18:49 +0100 Christian König <christian.koenig@amd.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: fix memory leak gst_omx_video_dec_negotiate
+ https://bugzilla.gnome.org/show_bug.cgi?id=725907
+
+2014-03-05 18:54:05 +0100 Christian König <christian.koenig@amd.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: fix a memory leak in gst_omx_video_enc_getcaps
+ https://bugzilla.gnome.org/show_bug.cgi?id=725826
+
+2014-03-05 17:43:33 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * Makefile.am:
+ Makefile.am: build examples
+ There's no reason to not build the examples now that are ported to 1.x.
+
+2014-03-05 17:25:09 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * examples/egl/testegl.c:
+ examples: avoid a clashing name with the recently added GstEGLImagePool
+ Fixes build with current master.
+
+2013-09-05 03:41:10 -0600 Christian König <christian.koenig@amd.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: simplify _find_nearest_frame
+ Just the same as we did with the decoder. Also give the
+ function a gst_omx_video_enc prefix to distinct it from
+ the decoder function.
+ https://bugzilla.gnome.org/show_bug.cgi?id=724236
+
+2013-09-05 02:23:39 -0600 Christian König <christian.koenig@amd.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: simplify _find_nearest_frame
+ No need to make it more complicated and error prone than
+ necessary. Also give the function a gst_omx_video_dec prefix
+ to distinct it from the encoder function.
+ https://bugzilla.gnome.org/show_bug.cgi?id=724236
+
+2013-09-05 02:05:52 -0600 Christian König <christian.koenig@amd.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: remove dead code
+ This code doesn't seems to be used for quite a while,
+ remove it before it starts to rot.
+ https://bugzilla.gnome.org/show_bug.cgi?id=724236
+
+2014-03-01 22:28:24 +0100 Christian König <christian.koenig@amd.com>
+
+ * omx/gstomx.c:
+ omx: fix two serious message handling bugs
+ Waiting for the next message if we already got one
+ is nonsense and can lead to lockups.
+ https://bugzilla.gnome.org/show_bug.cgi?id=725468
+
+2014-03-01 18:49:41 +0100 Christian König <christian.koenig@amd.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: fix startup race condition
+ The reset function shouldn't start the src pad
+ loop if it wasn't started before.
+ Signed-off-by: Christian König <christian.koenig@amd.com>
+
+2014-03-01 18:48:17 +0100 Christian König <christian.koenig@amd.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: fix startup race condition
+ The reset function shouldn't start the src pad
+ loop if it wasn't started before.
+ Signed-off-by: Christian König <christian.koenig@amd.com>
+
+2014-02-28 09:36:13 +0100 Sebastian Dröge <sebastian@centricular.com>
+
+ * common:
+ Automatic update of common submodule
+ From fe1672e to bcb1518
+
+2014-02-26 22:15:00 +0100 Stefan Sauer <ensonic@users.sf.net>
+
+ * common:
+ Automatic update of common submodule
+ From 1a07da9 to fe1672e
+
+2014-01-30 10:45:18 +0100 Edward Hervey <bilboed@bilboed.com>
+
+ * common:
+ Automatic update of common submodule
+ From d48bed3 to 1a07da9
+
+2014-01-25 17:44:14 +0100 Sebastian Dröge <sebastian@centricular.com>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Don't handle FLUSHING and NOT_LINKED as errors
+ Also don't stop the task on NOT_LINKED. We're not a demuxer.
+
+2013-12-22 22:35:31 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * common:
+ Automatic update of common submodule
+ From dbedaa0 to d48bed3
+
+2013-11-05 11:22:02 +0000 Tim-Philipp Müller <tim@centricular.com>
+
+ * common:
+ Automatic update of common submodule
+ From 865aa20 to dbedaa0
+
+2013-09-28 13:32:37 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * examples/egl/testegl.c:
+ examples: simplify the thread synchronization code
+ Make everithing more simple and fix the races conditions remaining in
+ the previous approaches.
+
+2013-09-25 19:17:17 +0200 Sebastian Dröge <slomo@circular-chaos.org>
+
+ * config/rpi/gstomx.conf:
+ rpi: The WMV/VC1 decoder can only do WMV9 and VC1, no older versions
+
+2013-09-24 18:34:42 +0100 Tim-Philipp Müller <tim@centricular.net>
+
+ * common:
+ Automatic update of common submodule
+ From 6b03ba7 to 865aa20
+
+2013-09-24 18:48:24 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * examples/egl/testegl.c:
+ examples: fix another race condition
+ Fix a race condition that caused randome deadlocks on EOS.
+
+2013-09-20 17:19:53 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * config/rpi/gstomx.conf:
+ rpi: fix a copy paste error in the config file
+
+2013-09-20 17:09:52 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * examples/egl/testegl.c:
+ examples: fix a race condition when seeking
+ Fixes a race condition that caused pipeline deadlock during seeks.
+
+2013-09-20 10:38:12 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * examples/egl/testegl.c:
+ examples: display QoS statistics
+
+2013-09-20 09:34:37 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * examples/egl/testegl.c:
+ examples: use dedicated thread for rendering the scene
+ Produces smother animation and prevents dropping frames due busy
+ mainloop.
+
+2013-09-20 08:25:21 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * examples/egl/testegl.c:
+ examples: don't force an specific audio sink
+ Let playbin2 choose the audiosink available in the system.
+
+2013-09-20 08:19:48 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * examples/egl/Makefile.am:
+ examples: drop remnants of initial appsink attempt
+
+2013-09-20 16:18:18 +0200 Edward Hervey <edward@collabora.com>
+
+ * common:
+ Automatic update of common submodule
+ From b613661 to 6b03ba7
+
+2013-09-19 18:45:36 +0100 Tim-Philipp Müller <tim@centricular.net>
+
+ * common:
+ Automatic update of common submodule
+ From 74a6857 to b613661
+
+2013-09-19 17:38:30 +0100 Tim-Philipp Müller <tim@centricular.net>
+
+ * common:
+ Automatic update of common submodule
+ From 01a7a46 to 74a6857
+
+2013-08-20 16:00:07 +0100 Tim-Philipp Müller <tim@centricular.net>
+
+ * omx/gstomx.c:
+ * omx/gstomxvideodec.c:
+ omx: don't use the 'z' modifier to print size_t
+ gcc will warn in some cases even if the size of the type
+ is exactly that of size_t on the platform.
+ https://bugzilla.gnome.org/show_bug.cgi?id=699008
+
+2013-07-01 15:48:47 +0200 Roman Arutyunyan <arutyunyan.roman@gmail.com>
+
+ * omx/gstomxvideoenc.c:
+ gstomxvideoenc: Set bitrate in setcaps
+ Otherwise it gets lost whenever we configure new caps
+ https://bugzilla.gnome.org/show_bug.cgi?id=698049
+
+2013-06-30 18:17:05 +0700 Ilya Smelykh <ilya@videoexpertsgroup.com>
+
+ * examples/egl/testegl.c:
+ examples: enable audio in testegl example
+
+2013-06-12 09:38:22 +0200 Sebastian Dröge <slomo@circular-chaos.org>
+
+ * configure.ac:
+ configure: Allow build without gstreamer-egl
+
+2013-06-07 12:39:18 +0700 Ilya Smelykh <ilya@videoexpertsgroup.com>
+
+ * examples/egl/Makefile.am:
+ * examples/egl/testegl.c:
+ examples: testegl example port to 1.x
+ https://bugzilla.gnome.org/show_bug.cgi?id=701706
+
+2013-06-05 15:17:16 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * common:
+ Automatic update of common submodule
+ From 098c0d7 to 01a7a46
+
+2013-05-20 12:06:34 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Take lock on EOS to update the flow return value
+ Fixes "GThread-ERROR **: file gthread-posix.c: line 171
+ (g_mutex_free_posix_impl): error 'Device or resource busy' during
+ 'pthread_mutex_destroy ((pthread_mutex_t *) mutex)'" in _finalize.
+
+2013-05-15 10:54:12 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * common:
+ Automatic update of common submodule
+ From 5edcd85 to 098c0d7
+
+2013-04-11 17:35:19 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * Makefile.am:
+ * configure.ac:
+ * examples/Makefile.am:
+ * examples/egl/Makefile.am:
+ * examples/egl/cube_texture_and_coords.h:
+ * examples/egl/testegl.c:
+ examples: add an example aplication based OpenGL ES + EGL
+ Application that shows how to integrate playbin with an OpenGL ES
+ scene through EGL. Renders a video on the surfaces of an animated cube.
+ The code is not ported to 1.x so it's not built by default.
+
+2013-05-10 12:25:07 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Redesign video size change reconfiguration code
+ Ensure stop the decoder before clossing the tunnel.
+
+2013-05-06 16:25:27 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * Makefile.am:
+ Makefile.am: Add -I common/m4
+ This allows autoreconf to work correctly and automatic regeneration
+ of autotools files if something changed.
+
+2013-05-06 19:03:59 +0530 jitendra <jvarshney20@gmail.com>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Add pads based on element type
+ This allows to later add sources and sink that only have a srcpad
+ or sinkpad.
+ https://bugzilla.gnome.org/show_bug.cgi?id=699754
+
+2013-04-27 02:50:25 +0200 Carlos Rafael Giani <dv@pseudoterminal.org>
+
+ * omx/gstomx.c:
+ omx: fixed type error in printf call
+ %zu expects size_t
+ https://bugzilla.gnome.org/show_bug.cgi?id=699008
+
+2013-04-08 17:26:16 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * configure.ac:
+ * omx/Makefile.am:
+ * omx/gstomxvideodec.c:
+ Check for gstreamer-egl
+ And don't use if not available.
+ https://bugzilla.gnome.org/show_bug.cgi?id=697574
+
+2013-04-23 09:53:18 +0100 Tim-Philipp Müller <tim@centricular.net>
+
+ * configure.ac:
+ configure: error out if no OMX target has been set explicitly with --with-omx-target=x
+ Avoids people building for e.g. the Raspberry Pi and then wondering
+ why things don't work as expected (since structs are packed differently
+ there).
+
+2013-04-22 23:55:03 +0100 Tim-Philipp Müller <tim@centricular.net>
+
+ * common:
+ Automatic update of common submodule
+ From 3cb3d3c to 5edcd85
+
+2013-04-18 22:07:28 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxh263enc.c:
+ * omx/gstomxh264enc.c:
+ * omx/gstomxmpeg4videoenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: more printf format fixes
+ Fix printf formats again, so that gst-omx compiles warning-
+ free on the Raspberry Pi as well. Unfortunately OMX_UINT32
+ maybe be typedefed to uint32_t or unsigned long, which
+ doesn't work well with our debugging printf format strings,
+ so just use %u for those and cast to guint.
+
+2013-04-18 16:40:06 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomx.c:
+ omx: fixes unused variable 'comp' when GStreamer is built without debug
+
+2013-04-18 16:03:56 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: don't use 'self->dec_out_port' anymore and use just 'port'
+ Fixes some criticals.
+
+2013-04-18 15:21:32 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: fixes 'port' may be used uninitialized in this function
+
+2013-04-18 12:03:31 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: silence warnings building for RPI related to 'vcos_*'
+
+2013-04-18 11:19:52 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Use new type from libgstvideo
+
+2013-04-16 14:50:49 +0530 jitendra <jvarshney20@gmail.com>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Disable output port before transition to idle state
+ https://bugzilla.gnome.org/show_bug.cgi?id=698109
+
+2012-10-24 12:19:41 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * configure.ac:
+ gst: Add better support for static plugins
+
+2013-04-14 17:57:34 +0100 Tim-Philipp Müller <tim@centricular.net>
+
+ * common:
+ Automatic update of common submodule
+ From aed87ae to 3cb3d3c
+
+2013-04-12 17:58:30 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * configure.ac:
+ configure: add --disable-fatal-warnings for disabling -Werror
+
+2013-04-09 21:02:09 +0200 Stefan Sauer <ensonic@users.sf.net>
+
+ * common:
+ Automatic update of common submodule
+ From 04c7a1e to aed87ae
+
+2013-04-08 17:02:32 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxh263enc.c:
+ * omx/gstomxh264enc.c:
+ * omx/gstomxmpeg4videoenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: fix printf formats in debug messages
+ OMX_U32 is typedefed to an unsigned long,
+ OMX_TICKS to a 64-bit integer.
+
+2013-04-08 16:52:19 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: use the correct printf format in a debug message
+
+2013-04-08 16:31:33 +0200 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: use the correct OMX_IndexParam value
+ Fixes playback is not smooth in the EGL path.
+
+2013-04-05 13:45:24 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Don't use API that is not in master yet
+ It's not really needed here yet, will be needed in future versions
+
+2013-02-25 11:55:04 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * configure.ac:
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: Add support for egl_render on RPi
+
+2013-03-22 19:26:54 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * configure.ac:
+ Back to development
+
+2013-03-22 19:23:14 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * omx/gstomxh263enc.c:
+ * omx/gstomxh264enc.c:
+ * omx/gstomxmpeg4videoenc.c:
+ omx: fix compiler warnings when compiling with -DG_DISABLE_ASSERT
+ As we do for releases. Fixes 'variable may be used uninitialized'
+ warnings.
+
+=== release 1.0.0 ===
+
+2013-03-22 17:16:33 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * AUTHORS:
+ * ChangeLog:
+ * Makefile.am:
+ * NEWS:
+ * RELEASE:
+ * configure.ac:
+ * gst-omx.doap:
+ Release 1.0.0
+
+2013-03-19 16:40:09 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * omx/gstomxtheoradec.h:
+ * omx/gstomxvp8dec.h:
+ omx: fix typo in copyright headers
+
+2013-03-19 13:46:33 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * config/rpi/gstomx.conf:
+ rpi: Fix commit that added the VC1 decoder
+
+2013-03-19 13:27:35 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * config/rpi/gstomx.conf:
+ * omx/gstomxh263dec.c:
+ * omx/gstomxh264dec.c:
+ * omx/gstomxmjpegdec.c:
+ * omx/gstomxmpeg2videodec.c:
+ * omx/gstomxmpeg4videodec.c:
+ * omx/gstomxtheoradec.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvp8dec.c:
+ * omx/gstomxwmvdec.c:
+ omx: Add more constraints to the default sink template caps
+
+2013-03-19 13:10:39 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * config/rpi/gstomx.conf:
+ rpi: Add VC1/WMV3 decoder
+ WMV2 and WMV1 (aka WMV 1-8) are not supported by RPi.
+
+2013-03-19 12:59:20 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * config/rpi/gstomx.conf:
+ rpi: Add MJPEG decoder
+
+2013-03-19 12:56:50 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * config/rpi/gstomx.conf:
+ rpi: Add VP8 decoder
+
+2013-03-19 12:55:09 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Set ENDOFFRAME flag for the end of frames
+
+2013-03-19 12:28:50 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * config/rpi/gstomx.conf:
+ rpi: Add Theora decoder to the config
+
+2013-03-19 09:36:18 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * configure.ac:
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomxtheoradec.c:
+ * omx/gstomxtheoradec.h:
+ omx: Add Theora decoder
+
+2013-03-18 16:43:24 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Remove additional comma
+
+2013-03-18 16:34:21 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * config/rpi/gstomx.conf:
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomxmpeg2dec.h:
+ * omx/gstomxmpeg2videodec.c:
+ * omx/gstomxmpeg2videodec.h:
+ omx: Rename MPEG2 decoder for consistency everywhere
+
+2013-03-18 16:30:40 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomxmjpegdec.c:
+ * omx/gstomxmjpegdec.h:
+ omx: Add MJPEG decoder support
+
+2013-03-18 16:06:54 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * configure.ac:
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomxvp8dec.c:
+ * omx/gstomxvp8dec.h:
+ omx: Add VP8 decoder support
+
+2013-03-18 15:44:23 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * config/rpi/gstomx.conf:
+ rpi: Add h263 decoder and rename MPEG2 decoder for consistency
+
+2013-03-16 13:20:27 +0000 Tim-Philipp Müller <tim@centricular.net>
+
+ * omx/gstomxmpeg2dec.c:
+ omxmpeg2dec: mpeg-2 decoder should be able to handle mpeg-1 too
+ https://bugzilla.gnome.org/show_bug.cgi?id=695879
+
+2013-03-16 10:13:06 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomx.c:
+ omx: minor stylistic change for consistency with other similar code
+
+2013-03-16 10:00:24 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Clarify that loop task is also paused in EOS
+
+2013-03-16 09:59:01 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenec: Don't forget propagate flow return value upstream
+
+2013-03-15 13:16:39 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: improve debug logging some more
+
+2013-03-15 14:09:45 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Make sure that the first frame we pass to OpenMAX is a sync frame
+
+2013-03-15 11:46:34 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Stop output port task after draining
+
+2013-03-15 10:58:58 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Reset EOS flag in more places
+
+2013-03-15 10:38:43 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Deallocate output buffers with the right function
+
+2013-03-15 01:06:05 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: log commands as strings
+ Makes logs easier to read.
+
+2013-03-15 00:47:47 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: log states as strings
+
+2013-03-15 00:28:02 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: log component name in debug messages
+ Useful when we have more different components
+ active at the same time.
+
+2013-03-15 09:51:42 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Don't interpolate timestamps
+ We will get exactly one frame per input buffer and assigning
+ timestamps between frames if more than one OMX buffer is required
+ per frame easily confuses timestamp tracking in OMX.
+
+2013-03-15 09:32:42 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Give the codec_data the timestamp of the first frame and no duration
+
+2013-03-14 17:31:17 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * config/rpi/gstomx.conf:
+ omx: The MPEG4 encoder is not available on RPi and probably never will
+
+2013-03-14 17:26:30 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Reset some more buffer fields as required
+
+2013-03-14 17:01:08 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * config/rpi/gstomx.conf:
+ * omx/gstomx.c:
+ omx: The hack to disable usage of EOS buffers is not necessary anymore on RPi
+
+2013-03-14 17:00:12 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Reset the flags for output ports when releasing a buffer, not for input ports
+
+2013-03-14 15:03:02 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxh263enc.c:
+ * omx/gstomxh264enc.c:
+ * omx/gstomxmpeg4videoenc.c:
+ omx: Only unref caps after usage of its fields
+
+2013-03-14 14:51:32 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Simplify bufferpool implementation
+
+2013-03-13 13:23:35 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Improve min/max buffer counts handling
+
+2013-03-14 12:49:42 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Handle the OMX_EventBufferFlag to detect EOS too
+
+2013-03-13 10:29:23 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: Mark OpenMAX buffers as EGLImage if they contain one
+ Needs special handling in some places, e.g. because nFilledLen
+ will always be 0.
+
+2013-03-13 10:21:49 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Properly check the nVersion field
+
+2013-03-13 09:34:43 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: RPi returns garbage for OMX_IndexParamVideoBitrate, work around that
+
+2013-03-12 20:02:53 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Make sure to always get the right buffer
+
+2013-03-12 19:35:39 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Make sure the buffer is released to the pool if it's not the one we wanted
+
+2013-03-12 19:17:08 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Drop too late frames instead of finishing them
+
+2013-03-12 19:16:46 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omx: Release buffers to the correct port
+
+2013-03-13 09:37:02 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Always load the OpenMAX IL cores with G_MODULE_BIND_LOCAL
+
+2013-03-12 18:20:22 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Lazy-load symbols of libbcm_host.so
+ It exports eglIntOpenMAXILDoneMarker(), which is also
+ exported by libopenmaxil.so... but we need the version
+ from libopenmaxil.so as the other one is just a stub.
+
+2013-03-11 13:59:15 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaacenc.c:
+ * omx/gstomxh263enc.c:
+ * omx/gstomxmpeg4videoenc.c:
+ omx: Don't set profile/level in other encoders if downstream caps don't specify any
+
+2013-03-11 13:49:38 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: If caps specify no profile/level use the component's defaults
+
+2013-03-11 13:45:04 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Always allocate output buffers from the loop function
+
+2013-03-11 13:12:57 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: The h264 encoders are supposed to output byte-stream/au
+
+2013-03-11 11:47:42 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Wait until the Executing state is reached before passing buffers to the component
+
+2013-03-11 10:39:25 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Don't provide buffers to downstream
+ This only works reliable if we have a way to tell downstream to
+ release all our buffers for reconfiguration.
+
+2013-03-11 10:29:44 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Disable output port when setting a new format
+
+2013-03-11 10:29:30 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Disable output port when setting a new format
+
+2013-03-11 10:22:07 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Disable output port when setting a new format
+ Based on a patch by Josep Torra <n770galaxy@gmail.com>
+
+2013-03-11 10:04:10 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Catch errors when releasing buffers to a port and handle them
+
+2013-03-10 12:09:23 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Use the correct video codec state when filling an input buffer
+
+2013-03-10 12:05:50 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Store correct input state
+
+2013-03-10 11:27:34 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Allocate output buffers as early as possible
+
+2013-03-10 11:01:57 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Log unknown events
+
+2013-03-09 14:14:40 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Fix deadlock in encoders and add explainatory comments.
+
+2013-03-09 13:27:08 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: fix printf format identifier
+
+2013-03-09 13:07:59 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxvideodec.c:
+ omx: Minor changes on debuging info
+
+2013-03-09 13:00:33 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: avoid a deadlock
+
+2013-03-08 15:56:40 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Don't forget to populate output port
+
+2013-03-08 15:11:27 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Flush and stop srcpad when configuring new caps
+
+2013-03-07 17:40:21 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * config/rpi/gstomx.conf:
+ * omx/gstomx.c:
+ Revert "omx: use no-component-reconfigure hack on the Raspberry PI"
+ This reverts commit e123b2089f69a413241f30a2428ea6edd8f231e7.
+ It's not required anymore after the fix from the last commit.
+
+2013-03-07 17:38:40 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Only negotiate a color format with downstream on the initial caps
+
+2013-03-07 17:29:43 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Make sure the output port is disabled while we allocate buffers
+
+2013-03-07 17:27:05 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Also wait for disabled output ports to be reconfigured
+
+2013-03-07 14:10:12 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: Add buffer pool for sharing OpenMAX memory with downstream
+
+2013-03-07 11:11:58 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Add timeout to the flush operation and move buffer populating to a separate function
+
+2013-03-06 17:33:23 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * config/rpi/gstomx.conf:
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: Remove min buffer count hack for RPi again
+ It's not necessary anymore
+
+2013-03-06 17:05:51 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Do number of buffers configuration explicitely
+
+2013-03-07 11:24:54 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: fixes reconfiguration
+ Avoid having fixed fields from previous caps on reconfiguration.
+
+2013-03-07 11:02:39 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * config/rpi/gstomx.conf:
+ * omx/gstomx.c:
+ omx: use no-component-reconfigure hack on the Raspberry PI
+
+2013-03-07 00:03:28 +0000 Tim-Philipp Müller <tim@centricular.net>
+
+ * common:
+ Automatic update of common submodule
+ From 2de221c to 04c7a1e
+
+2013-03-01 15:32:47 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: drop unused data member
+
+2013-03-01 12:23:54 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxh263enc.c:
+ * omx/gstomxh264enc.c:
+ * omx/gstomxmpeg4videoenc.c:
+ omxvideoenc: And set it actually on the right port
+
+2013-03-01 12:18:08 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxh263enc.c:
+ * omx/gstomxh264enc.c:
+ * omx/gstomxmpeg4videoenc.c:
+ omxvideoenc: Set the coding type in the subclasses to the specific codec
+
+2013-03-01 11:49:53 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: gst_omx_port_update_port_definition() returns a OMX_ERRORTYPE, not a gboolean
+
+2013-03-01 11:44:17 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omxvideo{dec,enc}: Don't use the input state if it wasn't set yet
+
+2013-03-01 11:25:04 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Only enable the output port after we know the output format
+
+2013-03-01 11:24:56 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Only enable the output port after we know the output format
+
+2013-02-28 17:02:31 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Only enable the output port after we know the output format
+
+2013-03-01 11:18:18 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: Handle errors more gracefully
+
+2013-02-28 15:48:53 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxh263dec.c:
+ * omx/gstomxh264dec.c:
+ * omx/gstomxmpeg2dec.c:
+ * omx/gstomxmpeg4videodec.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxwmvdec.c:
+ omx: Return the OMX_ERRORTYPE from gst_omx_port_update_port_definition
+
+2013-02-28 15:37:53 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Return port definition update errors
+
+2013-02-28 13:57:43 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * config/rpi/gstomx.conf:
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: Add hack for RPi for the minimum number of buffers required for a port
+ The value in the port definition is invalid and the initial actual
+ buffer count should be used.
+
+2013-02-28 13:26:56 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Always tell the component about the right number of buffers that we're going to allocate
+
+2013-02-28 13:07:58 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Invert assertion to let it express what was intended
+
+2013-02-28 11:19:07 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Add API for allocating a specific number of buffers and using EGLImages or buffers allocated elsewhere
+
+2013-02-27 16:55:16 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Refactor code flow a bit if output port settings have changed
+
+2013-02-27 15:49:56 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Clean up port settings change handling
+
+2013-02-27 11:30:14 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: initialize param structure before using it
+
+2013-02-27 10:21:39 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: prevent a NULL pointer access
+
+2013-02-26 17:25:49 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: prevent a NULL pointer access
+
+2013-02-25 13:11:16 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Fix deadlock during reconfiguration
+
+2013-02-25 12:38:27 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Auto-detect the port indizes if possible
+
+2013-02-25 11:42:38 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Refactor querying of component supported caps into its own function
+
+2013-02-25 10:41:12 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Refactor waiting for buffers to be released by the component to a separate function
+
+2013-01-11 17:44:13 +0000 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: Add methods to set up and close a tunnel between components
+
+2013-02-25 09:15:53 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaacenc.c:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxaudioenc.h:
+ omxaudioenc: Rename component variable
+
+2013-02-25 09:15:46 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxh263enc.c:
+ * omx/gstomxh264enc.c:
+ * omx/gstomxmpeg4videoenc.c:
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: Rename component variable
+
+2013-02-25 09:12:22 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: Rename component variable
+
+2013-02-22 16:27:33 +0100 Josep Torra <n770galaxy@gmail.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: remove duplicated line
+
+2013-02-22 10:42:08 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ Retry loading libbcm_host.so without an absolute path if that failed
+
+2013-02-21 20:32:42 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * config/bellagio/Makefile.am:
+ Add missing file from last commit
+
+2013-02-21 11:01:28 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * config/Makefile.am:
+ * config/bellagio/gstomx.conf:
+ * configure.ac:
+ * omx/Makefile.am:
+ Add OpenMAX IL target for Bellagio
+ Not tested since a very long time though.
+
+2013-02-21 10:59:29 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * configure.ac:
+ * omx/Makefile.am:
+ Allow using external OpenMAX IL headers
+
+2013-02-21 10:14:12 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * .gitignore:
+ Update .gitignore
+
+2013-02-21 10:13:16 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * config/Makefile.am:
+ * config/rpi/Makefile.am:
+ * config/rpi/gstomx.conf:
+ * configure.ac:
+ Install the RPI config when the RPI target is selected
+
+2013-02-21 10:08:07 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ Set default hacks for the RPI target and always initialize bcm_host
+
+2013-02-21 10:05:37 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * configure.ac:
+ Add configure parameter for setting the OpenMAX IL target
+
+2013-02-12 11:55:39 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Add FIXME for the future
+
+2013-02-12 11:49:21 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxaudioenc.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omx: Some minor refactoring and cleanup
+
+2013-02-12 11:45:40 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Don't access the port's buffers array if it wasn't allocated yet
+
+2013-02-12 11:44:40 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Mark an array as const
+
+2013-02-12 11:41:43 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Split enabling/disabling of port into sending the command and waiting for it
+ This allows to do anything necessary after sending the command to actually let it finish
+
+2013-02-12 11:37:38 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Flushing is also allowed in Paused state
+
+2013-02-12 11:28:36 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Set stride, slice height and buffer size
+
+2013-02-12 11:09:30 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * config/raspberry-pi.conf:
+ config: Add h264 and mpeg2 encoders to the raspberry pi config
+ Not completely working yet though.
+
+2013-02-12 11:03:32 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Properly negotiate OMX color format with the component
+
+2013-02-12 10:53:24 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Implement getcaps() vfunc
+
+2013-01-29 21:32:53 +0000 Tim-Philipp Müller <tim@centricular.net>
+
+ * configure.ac:
+ configure: use 1.0 gstconfig.h to detect disabled subsystems
+ Update unused configure check for GStreamer core subsystem
+ features from 0.10 to 1.0.
+
+2013-01-28 20:44:41 +0100 Stefan Sauer <ensonic@users.sf.net>
+
+ * common:
+ Automatic update of common submodule
+ From a942293 to 2de221c
+
+2013-01-24 14:02:36 +0100 Julian Scheel <julian@jusst.de>
+
+ * config/raspberry-pi.conf:
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomxmpeg2dec.c:
+ * omx/gstomxmpeg2dec.h:
+ omx: add mpeg2 video decoder
+ This adds a decoder class for mpeg2, as well as an extended
+ configuration for raspberry pi.
+ https://bugzilla.gnome.org/show_bug.cgi?id=692446
+ Signed-off-by: Julian Scheel <julian@jusst.de>
+
+2013-01-18 16:47:04 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Minimize the time when the messages lock is held
+ Fixes a deadlock if any OMX functions are called when the
+ messages are handled.
+ Thanks to Nicolas Dufresne for noticing.
+
+2013-01-18 15:28:20 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: improve debug message when we can't find the config file
+ Mention where we looked for the config file.
+
+2013-01-18 12:34:38 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * configure.ac:
+ build: fix autogen.sh with automake 1.13
+ AM_CONFIG_HEADER -> AC_CONFIG_HEADERS
+
+2013-01-17 18:07:41 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.h:
+ * omx/gstomxaudioenc.h:
+ * omx/gstomxvideodec.h:
+ * omx/gstomxvideoenc.h:
+ omx: Fix includes to properly work with the 1.0 releases
+
+2013-01-15 15:08:28 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * common:
+ Automatic update of common submodule
+ From a72faea to a942293
+
+2013-01-15 14:34:45 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Update port definition when changing some port setting
+
+2013-01-14 11:41:57 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ omx: Rename from libgstopenmax.so to ligstomx.so for consistency
+
+2013-01-11 15:32:22 +0000 Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+ * omx/gstomx.c:
+ omx: Add a method to send message
+
+2013-01-11 15:44:38 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: Atomic ops are not required anymore for the reconfiguration
+
+2013-01-11 12:52:10 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Fix some memory leaks and suboptimal locking
+
+2013-01-11 12:34:04 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Don't forget to unmap frame in error cases
+
+2013-01-11 12:29:20 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Fix copying of the video frames to the OMX buffers
+
+2013-01-11 12:24:13 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Fix copying of the video frames from the OMX buffers
+
+2013-01-10 14:44:33 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxrecmutex.c:
+ * omx/gstomxrecmutex.h:
+ omx: Implement new approach for locking that should solve all deadlocks on RPi
+ No mutex is locked while calling any OpenMAX functions anymore
+ and everything from the OpenMAX callbacks is inserted into a message
+ queue and handled from outside the callbacks.
+ Also there's only a single mutex and condition variable per component
+ now for handling anything from OpenMAX callbacks and a single mutex
+ for keeping our component/port state sane.
+
+2012-12-20 19:30:38 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Set the OMX buffer nFilledLength field properly
+
+2012-12-20 18:48:21 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxrecmutex.c:
+ * omx/gstomxrecmutex.h:
+ omxrecmutex: Fix another race condition when two threads are trying to lock for recursion at the same time
+
+2012-12-20 18:16:43 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxrecmutex.c:
+ * omx/gstomxrecmutex.h:
+ omxrecmutex: Fix yet another race condition that resulted in deadlocks
+
+2012-12-20 17:46:36 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomxrecmutex.c:
+ * omx/gstomxrecmutex.h:
+ omx: Fix another race condition in the recursive mutex
+ Between lock() and begin_recursion() it was possible for another thread to
+ try to do a recursive_lock(). This would block because the mutex was already
+ locked(), but not ready for recursive locking yet. unlock() would never
+ happen in the original thread because it was waiting for the other thread
+ to finish first.
+ Happened on the Raspberry Pi.
+
+2012-12-20 14:45:18 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxrecmutex.c:
+ * omx/gstomxrecmutex.h:
+ omxrecmutex: Fix a small race condition when unlocking a non-recursive lock
+
+2012-12-20 12:30:05 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Fix ununsed variable compiler warning
+
+2012-12-20 12:27:47 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: No need to start the srcpad task in ::start() already
+ It will be started properly after the caps are set.
+
+2012-12-20 12:23:49 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: OMX_ErrorNoMore is no error and just means we ended iteration
+
+2012-12-20 12:20:31 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Improve debug output
+
+2012-12-20 12:02:30 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Don't forget to free a GList
+
+2012-12-20 11:56:29 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Map OMX_COLOR_FormatYUV420PackedPlanar to I420 too
+ This is used on the Raspberry Pi.
+
+2012-12-20 11:55:36 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: During negotiation of the output format make sure we use the correct OpenMAX format
+
+2012-12-20 11:42:17 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: If negotiation fails this could also mean that the component can't do it at this point yet
+
+2012-12-20 11:40:13 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Improve format negotiation a bit
+ Don't leak caps and make sure to fixate caps.
+
+2012-12-19 13:05:28 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.h:
+ omx: Also initialize nStep field of the OMX structures
+
+2012-12-19 13:03:37 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.h:
+ omx: Initialize struct version with the OMX version we compiled with
+
+2012-12-19 12:44:31 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Extract data from the input buffer, not the codec data
+
+2012-12-19 12:19:12 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * tools/listcomponents.c:
+ omx: Use has_suffix() instead of has_prefix() for the Broadcom hack
+
+2012-12-19 12:08:35 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * Makefile.am:
+ * configure.ac:
+ * tools/Makefile.am:
+ * tools/listcomponents.c:
+ tools: Add tool to list all components and their roles
+
+2012-12-19 11:31:51 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Add hack to load and initialize libbcm_host.so
+ Needed on the Raspberry Pi. Patch based on a patch by
+ George Kiagiadakis <george.kiagiadakis@collabora.com>
+
+2012-12-19 11:22:16 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * configure.ac:
+ * omx/gstomx.h:
+ configure: Add configure option to pack OpenMAX structures
+ This is required to set to 4 for the Raspberry Pi for example.
+
+2012-12-19 11:07:44 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * configure.ac:
+ configure: Require GStreamer 1.0.0
+
+2012-04-20 17:13:52 +0300 George Kiagiadakis <george.kiagiadakis@collabora.com>
+
+ * omx/gstomx.h:
+ omx: Initialize structures to version 1.1.2
+
+2012-12-19 09:51:22 +0000 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * Makefile.am:
+ * config/Makefile.am:
+ * config/raspberry-pi.conf:
+ * configure.ac:
+ config: Add raspberry-pi configuration in a different directory
+
+2012-05-20 20:11:59 +0300 George Kiagiadakis <george.kiagiadakis@collabora.com>
+
+ * omx/gstomx-raspberry.conf:
+ raspberry: Add a gstomx.conf for the Raspberry Pi
+
+2012-12-12 17:45:39 +0000 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.h:
+ * omx/gstomxvideoenc.h:
+ omx: Fix some compilation errors caused by circular includes
+
+2012-11-19 11:29:44 +0000 Tim-Philipp Müller <tim@centricular.net>
+
+ * common:
+ Automatic update of common submodule
+ From 6bb6951 to a72faea
+
+2012-11-12 15:14:09 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Fix refcount problem with frames being dropped because of decoder bugs
+
+2012-11-12 11:29:48 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxaudioenc.h:
+ * omx/gstomxrecmutex.c:
+ * omx/gstomxrecmutex.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omx: Update to new GLib thread API
+
+2012-10-22 14:34:53 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Use open/close vfuncs
+
+2012-10-22 14:28:04 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Handle video meta correctly
+
+2012-06-20 13:11:58 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ * omx/gstbasevideocodec.c:
+ * omx/gstbasevideocodec.h:
+ * omx/gstbasevideodecoder.c:
+ * omx/gstbasevideodecoder.h:
+ * omx/gstbasevideoencoder.c:
+ * omx/gstbasevideoencoder.h:
+ * omx/gstbasevideoutils.c:
+ * omx/gstbasevideoutils.h:
+ * omx/gstomxh263dec.c:
+ * omx/gstomxh263enc.c:
+ * omx/gstomxh264dec.c:
+ * omx/gstomxh264enc.c:
+ * omx/gstomxmpeg4videodec.c:
+ * omx/gstomxmpeg4videoenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ * omx/gstomxwmvdec.c:
+ omx: Port to video base classes from -base
+
+2012-10-17 17:57:43 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * omx/gstomxaacenc.c:
+ * omx/gstomxh263dec.c:
+ * omx/gstomxh263enc.c:
+ * omx/gstomxh264dec.c:
+ * omx/gstomxh264enc.c:
+ * omx/gstomxmpeg4videodec.c:
+ * omx/gstomxmpeg4videoenc.c:
+ * omx/gstomxwmvdec.c:
+ omx: gst_element_class_set_details_simple() -> set_static_metadata()
+
+2012-10-06 15:01:11 +0100 Tim-Philipp Müller <tim@centricular.net>
+
+ * common:
+ Automatic update of common submodule
+ From 6c0b52c to 6bb6951
+
+2012-09-22 16:10:38 +0100 Tim-Philipp Müller <tim@centricular.net>
+
+ * common:
+ Automatic update of common submodule
+ From 4f962f7 to 6c0b52c
+
+2012-06-21 20:22:13 +0300 George Kiagiadakis <george.kiagiadakis@collabora.com>
+
+ * omx/gstomx.c:
+ omx: fix debug statement
+
+2012-06-21 20:21:03 +0300 George Kiagiadakis <george.kiagiadakis@collabora.com>
+
+ * omx/gstomx.c:
+ omx: use recursive_lock inside set_last_error(), since this function may be called from an event handler
+
+2012-08-22 13:31:59 +0200 Stefan Sauer <ensonic@users.sf.net>
+
+ * common:
+ Automatic update of common submodule
+ From 668acee to 4f962f7
+
+2012-08-05 16:42:43 +0100 Tim-Philipp Müller <tim@centricular.net>
+
+ * common:
+ Automatic update of common submodule
+ From 94ccf4c to 668acee
+
+2012-08-03 19:32:13 +0100 Tim-Philipp Müller <tim@centricular.net>
+
+ * omx/gstomx.c:
+ omx: fix plugin name for new GST_PLUGIN_DEFINE API
+
+2012-07-23 08:47:32 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * common:
+ Automatic update of common submodule
+ From 98e386f to 94ccf4c
+
+2012-07-10 09:57:09 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideodecoder.c:
+ omx: Update for allocation query API changes
+
+2012-06-20 11:09:13 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Fix compilation after gst_pad_start_task() API changes
+
+2012-06-08 15:06:35 +0200 Edward Hervey <edward.hervey@collabora.co.uk>
+
+ * common:
+ Automatic update of common submodule
+ From 03a0e57 to 98e386f
+
+2012-06-06 18:20:18 +0200 Edward Hervey <edward.hervey@collabora.co.uk>
+
+ * common:
+ Automatic update of common submodule
+ From 1fab359 to 03a0e57
+
+2012-06-01 10:30:27 +0200 Edward Hervey <edward.hervey@collabora.co.uk>
+
+ * common:
+ Automatic update of common submodule
+ From f1b5a96 to 1fab359
+
+2012-05-31 13:10:33 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * common:
+ Automatic update of common submodule
+ From 92b7266 to f1b5a96
+
+2012-05-30 12:47:59 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * common:
+ Automatic update of common submodule
+ From ec1c4a8 to 92b7266
+
+2012-05-30 11:26:30 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * common:
+ Automatic update of common submodule
+ From 3429ba6 to ec1c4a8
+
+2012-05-13 15:58:10 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * common:
+ Automatic update of common submodule
+ From dc70203 to 3429ba6
+
+2012-05-08 16:13:32 +0300 George Kiagiadakis <george.kiagiadakis@collabora.com>
+
+ * omx/gstomx.c:
+ omx: Fix spelling mistake found by lintian: s/Seperate/Separate/
+
+2012-04-30 23:58:43 +0300 George Kiagiadakis <george.kiagiadakis@collabora.com>
+
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxrecmutex.c:
+ * omx/gstomxrecmutex.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ Implement a new custom recursive mutex type and fix locking in callbacks so that in-context calls are allowed.
+ According to the OMX specification, implementations are allowed to call
+ callbacks in the context of their function calls. However, our callbacks
+ take locks and this causes deadlocks if the unerlying OMX implementation
+ uses this kind of in-context calls.
+ A solution to the problem would be a recursive mutex. However, a normal
+ recursive mutex does not fix the problem because it is not guaranteed
+ that the callbacks are called from the same thread. What we see in Broadcom's
+ implementation for example is:
+ - OMX_Foo is called
+ - OMX_Foo waits on a condition
+ - A callback is executed in a different thread
+ - When the callback returns, its calling function
+ signals the condition that OMX_Foo waits on
+ - OMX_Foo wakes up and returns
+ The solution I came up with here is to take a second lock inside the callback,
+ but only if recursion is expected to happen. Therefore, all calls to OMX
+ functions are guarded by calls to gst_omx_rec_mutex_begin_recursion() / _end_recursion(),
+ which effectively tells the mutex that at this point we want to allow calls
+ to _recursive_lock() to succeed, although we are still holding the master lock.
+
+2012-04-20 14:51:34 +0000 George Kiagiadakis <george.kiagiadakis@collabora.com>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: Add hack to disable setting roles to components.
+ Conflicts:
+ omx/gstomx.c
+
+2012-04-30 23:20:24 +0000 George Kiagiadakis <george.kiagiadakis@collabora.com>
+
+ * omx/gstomx.h:
+ * omx/gstomxvideodec.c:
+ omxvideodec: Implement no-empty-eos-buffer hack, as in omxvideoenc.
+ Conflicts:
+ omx/gstomxvideodec.c
+
+2012-04-30 23:19:55 +0000 George Kiagiadakis <george.kiagiadakis@collabora.com>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Fix coding style in the drain-may-not-return hack code
+
+2012-04-25 19:03:48 +0530 Arun Raghavan <arun.raghavan@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Fix trivial debug print bug
+
+2012-04-25 19:01:32 +0530 Arun Raghavan <arun.raghavan@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideodec.c:
+ omxvideodec: Add hack for Ducati components not returning from drain
+ This happens on the Galaxy Nexus, and causes the pipeline to hang waiting
+ endlessly for a drain. The hack replaces the wait with a wait + 500ms timeout.
+
+2012-04-25 16:35:40 +0530 Arun Raghavan <arun.raghavan@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Fix deadlock between ending a flush and the event handler
+ gst_omx_port_set_flushing() calls OMX_FillThisBuffer at the end of a flush
+ without releasing the port lock, and this can cause a deadlock with the
+ EventHandler. This patches fixes this by dropping the lock for the duration of
+ the fill buffer call.
+
+2012-04-24 15:41:38 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideodecoder.c:
+ * omx/gstbasevideoencoder.c:
+ omx: Update video encoder/decoder base classes from gst-plugins-bad
+
+2012-04-16 09:16:10 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * configure.ac:
+ configure: Modernize autotools setup a bit
+ Also we now only create tar.bz2 and tar.xz tarballs.
+
+2012-04-16 09:12:37 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * common:
+ Automatic update of common submodule
+
+2012-04-16 08:34:56 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Use gst_buffer_extract() to copy the input buffer data to the OpenMAX buffer
+
+2012-04-13 17:16:42 -0400 Alessandro Decina <alessandro.decina@collabora.com>
+
+ * omx/Makefile.am:
+ Fix relative/absolute path glitch
+ Signed-off-by: Reynaldo H. Verdejo Pinochet <reynaldo@collabora.com>
+
+2012-04-12 15:57:32 -0400 Olivier Crête <olivier.crete@collabora.com>
+
+ * common:
+ * configure.ac:
+ * omx/Makefile.am:
+ * omx/gstbasevideocodec.c:
+ * omx/gstbasevideocodec.h:
+ * omx/gstbasevideodecoder.c:
+ * omx/gstbasevideodecoder.h:
+ * omx/gstbasevideoencoder.c:
+ * omx/gstbasevideoencoder.h:
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxaacenc.c:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxaudioenc.h:
+ * omx/gstomxh263dec.c:
+ * omx/gstomxh263enc.c:
+ * omx/gstomxh264dec.c:
+ * omx/gstomxh264enc.c:
+ * omx/gstomxmpeg4videodec.c:
+ * omx/gstomxmpeg4videoenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ * omx/gstomxwmvdec.c:
+ Port to Gst 0.11
+
+2012-01-18 16:53:16 -0300 Reynaldo H. Verdejo Pinochet <reynaldo@collabora.com>
+
+ * Android.mk:
+ * omx/Makefile.am:
+ Enable building with Android's buildsystem
+ This change adds prelimary buildsystem hooks to
+ build gst-omx with the Android buildsystem. Like
+ the rest of GStreamer's Android hooks, the process
+ relies on the availability of androgenizer. A tool
+ developed by Collabora to automatically generate
+ Android.mk files from within the auto* setup.
+ Androgenizer is currently available at:
+ http://cgit.collabora.com/git/user/derek/androgenizer.git/
+
+2011-12-13 10:17:41 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideocodec.c:
+ basevideocodec: Don't use G_TYPE_REGISTER_BOXED() yet
+ This would require GLib 2.26.
+
+2011-12-14 10:09:34 +0100 Jonas Larsson <Jonas.Larsson@palm.com>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Add hack for encoder components that don't allow empty EOS buffers
+
+2011-12-14 10:07:29 +0100 Jonas Larsson <Jonas.Larsson@palm.com>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Fix deadlock when using the EOS hack
+
+2011-12-12 14:26:48 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Remove workaround for basevideocodec bug
+
+2011-12-12 14:26:34 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Remove workaround for basevideocodec bug
+
+2011-12-05 17:57:01 +0000 Matej Knopp <matej.knopp@gmail.com>
+
+ * omx/gstbasevideocodec.c:
+ * omx/gstbasevideocodec.h:
+ * omx/gstbasevideodecoder.c:
+ * omx/gstbasevideoencoder.c:
+ basevideo: Make GstVideoFrame a reference counted boxed object
+ ...and also clear all existing frames when resetting the decoder or encoder.
+
+2011-12-09 12:17:29 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideoenc.c:
+ omx: Add hack for encoder components that don't allow empty EOS buffers
+
+2011-12-09 10:21:47 +0100 Dake Gu <Dake.Gu@palm.com>
+
+ * omx/gstomxaacenc.c:
+ omxaacenc: Generate and set codec_data on the caps for raw AAC
+
+2011-10-31 11:36:06 +0100 Alessandro Decina <alessandro.decina@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ basevideoencoder: handle failures in start() and stop()
+
+2011-08-26 10:50:38 +0100 Vincent Penquerc'h <vincent.penquerch@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ basevideoenc: do not try to calculate latency from an unknown framerate
+ It'll divide by zero, and latency is unknown for an unknown framerate.
+ Fixes an assert in the schroenc test.
+ https://bugzilla.gnome.org/show_bug.cgi?id=657419
+
+2011-12-08 11:50:49 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ basevideoencoder: Only make the header buffer metadata writable, not the buffer
+
+2011-12-08 10:18:36 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ basevideoencoder: Fix handling of force-keyunit events
+
+2011-12-06 13:28:41 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Don't forward EOS events immediately but let all other events be handled by the base class
+ Previously this logic was inversed, which did not make any sense at all.
+
+2011-12-06 12:47:25 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxaudioenc.h:
+ omxaudioenc: Use correct timestamp, duration and filled length for the EOS buffers
+
+2011-12-06 12:47:12 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: Use correct timestamp, duration and filled length for the EOS buffers
+
+2011-12-06 12:46:51 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: Use correct timestamp, duration and filled length for the EOS buffers
+
+2011-12-05 13:18:09 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Improve debugging of buffer handling
+
+2011-12-05 08:12:48 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Drop EOS events in ::finish()
+ The event will be forwarded downstream from the srcpad
+ loop function after the last buffer was generated by the
+ component. Forwarding it after ::finish() will use the
+ sinkpad streaming thread and does not guarantee that
+ the encoder is completely drained.
+
+2011-12-01 16:20:36 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Properly drop frames due to QoS
+ Instead of finishing them they should be passed to drop(), which
+ will then send QoS messages.
+
+2011-11-29 12:21:32 +0100 Jonas Larsson <jonas@hallerud.se>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: Add support for resending headers after a forced-keyframe
+
+2011-11-29 12:12:33 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideocodec.h:
+ * omx/gstbasevideoencoder.c:
+ basevideoencoder: Pass the all-headers field of the force-key-unit event to the subclass
+
+2011-11-29 12:12:04 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ * omx/gstbasevideoencoder.h:
+ basevideoencoder: Implement full support for the new force-key-unit event
+ Including support for the running-time and count fields.
+
+2011-11-29 09:31:11 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ basevideoencoder: Use new force-keyunit event API from gst-plugins-base
+
+2011-11-29 09:18:19 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ * omx/gstbasevideoencoder.h:
+ basevideoencoder: Adjusting padding is not required for -bad libraries
+
+2011-11-28 19:48:01 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.h:
+ basevideoencoder: Move some fields to the private part of the instance struct
+
+2011-11-28 19:36:56 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ basevideoencoder: Make headers metadata writable before pushing downstream
+ The timestamp, duration, etc of the headers has to be changed.
+
+2011-11-28 19:35:40 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ * omx/gstbasevideoencoder.h:
+ basevideoencoder: Push the downstream force-keyframe event after the next keyframe
+ Even if the corresponding GstVideoFrame doesn't have the is_sync_point
+ flag set.
+
+2011-11-28 19:29:13 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ * omx/gstbasevideoencoder.h:
+ basevideoencoder: Don't push an upstream force-keyunit event downstream
+
+2011-11-25 11:48:08 +0100 Jonas Larsson <jonas@hallerud.se>
+
+ * omx/gstbasevideoencoder.c:
+ * omx/gstbasevideoencoder.h:
+ basevideoencoder: Add initial support for the all-headers field of the force-keyframe event
+ See bug #607742.
+
+2011-11-25 11:37:39 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * omx/gstbasevideodecoder.c:
+ basevideodecoder: some more debug logging
+
+2011-11-23 20:03:32 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * omx/gstbasevideodecoder.c:
+ * omx/gstbasevideodecoder.h:
+ basevideodecoder: add API to drop a frame and post a QoS message on the bus
+ https://bugzilla.gnome.org/show_bug.cgi?id=640017
+ API: gst_base_video_decoder_drop_frame()
+
+2011-11-22 23:04:49 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * omx/gstbasevideodecoder.c:
+ docs: fix comment in gst_base_video_decoder_get_max_decode_time() docs
+
+2011-11-22 19:57:07 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+ * omx/gstbasevideodecoder.c:
+ basevideodecoder: fix weird event list handling
+ Get rid of weird code that copies a list manually, taking
+ ownership of the elements and then frees the old list. Instead,
+ just take over the old list entirely. (If the intent was to
+ reverse the list, one could use g_list_reverse() instead).
+ Then, push events in the list out from last to first (since they
+ were prepended as they came in) instead of just pushing out the
+ last in the list and leaking the others.
+
+2011-11-25 11:31:58 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * configure.ac:
+ * omx/Makefile.am:
+ * omx/gstbaseaudiodecoder.c:
+ * omx/gstbaseaudiodecoder.h:
+ * omx/gstbaseaudioencoder.c:
+ * omx/gstbaseaudioencoder.h:
+ * omx/gstbaseaudioutils.c:
+ * omx/gstbaseaudioutils.h:
+ * omx/gstomxaacenc.c:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxaudioenc.h:
+ omxaudioenc: Use audio base classes from gst-plugins-base instead of having our own copies
+
+2011-11-18 10:00:31 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: First set ports to flushing before waiting for the srcpad streaming thread to finish
+
+2011-11-18 09:59:43 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: First set ports to flushing before waiting for the srcpad streaming thread to finish
+
+2011-11-18 09:58:58 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: First set ports to flushing before waiting for the srcpad streaming thread to finish
+
+2011-11-17 14:38:54 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Only disabling of a port is like flushing, enabling is like unflushing
+
+2011-11-17 13:33:35 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Enabling/disabling a port is also like flushing
+ The component returns all buffers to us and shouldn't get any
+ new buffers passed anymore.
+
+2011-11-17 11:26:33 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Signal the drain GCond even if downstream returned an error
+
+2011-11-17 11:26:20 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Signal the drain GCond even if downstream returned an error
+
+2011-11-17 11:25:52 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Signal the drain GCond even if downstream returned an error
+
+2011-11-17 10:34:19 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ basevideoencoder: Only call ::reset once in READY->PAUSED
+
+2011-11-17 10:19:35 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Shutdown component in PAUSED->READY and deallocate buffers
+
+2011-11-17 10:19:30 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Shutdown component in PAUSED->READY and deallocate buffers
+
+2011-11-17 10:19:10 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Shutdown component in PAUSED->READY and deallocate buffers
+
+2011-11-16 12:02:08 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Set force_keyframe to FALSE after handling it
+ There's no reason why the base class should forward the event
+ further downstream if we already handled it and will insert a
+ keyframe.
+
+2011-11-16 11:21:25 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Always push buffers downstream, even if we didn't find a corresponding GstVideoFrame
+
+2011-11-15 09:47:55 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Fix debug level for flushing in wrong state from ERROR to DEBUG
+ It's not really an error and doesn't matter at all if flush is called
+ when the component is not running.
+
+2011-11-15 08:40:07 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: Detect bytestream stream format and don't put SPS/PPS into the caps for this format
+
+2011-11-15 08:28:32 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: Add vfunc for handling the output frames
+ This can be used by subclasses to override the buffer flags
+ or to handle some frames differently than the default behaviour.
+
+2011-11-14 12:50:26 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Don't release buffers twice if dropping because of QoS
+
+2011-11-14 09:13:06 -0800 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Add XXX to the nOffset reset hack comment for QCOM
+
+2011-11-10 15:18:08 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Make srcpad caps setting threadsafe
+
+2011-11-10 15:17:56 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Make srcpad caps setting threadsafe
+
+2011-11-10 15:17:41 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Make srcpad caps setting threadsafe
+
+2011-11-10 15:10:14 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Make the srcpad task and the sinkpad streaming thread handling threadsafe
+
+2011-11-10 15:03:05 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Always flush the ports and make sure no processing is happening in ::flush
+ This fixes a race condition that happened when seeking
+ very often in a short period of time.
+
+2011-11-10 15:02:22 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Always flush the ports and make sure no processing is happening in ::reset
+ This fixes a race condition that happened when seeking
+ very often in a short period of time.
+
+2011-11-10 15:01:36 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Fix minor race condition when draining after upstream signalled EOS
+
+2011-11-10 14:56:19 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Improve EOS handling
+ If downstream return UNEXPECTED we should still signal the
+ drain cond because nothing will trigger this again later.
+
+2011-11-10 14:56:11 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Improve EOS handling
+ If downstream return UNEXPECTED we should still signal the
+ drain cond because nothing will trigger this again later.
+
+2011-11-10 14:54:33 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Improve debugging of EOS and draining
+
+2011-11-10 14:54:17 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Improve debugging of EOS and draining
+
+2011-11-10 14:51:06 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Log if acquiring buffer for EOS failed
+
+2011-11-10 14:42:13 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: The component is not started in READY
+
+2011-11-10 14:39:40 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: No need to signal the drain cond when going from READY to PAUSED
+ Also the component is not started in READY
+
+2011-11-10 14:40:56 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: No need to signal the drain cond when going from READY to PAUSED
+ Also the component is not started in READY.
+
+2011-11-09 15:46:02 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Always flush the ports and make sure no processing is happening in ::reset
+ This fixes a race condition that happened when seeking
+ very often in a short period of time.
+
+2011-11-09 15:45:20 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Fix minor race condition when draining after upstream signalled EOS
+
+2011-11-09 15:44:11 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Improve EOS handling
+ If downstream return UNEXPECTED we should still signal the
+ drain cond because nothing will trigger this again later.
+
+2011-11-09 15:43:32 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Improve debugging of EOS and draining
+
+2011-11-09 15:42:46 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: The component is not started already when going from READY to PAUSED
+
+2011-11-09 15:42:13 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: No need to signal the drain cond when going from READY to PAUSED
+
+2011-11-09 15:41:02 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Always reset buffer flags for output ports, even in flushing/error state
+
+2011-11-09 09:00:57 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Improve debugging in case of QoS-related frame drops
+
+2011-11-08 12:46:31 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Release the video codec stream lock before acquiring an input buffer
+ Otherwise the srcpad task might block on this lock and
+ no buffers ever become available again.
+
+2011-11-08 12:45:16 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Release the audio encoder stream lock before acquiring an input buffer
+ Otherwise the srcpad task might block on this lock and
+ no buffers ever become available again.
+
+2011-11-08 12:42:58 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Release the video codec stream lock before acquiring an input buffer
+ Otherwise the srcpad task might block on this lock and
+ no buffers ever become available again.
+
+2011-11-08 11:07:01 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxaudioenc.h:
+ omxaudioenc: Don't try to drain the component after EOS
+ And don't send EOS twice in any case. This most likely
+ will cause the component to not output it again and
+ is not necessary anyway.
+
+2011-11-08 11:03:29 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: Don't try to drain the component after EOS
+ And don't send EOS twice in any case. This most likely
+ will cause the component to not output it again and
+ is not necessary anyway.
+
+2011-11-08 10:46:36 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: Don't try to drain the component after EOS
+ And don't send EOS twice in any case. This most likely
+ will cause the component to not output it again and
+ is not necessary anyway.
+
+2011-11-08 09:09:28 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Implement dropping of too late frames via QoS
+
+2011-11-08 08:31:58 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Minor code refactoring
+
+2011-11-08 08:31:43 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Minor code refactoring
+
+2011-11-08 08:31:32 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Make sure to always release buffers back to OMX
+
+2011-11-08 08:24:19 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Also properly release buffers when in error state
+
+2011-11-08 08:22:08 +0100 Jonas Larsson <Jonas.Larsson@palm.com>
+
+ * omx/gstomx.c:
+ omx: Properly release buffers during flushing
+ We can't pass them back to OMX_FillThisBuffer() or OMX_EmptyThisBuffer()
+ but instead of doing nothing we have to put them back into our queue.
+ Otherwise the buffer is leaked and we will have too few buffers in
+ the future.
+
+2011-11-07 14:00:47 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Free pending frames after draining component
+
+2011-11-07 14:00:35 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Free pending frames after draining the component
+
+2011-11-07 11:07:01 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Make handling and usage of the base video codec frames threadsafe
+
+2011-11-07 11:05:29 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Fix deadlock between srcpad stream lock and ::reset()
+
+2011-11-07 11:04:27 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideoenc: Make handling and usage of the base video codec frames threadsafe
+
+2011-11-07 10:58:44 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Free all pending frames after draining the component
+
+2011-11-07 10:58:24 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Always free all pending frames when caps changes require reconfiguration
+
+2011-11-04 09:43:48 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Only drain the component a single time and only after processing started
+
+2011-11-04 09:43:32 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Only drain the component a single time and only after processing started
+
+2011-11-04 09:43:12 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Only drain the component a single time and only after processing started
+
+2011-11-04 09:04:16 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Reset buffer flags to 0 after it was consumed by the component or the element
+ Some implementations don't reset the flags and the standard is not
+ really clear on the expected behaviour. Let's just always reset the
+ flags as they're not valid at this point anymore.
+
+2011-11-02 13:50:14 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: Better handling of encoder parameters
+ Only set them if necessary and allow to use the component
+ defaults.
+
+2011-11-02 13:22:50 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Make unsupported bitrate/quantizer settings less fatal
+
+2011-11-02 10:39:50 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: If no stride was set for the OMX output port assume GStreamer stride
+ This is not really correct but there's nothing else we could do.
+
+2011-11-02 10:39:10 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: If no stride was set for the OMX input port assume GStreamer stride
+ This is not really correct but there's nothing else we could do.
+
+2011-11-01 16:46:09 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxaudioenc.h:
+ omxaudioenc: Implement draining of the component and use it
+ This makes sure that all buffers are encoded and pushed downstream
+ before flushing the ports and losing some buffers.
+
+2011-11-01 16:41:46 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: Implement draining of the component and use it
+ This makes sure that all buffers are encoded and pushed downstream
+ before flushing the ports and losing some buffers.
+
+2011-11-01 16:08:59 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: Implement draining of the component and use it
+ This makes sure that all buffers are decoded and pushed downstream
+ before flushing the ports and losing some buffers.
+
+2011-10-20 14:32:40 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Fix deadlock if ::reset is called before finding the corresponding frame of a decoded buffer
+
+2011-11-01 15:10:12 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxaudioenc.h:
+ * omx/gstomxvideoenc.h:
+ omxaudioenc: Forward downstream flow returns to upstream
+
+2011-11-01 15:10:01 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Forward downstream flow returns to upstream
+
+2011-11-01 13:58:38 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: Forward downstream flow returns to upstream
+
+2011-10-25 14:23:38 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * README:
+ omx: Add minimal README file
+
+2011-10-20 15:21:07 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Fix deadlock caused by calling reset while the loop function does something with the base video codec stream lock
+
+2011-10-20 15:20:47 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Fix deadlock caused by calling reset while the loop function does something with the base video codec stream lock
+
+2011-10-20 14:30:38 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Move locking at the correct place
+
+2011-10-14 10:27:47 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: Remove QCOM hack to reset nOffset in EmptyBufferDone
+ This is now done in a generic way that does not require any
+ hacks because it will work without any side effects on any
+ OMX implementation.
+
+2011-10-14 10:26:00 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Reset nOffset to 0 in EmptyBufferDone if nFilledLen is 0
+ Some OMX implementations don't reset nOffset when the complete
+ buffer is emptied but instead only reset nFilledLen. We reset
+ nOffset to 0 if nFilledLen == 0, which is safe to do because
+ the offset *must* be 0 if the buffer is not filled at all.
+ Seen in QCOM's OMX implementation.
+
+2011-10-04 10:56:33 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: If one parameter/configuration is not supported don't skip the next
+
+2011-10-03 09:12:44 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxh264dec.c:
+ omxh264dec: Require stream-format=byte-stream
+ Other stream-formats are unlikely to be supported by OMX components.
+
+2011-09-29 10:37:32 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: Add API for subclasses to prepare/convert frames
+
+2011-09-27 15:08:54 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Switch to Idle first and wait before switching to Loaded and deallocating buffers
+ Allocating buffers before the Idle state is reached can lead to crashes.
+
+2011-09-27 15:08:44 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Switch to Idle first and wait before switching to Loaded and deallocating buffers
+ Allocating buffers before the Idle state is reached can lead to crashes.
+
+2011-09-27 15:05:19 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Switch to Idle first and wait before switching to Loaded and deallocating buffers
+ Allocating buffers before the Idle state is reached can lead to crashes.
+
+2011-09-27 14:15:06 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideodec.c:
+ omxvideodec: New hack for QCOM to recreate the component instead of reconfiguring it on caps changes
+
+2011-09-27 12:13:56 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Change a g_assert() into a GST_WARNING_OBJECT()
+
+2011-09-26 13:04:18 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: Add hack for Qualcomm's OMX implementation to manually reset nOffset in EmptyBufferDone
+
+2011-09-23 17:02:49 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Add a check to prevent a zero-sized OMX buffer
+
+2011-09-23 17:02:19 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Add some more checks for correct OMX buffer sizes
+
+2011-09-23 15:53:49 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Add some more checks for OMX buffer sizes
+
+2011-09-14 10:15:38 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omx: Wait until the Executing state is reached before calling OMX_FillThisBuffer()
+ This correctly works around the QCOM race condition that happens when calling
+ FTB after setting the new state and before reaching it.
+
+2011-09-02 14:43:43 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Negotiate video format with downstream and what the component claims to support
+
+2011-08-25 19:56:58 +0100 Vincent Penquerc'h <vincent.penquerch@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ basevideoencoder: fix element leak
+ and this concludes an hour of yelling at the bloody test failing,
+ only to track down the problem not being in the test.
+ https://bugzilla.gnome.org/show_bug.cgi?id=657368
+
+2011-08-19 09:20:39 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Release basevideocodec stream lock while waiting for a buffer
+ This prevents deadlocks if no empty input buffers are available and
+ releasing input buffers requires the loop function to handle some
+ output buffers first.
+
+2011-08-19 09:19:22 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Release basevideocodec stream lock while waiting for a buffer
+ This prevents deadlocks if no empty input buffers are available and
+ releasing input buffers requires the loop function to handle some
+ output buffers first.
+
+2011-08-18 10:24:26 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideodecoder.c:
+ basevideodecoder: Fix deadlock
+
+2011-08-18 10:03:20 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbaseaudiodecoder.c:
+ baseaudiodecoder: Don't take the stream lock in the seek handler
+ This will lead to deadlocks
+
+2011-08-18 10:02:50 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideocodec.c:
+ * omx/gstbasevideocodec.h:
+ * omx/gstbasevideodecoder.c:
+ * omx/gstbasevideoencoder.c:
+ basevideo: Fix locking, especially if both pads have different streaming threads
+
+2011-08-18 09:42:02 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideodecoder.c:
+ * omx/gstbasevideoencoder.c:
+ basevideo: Don't call g_type_class_peek_parent() in class_init
+ This is already done by the GObject boilerplate macro
+
+2011-08-18 09:40:46 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbaseaudiodecoder.c:
+ baseaudiodecoder: Don't call g_type_class_peek_parent() in class_init
+ This is already done by the boilerplate macro
+
+2011-08-18 09:34:38 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbaseaudiodecoder.c:
+ * omx/gstbaseaudiodecoder.h:
+ baseaudiodecoder: Fix thread safety issues if both pads have different streaming threads
+
+2011-08-18 09:17:04 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbaseaudiodecoder.c:
+ baseaudiodecoder: Delay sending of serialized events to finish_frame()
+
+2011-08-17 14:33:31 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Always require at least OMX_MIN_PCMPAYLOAD_MSEC per input buffer
+
+2011-08-17 14:28:44 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbaseaudioencoder.c:
+ * omx/gstbaseaudioencoder.h:
+ baseaudioencoder: Add support for requesting a minimum and maximum number of samples per frame
+ This extends the special case of a fixed number of samples per frame
+ that was supported before already.
+
+2011-08-17 14:17:18 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Handle inbuf==NULL properly in ::handle_frame()
+
+2011-08-17 13:04:19 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaacenc.c:
+ omxaacenc: Implement ::get_num_samples() vfunc
+
+2011-08-17 13:03:50 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxaudioenc.h:
+ omxaudioenc: Add vfunc to get the number of samples inside a buffer
+
+2011-08-17 11:34:31 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Release baseaudioencoder stream lock while waiting for a buffer in ::handle_frame()
+ This prevents deadlocks if no empty input buffers are available and
+ releasing input buffers requires the loop function to handle some
+ output buffers first.
+
+2011-08-17 11:34:04 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbaseaudioencoder.c:
+ * omx/gstbaseaudioencoder.h:
+ baseaudioencoder: Fix thread safety issues if both pads have different streaming threads
+
+2011-08-17 09:58:01 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbaseaudioencoder.c:
+ baseaudioencoder: Taking the OBJECT lock in reset() is not needed
+
+2011-08-16 11:03:24 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxaudioenc.c:
+ omxaudioenc: Remove hack that only applies to the video encoder class
+
+2011-08-16 10:49:21 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomx.conf:
+ * omx/gstomxaacenc.c:
+ * omx/gstomxaacenc.h:
+ omxaacenc: Add initial version of OpenMAX AAC encoder element
+
+2011-08-15 15:10:04 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ * omx/gstomxaudioenc.c:
+ * omx/gstomxaudioenc.h:
+ omxaudioenc: Add initial version of audio encoder base class
+
+2011-08-15 14:14:11 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbaseaudioencoder.c:
+ baseaudioencoder: Delay sending of serialized events to finish_frame()
+
+2011-08-15 13:06:51 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ * omx/gstbaseaudiodecoder.c:
+ * omx/gstbaseaudiodecoder.h:
+ * omx/gstbaseaudioencoder.c:
+ * omx/gstbaseaudioencoder.h:
+ audio: Integrate audio base classes into the build system and fixup
+
+2011-08-15 12:56:00 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbaseaudiodecoder.c:
+ * omx/gstbaseaudiodecoder.h:
+ * omx/gstbaseaudioencoder.c:
+ * omx/gstbaseaudioencoder.h:
+ * omx/gstbaseaudioutils.c:
+ * omx/gstbaseaudioutils.h:
+ audio: Add audio decoder/encoder base classes
+ Taken from http://cgit.collabora.com/git/user/manauw/gst-plugins-bad.git/log/?h=baseaudio
+
+2011-08-12 12:25:03 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ basevideoencoder: Proxy the width/height/framerate/PAR constraints of downstream caps to upstream
+ This allows to specify constraints on the compressed downstream caps
+ by muxers or capsfilters, which will then be forwarded to upstream
+ and allows video converters to fulfill the constraints.
+ Code based on Mark Nauwelaerts audio encoder base class.
+
+2011-08-12 12:13:45 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.h:
+ basevideoencoder: Remove old ::getcaps() comment
+
+2011-08-12 12:06:23 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ * omx/gstbasevideoencoder.h:
+ basevideoencoder: Remove ::get_caps() vfunc
+ Subclasses can set the caps more efficiently and this only
+ caused additional indirections.
+
+2011-08-10 10:24:21 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxh263enc.c:
+ * omx/gstomxh264enc.c:
+ * omx/gstomxmpeg4videoenc.c:
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Use "video/x-raw-yuv" as sink template caps instead of strict I420 caps
+
+2011-08-10 10:23:39 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxmpeg4videodec.c:
+ omxmpeg4videodec: Don't require width/height on sink pad caps
+
+2011-08-10 10:11:37 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxh263dec.c:
+ * omx/gstomxh264dec.c:
+ * omx/gstomxmpeg4videodec.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxwmvdec.c:
+ omxvideodec: Use "video/x-raw-yuv" as src template caps instead of strict I420 caps
+
+2011-08-10 09:56:30 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Set the state back to StateLoaded even if an error happened
+
+2011-08-10 09:49:57 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Don't hold any locks while calling OMX_SendCommand()
+ It might call into one of the callbacks and lead to deadlocks, e.g.
+ with the Qualcomm OMX implementation.
+
+2011-08-10 09:32:01 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Move some code
+
+2011-08-10 09:23:10 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Reset pending reconfigure output ports when changing the state from Executing to any lower state
+
+2011-08-10 09:08:00 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Fix crash when setting last error after the ports were freed
+
+2011-08-10 09:03:52 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Free component structure
+
+2011-08-10 09:02:52 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Make component destruction safer
+
+2011-08-10 08:53:05 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Set pAppPrivate of buffers to NULL when deallocating buffers
+ This prevents usage of freed memory later if the OMX component
+ has weird behaviour.
+
+2011-08-10 08:52:25 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Set the state back to StateLoaded even if an error happened
+
+2011-08-10 08:51:54 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Add some assertions to check if the buffer pAppPrivate is still correct
+
+2011-08-08 13:04:30 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.h:
+ omx: Add parenthesis at correct places in the struct init macro
+
+2011-08-08 12:12:58 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Only prevent setting a higher state if the component is in an error state
+
+2011-08-03 16:02:01 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideodecoder.c:
+ basevideodecoder: Use the cached video frame size instead of recalculating it
+
+2011-08-03 15:35:01 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Improve debugging in param/config getter/setter wrappers
+
+2011-08-03 13:10:33 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Don't abort if the color format is not supported but give a useful error message
+
+2011-08-02 15:14:37 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxh263enc.c:
+ * omx/gstomxh264enc.c:
+ * omx/gstomxmpeg4videoenc.c:
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Don't fail if setting the bitrate or profile is not supported by the component
+ Also always set/get the profile, even if there are no peer caps.
+
+2011-08-02 15:14:24 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ basevideoencoder: Make access to the list of frames threadsafe
+
+2011-08-01 13:22:05 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: Add a hacks flag for the Qualcomm 7x30 OMX_FillThisBuffer() race and make it optional
+
+2011-07-29 13:56:59 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Add workaround for QCOM 7x30 race condition
+
+2011-07-29 12:06:21 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomxh263enc.c:
+ * omx/gstomxh263enc.h:
+ omxh263enc: Add H.263 encoder element
+
+2011-07-29 11:26:39 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxmpeg4videoenc.c:
+ omxmpeg4videoenc: Add support for setting profile/level via caps
+
+2011-07-28 14:14:45 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxh264enc.c:
+ omxh264enc: Add support for setting profile/level via caps
+
+2011-07-28 12:58:25 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Add support for forcing the next frame to be a keyframe
+
+2011-07-28 11:54:16 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: Add support for setting bitrate/quantization related parameters
+
+2011-07-28 10:23:08 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: Add wrapper functions for OMX_[GS]et{Config,Parameter}
+
+2011-07-28 09:54:53 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: Add macro to initialize OpenMAX structures
+
+2011-07-28 09:08:38 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Don't output 0-byte buffers
+
+2011-07-25 15:05:08 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Ensure that the pAppPrivate pointer in OMX buffers is set correctly
+
+2011-07-25 13:19:06 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideoenc.c:
+ omxvideo{enc,dec}: Only set/unset flushing state on ports if they were created already
+
+2011-07-25 12:01:05 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomxwmvdec.c:
+ * omx/gstomxwmvdec.h:
+ omxwmvdec: Add WMV video decoder element
+
+2011-07-25 11:44:56 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomxh263dec.c:
+ * omx/gstomxh263dec.h:
+ omxh263dec: Add H.263 decoder element
+
+2011-07-25 11:32:51 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomxh264enc.c:
+ * omx/gstomxh264enc.h:
+ omxh264enc: Add H.264 encoder element
+
+2011-07-25 10:48:58 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Try harder to deallocate the buffers after errors happened
+
+2011-07-25 10:47:28 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Try harder to deallocate the buffers after errors happened
+
+2011-07-25 10:46:49 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Deallocate port buffers before freeing the component
+ They should be deallocated by the caller before reaching the
+ Loaded state but to be on the safe side we will make sure
+ they're really deallocated here.
+
+2011-07-21 11:15:14 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Add initial support for stride conversion
+
+2011-07-21 10:38:26 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxh264dec.c:
+ * omx/gstomxmpeg4videodec.c:
+ * omx/gstomxmpeg4videoenc.c:
+ omx: Set default roles for the components if none were set from the config file
+
+2011-07-21 10:36:19 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Failure to set the component role is fatal
+
+2011-07-21 07:53:25 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Add support for setting codec_data on the srcpad caps
+
+2011-07-21 07:44:34 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Free/drop GstVideoFrames that resulted in an empty buffer
+
+2011-07-21 07:44:10 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ basevideoencoder: Allow finishing of frames with no src_buffer to drop/free the GstVideoFrame
+
+2011-07-21 07:31:05 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideoenc.c:
+ omxvideoenc: Remove obsolete TODO comment
+
+2011-07-20 11:09:54 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ omx: Use libgstopenmax.so for the plugin filename and openmax for the plugin name
+ Resolves conflicts with gst-openmax.
+
+2011-07-20 08:34:33 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomx.conf:
+ * omx/gstomx.h:
+ * omx/gstomxmpeg4videoenc.c:
+ * omx/gstomxmpeg4videoenc.h:
+ * omx/gstomxvideoenc.c:
+ * omx/gstomxvideoenc.h:
+ omxvideoenc: Add video encoder base class and MPEG4 video encoder
+ Unfortunately requires lots of hacks again to work properly with
+ Bellagio.
+
+2011-07-20 10:39:51 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ basevideoencoder: Only get caps from the subclass if they were not set yet by the subclass
+
+2011-07-20 09:25:28 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ * omx/gstbasevideoencoder.h:
+ basevideoencoder: Delay sending of serialized sink events until finish_frame()
+
+2011-07-20 09:09:25 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ * omx/gstbasevideoencoder.h:
+ basevideoencoder: Add ::reset vfunc and handle ::reset/::finish the same way as in the decoder
+
+2011-07-19 12:50:43 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideoencoder.c:
+ basevideoencoder: Use a temporary GstVideoState until the subclass accepted the caps
+ Also store the caps in the GstVideoState and assume a PAR of 1/1 instead
+ of 0/1 if no PAR is specified in the caps.
+
+2011-07-19 12:29:51 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomxvideodec.c:
+ omx: Improve debug output a bit
+
+2011-07-19 10:33:54 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideodec.c:
+ omx: Rework port reconfiguration again and only use the Bellagio specific hacks with Bellagio
+ We only reconfigure ports that need to be reconfigured now instead of
+ always all ports.
+
+2011-07-19 10:33:15 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.conf:
+ * omx/gstomx.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omx: Add infrastructure to enable special hacks for broken OpenMAX implementations
+
+2011-07-18 13:10:49 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: When acquiring a buffer from an input port always wait until all output ports are reconfigured
+
+2011-07-18 08:41:20 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Add support for converting between omx and gst rowstrides
+
+2011-07-14 10:34:09 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Provide all buffers to output ports after enabling them
+
+2011-07-14 08:29:03 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Add support for NV12 / OMX_COLOR_FormatYUV420SemiPlanar
+
+2011-07-14 07:58:41 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: Only flush the component ports after we passed input to them
+
+2011-07-13 21:19:34 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Only change states downwards if an upper state was reached
+
+2011-07-13 20:37:02 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omx: Add support for setting the component-role
+
+2011-07-13 20:22:51 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideodec.c:
+ omx: Improve error reporting by formatting the error codes better and also providing their string representation
+
+2011-07-13 14:36:14 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * Makefile.am:
+ build: Dist autogen.sh
+
+2011-07-13 14:35:51 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * configure.ac:
+ * omx/gstomx.c:
+ build: Only require GStreamer >= 0.10.29 and GLib >= 2.16
+
+2011-07-13 14:04:47 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ build: Dist gstomx.conf
+
+2011-07-13 14:04:20 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * Makefile.am:
+ build: Clean _stdint.h on "make distclean"
+
+2011-07-13 14:02:50 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Fix typo
+
+2011-07-13 13:59:50 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ omx: Dist gstomx.h
+
+2011-07-13 12:46:50 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Set SYNCFRAME flag on the OMX buffers for non-delta units
+
+2011-07-13 12:37:44 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Free all pending frames when resetting the decoder
+ Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=654529
+
+2011-07-13 09:59:49 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Handle output buffers without a corresponding GstVideoFrame more gracefully
+ This can happen on EOS in some cases and when the input is not
+ properly framed.
+
+2011-07-13 09:31:22 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Fix deadlock when finishing old frames that are left over by the decoder
+
+2011-07-12 11:37:28 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxh264dec.c:
+ omxh264dec: It's called H.264, not H264
+
+2011-07-12 11:36:42 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxh264dec.c:
+ * omx/gstomxmpeg4videodec.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: Make sink/src pad template caps configurable
+
+2011-07-12 11:13:50 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Allow to set a preferred configuration directory with the GST_OMX_CONFIG_DIR environment variable
+
+2011-07-12 10:55:57 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxh264dec.c:
+ * omx/gstomxmpeg4videodec.c:
+ * omx/gstomxvideodec.c:
+ omxvideodec: Make core/component-name and in/outport index configurable
+
+2011-07-12 10:05:31 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.conf:
+ * omx/gstomx.h:
+ omx: Add initial version of configuration system
+ This now only registers elements that are specified in the
+ configuration file.
+ The configuration file is a keyfile in the first XDG configuration
+ directory with the name gstomx.conf.
+
+2011-07-12 08:53:15 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomxh264dec.c:
+ * omx/gstomxh264dec.h:
+ * omx/gstomxh264videodec.h:
+ omxh264dec: Rename from omxh264videodec to omxh264dec
+
+2011-07-12 08:40:48 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxh264videodec.c:
+ omxh264videodec: Require alignment=au and stream-format={avc,bytestream}
+
+2011-07-11 12:59:07 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideodecoder.c:
+ basevideodecoder: First inform subclass about resetting before resetting/freeing all internal state
+ The subclass might want to access the old state.
+
+2011-07-11 12:36:42 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideodecoder.c:
+ basevideodecoder: Track present position on discont before resetting it
+
+2011-07-11 11:52:33 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideodecoder.c:
+ basevideodecoder: Also protect the list of pending frames from concurrent access when pushing all pendings events
+
+2011-07-11 11:28:40 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideocodec.c:
+ * omx/gstbasevideocodec.h:
+ * omx/gstbasevideodecoder.c:
+ basevideocodec: Protect access to the list of pending frames with the object lock
+ This is required if ::finish_frame() and all buffer output happens
+ on a different thread than the sinkpad streaming thread.
+
+2011-07-11 09:35:25 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideodecoder.c:
+ basevideodecoder: Set the correct lists to NULL after freeing
+
+2011-07-11 08:54:53 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideodecoder.c:
+ basevideodecoder: Work with a copy of the GstVideoState in setcaps until the caps are accepted
+ Also fix a refcount problem with the codec_data.
+
+2011-07-12 08:34:44 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomxh264videodec.c:
+ * omx/gstomxh264videodec.h:
+ omxh264videodec: Add h.264 video decoder
+
+2011-07-12 08:29:15 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxmpeg4videodec.c:
+ omxmpeg4videodec: Fix debug category name
+
+2011-07-09 11:41:42 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ * omx/gstbasevideocodec.h:
+ * omx/gstbasevideodecoder.c:
+ * omx/gstbasevideoencoder.c:
+ * omx/gstbasevideoutils.c:
+ * omx/gstbasevideoutils.h:
+ basevideo: Move the utils from the codec header to its own header
+
+2011-07-09 11:32:06 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideocodec.c:
+ * omx/gstbasevideodecoder.c:
+ basevideo: Use GSlice for allocating GstVideoFrame and don't duplicate code in the decoder base class
+
+2011-07-09 11:05:37 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Use the destroy notify to free the coder_hook
+
+2011-07-09 10:57:52 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideocodec.c:
+ * omx/gstbasevideocodec.h:
+ * omx/gstbasevideodecoder.c:
+ basevideo: Add destroy notify for the coder_hook to prevent memory leaks
+ Fixes bug #654293.
+
+2011-07-09 10:44:16 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ basevideo: Fix GType names to not conflict with the public video base classes
+ It's still not possible to include headers of both in the same file
+ or compile/link both into the same plugin but that shouldn't be
+ necessary anyway.
+
+2011-07-08 15:42:56 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Fix some minor memory leaks
+
+2011-07-08 15:25:07 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideodec.c:
+ omx: Rework port reconfiguration
+ We always reconfigure all ports now if the settings of one
+ port changes to prevent lots of race conditions, dropped
+ frames and similar issues.
+
+2011-07-08 13:16:45 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: Use the frames storage of the base class instead of implementing our own
+ They could get out of sync and we could store already destroyed frames.
+
+2011-07-07 12:51:03 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.h:
+ omx: Clarify GQueue/GPtrArray element types
+
+2011-07-07 12:23:24 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxvideodec.c:
+ omx: Add more checks to acquire_buffer() and return the current state additional to the buffer
+ Also refactor the code flow in the video decoder for this. This makes
+ the usage of acquire_buffer() easier and more atomic.
+
+2011-07-07 12:22:57 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Also flush/unflush the input port when changing the state PAUSED<->READY
+
+2011-07-07 12:21:31 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Don't broadcast port->port_cond after allocating buffers successfully
+ Allocating buffers must happen while no thread is waiting for the
+ cond and especially must happen from the thread that would acquire
+ buffers from the port.
+
+2011-07-07 11:27:15 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Don't leak the codec_data after sending it
+
+2011-07-07 10:27:31 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Always check if the component is in an error state before waiting for a condition variable to be signalled
+ Otherwise we might wait forever because nothing is going to signal
+ the condition variable anymore.
+
+2011-07-07 10:22:12 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Always hold port->port_lock before signalling port->port_cond when notifying about errors
+ Otherwise a port might be in the critical section, has checked the error state
+ already but waits after port->port_cond is signalled, which will lead
+ to a deadlock.
+
+2011-07-07 10:07:43 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Remove reconfiguration test hack
+
+2011-07-06 13:27:12 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Improve debug output a bit
+
+2011-07-06 13:26:51 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Always try to deallocate buffers, even if there's a component error
+
+2011-07-06 13:26:01 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ omx: Use G_USEC_PER_SEC for clarity instead of 1000000
+
+2011-07-06 13:19:15 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Error out if the GStreamer allocated buffer is smaller than the OpenMAX output buffer
+ Usually this must never happen but currently it happens during reconfigurations
+ because of a race condition. Still it's better than crashing.
+
+2011-07-06 10:40:13 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: Don't use port_def.bEnabled to check if the Enable/Disable command is finished
+ bEnabled should be set immediately after sending the command, it's only
+ Bellagio that waits until the command is finished before setting it.
+
+2011-07-06 10:30:11 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxvideodec.c:
+ omxvideodec: Remove obsolete FIXME comment
+
+2011-07-06 10:29:54 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ omx: Improve error handling and reporting
+
+2011-07-06 08:48:37 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstomxmpeg4videodec.c:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omxvideodec: Make the inport and outport index configurable by the subclass
+
+2011-06-28 08:51:23 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/Makefile.am:
+ * omx/gstomx.c:
+ * omx/gstomx.h:
+ * omx/gstomxmpeg4videodec.c:
+ * omx/gstomxmpeg4videodec.h:
+ * omx/gstomxvideodec.c:
+ * omx/gstomxvideodec.h:
+ omx: Add initial version of OpenMAX framework, video decoder base class and MPEG4 video decoder
+ This currently hardcodes a lot of stuff but works at least.
+ Also adds a generic framework for handling OpenMAX cores, components
+ and ports.
+
+2011-06-28 11:47:25 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideocodec.c:
+ * omx/gstbasevideocodec.h:
+ * omx/gstbasevideodecoder.c:
+ * omx/gstbasevideodecoder.h:
+ basevideodecoder: Don't reorder serialized src events
+ And allow to drop EOS by the subclass if ::finish returns
+ DROPPED.
+ Fixes bug #653544.
+
+2011-06-27 09:41:40 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideocodec.c:
+ * omx/gstbasevideocodec.h:
+ * omx/gstbasevideodecoder.c:
+ basevideo: Add the caps to the GstVideoState and clean up caps/codec_data properly
+
+2011-06-27 09:37:03 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/gstbasevideocodec.c:
+ * omx/gstbasevideocodec.h:
+ * omx/gstbasevideodecoder.c:
+ * omx/gstbasevideodecoder.h:
+ * omx/gstbasevideoencoder.c:
+ * omx/gstbasevideoencoder.h:
+ * omx/gstbasevideoutils.c:
+ basevideo: Add video encoder/decoder base classes from gst-plugins-bad
+
+2011-06-21 11:17:35 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+ * omx/openmax/OMX_Audio.h:
+ * omx/openmax/OMX_Component.h:
+ * omx/openmax/OMX_ComponentExt.h:
+ * omx/openmax/OMX_ContentPipe.h:
+ * omx/openmax/OMX_Core.h:
+ * omx/openmax/OMX_CoreExt.h:
+ * omx/openmax/OMX_IVCommon.h:
+ * omx/openmax/OMX_Image.h:
+ * omx/openmax/OMX_Index.h:
+ * omx/openmax/OMX_IndexExt.h:
+ * omx/openmax/OMX_Other.h:
+ * omx/openmax/OMX_Types.h:
+ * omx/openmax/OMX_Video.h:
+ * omx/openmax/OMX_VideoExt.h:
+ openmax: Add OpenMAX IL 1.1.2 headers
+
diff --git a/subprojects/gst-omx/NEWS b/subprojects/gst-omx/NEWS
new file mode 100644
index 0000000000..0e581c39b8
--- /dev/null
+++ b/subprojects/gst-omx/NEWS
@@ -0,0 +1,299 @@
+GStreamer 1.20 Release Notes
+
+GStreamer 1.20 has not been released yet. It is scheduled for release
+around October/November 2021.
+
+1.19.x is the unstable development version that is being developed in
+the git main branch and which will eventually result in 1.20, and 1.19.2
+is the current development release in that series
+
+It is expected that feature freeze will be in early October 2021,
+followed by one or two 1.19.9x pre-releases and the new 1.20 stable
+release around October/November 2021.
+
+1.20 will be backwards-compatible to the stable 1.18, 1.16, 1.14, 1.12,
+1.10, 1.8, 1.6,, 1.4, 1.2 and 1.0 release series.
+
+See https://gstreamer.freedesktop.org/releases/1.20/ for the latest
+version of this document.
+
+Last updated: Wednesday 22 September 2021, 18:00 UTC (log)
+
+Introduction
+
+The GStreamer team is proud to announce a new major feature release in
+the stable 1.x API series of your favourite cross-platform multimedia
+framework!
+
+As always, this release is again packed with many new features, bug
+fixes and other improvements.
+
+Highlights
+
+- this section will be completed in due course
+
+Major new features and changes
+
+Noteworthy new features and API
+
+- this section will be filled in in due course
+
+New elements
+
+- this section will be filled in in due course
+
+New element features and additions
+
+- this section will be filled in in due course
+
+Plugin and library moves
+
+- this section will be filled in in due course
+
+- There were no plugin moves or library moves in this cycle.
+
+Plugin removals
+
+The following elements or plugins have been removed:
+
+- this section will be filled in in due course
+
+Miscellaneous API additions
+
+- this section will be filled in in due course
+
+Miscellaneous performance, latency and memory optimisations
+
+- this section will be filled in in due course
+
+Miscellaneous other changes and enhancements
+
+- this section will be filled in in due course
+
+Tracing framework and debugging improvements
+
+- this section will be filled in in due course
+
+Tools
+
+- this section will be filled in in due course
+
+GStreamer RTSP server
+
+- this section will be filled in in due course
+
+GStreamer VAAPI
+
+- this section will be filled in in due course
+
+GStreamer OMX
+
+- this section will be filled in in due course
+
+GStreamer Editing Services and NLE
+
+- this section will be filled in in due course
+
+GStreamer validate
+
+- this section will be filled in in due course
+
+GStreamer Python Bindings
+
+- this section will be filled in in due course
+
+GStreamer C# Bindings
+
+- this section will be filled in in due course
+
+GStreamer Rust Bindings and Rust Plugins
+
+The GStreamer Rust bindings are released separately with a different
+release cadence that’s tied to gtk-rs, but the latest release has
+already been updated for the upcoming new GStreamer 1.20 API.
+
+gst-plugins-rs, the module containing GStreamer plugins written in Rust,
+has also seen lots of activity with many new elements and plugins.
+
+What follows is a list of elements and plugins available in
+gst-plugins-rs, so people don’t miss out on all those potentially useful
+elements that have no C equivalent.
+
+- FIXME: add new elements
+
+Rust audio plugins
+
+- audiornnoise: New element for audio denoising which implements the
+ noise removal algorithm of the Xiph RNNoise library, in Rust
+- rsaudioecho: Port of the audioecho element from gst-plugins-good
+ rsaudioloudnorm: Live audio loudness normalization element based on
+ the FFmpeg af_loudnorm filter
+- claxondec: FLAC lossless audio codec decoder element based on the
+ pure-Rust claxon implementation
+- csoundfilter: Audio filter that can use any filter defined via the
+ Csound audio programming language
+- lewtondec: Vorbis audio decoder element based on the pure-Rust
+ lewton implementation
+
+Rust video plugins
+
+- cdgdec/cdgparse: Decoder and parser for the CD+G video codec based
+ on a pure-Rust CD+G implementation, used for example by karaoke CDs
+- cea608overlay: CEA-608 Closed Captions overlay element
+- cea608tott: CEA-608 Closed Captions to timed-text (e.g. VTT or SRT
+ subtitles) converter
+- tttocea608: CEA-608 Closed Captions from timed-text converter
+- mccenc/mccparse: MacCaption Closed Caption format encoder and parser
+- sccenc/sccparse: Scenarist Closed Caption format encoder and parser
+- dav1dec: AV1 video decoder based on the dav1d decoder implementation
+ by the VLC project
+- rav1enc: AV1 video encoder based on the fast and pure-Rust rav1e
+ encoder implementation
+- rsflvdemux: Alternative to the flvdemux FLV demuxer element from
+ gst-plugins-good, not feature-equivalent yet
+- rsgifenc/rspngenc: GIF/PNG encoder elements based on the pure-Rust
+ implementations by the image-rs project
+
+Rust text plugins
+
+- textwrap: Element for line-wrapping timed text (e.g. subtitles) for
+ better screen-fitting, including hyphenation support for some
+ languages
+
+Rust network plugins
+
+- reqwesthttpsrc: HTTP(S) source element based on the Rust
+ reqwest/hyper HTTP implementations and almost feature-equivalent
+ with the main GStreamer HTTP source souphttpsrc
+- s3src/s3sink: Source/sink element for the Amazon S3 cloud storage
+- awstranscriber: Live audio to timed text transcription element using
+ the Amazon AWS Transcribe API
+
+Generic Rust plugins
+
+- sodiumencrypter/sodiumdecrypter: Encryption/decryption element based
+ on libsodium/NaCl
+- togglerecord: Recording element that allows to pause/resume
+ recordings easily and considers keyframe boundaries
+- fallbackswitch/fallbacksrc: Elements for handling potentially
+ failing (network) sources, restarting them on errors/timeout and
+ showing a fallback stream instead
+- threadshare: Set of elements that provide alternatives for various
+ existing GStreamer elements but allow to share the streaming threads
+ between each other to reduce the number of threads
+- rsfilesrc/rsfilesink: File source/sink elements as replacements for
+ the existing filesrc/filesink elements
+
+Build and Dependencies
+
+- this section will be filled in in due course
+
+gst-build
+
+- this section will be filled in in due course
+
+Cerbero
+
+Cerbero is a meta build system used to build GStreamer plus dependencies
+on platforms where dependencies are not readily available, such as
+Windows, Android, iOS and macOS.
+
+General improvements
+
+- this section will be filled in in due course
+
+macOS / iOS
+
+- this section will be filled in in due course
+
+Windows
+
+- this section will be filled in in due course
+
+Windows MSI installer
+
+- this section will be filled in in due course
+
+Linux
+
+- this section will be filled in in due course
+
+Android
+
+- this section will be filled in in due course
+
+Platform-specific changes and improvements
+
+Android
+
+- this section will be filled in in due course
+
+macOS and iOS
+
+- this section will be filled in in due course
+
+Windows
+
+- this section will be filled in in due course
+
+Linux
+
+- this section will be filled in in due course
+
+Documentation improvements
+
+- this section will be filled in in due course
+
+Possibly Breaking Changes
+
+- this section will be filled in in due course
+- MPEG-TS SCTE-35 API changes (FIXME: flesh out)
+- gst_parse_launch() and friends now error out on non-existing
+ properties on top-level bins where they would silently fail and
+ ignore those before.
+
+Known Issues
+
+- this section will be filled in in due course
+
+- There are a couple of known WebRTC-related regressions/blockers:
+
+ - webrtc: DTLS setup with Chrome is broken
+ - webrtcbin: First keyframe is usually lost
+
+Contributors
+
+- this section will be filled in in due course
+
+… and many others who have contributed bug reports, translations, sent
+suggestions or helped testing.
+
+Stable 1.20 branch
+
+After the 1.20.0 release there will be several 1.20.x bug-fix releases
+which will contain bug fixes which have been deemed suitable for a
+stable branch, but no new features or intrusive changes will be added to
+a bug-fix release usually. The 1.20.x bug-fix releases will be made from
+the git 1.20 branch, which will be a stable branch.
+
+1.20.0
+
+1.20.0 is scheduled to be released around October/November 2021.
+
+Schedule for 1.22
+
+Our next major feature release will be 1.22, and 1.21 will be the
+unstable development version leading up to the stable 1.22 release. The
+development of 1.21/1.22 will happen in the git main branch.
+
+The plan for the 1.22 development cycle is yet to be confirmed.
+
+1.22 will be backwards-compatible to the stable 1.20, 1.18, 1.16, 1.14,
+1.12, 1.10, 1.8, 1.6, 1.4, 1.2 and 1.0 release series.
+
+------------------------------------------------------------------------
+
+These release notes have been prepared by Tim-Philipp Müller with
+contributions from …
+
+License: CC BY-SA 4.0
diff --git a/subprojects/gst-omx/README b/subprojects/gst-omx/README
new file mode 100644
index 0000000000..6e94c384c2
--- /dev/null
+++ b/subprojects/gst-omx/README
@@ -0,0 +1,17 @@
+GStreamer OpenMAX IL wrapper plugin
+--------------------------
+
+ This plugin wraps available OpenMAX IL components and makes
+ them available as standard GStreamer elements.
+
+License:
+--------
+
+ This package and its contents are licensend under the GNU Lesser General
+Public License (LGPL).
+
+Dependencies:
+-------------
+
+ * GStreamer core
+ * gst-plugins-base
diff --git a/subprojects/gst-omx/RELEASE b/subprojects/gst-omx/RELEASE
new file mode 100644
index 0000000000..8bc336771f
--- /dev/null
+++ b/subprojects/gst-omx/RELEASE
@@ -0,0 +1,96 @@
+This is GStreamer gst-omx 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
diff --git a/subprojects/gst-omx/config/bellagio/gstomx.conf b/subprojects/gst-omx/config/bellagio/gstomx.conf
new file mode 100644
index 0000000000..0e856bea86
--- /dev/null
+++ b/subprojects/gst-omx/config/bellagio/gstomx.conf
@@ -0,0 +1,60 @@
+[omxmpeg4videodec]
+type-name=GstOMXMPEG4VideoDec
+core-name=/usr/local/lib/libomxil-bellagio.so.0
+component-name=OMX.st.video_decoder.mpeg4
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1
+
+[omxh264dec]
+type-name=GstOMXH264Dec
+core-name=/usr/local/lib/libomxil-bellagio.so.0
+component-name=OMX.st.video_decoder.avc
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1
+
+[omxmpeg4videoenc]
+type-name=GstOMXMPEG4VideoEnc
+core-name=/usr/local/lib/libomxil-bellagio.so.0
+component-name=OMX.st.video_encoder.mpeg4
+rank=0
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used
+
+[omxaacenc]
+type-name=GstOMXAACEnc
+core-name=/usr/local/lib/libomxil-bellagio.so.0
+component-name=OMX.st.audio_encoder.aac
+rank=0
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap
+
+[omxmp3dec]
+type-name=GstOMXMP3Dec
+core-name=/usr/lib/libomxil-bellagio.so.0
+component-name=OMX.st.audio_decoder.mp3.mad
+rank=0
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;no-component-role;no-disable-outport;drain-may-not-return
+
+[omxh264dec]
+type-name=GstOMXH264Dec
+core-name=/usr/lib/libomxil-bellagio.so.0
+component-name=OMX.mesa.video_decoder.avc
+rank=0
+in-port-index=0
+out-port-index=1
+
+[omxmpeg2dec]
+type-name=GstOMXMPEG2VideoDec
+core-name=/usr/lib/libomxil-bellagio.so.0
+component-name=OMX.mesa.video_decoder.mpeg2
+rank=0
+in-port-index=0
+out-port-index=1
diff --git a/subprojects/gst-omx/config/bellagio/meson.build b/subprojects/gst-omx/config/bellagio/meson.build
new file mode 100644
index 0000000000..dc99c08bc1
--- /dev/null
+++ b/subprojects/gst-omx/config/bellagio/meson.build
@@ -0,0 +1 @@
+install_data (['gstomx.conf'], install_dir : omx_conf_dir)
diff --git a/subprojects/gst-omx/config/meson.build b/subprojects/gst-omx/config/meson.build
new file mode 100644
index 0000000000..1068c6d9c6
--- /dev/null
+++ b/subprojects/gst-omx/config/meson.build
@@ -0,0 +1,20 @@
+if omx_target == 'rpi'
+ sub = 'rpi'
+elif omx_target == 'bellagio'
+ sub = 'bellagio'
+elif omx_target == 'zynqultrascaleplus'
+ sub = 'zynqultrascaleplus'
+elif omx_target == 'tizonia'
+ sub = 'tizonia'
+else
+ # No config file defined for the 'generic' target
+ sub = ''
+endif
+
+if sub != ''
+ subdir (sub)
+ # Used by tests to load the proper conf file
+ omx_config_dir = join_paths (meson.current_source_dir(), sub)
+else
+ omx_config_dir = ''
+endif
diff --git a/subprojects/gst-omx/config/rpi/gstomx.conf b/subprojects/gst-omx/config/rpi/gstomx.conf
new file mode 100644
index 0000000000..d3ea56a883
--- /dev/null
+++ b/subprojects/gst-omx/config/rpi/gstomx.conf
@@ -0,0 +1,102 @@
+[omxmpeg2videodec]
+type-name=GstOMXMPEG2VideoDec
+core-name=/opt/vc/lib/libopenmaxil.so
+component-name=OMX.broadcom.video_decode
+rank=257
+in-port-index=130
+out-port-index=131
+hacks=no-component-role
+
+[omxmpeg4videodec]
+type-name=GstOMXMPEG4VideoDec
+core-name=/opt/vc/lib/libopenmaxil.so
+component-name=OMX.broadcom.video_decode
+rank=257
+in-port-index=130
+out-port-index=131
+hacks=no-component-role
+
+[omxh263dec]
+type-name=GstOMXH263Dec
+core-name=/opt/vc/lib/libopenmaxil.so
+component-name=OMX.broadcom.video_decode
+rank=257
+in-port-index=130
+out-port-index=131
+hacks=no-component-role
+
+[omxh264dec]
+type-name=GstOMXH264Dec
+core-name=/opt/vc/lib/libopenmaxil.so
+component-name=OMX.broadcom.video_decode
+rank=257
+in-port-index=130
+out-port-index=131
+hacks=no-component-role;signals-premature-eos
+
+[omxtheoradec]
+type-name=GstOMXTheoraDec
+core-name=/opt/vc/lib/libopenmaxil.so
+component-name=OMX.broadcom.video_decode
+rank=257
+in-port-index=130
+out-port-index=131
+hacks=no-component-role
+
+[omxvp8dec]
+type-name=GstOMXVP8Dec
+core-name=/opt/vc/lib/libopenmaxil.so
+component-name=OMX.broadcom.video_decode
+rank=257
+in-port-index=130
+out-port-index=131
+hacks=no-component-role
+
+[omxmjpegdec]
+type-name=GstOMXMJPEGDec
+core-name=/opt/vc/lib/libopenmaxil.so
+component-name=OMX.broadcom.video_decode
+rank=257
+in-port-index=130
+out-port-index=131
+hacks=no-component-role
+
+[omxvc1dec]
+type-name=GstOMXWMVDec
+core-name=/opt/vc/lib/libopenmaxil.so
+component-name=OMX.broadcom.video_decode
+rank=257
+in-port-index=130
+out-port-index=131
+hacks=no-component-role
+sink-template-caps=video/x-wmv,wmvversion=(int)3,format=(string){WMV3,WVC1},width=(int)[1,MAX],height=(int)[1,MAX]
+
+[omxh264enc]
+type-name=GstOMXH264Enc
+core-name=/opt/vc/lib/libopenmaxil.so
+component-name=OMX.broadcom.video_encode
+rank=257
+in-port-index=200
+out-port-index=201
+hacks=no-component-role;no-component-reconfigure
+
+[omxanalogaudiosink]
+type-name=GstOMXAnalogAudioSink
+core-name=/opt/vc/lib/libopenmaxil.so
+component-name=OMX.broadcom.audio_render
+rank=257
+in-port-index=100
+out-port-index=101
+hacks=no-component-role
+sink-template-caps=audio/x-raw,format=(string){S16LE,S32LE},layout=(string)interleaved,rate=(int){8000,11025,16000,22050,24000,32000,44100,48000,88200,96000,176400,192000},channels=(int)[1,2]
+
+[omxhdmiaudiosink]
+type-name=GstOMXHdmiAudioSink
+core-name=/opt/vc/lib/libopenmaxil.so
+component-name=OMX.broadcom.audio_render
+rank=258
+in-port-index=100
+out-port-index=101
+hacks=no-component-role
+sink-template-caps=audio/x-raw,format=(string){S16LE,S32LE},layout=(string)interleaved,rate=(int){8000,11025,16000,22050,24000,32000,44100,48000,88200,96000,176400,192000},channels=(int)[1,8];audio/x-ac3,framed=(boolean)true;audio/x-dts,framed=(boolean)true,block-size=(int){512,1024,2048}
+
diff --git a/subprojects/gst-omx/config/rpi/meson.build b/subprojects/gst-omx/config/rpi/meson.build
new file mode 100644
index 0000000000..dc99c08bc1
--- /dev/null
+++ b/subprojects/gst-omx/config/rpi/meson.build
@@ -0,0 +1 @@
+install_data (['gstomx.conf'], install_dir : omx_conf_dir)
diff --git a/subprojects/gst-omx/config/tizonia/gstomx.conf.in b/subprojects/gst-omx/config/tizonia/gstomx.conf.in
new file mode 100644
index 0000000000..4f7fb2b74e
--- /dev/null
+++ b/subprojects/gst-omx/config/tizonia/gstomx.conf.in
@@ -0,0 +1,49 @@
+[omxmp3dec]
+type-name=GstOMXMP3Dec
+core-name=@TIZONIA_LIBDIR@/libtizcore.so
+component-name=OMX.Aratelia.audio_decoder.mp3
+rank=0
+in-port-index=0
+out-port-index=1
+
+[omxmp3enc]
+type-name=GstOMXMP3Enc
+core-name=@TIZONIA_LIBDIR@/libtizcore.so
+component-name=OMX.Aratelia.audio_encoder.mp3
+rank=0
+in-port-index=0
+out-port-index=1
+
+[omxaacdec]
+type-name=GstOMXAACDec
+core-name=@TIZONIA_LIBDIR@/libtizcore.so
+component-name=OMX.Aratelia.audio_decoder.aac
+rank=0
+in-port-index=0
+out-port-index=1
+
+[omxvp8dec]
+type-name=GstOMXVP8Dec
+core-name=@TIZONIA_LIBDIR@/libtizcore.so
+component-name=OMX.Aratelia.video_decoder.vp8
+rank=0
+in-port-index=0
+out-port-index=1
+
+[omxh264dec]
+type-name=GstOMXH264Dec
+core-name=@TIZONIA_LIBDIR@/libtizcore.so
+component-name=OMX.mesa.video.all
+component-role=video_decoder.avc
+rank=0
+in-port-index=0
+out-port-index=1
+
+[omxh264enc]
+type-name=GstOMXH264Enc
+core-name=@TIZONIA_LIBDIR@/libtizcore.so
+component-name=OMX.mesa.video.all
+component-role=video_encoder.avc
+rank=0
+in-port-index=0
+out-port-index=1
diff --git a/subprojects/gst-omx/config/tizonia/meson.build b/subprojects/gst-omx/config/tizonia/meson.build
new file mode 100644
index 0000000000..86b191db79
--- /dev/null
+++ b/subprojects/gst-omx/config/tizonia/meson.build
@@ -0,0 +1,5 @@
+tizonia_cdata = cdata
+configure_file(input : 'gstomx.conf.in',
+ output : 'gstomx.conf',
+ configuration : tizonia_cdata,
+ install_dir : omx_conf_dir)
diff --git a/subprojects/gst-omx/config/zynqultrascaleplus/gstomx.conf b/subprojects/gst-omx/config/zynqultrascaleplus/gstomx.conf
new file mode 100644
index 0000000000..ca6f4412f0
--- /dev/null
+++ b/subprojects/gst-omx/config/zynqultrascaleplus/gstomx.conf
@@ -0,0 +1,35 @@
+[omxh264enc]
+type-name=GstOMXH264Enc
+core-name=/usr/lib/libOMX.allegro.core.so.1
+component-name=OMX.allegro.h264.encoder
+in-port-index=0
+out-port-index=1
+rank=257
+hacks=ensure-buffer-count-actual
+
+[omxh264dec]
+type-name=GstOMXH264Dec
+core-name=/usr/lib/libOMX.allegro.core.so.1
+component-name=OMX.allegro.h264.decoder
+in-port-index=0
+out-port-index=1
+rank=257
+hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual
+
+[omxh265enc]
+type-name=GstOMXH265Enc
+core-name=/usr/lib/libOMX.allegro.core.so.1
+component-name=OMX.allegro.h265.encoder
+in-port-index=0
+out-port-index=1
+rank=257
+hacks=ensure-buffer-count-actual
+
+[omxh265dec]
+type-name=GstOMXH265Dec
+core-name=/usr/lib/libOMX.allegro.core.so.1
+component-name=OMX.allegro.h265.decoder
+in-port-index=0
+out-port-index=1
+rank=257
+hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual
diff --git a/subprojects/gst-omx/config/zynqultrascaleplus/meson.build b/subprojects/gst-omx/config/zynqultrascaleplus/meson.build
new file mode 100644
index 0000000000..dc99c08bc1
--- /dev/null
+++ b/subprojects/gst-omx/config/zynqultrascaleplus/meson.build
@@ -0,0 +1 @@
+install_data (['gstomx.conf'], install_dir : omx_conf_dir)
diff --git a/subprojects/gst-omx/docs/gst_plugins_cache.json b/subprojects/gst-omx/docs/gst_plugins_cache.json
new file mode 100644
index 0000000000..2fa2156c4c
--- /dev/null
+++ b/subprojects/gst-omx/docs/gst_plugins_cache.json
@@ -0,0 +1,13 @@
+{
+ "omx": {
+ "description": "GStreamer OpenMAX Plug-ins",
+ "elements": {},
+ "filename": "gstomx",
+ "license": "LGPL",
+ "other-types": {},
+ "package": "GStreamer OpenMAX Plug-ins",
+ "source": "gst-omx",
+ "tracers": {},
+ "url": "Unknown package origin"
+ }
+} \ No newline at end of file
diff --git a/subprojects/gst-omx/docs/index.md b/subprojects/gst-omx/docs/index.md
new file mode 100644
index 0000000000..b5d574b93f
--- /dev/null
+++ b/subprojects/gst-omx/docs/index.md
@@ -0,0 +1,3 @@
+---
+short-description: GStreamer plugins from OpenMax
+... \ No newline at end of file
diff --git a/subprojects/gst-omx/docs/meson.build b/subprojects/gst-omx/docs/meson.build
new file mode 100644
index 0000000000..908b4cfb75
--- /dev/null
+++ b/subprojects/gst-omx/docs/meson.build
@@ -0,0 +1,62 @@
+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 the docmentation while cross building is not supported yet.')
+ subdir_done()
+endif
+
+required_hotdoc_extensions = ['gst-extension']
+if gst_dep.type_name() == 'internal'
+ gst_proj = subproject('gstreamer')
+ plugins_cache_generator = gst_proj.get_variable('plugins_cache_generator')
+else
+ required_hotdoc_extensions += ['gst-extension']
+ 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('omx-plugins-doc-cache',
+ command: [plugins_cache_generator, plugins_cache, '@OUTPUT@', '@INPUT@'],
+ input: plugins,
+ output: 'gst_plugins_cache.json',
+ )
+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
+
+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('omx',
+ 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: 'omx',
+ dependencies: [gstomx],
+)]
diff --git a/subprojects/gst-omx/docs/sitemap.txt b/subprojects/gst-omx/docs/sitemap.txt
new file mode 100644
index 0000000000..058a2713a4
--- /dev/null
+++ b/subprojects/gst-omx/docs/sitemap.txt
@@ -0,0 +1 @@
+gst-index
diff --git a/subprojects/gst-omx/examples/egl/cube_texture_and_coords.h b/subprojects/gst-omx/examples/egl/cube_texture_and_coords.h
new file mode 100644
index 0000000000..1832df3e9f
--- /dev/null
+++ b/subprojects/gst-omx/examples/egl/cube_texture_and_coords.h
@@ -0,0 +1,100 @@
+/*
+Copyright (c) 2012, Broadcom Europe Ltd
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the copyright holder nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// Spatial coordinates for the cube
+
+static const GLfloat quadx[6*4*3] = {
+ /* FRONT */
+ -1.f, -1.f, 1.f,
+ 1.f, -1.f, 1.f,
+ -1.f, 1.f, 1.f,
+ 1.f, 1.f, 1.f,
+
+ /* BACK */
+ -1.f, -1.f, -1.f,
+ -1.f, 1.f, -1.f,
+ 1.f, -1.f, -1.f,
+ 1.f, 1.f, -1.f,
+
+ /* LEFT */
+ -1.f, -1.f, 1.f,
+ -1.f, 1.f, 1.f,
+ -1.f, -1.f, -1.f,
+ -1.f, 1.f, -1.f,
+
+ /* RIGHT */
+ 1.f, -1.f, -1.f,
+ 1.f, 1.f, -1.f,
+ 1.f, -1.f, 1.f,
+ 1.f, 1.f, 1.f,
+
+ /* TOP */
+ -1.f, 1.f, 1.f,
+ 1.f, 1.f, 1.f,
+ -1.f, 1.f, -1.f,
+ 1.f, 1.f, -1.f,
+
+ /* BOTTOM */
+ -1.f, -1.f, 1.f,
+ -1.f, -1.f, -1.f,
+ 1.f, -1.f, 1.f,
+ 1.f, -1.f, -1.f,
+};
+
+/** Texture coordinates for the quad. */
+static const GLfloat texCoords[6 * 4 * 2] = {
+ 0.f, 0.f,
+ 1.f, 0.f,
+ 0.f, 1.f,
+ 1.f, 1.f,
+
+ 0.f, 0.f,
+ 1.f, 0.f,
+ 0.f, 1.f,
+ 1.f, 1.f,
+
+ 0.f, 0.f,
+ 1.f, 0.f,
+ 0.f, 1.f,
+ 1.f, 1.f,
+
+ 0.f, 0.f,
+ 1.f, 0.f,
+ 0.f, 1.f,
+ 1.f, 1.f,
+
+ 0.f, 0.f,
+ 1.f, 0.f,
+ 0.f, 1.f,
+ 1.f, 1.f,
+
+ 0.f, 0.f,
+ 1.f, 0.f,
+ 0.f, 1.f,
+ 1.f, 1.f,
+};
+
diff --git a/subprojects/gst-omx/examples/egl/meson.build b/subprojects/gst-omx/examples/egl/meson.build
new file mode 100644
index 0000000000..5ba6fc43ea
--- /dev/null
+++ b/subprojects/gst-omx/examples/egl/meson.build
@@ -0,0 +1,31 @@
+optional_deps = []
+if x11_dep.found()
+ optional_deps += x11_dep
+endif
+
+if x11_dep.found() or omx_target == 'rpi'
+ egl_sources = ['testegl.c']
+
+ egl_dep = dependency('egl', required : false)
+ if not egl_dep.found()
+ egl_dep = cc.find_library ('EGL')
+ endif
+
+ gles2_dep = dependency('glesv2', required : false)
+ if not gles2_dep.found()
+ gles2_dep = cc.find_library ('GLESv2')
+ endif
+
+ if omx_target == 'rpi'
+ brcmegl_dep = dependency('brcmegl', required : true)
+ optional_deps += brcmegl_dep
+ endif
+
+ executable ('testegl',
+ sources : egl_sources,
+ c_args : gst_omx_args,
+ include_directories : [configinc],
+ dependencies : [libm, gst_dep, gstvideo_dep, gstgl_dep, egl_dep,
+ gles2_dep] + optional_deps
+ )
+endif
diff --git a/subprojects/gst-omx/examples/egl/testegl.c b/subprojects/gst-omx/examples/egl/testegl.c
new file mode 100644
index 0000000000..b7e77450e8
--- /dev/null
+++ b/subprojects/gst-omx/examples/egl/testegl.c
@@ -0,0 +1,1611 @@
+/*
+Copyright (c) 2012, Broadcom Europe Ltd
+Copyright (c) 2012, OtherCrashOverride
+Copyright (C) 2013, Fluendo S.A.
+ @author: Josep Torra <josep@fluendo.com>
+Copyright (C) 2013, Video Experts Group LLC.
+ @author: Ilya Smelykh <ilya@videoexpertsgroup.com>
+Copyright (C) 2014 Julien Isorce <julien.isorce@collabora.co.uk>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the copyright holder nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* A rotating cube rendered with OpenGL|ES and video played using GStreamer on
+ * the cube faces.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined (USE_OMX_TARGET_RPI) && defined (__GNUC__)
+#ifndef __VCCOREVER__
+#define __VCCOREVER__ 0x04000000
+#endif
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+#pragma GCC optimize ("gnu89-inline")
+#endif
+
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include <unistd.h>
+
+#include <gst/gst.h>
+
+#define GST_USE_UNSTABLE_API
+#include <gst/gl/gl.h>
+#include <gst/gl/egl/gstgldisplay_egl.h>
+
+#if defined (USE_OMX_TARGET_RPI)
+#include <bcm_host.h>
+#include <EGL/eglext.h>
+#elif defined(HAVE_X11)
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#endif
+
+#if defined (USE_OMX_TARGET_RPI) && defined (__GNUC__)
+#pragma GCC reset_options
+#pragma GCC diagnostic pop
+#endif
+
+#include "cube_texture_and_coords.h"
+
+#ifndef M_PI
+#define M_PI 3.141592654
+#endif
+
+#define SYNC_BUFFERS TRUE
+
+#define TRACE_VC_MEMORY_ENABLED 0
+
+#if defined (USE_OMX_TARGET_RPI) && TRACE_VC_MEMORY_ENABLED
+#define TRACE_VC_MEMORY(str) \
+ fprintf (stderr, "\n\n" str "\n"); \
+ system ("vcdbg reloc >&2")
+
+#define TRACE_VC_MEMORY_DEFINE_ID(id) \
+ static int id = 0
+
+#define TRACE_VC_MEMORY_RESET_ID(id) \
+ G_STMT_START { \
+ id = 0; \
+ } G_STMT_END
+
+#define TRACE_VC_MEMORY_ONCE_FOR_ID(str,id) \
+ G_STMT_START { \
+ if (id == 0) { \
+ fprintf (stderr, "\n\n" str "\n"); \
+ system ("vcdbg reloc >&2"); \
+ id = 1; \
+ } \
+ } G_STMT_END
+
+#define TRACE_VC_MEMORY_ONCE(str,id) \
+ G_STMT_START { \
+ static int id = 0; \
+ if (id == 0) { \
+ fprintf (stderr, "\n\n" str "\n"); \
+ system ("vcdbg reloc >&2"); \
+ id = 1; \
+ } \
+ } G_STMT_END
+
+#else
+#define TRACE_VC_MEMORY(str) while(0)
+#define TRACE_VC_MEMORY_DEFINE_ID(id)
+#define TRACE_VC_MEMORY_RESET_ID(id) while(0)
+#define TRACE_VC_MEMORY_ONCE_FOR_ID(str,id) while(0)
+#define TRACE_VC_MEMORY_ONCE(str,id) while(0)
+#endif
+
+/* some helpers that we should provide in libgstgl */
+
+typedef struct
+{
+ GLfloat m[4][4];
+} GstGLMatrix;
+
+static void
+gst_gl_matrix_load_identity (GstGLMatrix * matrix)
+{
+ memset (matrix, 0x0, sizeof (GstGLMatrix));
+ matrix->m[0][0] = 1.0f;
+ matrix->m[1][1] = 1.0f;
+ matrix->m[2][2] = 1.0f;
+ matrix->m[3][3] = 1.0f;
+}
+
+static void
+gst_gl_matrix_multiply (GstGLMatrix * matrix, GstGLMatrix * srcA,
+ GstGLMatrix * srcB)
+{
+ GstGLMatrix tmp;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ tmp.m[i][0] = (srcA->m[i][0] * srcB->m[0][0]) +
+ (srcA->m[i][1] * srcB->m[1][0]) +
+ (srcA->m[i][2] * srcB->m[2][0]) + (srcA->m[i][3] * srcB->m[3][0]);
+
+ tmp.m[i][1] = (srcA->m[i][0] * srcB->m[0][1]) +
+ (srcA->m[i][1] * srcB->m[1][1]) +
+ (srcA->m[i][2] * srcB->m[2][1]) + (srcA->m[i][3] * srcB->m[3][1]);
+
+ tmp.m[i][2] = (srcA->m[i][0] * srcB->m[0][2]) +
+ (srcA->m[i][1] * srcB->m[1][2]) +
+ (srcA->m[i][2] * srcB->m[2][2]) + (srcA->m[i][3] * srcB->m[3][2]);
+
+ tmp.m[i][3] = (srcA->m[i][0] * srcB->m[0][3]) +
+ (srcA->m[i][1] * srcB->m[1][3]) +
+ (srcA->m[i][2] * srcB->m[2][3]) + (srcA->m[i][3] * srcB->m[3][3]);
+ }
+
+ memcpy (matrix, &tmp, sizeof (GstGLMatrix));
+}
+
+static void
+gst_gl_matrix_translate (GstGLMatrix * matrix, GLfloat tx, GLfloat ty,
+ GLfloat tz)
+{
+ matrix->m[3][0] +=
+ (matrix->m[0][0] * tx + matrix->m[1][0] * ty + matrix->m[2][0] * tz);
+ matrix->m[3][1] +=
+ (matrix->m[0][1] * tx + matrix->m[1][1] * ty + matrix->m[2][1] * tz);
+ matrix->m[3][2] +=
+ (matrix->m[0][2] * tx + matrix->m[1][2] * ty + matrix->m[2][2] * tz);
+ matrix->m[3][3] +=
+ (matrix->m[0][3] * tx + matrix->m[1][3] * ty + matrix->m[2][3] * tz);
+}
+
+static void
+gst_gl_matrix_frustum (GstGLMatrix * matrix, GLfloat left, GLfloat right,
+ GLfloat bottom, GLfloat top, GLfloat nearZ, GLfloat farZ)
+{
+ GLfloat deltaX = right - left;
+ GLfloat deltaY = top - bottom;
+ GLfloat deltaZ = farZ - nearZ;
+ GstGLMatrix frust;
+
+ if ((nearZ <= 0.0f) || (farZ <= 0.0f) ||
+ (deltaX <= 0.0f) || (deltaY <= 0.0f) || (deltaZ <= 0.0f))
+ return;
+
+ frust.m[0][0] = 2.0f * nearZ / deltaX;
+ frust.m[0][1] = frust.m[0][2] = frust.m[0][3] = 0.0f;
+
+ frust.m[1][1] = 2.0f * nearZ / deltaY;
+ frust.m[1][0] = frust.m[1][2] = frust.m[1][3] = 0.0f;
+
+ frust.m[2][0] = (right + left) / deltaX;
+ frust.m[2][1] = (top + bottom) / deltaY;
+ frust.m[2][2] = -(nearZ + farZ) / deltaZ;
+ frust.m[2][3] = -1.0f;
+
+ frust.m[3][2] = -2.0f * nearZ * farZ / deltaZ;
+ frust.m[3][0] = frust.m[3][1] = frust.m[3][3] = 0.0f;
+
+ gst_gl_matrix_multiply (matrix, &frust, matrix);
+}
+
+static void
+gst_gl_matrix_perspective (GstGLMatrix * matrix, GLfloat fovy, GLfloat aspect,
+ GLfloat nearZ, GLfloat farZ)
+{
+ GLfloat frustumW, frustumH;
+
+ frustumH = tanf (fovy / 360.0f * M_PI) * nearZ;
+ frustumW = frustumH * aspect;
+
+ gst_gl_matrix_frustum (matrix, -frustumW, frustumW, -frustumH, frustumH,
+ nearZ, farZ);
+}
+
+/* *INDENT-OFF* */
+
+/* vertex source */
+static const gchar *cube_v_src =
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "uniform float u_rotx; \n"
+ "uniform float u_roty; \n"
+ "uniform float u_rotz; \n"
+ "uniform mat4 u_modelview; \n"
+ "uniform mat4 u_projection; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " float PI = 3.14159265; \n"
+ " float xrot = u_rotx*2.0*PI/360.0; \n"
+ " float yrot = u_roty*2.0*PI/360.0; \n"
+ " float zrot = u_rotz*2.0*PI/360.0; \n"
+ " mat4 matX = mat4 ( \n"
+ " 1.0, 0.0, 0.0, 0.0, \n"
+ " 0.0, cos(xrot), sin(xrot), 0.0, \n"
+ " 0.0, -sin(xrot), cos(xrot), 0.0, \n"
+ " 0.0, 0.0, 0.0, 1.0 ); \n"
+ " mat4 matY = mat4 ( \n"
+ " cos(yrot), 0.0, -sin(yrot), 0.0, \n"
+ " 0.0, 1.0, 0.0, 0.0, \n"
+ " sin(yrot), 0.0, cos(yrot), 0.0, \n"
+ " 0.0, 0.0, 0.0, 1.0 ); \n"
+ " mat4 matZ = mat4 ( \n"
+ " cos(zrot), sin(zrot), 0.0, 0.0, \n"
+ " -sin(zrot), cos(zrot), 0.0, 0.0, \n"
+ " 0.0, 0.0, 1.0, 0.0, \n"
+ " 0.0, 0.0, 0.0, 1.0 ); \n"
+ " gl_Position = u_projection * u_modelview * matZ * matY * matX * a_position;\n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
+/* fragment source */
+static const gchar *cube_f_src =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = texture2D (s_texture, v_texCoord); \n"
+ "} \n";
+/* *INDENT-ON* */
+
+typedef struct
+{
+#if defined (USE_OMX_TARGET_RPI)
+ DISPMANX_DISPLAY_HANDLE_T dispman_display;
+ DISPMANX_ELEMENT_HANDLE_T dispman_element;
+#endif
+
+ uint32_t screen_width;
+ uint32_t screen_height;
+ gboolean animate;
+
+ GstCaps *caps;
+
+ /* OpenGL|ES objects */
+ EGLDisplay display;
+ EGLSurface surface;
+ EGLContext context;
+ GLuint tex;
+
+ GLint vshader;
+ GLint fshader;
+ GLint program;
+
+ GLint u_modelviewmatrix;
+ GLint u_projectionmatrix;
+ GLint s_texture;
+ GLint u_rotx;
+ GLint u_roty;
+ GLint u_rotz;
+
+ GstGLMatrix modelview;
+ GstGLMatrix projection;
+ GLfloat fov;
+ GLfloat aspect;
+
+ /* model rotation vector and direction */
+ GLfloat rot_angle_x_inc;
+ GLfloat rot_angle_y_inc;
+ GLfloat rot_angle_z_inc;
+
+ /* current model rotation angles */
+ GLfloat rot_angle_x;
+ GLfloat rot_angle_y;
+ GLfloat rot_angle_z;
+
+ /* current distance from camera */
+ GLfloat distance;
+ GLfloat distance_inc;
+
+ /* GStreamer related resources */
+ GstElement *pipeline;
+ GstElement *vsink;
+ GstGLDisplayEGL *gst_display;
+ GstGLContext *gl_context;
+ gboolean can_avoid_upload;
+
+ /* Interthread comunication */
+ GAsyncQueue *queue;
+ GMutex queue_lock;
+ GCond cond;
+ gboolean flushing;
+ GstMiniObject *popped_obj;
+ GstBuffer *current_buffer;
+
+ /* GLib mainloop */
+ GMainLoop *main_loop;
+ GstBuffer *last_buffer;
+
+ /* Rendering thread state */
+ gboolean running;
+
+ /* number of rendered and dropped frames */
+ guint64 rendered;
+ guint64 dropped;
+
+#if !defined (USE_OMX_TARGET_RPI) && defined(HAVE_X11)
+ Display *xdisplay;
+ Window xwindow;
+#endif
+} APP_STATE_T;
+
+static void init_ogl (APP_STATE_T * state);
+static void init_model_proj (APP_STATE_T * state);
+static void reset_model (APP_STATE_T * state);
+static GLfloat inc_and_wrap_angle (GLfloat angle, GLfloat angle_inc);
+static void redraw_scene (APP_STATE_T * state);
+static void update_model (APP_STATE_T * state);
+static void init_textures (APP_STATE_T * state, GstBuffer * buffer);
+static APP_STATE_T _state, *state = &_state;
+static gboolean queue_object (APP_STATE_T * state, GstMiniObject * obj,
+ gboolean synchronous);
+
+TRACE_VC_MEMORY_DEFINE_ID (gid0);
+TRACE_VC_MEMORY_DEFINE_ID (gid1);
+TRACE_VC_MEMORY_DEFINE_ID (gid2);
+
+typedef enum
+{
+ GST_PLAY_FLAG_VIDEO = (1 << 0),
+ GST_PLAY_FLAG_AUDIO = (1 << 1),
+ GST_PLAY_FLAG_TEXT = (1 << 2),
+ GST_PLAY_FLAG_VIS = (1 << 3),
+ GST_PLAY_FLAG_SOFT_VOLUME = (1 << 4),
+ GST_PLAY_FLAG_NATIVE_AUDIO = (1 << 5),
+ GST_PLAY_FLAG_NATIVE_VIDEO = (1 << 6),
+ GST_PLAY_FLAG_DOWNLOAD = (1 << 7),
+ GST_PLAY_FLAG_BUFFERING = (1 << 8),
+ GST_PLAY_FLAG_DEINTERLACE = (1 << 9),
+ GST_PLAY_FLAG_SOFT_COLORBALANCE = (1 << 10)
+} GstPlayFlags;
+
+/***********************************************************
+ * Name: init_ogl
+ *
+ * Arguments:
+ * APP_STATE_T *state - holds OGLES model info
+ *
+ * Description: Sets the display, OpenGL|ES context and screen stuff
+ *
+ * Returns: void
+ *
+ ***********************************************************/
+static void
+init_ogl (APP_STATE_T * state)
+{
+#if defined (USE_OMX_TARGET_RPI)
+ int32_t success = 0;
+#else
+ gint screen_num = 0;
+ gulong black_pixel = 0;
+#endif
+ EGLBoolean result;
+ EGLint num_config;
+ EGLNativeWindowType window_handle = (EGLNativeWindowType) 0;
+
+#if defined (USE_OMX_TARGET_RPI)
+ static EGL_DISPMANX_WINDOW_T nativewindow;
+
+ DISPMANX_UPDATE_HANDLE_T dispman_update;
+ VC_RECT_T dst_rect;
+ VC_RECT_T src_rect;
+
+ VC_DISPMANX_ALPHA_T alpha = { DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS, 255, 0 };
+#endif
+
+ static const EGLint attribute_list[] = {
+ EGL_DEPTH_SIZE, 16,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_NONE
+ };
+
+ static const EGLint context_attributes[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+
+ EGLConfig config;
+
+ /* get an EGL display connection */
+ state->display = eglGetDisplay (EGL_DEFAULT_DISPLAY);
+ assert (state->display != EGL_NO_DISPLAY);
+
+ /* initialize the EGL display connection */
+ result = eglInitialize (state->display, NULL, NULL);
+ assert (EGL_FALSE != result);
+
+#if defined (USE_OMX_TARGET_RPI)
+ /* get an appropriate EGL frame buffer configuration
+ * this uses a BRCM extension that gets the closest match, rather
+ * than standard which returns anything that matches. */
+ result =
+ eglSaneChooseConfigBRCM (state->display, attribute_list, &config, 1,
+ &num_config);
+ assert (EGL_FALSE != result);
+#else
+ result =
+ eglChooseConfig (state->display, attribute_list, &config, 1, &num_config);
+#endif
+
+ /* create an EGL rendering context */
+ state->context =
+ eglCreateContext (state->display, config, EGL_NO_CONTEXT,
+ context_attributes);
+ assert (state->context != EGL_NO_CONTEXT);
+
+#if defined (USE_OMX_TARGET_RPI)
+ /* create an EGL window surface */
+ success = graphics_get_display_size (0 /* LCD */ , &state->screen_width,
+ &state->screen_height);
+ assert (success >= 0);
+
+ dst_rect.x = 0;
+ dst_rect.y = 0;
+ dst_rect.width = state->screen_width;
+ dst_rect.height = state->screen_height;
+
+ src_rect.x = 0;
+ src_rect.y = 0;
+ src_rect.width = state->screen_width << 16;
+ src_rect.height = state->screen_height << 16;
+
+ state->dispman_display = vc_dispmanx_display_open (0 /* LCD */ );
+ dispman_update = vc_dispmanx_update_start (0);
+
+ state->dispman_element =
+ vc_dispmanx_element_add (dispman_update, state->dispman_display,
+ 0 /*layer */ , &dst_rect, 0 /*src */ ,
+ &src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0 /*clamp */ ,
+ 0 /*transform */ );
+
+ nativewindow.element = state->dispman_element;
+ nativewindow.width = state->screen_width;
+ nativewindow.height = state->screen_height;
+ vc_dispmanx_update_submit_sync (dispman_update);
+
+ window_handle = &nativewindow;
+#elif defined(HAVE_X11)
+ state->screen_width = 1280;
+ state->screen_height = 720;
+ state->xdisplay = XOpenDisplay (NULL);
+ screen_num = DefaultScreen (state->xdisplay);
+ black_pixel = XBlackPixel (state->xdisplay, screen_num);
+ state->xwindow = XCreateSimpleWindow (state->xdisplay,
+ DefaultRootWindow (state->xdisplay), 0, 0, state->screen_width,
+ state->screen_height, 0, 0, black_pixel);
+ XSetWindowBackgroundPixmap (state->xdisplay, state->xwindow, None);
+ XMapRaised (state->xdisplay, state->xwindow);
+ XSync (state->xdisplay, FALSE);
+ window_handle = state->xwindow;
+#endif
+
+ state->surface =
+ eglCreateWindowSurface (state->display, config, window_handle, NULL);
+ assert (state->surface != EGL_NO_SURFACE);
+
+ /* connect the context to the surface */
+ result =
+ eglMakeCurrent (state->display, state->surface, state->surface,
+ state->context);
+ assert (EGL_FALSE != result);
+
+ state->gst_display = gst_gl_display_egl_new_with_egl_display (state->display);
+ state->gl_context =
+ gst_gl_context_new_wrapped (GST_GL_DISPLAY (state->gst_display),
+ (guintptr) state->context, GST_GL_PLATFORM_EGL, GST_GL_API_GLES2);
+}
+
+/***********************************************************
+ * Name: init_model_proj
+ *
+ * Arguments:
+ * APP_STATE_T *state - holds OGLES model info
+ *
+ * Description: Sets the OpenGL|ES model to default values
+ *
+ * Returns: void
+ *
+ ***********************************************************/
+static void
+init_model_proj (APP_STATE_T * state)
+{
+ GLint ret = 0;
+
+ state->vshader = glCreateShader (GL_VERTEX_SHADER);
+
+ glShaderSource (state->vshader, 1, &cube_v_src, NULL);
+ glCompileShader (state->vshader);
+ assert (glGetError () == GL_NO_ERROR);
+
+ state->fshader = glCreateShader (GL_FRAGMENT_SHADER);
+
+ glShaderSource (state->fshader, 1, &cube_f_src, NULL);
+ glCompileShader (state->fshader);
+ assert (glGetError () == GL_NO_ERROR);
+
+ state->program = glCreateProgram ();
+
+ glAttachShader (state->program, state->vshader);
+ glAttachShader (state->program, state->fshader);
+
+ glBindAttribLocation (state->program, 0, "a_position");
+ glBindAttribLocation (state->program, 1, "a_texCoord");
+
+ glLinkProgram (state->program);
+
+ glGetProgramiv (state->program, GL_LINK_STATUS, &ret);
+ assert (ret == GL_TRUE);
+
+ glUseProgram (state->program);
+
+ state->u_rotx = glGetUniformLocation (state->program, "u_rotx");
+ state->u_roty = glGetUniformLocation (state->program, "u_roty");
+ state->u_rotz = glGetUniformLocation (state->program, "u_rotz");
+
+ state->u_modelviewmatrix =
+ glGetUniformLocation (state->program, "u_modelview");
+
+ state->u_projectionmatrix =
+ glGetUniformLocation (state->program, "u_projection");
+
+ state->s_texture = glGetUniformLocation (state->program, "s_texture");
+
+ glViewport (0, 0, (GLsizei) state->screen_width,
+ (GLsizei) state->screen_height);
+
+ state->fov = 45.0f;
+ state->distance = 5.0f;
+ state->aspect =
+ (GLfloat) state->screen_width / (GLfloat) state->screen_height;
+
+ gst_gl_matrix_load_identity (&state->projection);
+ gst_gl_matrix_perspective (&state->projection, state->fov, state->aspect,
+ 1.0f, 100.0f);
+
+ gst_gl_matrix_load_identity (&state->modelview);
+ gst_gl_matrix_translate (&state->modelview, 0.0f, 0.0f, -state->distance);
+
+ reset_model (state);
+}
+
+/***********************************************************
+ * Name: reset_model
+ *
+ * Arguments:
+ * APP_STATE_T *state - holds OGLES model info
+ *
+ * Description: Resets the Model projection and rotation direction
+ *
+ * Returns: void
+ *
+ ***********************************************************/
+static void
+reset_model (APP_STATE_T * state)
+{
+ /* reset model rotation */
+ state->rot_angle_x = 45.f;
+ state->rot_angle_y = 30.f;
+ state->rot_angle_z = 0.f;
+ state->rot_angle_x_inc = 0.5f;
+ state->rot_angle_y_inc = 0.5f;
+ state->rot_angle_z_inc = 0.f;
+}
+
+/***********************************************************
+ * Name: update_model
+ *
+ * Arguments:
+ * APP_STATE_T *state - holds OGLES model info
+ *
+ * Description: Updates model projection to current position/rotation
+ *
+ * Returns: void
+ *
+ ***********************************************************/
+static void
+update_model (APP_STATE_T * state)
+{
+ if (state->animate) {
+ /* update position */
+ state->rot_angle_x =
+ inc_and_wrap_angle (state->rot_angle_x, state->rot_angle_x_inc);
+ state->rot_angle_y =
+ inc_and_wrap_angle (state->rot_angle_y, state->rot_angle_y_inc);
+ state->rot_angle_z =
+ inc_and_wrap_angle (state->rot_angle_z, state->rot_angle_z_inc);
+ }
+}
+
+/***********************************************************
+ * Name: inc_and_wrap_angle
+ *
+ * Arguments:
+ * GLfloat angle current angle
+ * GLfloat angle_inc angle increment
+ *
+ * Description: Increments or decrements angle by angle_inc degrees
+ * Wraps to 0 at 360 deg.
+ *
+ * Returns: new value of angle
+ *
+ ***********************************************************/
+static GLfloat
+inc_and_wrap_angle (GLfloat angle, GLfloat angle_inc)
+{
+ angle += angle_inc;
+
+ if (angle >= 360.0)
+ angle -= 360.f;
+ else if (angle <= 0)
+ angle += 360.f;
+
+ return angle;
+}
+
+/***********************************************************
+ * Name: redraw_scene
+ *
+ * Arguments:
+ * APP_STATE_T *state - holds OGLES model info
+ *
+ * Description: Draws the model and calls eglSwapBuffers
+ * to render to screen
+ *
+ * Returns: void
+ *
+ ***********************************************************/
+static void
+redraw_scene (APP_STATE_T * state)
+{
+ glBindFramebuffer (GL_FRAMEBUFFER, 0);
+
+ glEnable (GL_CULL_FACE);
+ glEnable (GL_DEPTH_TEST);
+
+ /* Set background color and clear buffers */
+ glClearColor (0.15f, 0.25f, 0.35f, 1.0f);
+ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glUseProgram (state->program);
+
+ glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, quadx);
+ glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
+
+ glEnableVertexAttribArray (0);
+ glEnableVertexAttribArray (1);
+
+ glActiveTexture (GL_TEXTURE0);
+ glBindTexture (GL_TEXTURE_2D, state->tex);
+ glUniform1i (state->s_texture, 0);
+
+ glUniform1f (state->u_rotx, state->rot_angle_x);
+ glUniform1f (state->u_roty, state->rot_angle_y);
+ glUniform1f (state->u_rotz, state->rot_angle_z);
+
+ glUniformMatrix4fv (state->u_modelviewmatrix, 1, GL_FALSE,
+ &state->modelview.m[0][0]);
+
+ glUniformMatrix4fv (state->u_projectionmatrix, 1, GL_FALSE,
+ &state->projection.m[0][0]);
+
+ /* draw first 4 vertices */
+ glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
+ glDrawArrays (GL_TRIANGLE_STRIP, 4, 4);
+ glDrawArrays (GL_TRIANGLE_STRIP, 8, 4);
+ glDrawArrays (GL_TRIANGLE_STRIP, 12, 4);
+ glDrawArrays (GL_TRIANGLE_STRIP, 16, 4);
+ glDrawArrays (GL_TRIANGLE_STRIP, 20, 4);
+
+ if (!eglSwapBuffers (state->display, state->surface)) {
+ g_main_loop_quit (state->main_loop);
+ return;
+ }
+
+ glDisable (GL_DEPTH_TEST);
+ glDisable (GL_CULL_FACE);
+}
+
+/***********************************************************
+ * Name: init_textures
+ *
+ * Arguments:
+ * APP_STATE_T *state - holds OGLES model info
+ *
+ * Description: Initialise OGL|ES texture surfaces to use image
+ * buffers
+ *
+ * Returns: void
+ *
+ ***********************************************************/
+static void
+init_textures (APP_STATE_T * state, GstBuffer * buffer)
+{
+ GstCapsFeatures *feature = gst_caps_get_features (state->caps, 0);
+
+ if (gst_caps_features_contains (feature, "memory:GLMemory")) {
+ g_print ("Prepare texture for GLMemory\n");
+ state->can_avoid_upload = TRUE;
+ state->tex = 0;
+ } else if (gst_caps_features_contains (feature,
+ "meta:GstVideoGLTextureUploadMeta")) {
+ GstVideoMeta *meta = NULL;
+ guint internal_format =
+ gst_gl_sized_gl_format_from_gl_format_type (state->gl_context,
+ GL_RGBA, GL_UNSIGNED_BYTE);
+
+ g_print ("Prepare texture for GstVideoGLTextureUploadMeta\n");
+ meta = gst_buffer_get_video_meta (buffer);
+ state->can_avoid_upload = FALSE;
+ glGenTextures (1, &state->tex);
+ glBindTexture (GL_TEXTURE_2D, state->tex);
+ glTexImage2D (GL_TEXTURE_2D, 0, internal_format, meta->width, meta->height,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ } else {
+ g_assert_not_reached ();
+ }
+
+#if 0
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+#else
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+#endif
+
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ assert (glGetError () == GL_NO_ERROR);
+}
+
+static void
+render_scene (APP_STATE_T * state)
+{
+ update_model (state);
+ redraw_scene (state);
+ TRACE_VC_MEMORY_ONCE_FOR_ID ("after render_scene", gid2);
+}
+
+static void
+update_image (APP_STATE_T * state, GstBuffer * buffer)
+{
+ GstVideoGLTextureUploadMeta *meta = NULL;
+
+ if (state->current_buffer) {
+ gst_buffer_unref (state->current_buffer);
+ } else {
+ /* Setup the model world */
+ init_model_proj (state);
+ TRACE_VC_MEMORY ("after init_model_proj");
+
+ /* initialize the OGLES texture(s) */
+ init_textures (state, buffer);
+ TRACE_VC_MEMORY ("after init_textures");
+ }
+ state->current_buffer = gst_buffer_ref (buffer);
+
+ TRACE_VC_MEMORY_ONCE_FOR_ID ("before GstVideoGLTextureUploadMeta", gid0);
+
+ if (state->can_avoid_upload) {
+ GstMemory *mem = gst_buffer_peek_memory (state->current_buffer, 0);
+ g_assert (gst_is_gl_memory (mem));
+ state->tex = ((GstGLMemory *) mem)->tex_id;
+ } else if ((meta = gst_buffer_get_video_gl_texture_upload_meta (buffer))) {
+ if (meta->n_textures == 1) {
+ guint ids[4] = { state->tex, 0, 0, 0 };
+ if (!gst_video_gl_texture_upload_meta_upload (meta, ids)) {
+ GST_WARNING ("failed to upload to texture");
+ }
+ }
+ }
+
+ TRACE_VC_MEMORY_ONCE_FOR_ID ("after GstVideoGLTextureUploadMeta", gid1);
+}
+
+static void
+init_intercom (APP_STATE_T * state)
+{
+ state->queue =
+ g_async_queue_new_full ((GDestroyNotify) gst_mini_object_unref);
+ g_mutex_init (&state->queue_lock);
+ g_cond_init (&state->cond);
+}
+
+static void
+terminate_intercom (APP_STATE_T * state)
+{
+ /* Release intercom */
+ if (state->queue) {
+ g_async_queue_unref (state->queue);
+ }
+
+ g_mutex_clear (&state->queue_lock);
+ g_cond_clear (&state->cond);
+}
+
+static void
+flush_internal (APP_STATE_T * state)
+{
+ if (state->current_buffer) {
+ gst_buffer_unref (state->current_buffer);
+ }
+ state->current_buffer = NULL;
+}
+
+static void
+flush_start (APP_STATE_T * state)
+{
+ GstMiniObject *object = NULL;
+
+ g_mutex_lock (&state->queue_lock);
+ state->flushing = TRUE;
+ g_cond_broadcast (&state->cond);
+ g_mutex_unlock (&state->queue_lock);
+
+ while ((object = g_async_queue_try_pop (state->queue))) {
+ gst_mini_object_unref (object);
+ }
+ g_mutex_lock (&state->queue_lock);
+ flush_internal (state);
+ state->popped_obj = NULL;
+ g_mutex_unlock (&state->queue_lock);
+}
+
+static void
+flush_stop (APP_STATE_T * state)
+{
+ GstMiniObject *object = NULL;
+
+ g_mutex_lock (&state->queue_lock);
+ while ((object = GST_MINI_OBJECT_CAST (g_async_queue_try_pop (state->queue)))) {
+ gst_mini_object_unref (object);
+ }
+ flush_internal (state);
+ state->popped_obj = NULL;
+ state->flushing = FALSE;
+ g_mutex_unlock (&state->queue_lock);
+}
+
+static void
+pipeline_pause (APP_STATE_T * state)
+{
+ gst_element_set_state (state->pipeline, GST_STATE_PAUSED);
+}
+
+static void
+pipeline_play (APP_STATE_T * state)
+{
+ gst_element_set_state (state->pipeline, GST_STATE_PLAYING);
+}
+
+static gint64
+pipeline_get_position (APP_STATE_T * state)
+{
+ gint64 position = -1;
+
+ if (state->pipeline) {
+ gst_element_query_position (state->vsink, GST_FORMAT_TIME, &position);
+ }
+
+ return position;
+}
+
+static gint64
+pipeline_get_duration (APP_STATE_T * state)
+{
+ gint64 duration = -1;
+
+ if (state->pipeline) {
+ gst_element_query_duration (state->pipeline, GST_FORMAT_TIME, &duration);
+ }
+
+ return duration;
+}
+
+static void
+pipeline_seek (APP_STATE_T * state, gint64 position)
+{
+ if (state->pipeline) {
+ GstEvent *event;
+ event = gst_event_new_seek (1.0,
+ GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT,
+ GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE);
+ if (!gst_element_send_event (state->vsink, event)) {
+ g_print ("seek failed\n");
+ }
+ }
+}
+
+static gboolean
+handle_queued_objects (APP_STATE_T * state)
+{
+ GstMiniObject *object = NULL;
+
+ g_mutex_lock (&state->queue_lock);
+ if (state->flushing) {
+ g_cond_broadcast (&state->cond);
+ goto beach;
+ } else if (g_async_queue_length (state->queue) == 0) {
+ goto beach;
+ }
+
+ if ((object = g_async_queue_try_pop (state->queue))) {
+ if (GST_IS_BUFFER (object)) {
+ GstBuffer *buffer = GST_BUFFER_CAST (object);
+ update_image (state, buffer);
+ render_scene (state);
+ gst_buffer_unref (buffer);
+ if (!SYNC_BUFFERS) {
+ object = NULL;
+ }
+ } else if (GST_IS_EVENT (object)) {
+ GstEvent *event = GST_EVENT_CAST (object);
+ g_print ("\nevent %p %s\n", event,
+ gst_event_type_get_name (GST_EVENT_TYPE (event)));
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_EOS:
+ flush_internal (state);
+ break;
+ default:
+ break;
+ }
+ gst_event_unref (event);
+ object = NULL;
+ }
+ }
+
+ if (object) {
+ state->popped_obj = object;
+ g_cond_broadcast (&state->cond);
+ }
+
+beach:
+ g_mutex_unlock (&state->queue_lock);
+
+ return FALSE;
+}
+
+static gboolean
+queue_object (APP_STATE_T * state, GstMiniObject * obj, gboolean synchronous)
+{
+ gboolean res = TRUE;
+
+ g_mutex_lock (&state->queue_lock);
+ if (state->flushing) {
+ gst_mini_object_unref (obj);
+ res = FALSE;
+ goto beach;
+ }
+
+ g_async_queue_push (state->queue, obj);
+
+ if (synchronous) {
+ /* Waiting for object to be handled */
+ do {
+ g_cond_wait (&state->cond, &state->queue_lock);
+ } while (!state->flushing && state->popped_obj != obj);
+ }
+
+beach:
+ g_mutex_unlock (&state->queue_lock);
+ return res;
+}
+
+static void
+preroll_cb (GstElement * fakesink, GstBuffer * buffer, GstPad * pad,
+ gpointer user_data)
+{
+ APP_STATE_T *state = (APP_STATE_T *) user_data;
+ queue_object (state, GST_MINI_OBJECT_CAST (gst_buffer_ref (buffer)), FALSE);
+}
+
+static void
+buffers_cb (GstElement * fakesink, GstBuffer * buffer, GstPad * pad,
+ gpointer user_data)
+{
+ APP_STATE_T *state = (APP_STATE_T *) user_data;
+ queue_object (state, GST_MINI_OBJECT_CAST (gst_buffer_ref (buffer)),
+ SYNC_BUFFERS);
+}
+
+static GstPadProbeReturn
+events_cb (GstPad * pad, GstPadProbeInfo * probe_info, gpointer user_data)
+{
+ APP_STATE_T *state = (APP_STATE_T *) user_data;
+ GstEvent *event = GST_PAD_PROBE_INFO_EVENT (probe_info);
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_CAPS:
+ {
+ if (state->caps) {
+ gst_caps_unref (state->caps);
+ state->caps = NULL;
+ }
+ gst_event_parse_caps (event, &state->caps);
+ if (state->caps)
+ gst_caps_ref (state->caps);
+ break;
+ }
+ case GST_EVENT_FLUSH_START:
+ flush_start (state);
+ break;
+ case GST_EVENT_FLUSH_STOP:
+ flush_stop (state);
+ break;
+ case GST_EVENT_EOS:
+ queue_object (state, GST_MINI_OBJECT_CAST (gst_event_ref (event)), FALSE);
+ break;
+ default:
+ break;
+ }
+
+ return GST_PAD_PROBE_OK;
+}
+
+static GstPadProbeReturn
+query_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
+{
+ APP_STATE_T *state = (APP_STATE_T *) user_data;
+ GstQuery *query = GST_PAD_PROBE_INFO_QUERY (info);
+
+ switch (GST_QUERY_TYPE (query)) {
+ case GST_QUERY_CONTEXT:
+ {
+ if (gst_gl_handle_context_query (state->pipeline, query,
+ (GstGLDisplay *) state->gst_display, NULL,
+ (GstGLContext *) state->gl_context))
+ return GST_PAD_PROBE_HANDLED;
+ break;
+ }
+ case GST_QUERY_DRAIN:
+ {
+ flush_internal (state);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return GST_PAD_PROBE_OK;
+}
+
+static gboolean
+init_playbin_player (APP_STATE_T * state, const gchar * uri)
+{
+ GstPad *pad = NULL;
+ GstPad *ghostpad = NULL;
+ GstElement *vbin = gst_bin_new ("vbin");
+
+ /* insert a gl filter so that the GstGLBufferPool
+ * is managed automatically */
+ GstElement *glfilter = gst_element_factory_make ("glupload", "glfilter");
+ GstElement *capsfilter = gst_element_factory_make ("capsfilter", NULL);
+ GstElement *vsink = gst_element_factory_make ("fakesink", "vsink");
+
+ g_object_set (capsfilter, "caps",
+ gst_caps_from_string ("video/x-raw(memory:GLMemory), format=RGBA"), NULL);
+ g_object_set (vsink, "sync", TRUE, "silent", TRUE, "qos", TRUE,
+ "enable-last-sample", FALSE, "max-lateness", 20 * GST_MSECOND,
+ "signal-handoffs", TRUE, NULL);
+
+ g_signal_connect (vsink, "preroll-handoff", G_CALLBACK (preroll_cb), state);
+ g_signal_connect (vsink, "handoff", G_CALLBACK (buffers_cb), state);
+
+ gst_bin_add_many (GST_BIN (vbin), glfilter, capsfilter, vsink, NULL);
+
+ pad = gst_element_get_static_pad (glfilter, "sink");
+ ghostpad = gst_ghost_pad_new ("sink", pad);
+ gst_object_unref (pad);
+ gst_element_add_pad (vbin, ghostpad);
+
+ pad = gst_element_get_static_pad (vsink, "sink");
+ gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, events_cb, state,
+ NULL);
+ gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM, query_cb, state,
+ NULL);
+ gst_object_unref (pad);
+
+ gst_element_link (glfilter, capsfilter);
+ gst_element_link (capsfilter, vsink);
+
+ /* Instantiate and configure playbin */
+ state->pipeline = gst_element_factory_make ("playbin", "player");
+ g_object_set (state->pipeline, "uri", uri,
+ "video-sink", vbin, "flags",
+ GST_PLAY_FLAG_NATIVE_VIDEO | GST_PLAY_FLAG_AUDIO, NULL);
+
+ state->vsink = gst_object_ref (vsink);
+ return TRUE;
+}
+
+static gboolean
+init_parse_launch_player (APP_STATE_T * state, const gchar * spipeline)
+{
+ GstElement *vsink;
+ GError *error = NULL;
+
+ /* ex:
+
+ ./testegl "filesrc location=big_buck_bunny_720p_h264.mov ! qtdemux ! \
+ h264parse ! omxh264dec ! glcolorscale ! fakesink name=vsink"
+
+ ./testegl "filesrc location=big_buck_bunny_720p_h264.mov ! qtdemux ! \
+ h264parse ! omxh264dec ! glcolorscale ! \
+ video/x-raw(memory:GLMemory) ! fakesink name=vsink"
+
+ ./testegl "filesrc location=big_buck_bunny_720p_h264.mov ! qtdemux ! \
+ h264parse ! omxh264dec ! glcolorscale ! \
+ video/x-raw(meta:GstVideoGLTextureUploadMeta) ! \
+ fakesink name=vsink"
+
+ */
+
+ /* pipeline 1 and 2 are the same and the most efficient as glcolorscale
+ * will enter in passthrough mode and testegl will just bind the eglimage
+ * to a gl texture without any copy. */
+
+ state->pipeline = gst_parse_launch (spipeline, &error);
+
+ if (!state->pipeline) {
+ g_printerr ("Unable to instatiate pipeline '%s': %s\n",
+ spipeline, error->message);
+ return FALSE;
+ }
+
+ vsink = gst_bin_get_by_name (GST_BIN (state->pipeline), "vsink");
+
+ if (!vsink) {
+ g_printerr ("Unable to find a fakesink named 'vsink'");
+ return FALSE;
+ }
+
+ g_object_set (vsink, "sync", TRUE, "silent", TRUE, "qos", TRUE,
+ "enable-last-sample", FALSE,
+ "max-lateness", 20 * GST_MSECOND, "signal-handoffs", TRUE, NULL);
+
+ g_signal_connect (vsink, "preroll-handoff", G_CALLBACK (preroll_cb), state);
+ g_signal_connect (vsink, "handoff", G_CALLBACK (buffers_cb), state);
+
+ gst_pad_add_probe (gst_element_get_static_pad (vsink, "sink"),
+ GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, events_cb, state, NULL);
+ gst_pad_add_probe (gst_element_get_static_pad (vsink, "sink"),
+ GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM, query_cb, state, NULL);
+
+ state->vsink = gst_object_ref (vsink);
+ return TRUE;
+}
+
+//------------------------------------------------------------------------------
+
+static void
+report_position_duration (APP_STATE_T * state)
+{
+ gint64 position, duration;
+
+ duration = pipeline_get_duration (state);
+ position = pipeline_get_position (state);
+
+ if (position != -1) {
+ g_print ("\n position / duration: %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (position));
+ } else {
+ g_print ("\n position / duration: unknown");
+ }
+
+ if (duration != -1) {
+ g_print (" / %" GST_TIME_FORMAT, GST_TIME_ARGS (duration));
+ } else {
+ g_print (" / unknown");
+ }
+ g_print ("\n");
+}
+
+static void
+seek_forward (APP_STATE_T * state)
+{
+ gint64 position, duration;
+
+ duration = pipeline_get_duration (state);
+ position = pipeline_get_position (state);
+
+ if (position != -1) {
+ position += 30 * GST_SECOND;
+ if (duration != -1) {
+ position = MIN (position, duration);
+ }
+ pipeline_seek (state, position);
+ }
+}
+
+static void
+seek_backward (APP_STATE_T * state)
+{
+ gint64 position;
+
+ position = pipeline_get_position (state);
+
+ if (position != -1) {
+ position -= 30 * GST_SECOND;
+ position = MAX (position, 0);
+ pipeline_seek (state, position);
+ }
+}
+
+#define SKIP(t) \
+ while (*t) { \
+ if ((*t == ' ') || (*t == '\n') || (*t == '\t') || (*t == '\r')) \
+ t++; \
+ else \
+ break; \
+ }
+
+/* Process keyboard input */
+static gboolean
+handle_keyboard (GIOChannel * source, GIOCondition cond, APP_STATE_T * state)
+{
+ gchar *str = NULL;
+ char op;
+
+ if (g_io_channel_read_line (source, &str, NULL, NULL,
+ NULL) == G_IO_STATUS_NORMAL) {
+
+ gchar *cmd = str;
+ SKIP (cmd)
+ op = *cmd;
+ cmd++;
+ switch (op) {
+ case 'a':
+ if (state->animate) {
+ state->animate = FALSE;
+ } else {
+ state->animate = TRUE;
+ }
+ break;
+ case 'p':
+ pipeline_pause (state);
+ break;
+ case 'r':
+ pipeline_play (state);
+ break;
+ case 'l':
+ report_position_duration (state);
+ break;
+ case 'f':
+ seek_forward (state);
+ break;
+ case 'b':
+ seek_backward (state);
+ break;
+ case 'q':
+ flush_start (state);
+ gst_element_set_state (state->pipeline, GST_STATE_READY);
+ break;
+ }
+ }
+ g_free (str);
+ return TRUE;
+}
+
+static GstBusSyncReply
+bus_sync_handler (GstBus * bus, GstMessage * message, GstPipeline * data)
+{
+ return GST_BUS_PASS;
+}
+
+/* on error print the error and quit the application */
+static void
+error_cb (GstBus * bus, GstMessage * msg, APP_STATE_T * state)
+{
+ GError *err;
+ gchar *debug_info;
+
+ gst_message_parse_error (msg, &err, &debug_info);
+ g_printerr ("Error received from element %s: %s\n",
+ GST_OBJECT_NAME (msg->src), err->message);
+ g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");
+ g_clear_error (&err);
+ g_free (debug_info);
+ flush_start (state);
+ gst_element_set_state (state->pipeline, GST_STATE_READY);
+}
+
+/* buffering */
+static void
+buffering_cb (GstBus * bus, GstMessage * msg, APP_STATE_T * state)
+{
+ gint percent;
+
+ gst_message_parse_buffering (msg, &percent);
+ g_print ("Buffering %3d%%\r", percent);
+ if (percent < 100)
+ pipeline_pause (state);
+ else {
+ g_print ("\n");
+ pipeline_play (state);
+ }
+}
+
+/* on EOS just quit the application */
+static void
+eos_cb (GstBus * bus, GstMessage * msg, APP_STATE_T * state)
+{
+ if (GST_MESSAGE_SRC (msg) == GST_OBJECT (state->pipeline)) {
+ g_print ("End-Of-Stream reached.\n");
+ gst_element_set_state (state->pipeline, GST_STATE_READY);
+ }
+}
+
+static void
+state_changed_cb (GstBus * bus, GstMessage * msg, APP_STATE_T * state)
+{
+ GstState old_state, new_state, pending_state;
+ if (GST_MESSAGE_SRC (msg) == GST_OBJECT (state->pipeline)) {
+ gst_message_parse_state_changed (msg, &old_state, &new_state,
+ &pending_state);
+ g_print ("State changed to %s\n", gst_element_state_get_name (new_state));
+ if (old_state == GST_STATE_PAUSED && new_state == GST_STATE_READY) {
+ g_main_loop_quit (state->main_loop);
+ }
+ }
+}
+
+static void
+qos_cb (GstBus * bus, GstMessage * msg, APP_STATE_T * state)
+{
+ GstFormat fmt = GST_FORMAT_BUFFERS;
+ gchar *name = gst_element_get_name (GST_MESSAGE_SRC (msg));
+ gst_message_parse_qos_stats (msg, &fmt, &state->rendered, &state->dropped);
+ g_print ("%s rendered: %" G_GUINT64_FORMAT " dropped: %" G_GUINT64_FORMAT
+ " %s\n",
+ name, state->rendered, state->dropped,
+ (fmt == GST_FORMAT_BUFFERS ? "frames" : "samples"));
+ g_free (name);
+}
+
+//==============================================================================
+
+static void
+close_ogl (void)
+{
+#if defined (USE_OMX_TARGET_RPI)
+ DISPMANX_UPDATE_HANDLE_T dispman_update;
+#endif
+
+ if (state->fshader) {
+ glDeleteShader (state->fshader);
+ glDetachShader (state->program, state->fshader);
+ }
+
+ if (state->vshader) {
+ glDeleteShader (state->vshader);
+ glDetachShader (state->program, state->vshader);
+ }
+
+ if (state->program)
+ glDeleteProgram (state->program);
+
+ if (state->tex)
+ glDeleteTextures (1, &state->tex);
+
+ /* clear screen */
+ glClear (GL_COLOR_BUFFER_BIT);
+ eglSwapBuffers (state->display, state->surface);
+
+ /* Release OpenGL resources */
+ eglMakeCurrent (state->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+ eglDestroySurface (state->display, state->surface);
+ eglDestroyContext (state->display, state->context);
+ gst_object_unref (state->gl_context);
+ gst_object_unref (state->gst_display);
+
+#if defined (USE_OMX_TARGET_RPI)
+ dispman_update = vc_dispmanx_update_start (0);
+ vc_dispmanx_element_remove (dispman_update, state->dispman_element);
+ vc_dispmanx_update_submit_sync (dispman_update);
+ vc_dispmanx_display_close (state->dispman_display);
+#elif defined(HAVE_X11)
+ XSync (state->xdisplay, FALSE);
+ XUnmapWindow (state->xdisplay, state->xwindow);
+ XDestroyWindow (state->xdisplay, state->xwindow);
+ XSync (state->xdisplay, FALSE);
+ XCloseDisplay (state->xdisplay);
+#endif
+}
+
+//==============================================================================
+
+static void
+open_ogl (void)
+{
+ TRACE_VC_MEMORY ("state 0");
+
+#if defined (USE_OMX_TARGET_RPI)
+ bcm_host_init ();
+ TRACE_VC_MEMORY ("after bcm_host_init");
+#endif
+
+ /* Create surface and gl context */
+ init_ogl (state);
+ TRACE_VC_MEMORY ("after init_ogl");
+}
+
+static gpointer
+render_func (gpointer data)
+{
+ open_ogl ();
+ state->running = TRUE;
+
+ do {
+ handle_queued_objects (state);
+ g_usleep (0);
+ } while (state->running == TRUE);
+
+ close_ogl ();
+ return NULL;
+}
+
+int
+main (int argc, char **argv)
+{
+ GstBus *bus;
+ GOptionContext *ctx;
+ GIOChannel *io_stdin;
+ GError *err = NULL;
+ gboolean res;
+ GOptionEntry options[] = {
+ {NULL}
+ };
+ GThread *rthread;
+
+ /* Clear application state */
+ memset (state, 0, sizeof (*state));
+ state->animate = TRUE;
+ state->current_buffer = NULL;
+ state->caps = NULL;
+
+ ctx = g_option_context_new ("[ADDITIONAL ARGUMENTS]");
+ g_option_context_add_main_entries (ctx, options, NULL);
+ g_option_context_add_group (ctx, gst_init_get_option_group ());
+ if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
+ g_print ("Error initializing: %s\n", GST_STR_NULL (err->message));
+ g_option_context_free (ctx);
+ g_clear_error (&err);
+ exit (1);
+ }
+ g_option_context_free (ctx);
+
+ if (argc != 2) {
+ g_print ("Usage: %s <URI> or <PIPELINE-DESCRIPTION>\n", argv[0]);
+ exit (1);
+ }
+
+ /* Initialize GStreamer */
+ gst_init (&argc, &argv);
+
+ /* initialize inter thread comunnication */
+ init_intercom (state);
+
+ TRACE_VC_MEMORY ("state 0");
+
+ if (!(rthread = g_thread_new ("render", (GThreadFunc) render_func, NULL))) {
+ g_print ("Render thread create failed\n");
+ exit (1);
+ }
+
+ /* Initialize player */
+ if (gst_uri_is_valid (argv[1])) {
+ res = init_playbin_player (state, argv[1]);
+ } else {
+ res = init_parse_launch_player (state, argv[1]);
+ }
+
+ if (!res)
+ goto done;
+
+ /* Create a GLib Main Loop */
+ state->main_loop = g_main_loop_new (NULL, FALSE);
+
+ /* Add a keyboard watch so we get notified of keystrokes */
+ io_stdin = g_io_channel_unix_new (fileno (stdin));
+ g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc) handle_keyboard, state);
+ g_io_channel_unref (io_stdin);
+
+ /* *INDENT-OFF* */
+ g_print ("Available commands: \n"
+ " a - Toggle animation \n"
+ " p - Pause playback \n"
+ " r - Resume playback \n"
+ " l - Query position/duration\n"
+ " f - Seek 30 seconds forward \n"
+ " b - Seek 30 seconds backward \n"
+ " q - Quit \n");
+ /* *INDENT-ON* */
+
+ /* Connect the bus handlers */
+ bus = gst_element_get_bus (state->pipeline);
+
+ gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bus_sync_handler, state,
+ NULL);
+
+ gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
+ gst_bus_enable_sync_message_emission (bus);
+
+ g_signal_connect (G_OBJECT (bus), "message::error", (GCallback) error_cb,
+ state);
+ g_signal_connect (G_OBJECT (bus), "message::buffering",
+ (GCallback) buffering_cb, state);
+ g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback) eos_cb, state);
+ g_signal_connect (G_OBJECT (bus), "message::qos", (GCallback) qos_cb, state);
+ g_signal_connect (G_OBJECT (bus), "message::state-changed",
+ (GCallback) state_changed_cb, state);
+ gst_object_unref (bus);
+
+ /* Make player start playing */
+ gst_element_set_state (state->pipeline, GST_STATE_PLAYING);
+
+ /* Start the mainloop */
+ g_main_loop_run (state->main_loop);
+
+done:
+ /* Release pipeline */
+ if (state->pipeline) {
+ gst_element_set_state (state->pipeline, GST_STATE_NULL);
+ if (state->vsink) {
+ gst_object_unref (state->vsink);
+ state->vsink = NULL;
+ }
+
+ gst_object_unref (state->pipeline);
+ }
+
+ /* Unref the mainloop */
+ if (state->main_loop) {
+ g_main_loop_unref (state->main_loop);
+ }
+
+ /* Stop rendering thread */
+ state->running = FALSE;
+ g_thread_join (rthread);
+
+ if (state->caps) {
+ gst_caps_unref (state->caps);
+ state->caps = NULL;
+ }
+
+ terminate_intercom (state);
+
+ TRACE_VC_MEMORY ("at exit");
+ return 0;
+}
diff --git a/subprojects/gst-omx/examples/meson.build b/subprojects/gst-omx/examples/meson.build
new file mode 100644
index 0000000000..5173880576
--- /dev/null
+++ b/subprojects/gst-omx/examples/meson.build
@@ -0,0 +1,3 @@
+if gstgl_dep.found()
+ subdir('egl')
+endif
diff --git a/subprojects/gst-omx/gst-omx.doap b/subprojects/gst-omx/gst-omx.doap
new file mode 100644
index 0000000000..ff6af4ed8f
--- /dev/null
+++ b/subprojects/gst-omx/gst-omx.doap
@@ -0,0 +1,332 @@
+<Project
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
+ xmlns="http://usefulinc.com/ns/doap#"
+ xmlns:foaf="http://xmlns.com/foaf/0.1/"
+ xmlns:admin="http://webns.net/mvcb/">
+
+ <name>GStreamer OpenMAX IL wrapper plugin</name>
+ <shortname>gst-omx</shortname>
+ <homepage rdf:resource="http://gstreamer.freedesktop.org/modules/gst-omx.html" />
+ <created>2005-06-17</created>
+ <shortdesc xml:lang="en">
+a basic collection of elements
+ </shortdesc>
+ <description xml:lang="en">
+ This plugin wraps available OpenMAX IL components and makes
+ them available as standard GStreamer elements.
+</description>
+ <category></category>
+ <bug-database rdf:resource="https://gitlab.freedesktop.org/gstreamer/gst-omx/issues/" />
+ <screenshots></screenshots>
+ <mailing-list rdf:resource="http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel" />
+ <programming-language>C</programming-language>
+ <license rdf:resource="http://usefulinc.com/doap/licenses/lgpl"/>
+ <download-page rdf:resource="http://gstreamer.freedesktop.org/download/" />
+
+ <repository>
+ <GitRepository>
+ <location rdf:resource="git://gitlab.freedesktop.org/gstreamer/gst-omx"/>
+ <browse rdf:resource="http://gitlab.freedesktop.org/gstreamer/gst-omx"/>
+ </GitRepository>
+ </repository>
+
+ <release>
+ <Version>
+ <revision>1.19.2</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2021-09-23</created>
+ <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.19.2.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.19.1</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2021-06-01</created>
+ <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.19.1.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.18.0</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2020-09-08</created>
+ <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.18.0.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.17.90</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2020-08-20</created>
+ <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.17.90.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.17.2</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2020-07-03</created>
+ <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.17.2.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.17.1</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2020-06-19</created>
+ <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.17.1.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.16.0</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2019-04-19</created>
+ <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.16.0.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.15.90</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2019-04-11</created>
+ <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.15.90.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.15.2</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2019-02-26</created>
+ <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.15.2.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.15.1</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2019-01-17</created>
+ <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.15.1.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.14.0</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2018-03-19</created>
+ <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.14.0.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.13.91</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2018-03-13</created>
+ <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.13.91.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.13.90</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2018-03-03</created>
+ <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.13.90.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.13.1</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2018-02-15</created>
+ <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.13.1.tar.xz" />
+ </Version>
+ </release>
+
+
+ <release>
+ <Version>
+ <revision>1.12.4</revision>
+ <branch>1.12</branch>
+ <name></name>
+ <created>2017-12-07</created>
+ <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.12.4.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.12.3</revision>
+ <branch>1.12</branch>
+ <name></name>
+ <created>2017-09-18</created>
+ <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.12.3.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.12.2</revision>
+ <branch>1.12</branch>
+ <name></name>
+ <created>2017-07-14</created>
+ <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.12.2.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.12.1</revision>
+ <branch>1.12</branch>
+ <name></name>
+ <created>2017-06-20</created>
+ <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.12.1.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.12.0</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2017-05-04</created>
+ <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.12.0.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.11.91</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2017-04-27</created>
+ <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.11.91.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.11.90</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2017-04-07</created>
+ <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.11.90.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.11.2</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2017-02-24</created>
+ <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.11.2.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.11.1</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2017-01-12</created>
+ <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.11.1.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.10.0</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2016-11-01</created>
+ <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.10.0.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.9.90</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2016-09-30</created>
+ <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.9.90.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.9.2</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2016-09-01</created>
+ <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.9.2.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.9.1</revision>
+ <branch>master</branch>
+ <name></name>
+ <created>2016-06-06</created>
+ <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.9.1.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.2.0</revision>
+ <branch>1.2</branch>
+ <name></name>
+ <created>2014-07-23</created>
+ <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.2.0.tar.xz" />
+ </Version>
+ </release>
+
+ <release>
+ <Version>
+ <revision>1.0.0</revision>
+ <branch>1.0</branch>
+ <name></name>
+ <created>2013-03-22</created>
+ <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.0.0.tar.xz" />
+ </Version>
+ </release>
+
+ <maintainer>
+ <foaf:Person>
+ <foaf:name>Sebastian Dröge</foaf:name>
+ <foaf:mbox_sha1sum>7c1069ea873ef7751e4eca5f1a42744b0e9a3a0a</foaf:mbox_sha1sum>
+ </foaf:Person>
+ </maintainer>
+
+</Project>
diff --git a/subprojects/gst-omx/hooks/pre-commit.hook b/subprojects/gst-omx/hooks/pre-commit.hook
new file mode 100755
index 0000000000..3c1062b9e0
--- /dev/null
+++ b/subprojects/gst-omx/hooks/pre-commit.hook
@@ -0,0 +1,83 @@
+#!/bin/sh
+#
+# Check that the code follows a consistant code style
+#
+
+# Check for existence of indent, and error out if not present.
+# On some *bsd systems the binary seems to be called gnunindent,
+# so check for that first.
+
+version=`gnuindent --version 2>/dev/null`
+if test "x$version" = "x"; then
+ version=`gindent --version 2>/dev/null`
+ if test "x$version" = "x"; then
+ version=`indent --version 2>/dev/null`
+ if test "x$version" = "x"; then
+ echo "GStreamer git pre-commit hook:"
+ echo "Did not find GNU indent, please install it before continuing."
+ exit 1
+ else
+ INDENT=indent
+ fi
+ else
+ INDENT=gindent
+ fi
+else
+ INDENT=gnuindent
+fi
+
+case `$INDENT --version` in
+ GNU*)
+ ;;
+ default)
+ echo "GStreamer git pre-commit hook:"
+ echo "Did not find GNU indent, please install it before continuing."
+ echo "(Found $INDENT, but it doesn't seem to be GNU indent)"
+ exit 1
+ ;;
+esac
+
+INDENT_PARAMETERS="--braces-on-if-line \
+ --case-brace-indentation0 \
+ --case-indentation2 \
+ --braces-after-struct-decl-line \
+ --line-length80 \
+ --no-tabs \
+ --cuddle-else \
+ --dont-line-up-parentheses \
+ --continuation-indentation4 \
+ --honour-newlines \
+ --tab-size8 \
+ --indent-level2 \
+ --leave-preprocessor-space"
+
+echo "--Checking style--"
+for file in `git diff-index --cached --name-only HEAD --diff-filter=ACMR| grep "\.c$"` ; do
+ # nf is the temporary checkout. This makes sure we check against the
+ # revision in the index (and not the checked out version).
+ nf=`git checkout-index --temp ${file} | cut -f 1`
+ newfile=`mktemp /tmp/${nf}.XXXXXX` || exit 1
+ $INDENT ${INDENT_PARAMETERS} \
+ $nf -o $newfile 2>> /dev/null
+ # FIXME: Call indent twice as it tends to do line-breaks
+ # different for every second call.
+ $INDENT ${INDENT_PARAMETERS} \
+ $newfile 2>> /dev/null
+ diff -u -p "${nf}" "${newfile}"
+ r=$?
+ rm "${newfile}"
+ rm "${nf}"
+ if [ $r != 0 ] ; then
+echo "================================================================================================="
+echo " Code style error in: $file "
+echo " "
+echo " Please fix before committing. Don't forget to run git add before trying to commit again. "
+echo " If the whole file is to be committed, this should work (run from the top-level directory): "
+echo " "
+echo " gst-indent $file; git add $file; git commit"
+echo " "
+echo "================================================================================================="
+ exit 1
+ fi
+done
+echo "--Checking style pass--"
diff --git a/subprojects/gst-omx/meson.build b/subprojects/gst-omx/meson.build
new file mode 100644
index 0000000000..d37fc7bd77
--- /dev/null
+++ b/subprojects/gst-omx/meson.build
@@ -0,0 +1,432 @@
+project('gst-omx', 'c',
+ version : '1.19.2',
+ meson_version : '>= 0.54',
+ default_options : [ 'warning_level=1',
+ 'buildtype=debugoptimized' ])
+
+gst_version = meson.project_version()
+version_arr = gst_version.split('.')
+gst_version_major = version_arr[0].to_int()
+gst_version_minor = version_arr[1].to_int()
+gst_version_micro = version_arr[2].to_int()
+ if version_arr.length() == 4
+ gst_version_nano = version_arr[3].to_int()
+else
+ gst_version_nano = 0
+endif
+
+glib_req = '>= 2.56.0'
+gst_req = '>= @0@.@1@.0'.format(gst_version_major, gst_version_minor)
+tizil_req = '>= 0.19.0'
+api_version = '1.0'
+
+plugins_install_dir = '@0@/gstreamer-1.0'.format(get_option('libdir'))
+
+cc = meson.get_compiler('c')
+
+if cc.get_id() == 'msvc'
+ msvc_args = [
+ # Ignore several spurious warnings for things gstreamer does very commonly
+ # If a warning is completely useless and spammy, use '/wdXXXX' to suppress it
+ # If a warning is harmless but hard to fix, use '/woXXXX' so it's shown once
+ # NOTE: Only add warnings here if you are sure they're spurious
+ '/wd4018', # implicit signed/unsigned conversion
+ '/wd4146', # unary minus on unsigned (beware INT_MIN)
+ '/wd4244', # lossy type conversion (e.g. double -> int)
+ '/wd4305', # truncating type conversion (e.g. double -> float)
+ cc.get_supported_arguments(['/utf-8']), # set the input encoding to utf-8
+
+ # Enable some warnings on MSVC to match GCC/Clang behaviour
+ '/w14062', # enumerator 'identifier' in switch of enum 'enumeration' is not handled
+ '/w14101', # 'identifier' : unreferenced local variable
+ '/w14189', # 'identifier' : local variable is initialized but not referenced
+ ]
+ add_project_arguments(msvc_args, language: 'c')
+ # Disable SAFESEH with MSVC for plugins and libs that use external deps that
+ # are built with MinGW
+ noseh_link_args = ['/SAFESEH:NO']
+else
+ noseh_link_args = []
+endif
+
+cdata = configuration_data()
+check_headers = [
+# ['HAVE_DLFCN_H', 'dlfcn.h'],
+# ['HAVE_FCNTL_H', 'fcntl.h'],
+# ['HAVE_INTTYPES_H', 'inttypes.h'],
+# ['HAVE_MEMORY_H', 'memory.h'],
+# ['HAVE_MSACM_H', 'msacm.h'],
+# ['HAVE_PTHREAD_H', 'pthread.h'],
+# ['HAVE_STDINT_H', 'stdint.h'],
+# ['HAVE_STDLIB_H', 'stdlib.h'],
+# ['HAVE_STRINGS_H', 'strings.h'],
+# ['HAVE_STRING_H', 'string.h'],
+# ['HAVE_SYS_PARAM_H', 'sys/param.h'],
+# ['HAVE_SYS_SOCKET_H', 'sys/socket.h'],
+# ['HAVE_SYS_STAT_H', 'sys/stat.h'],
+# ['HAVE_SYS_TIME_H', 'sys/time.h'],
+# ['HAVE_SYS_TYPES_H', 'sys/types.h'],
+# ['HAVE_SYS_UTSNAME_H', 'sys/utsname.h'],
+# ['HAVE_UNISTD_H', 'unistd.h'],
+]
+
+foreach h : check_headers
+ if cc.has_header(h.get(1))
+ cdata.set(h.get(0), 1)
+ endif
+endforeach
+
+check_functions = [
+# check token HAVE_CPU_ALPHA
+# check token HAVE_CPU_ARM
+# check token HAVE_CPU_CRIS
+# check token HAVE_CPU_CRISV32
+# check token HAVE_CPU_HPPA
+# check token HAVE_CPU_I386
+# check token HAVE_CPU_IA64
+# check token HAVE_CPU_M68K
+# check token HAVE_CPU_MIPS
+# check token HAVE_CPU_PPC
+# check token HAVE_CPU_PPC64
+# check token HAVE_CPU_S390
+# check token HAVE_CPU_SPARC
+# check token HAVE_CPU_X86_64
+# ['HAVE_DCGETTEXT', 'dcgettext'],
+# check token HAVE_EXPERIMENTAL
+# check token HAVE_EXTERNAL
+# ['HAVE_GETPAGESIZE', 'getpagesize'],
+# check token HAVE_GETTEXT
+]
+
+foreach f : check_functions
+ if cc.has_function(f.get(1))
+ cdata.set(f.get(0), 1)
+ endif
+endforeach
+
+#cdata.set('SIZEOF_CHAR', cc.sizeof('char'))
+#cdata.set('SIZEOF_INT', cc.sizeof('int'))
+#cdata.set('SIZEOF_LONG', cc.sizeof('long'))
+#cdata.set('SIZEOF_SHORT', cc.sizeof('short'))
+#cdata.set('SIZEOF_VOIDP', cc.sizeof('void*'))
+
+cdata.set('VERSION', '"@0@"'.format(gst_version))
+cdata.set('PACKAGE', '"gst-omx"')
+cdata.set('PACKAGE_VERSION', '"@0@"'.format(gst_version))
+cdata.set('PACKAGE_BUGREPORT', '"https://gitlab.freedesktop.org/gstreamer/gst-omx/issues/new"')
+cdata.set('PACKAGE_NAME', '"GStreamer OMX Plugins"')
+cdata.set('GETTEXT_PACKAGE', '"gst-omx-1.0"')
+cdata.set('GST_API_VERSION', '"@0@"'.format(api_version))
+cdata.set('GST_PACKAGE_NAME', '"GStreamer OpenMAX Plug-ins"')
+cdata.set('GST_PACKAGE_ORIGIN', '"Unknown package origin"')
+cdata.set('GST_LICENSE', '"LGPL"')
+cdata.set('LIBDIR', '"@0@"'.format(get_option('libdir')))
+
+# FIXME: This should be exposed as a configuration option
+host_system = host_machine.system()
+if host_system == 'linux'
+ cdata.set('DEFAULT_VIDEOSRC', '"v4l2src"')
+elif host_system == 'osx'
+ cdata.set('DEFAULT_VIDEOSRC', '"avfvideosrc"')
+else
+ cdata.set('DEFAULT_VIDEOSRC', '"videotestsrc"')
+endif
+
+# Mandatory GST deps
+gst_dep = dependency('gstreamer-1.0', version : gst_req,
+ fallback : ['gstreamer', 'gst_dep'])
+gstbase_dep = dependency('gstreamer-base-1.0', version : gst_req,
+ fallback : ['gstreamer', 'gst_base_dep'])
+gstcontroller_dep = dependency('gstreamer-controller-1.0', version : gst_req,
+ fallback : ['gstreamer', 'gst_controller_dep'])
+gstallocators_dep = dependency('gstreamer-allocators-1.0', version : gst_req,
+ fallback : ['gst-plugins-base', 'allocators_dep'])
+
+gstpbutils_dep = dependency('gstreamer-pbutils-1.0', version : gst_req,
+ fallback : ['gst-plugins-base', 'pbutils_dep'])
+gstaudio_dep = dependency('gstreamer-audio-1.0', version : gst_req,
+ fallback : ['gst-plugins-base', 'audio_dep'])
+gstfft_dep = dependency('gstreamer-fft-1.0', version : gst_req,
+ fallback : ['gst-plugins-base', 'fft_dep'])
+gsttag_dep = dependency('gstreamer-tag-1.0', version : gst_req,
+ fallback : ['gst-plugins-base', 'tag_dep'])
+gstvideo_dep = dependency('gstreamer-video-1.0', version : gst_req,
+ fallback : ['gst-plugins-base', 'video_dep'])
+
+gstgl_dep = dependency('gstreamer-gl-1.0', version : gst_req,
+ fallback : ['gst-plugins-base', 'gstgl_dep'], required : false)
+
+x11_dep = dependency('x11', required : false)
+
+gstcheck_dep = dependency('gstreamer-check-1.0', version : gst_req,
+ required : get_option('tests'),
+ fallback : ['gstreamer', 'gst_check_dep'])
+
+libm = cc.find_library('m', required : false)
+glib_dep = dependency('glib-2.0', version : glib_req, fallback: ['glib', 'libglib_dep'])
+gio_dep = dependency('gio-2.0', version : glib_req, fallback: ['glib', 'libgio_dep'] )
+gmodule_dep = dependency('gmodule-2.0', version : glib_req, fallback: ['glib', 'libgmodule_dep'])
+
+gst_omx_args = ['-DHAVE_CONFIG_H']
+configinc = include_directories('.')
+omx_header_path = get_option('header_path')
+if omx_header_path != ''
+ omx_inc = []
+ gst_omx_args += ['-I' + omx_header_path]
+else
+ omx_inc = include_directories (join_paths ('omx', 'openmax'))
+endif
+
+default_omx_struct_packing = 0
+omx_target = get_option ('target')
+if omx_target == 'generic'
+ cdata.set('USE_OMX_TARGET_GENERIC', 1)
+elif omx_target == 'rpi'
+ cdata.set('USE_OMX_TARGET_RPI', 1)
+ cdata.set('OMX_SKIP64BIT', 1)
+ default_omx_struct_packing = 4
+
+ if gstgl_dep.found()
+ if gstgl_dep.type_name() == 'pkgconfig'
+ gl_winsys = gstgl_dep.get_pkgconfig_variable('gl_winsys').split(' ')
+ gl_platforms = gstgl_dep.get_pkgconfig_variable('gl_platforms').split(' ')
+ elif gstgl_dep.type_name() == 'internal'
+ # XXX assume gst-plugins-base was built with dispmanx and egl support
+ gl_winsys = ['dispmanx']
+ gl_platforms = ['egl']
+ else
+ error ('unreachable dependency type')
+ endif
+
+ if not gl_winsys.contains('dispmanx') or not gl_platforms.contains ('egl')
+ gstgl_dep = dependency('', required : false)
+ endif
+ endif
+elif omx_target == 'bellagio'
+ cdata.set('USE_OMX_TARGET_BELLAGIO', 1)
+elif omx_target == 'zynqultrascaleplus'
+ cdata.set('USE_OMX_TARGET_ZYNQ_USCALE_PLUS', 1)
+ have_allegro_header = cc.has_header (
+ 'OMX_Allegro.h',
+ args : gst_omx_args,
+ include_directories : [omx_inc])
+ if not have_allegro_header
+ error ('Need Allegro OMX headers to build for Zynq UltraScale+. Use -Dheader_path option to specify the path of those headers.')
+ endif
+elif omx_target == 'tizonia'
+ if omx_header_path != ''
+ warning('Ignoring -Dheader_path because path is in tizilheaders.pc')
+ endif
+ cdata.set('USE_OMX_TARGET_TIZONIA', 1)
+ tizil_dep = dependency('tizilheaders', version : tizil_req)
+ cdata.set('TIZONIA_LIBDIR', tizil_dep.get_pkgconfig_variable('libdir'))
+ tizil_includedir = tizil_dep.get_pkgconfig_variable('includedir')
+ gst_omx_args += ['-I' + tizil_includedir + '/tizonia']
+ omx_inc = []
+else
+ error ('Unsupported omx target specified. Use the -Dtarget option')
+endif
+
+message ('OMX target: ' + omx_target)
+
+extra_video_headers = ''
+# Check for optional OpenMAX extension headers
+
+if cc.has_header (
+ 'OMX_VideoExt.h',
+ args : gst_omx_args,
+ include_directories : [omx_inc])
+ extra_video_headers += '''
+#include <OMX_VideoExt.h>'''
+ cdata.set ('HAVE_VIDEO_EXT', 1)
+endif
+
+if cc.has_header (
+ 'OMX_IndexExt.h',
+ args : gst_omx_args,
+ include_directories : [omx_inc])
+ cdata.set ('HAVE_INDEX_EXT', 1)
+endif
+
+if cc.has_header (
+ 'OMX_ComponentExt.h',
+ args : gst_omx_args,
+ include_directories : [omx_inc])
+ cdata.set ('HAVE_COMPONENT_EXT', 1)
+endif
+
+if cc.has_header (
+ 'OMX_CoreExt.h',
+ args : gst_omx_args)
+ cdata.set ('HAVE_CORE_EXT', 1)
+endif
+
+if cc.has_header (
+ 'OMX_AudioExt.h',
+ args : gst_omx_args)
+ cdata.set ('HAVE_AUDIO_EXT', 1)
+endif
+
+if cc.has_header (
+ 'OMX_IVCommonExt.h',
+ args : gst_omx_args)
+ cdata.set ('HAVE_IV_COMMON_EXT', 1)
+endif
+
+if cc.has_header (
+ 'OMX_ImageExt.h',
+ args : gst_omx_args)
+ cdata.set ('HAVE_IMAGE_EXT', 1)
+endif
+
+if cc.has_header (
+ 'OMX_OtherExt.h',
+ args : gst_omx_args)
+ cdata.set ('HAVE_OTHER_EXT', 1)
+endif
+
+have_omx_vp8 = cc.has_header_symbol(
+ 'OMX_Video.h',
+ 'OMX_VIDEO_CodingVP8',
+ prefix : extra_video_headers,
+ args : gst_omx_args,
+ include_directories : [omx_inc])
+if have_omx_vp8
+ cdata.set('HAVE_VP8', 1)
+endif
+
+have_omx_theora = cc.has_header_symbol(
+ 'OMX_Video.h',
+ 'OMX_VIDEO_CodingTheora',
+ prefix : extra_video_headers,
+ args : gst_omx_args,
+ include_directories : [omx_inc])
+if have_omx_theora
+ cdata.set('HAVE_THEORA', 1)
+endif
+
+have_omx_hevc = cc.has_header_symbol(
+ 'OMX_Video.h',
+ 'OMX_VIDEO_CodingHEVC',
+ prefix : extra_video_headers,
+ args : gst_omx_args,
+ include_directories : [omx_inc])
+if have_omx_hevc
+ cdata.set('HAVE_HEVC', 1)
+endif
+
+if gstgl_dep.found()
+ cdata.set ('HAVE_GST_GL', 1)
+endif
+
+if x11_dep.found()
+ cdata.set ('HAVE_X11', 1)
+endif
+
+omx_struct_packing = get_option ('struct_packing').to_int()
+if omx_struct_packing == 0
+ omx_struct_packing = default_omx_struct_packing
+endif
+if omx_struct_packing != 0
+ cdata.set('GST_OMX_STRUCT_PACKING', omx_struct_packing)
+endif
+
+omx_conf_dir = join_paths (get_option ('prefix'), get_option ('sysconfdir'), 'xdg')
+cdata.set_quoted('GST_OMX_CONFIG_DIR', omx_conf_dir)
+
+warning_flags = [
+ '-Wmissing-declarations',
+ '-Wredundant-decls',
+ '-Wwrite-strings',
+ '-Winit-self',
+ '-Wmissing-include-dirs',
+ '-Wno-multichar',
+ '-Wvla',
+ '-Wpointer-arith',
+ '-Wundef',
+]
+
+warning_c_flags = [
+ '-Wmissing-prototypes',
+ '-Wdeclaration-after-statement',
+ '-Wold-style-definition',
+ '-Waggregate-return',
+]
+
+have_cxx = add_languages('cpp', required : false)
+
+if have_cxx
+ cxx = meson.get_compiler('cpp')
+endif
+
+foreach extra_arg : warning_flags
+ if cc.has_argument (extra_arg)
+ add_project_arguments([extra_arg], language: 'c')
+ endif
+ if have_cxx and cxx.has_argument (extra_arg)
+ add_project_arguments([extra_arg], language: 'cpp')
+ endif
+endforeach
+
+foreach extra_arg : warning_c_flags
+ if cc.has_argument (extra_arg)
+ add_project_arguments([extra_arg], language: 'c')
+ endif
+endforeach
+
+# Disable compiler warnings for unused variables and args if gst debug system is disabled
+if gst_dep.type_name() == 'internal'
+ gst_debug_disabled = not subproject('gstreamer').get_variable('gst_debug')
+else
+ # We can't check that in the case of subprojects as we won't
+ # be able to build against an internal dependency (which is not built yet)
+ gst_debug_disabled = cc.has_header_symbol('gst/gstconfig.h', 'GST_DISABLE_GST_DEBUG', dependencies: gst_dep)
+endif
+
+if gst_debug_disabled
+ message('GStreamer debug system is disabled')
+ if cc.has_argument('-Wno-unused')
+ add_project_arguments('-Wno-unused', language: 'c')
+ endif
+ if have_cxx and cxx.has_argument ('-Wno-unused')
+ add_project_arguments('-Wno-unused', language: 'cpp')
+ endif
+else
+ message('GStreamer debug system is enabled')
+endif
+
+subdir('config')
+
+if not get_option('examples').disabled()
+ subdir('examples')
+endif
+
+subdir('omx')
+
+if not get_option('tools').disabled()
+ subdir('tools')
+endif
+
+if not get_option('tests').disabled() and gstcheck_dep.found()
+ subdir('tests')
+endif
+subdir('docs')
+
+# Set release date
+if gst_version_nano == 0
+ extract_release_date = find_program('scripts/extract-release-date-from-doap-file.py')
+ run_result = run_command(extract_release_date, gst_version, files('gst-omx.doap'))
+ if run_result.returncode() == 0
+ release_date = run_result.stdout().strip()
+ cdata.set_quoted('GST_PACKAGE_RELEASE_DATETIME', release_date)
+ message('Package release date: ' + release_date)
+ else
+ # Error out if our release can't be found in the .doap file
+ error(run_result.stderr())
+ endif
+endif
+
+configure_file(output: 'config.h', configuration: cdata)
+
+python3 = find_program('python3')
+run_command(python3, '-c', 'import shutil; shutil.copy("hooks/pre-commit.hook", ".git/hooks/pre-commit")')
diff --git a/subprojects/gst-omx/meson_options.txt b/subprojects/gst-omx/meson_options.txt
new file mode 100644
index 0000000000..e18beb25d8
--- /dev/null
+++ b/subprojects/gst-omx/meson_options.txt
@@ -0,0 +1,14 @@
+option('header_path', type : 'string', value : '',
+ description : 'An extra include directory to find the OpenMax headers')
+option('target', type : 'combo',
+ choices : ['none', 'generic', 'rpi', 'bellagio', 'tizonia', 'zynqultrascaleplus'], value : 'none',
+ description : 'The OMX platform to target')
+option('struct_packing', type : 'combo',
+ choices : ['0', '1', '2', '4', '8'], value : '0',
+ description : 'Force OpenMAX struct packing')
+
+# Common feature options
+option('examples', type : 'feature', value : 'auto', yield : true)
+option('tests', type : 'feature', value : 'auto', yield : true)
+option('tools', type : 'feature', value : 'auto', yield : true)
+option('doc', type : 'feature', value : 'auto', yield : true)
diff --git a/subprojects/gst-omx/omx/gstomx.c b/subprojects/gst-omx/omx/gstomx.c
new file mode 100644
index 0000000000..8aeb99b755
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomx.c
@@ -0,0 +1,4179 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ * Copyright (C) 2013, Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/allocators/gstdmabuf.h>
+#include <string.h>
+
+#include "gstomx.h"
+#include "gstomxmjpegdec.h"
+#include "gstomxmpeg2videodec.h"
+#include "gstomxmpeg4videodec.h"
+#include "gstomxh264dec.h"
+#include "gstomxh263dec.h"
+#include "gstomxh265dec.h"
+#include "gstomxvp8dec.h"
+#include "gstomxtheoradec.h"
+#include "gstomxwmvdec.h"
+#include "gstomxmpeg4videoenc.h"
+#include "gstomxh264enc.h"
+#include "gstomxh263enc.h"
+#include "gstomxh265enc.h"
+#include "gstomxaacdec.h"
+#include "gstomxmp3dec.h"
+#include "gstomxmp3enc.h"
+#include "gstomxaacenc.h"
+#include "gstomxamrdec.h"
+#include "gstomxanalogaudiosink.h"
+#include "gstomxhdmiaudiosink.h"
+
+GST_DEBUG_CATEGORY (gstomx_debug);
+#define GST_CAT_DEFAULT gstomx_debug
+
+GST_DEBUG_CATEGORY_STATIC (OMX_API_TRACE);
+
+/* Macros used to log result of OMX calls. Use the requested debug level if the
+ * operation succeeded and GST_LEVEL_ERROR if not.
+ * Don't consider OMX_ErrorNoMore as an error as it means we're done iterating. */
+#define DEBUG_IF_OK(obj,err,...) \
+ GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, (err == OMX_ErrorNone || err == OMX_ErrorNoMore) ? GST_LEVEL_DEBUG : GST_LEVEL_ERROR, obj, __VA_ARGS__)
+#define INFO_IF_OK(obj,err,...) \
+ GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, (err == OMX_ErrorNone || err == OMX_ErrorNoMore) ? GST_LEVEL_INFO : GST_LEVEL_ERROR, obj, __VA_ARGS__)
+
+G_LOCK_DEFINE_STATIC (core_handles);
+static GHashTable *core_handles;
+
+/* Cache used by gst_omx_buffer_flags_to_string() */
+G_LOCK_DEFINE_STATIC (buffer_flags_str);
+static GHashTable *buffer_flags_str;
+
+GstOMXCore *
+gst_omx_core_acquire (const gchar * filename)
+{
+ GstOMXCore *core;
+
+ G_LOCK (core_handles);
+ if (!core_handles)
+ core_handles =
+ g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ core = g_hash_table_lookup (core_handles, filename);
+ if (!core) {
+ core = g_slice_new0 (GstOMXCore);
+ g_mutex_init (&core->lock);
+ core->user_count = 0;
+ g_hash_table_insert (core_handles, g_strdup (filename), core);
+
+ /* Hack for the Broadcom OpenMAX IL implementation */
+#ifdef USE_OMX_TARGET_RPI
+ {
+#else
+ if (g_str_has_suffix (filename, "vc/lib/libopenmaxil.so")) {
+#endif
+ gchar *bcm_host_filename;
+ gchar *bcm_host_path;
+ GModule *bcm_host_module;
+ void (*bcm_host_init) (void);
+
+ bcm_host_path = g_path_get_dirname (filename);
+ bcm_host_filename =
+ g_build_filename (bcm_host_path, "libbcm_host.so", NULL);
+
+ bcm_host_module =
+ g_module_open (bcm_host_filename,
+ G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+
+ g_free (bcm_host_filename);
+ g_free (bcm_host_path);
+
+ if (!bcm_host_module) {
+ /* Retry without an absolute path */
+ bcm_host_module =
+ g_module_open ("libbcm_host.so",
+ G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+ if (!bcm_host_module) {
+ GST_ERROR ("Failed to load libbcm_host.so");
+ goto error;
+ }
+ }
+
+ if (!g_module_symbol (bcm_host_module, "bcm_host_init",
+ (gpointer *) & bcm_host_init)) {
+ GST_ERROR ("Failed to load symbol 'bcm_host_init' from libbcm_host.so");
+ goto error;
+ }
+
+ bcm_host_init ();
+ }
+
+ core->module =
+ g_module_open (filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+ if (!core->module)
+ goto load_failed;
+
+ if (!g_module_symbol (core->module, "OMX_Init", (gpointer *) & core->init))
+ goto symbol_error;
+ if (!g_module_symbol (core->module, "OMX_Deinit",
+ (gpointer *) & core->deinit))
+ goto symbol_error;
+ if (!g_module_symbol (core->module, "OMX_GetHandle",
+ (gpointer *) & core->get_handle))
+ goto symbol_error;
+ if (!g_module_symbol (core->module, "OMX_FreeHandle",
+ (gpointer *) & core->free_handle))
+ goto symbol_error;
+ if (!g_module_symbol (core->module, "OMX_SetupTunnel",
+ (gpointer *) & core->setup_tunnel))
+ goto symbol_error;
+
+ GST_DEBUG ("Successfully loaded core '%s'", filename);
+ }
+
+ g_mutex_lock (&core->lock);
+ core->user_count++;
+ if (core->user_count == 1) {
+ OMX_ERRORTYPE err;
+
+ err = core->init ();
+ if (err != OMX_ErrorNone) {
+ GST_ERROR ("Failed to initialize core '%s': 0x%08x", filename, err);
+ g_mutex_unlock (&core->lock);
+ goto error;
+ }
+
+ GST_DEBUG ("Successfully initialized core '%s'", filename);
+ }
+
+ g_mutex_unlock (&core->lock);
+ G_UNLOCK (core_handles);
+
+ return core;
+
+load_failed:
+ {
+ GST_ERROR ("Failed to load module '%s': %s", filename, g_module_error ());
+ goto error;
+ }
+symbol_error:
+ {
+ GST_ERROR ("Failed to locate required OpenMAX symbol in '%s': %s", filename,
+ g_module_error ());
+ g_module_close (core->module);
+ core->module = NULL;
+ goto error;
+ }
+error:
+ {
+ g_hash_table_remove (core_handles, filename);
+ g_mutex_clear (&core->lock);
+ g_slice_free (GstOMXCore, core);
+
+ G_UNLOCK (core_handles);
+
+ return NULL;
+ }
+}
+
+void
+gst_omx_core_release (GstOMXCore * core)
+{
+ g_return_if_fail (core != NULL);
+
+ G_LOCK (core_handles);
+
+ g_mutex_lock (&core->lock);
+
+ GST_DEBUG ("Releasing core %p", core);
+
+ core->user_count--;
+ if (core->user_count == 0) {
+ GST_DEBUG ("Deinit core %p", core);
+ core->deinit ();
+
+ G_LOCK (buffer_flags_str);
+ g_clear_pointer (&buffer_flags_str, g_hash_table_unref);
+ G_UNLOCK (buffer_flags_str);
+ }
+
+ g_mutex_unlock (&core->lock);
+
+ G_UNLOCK (core_handles);
+}
+
+/* NOTE: comp->messages_lock will be used */
+static void
+gst_omx_component_flush_messages (GstOMXComponent * comp)
+{
+ GstOMXMessage *msg;
+
+ g_mutex_lock (&comp->messages_lock);
+ while ((msg = g_queue_pop_head (&comp->messages))) {
+ g_slice_free (GstOMXMessage, msg);
+ }
+ g_mutex_unlock (&comp->messages_lock);
+}
+
+static void
+gst_omx_buffer_reset (GstOMXBuffer * buf)
+{
+ buf->omx_buf->nFlags = 0;
+ buf->omx_buf->nOffset = 0;
+ buf->omx_buf->nFilledLen = 0;
+ GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp, G_GUINT64_CONSTANT (0));
+}
+
+static void gst_omx_buffer_unmap (GstOMXBuffer * buffer);
+
+/* NOTE: Call with comp->lock, comp->messages_lock will be used */
+static void
+gst_omx_component_handle_messages (GstOMXComponent * comp)
+{
+ GstOMXMessage *msg;
+
+ g_mutex_lock (&comp->messages_lock);
+ while ((msg = g_queue_pop_head (&comp->messages))) {
+ g_mutex_unlock (&comp->messages_lock);
+
+ switch (msg->type) {
+ case GST_OMX_MESSAGE_STATE_SET:{
+ GST_INFO_OBJECT (comp->parent, "%s state change to %s finished",
+ comp->name, gst_omx_state_to_string (msg->content.state_set.state));
+ comp->state = msg->content.state_set.state;
+ if (comp->state == comp->pending_state)
+ comp->pending_state = OMX_StateInvalid;
+ break;
+ }
+ case GST_OMX_MESSAGE_FLUSH:{
+ GstOMXPort *port = NULL;
+ OMX_U32 index = msg->content.flush.port;
+
+ port = gst_omx_component_get_port (comp, index);
+ if (!port)
+ break;
+
+ GST_DEBUG_OBJECT (comp->parent, "%s port %u flushed", comp->name,
+ port->index);
+
+ if (port->flushing) {
+ port->flushed = TRUE;
+ } else {
+ GST_ERROR_OBJECT (comp->parent, "%s port %u was not flushing",
+ comp->name, port->index);
+ }
+
+ break;
+ }
+ case GST_OMX_MESSAGE_ERROR:{
+ OMX_ERRORTYPE error = msg->content.error.error;
+
+ if (error == OMX_ErrorNone)
+ break;
+
+ GST_ERROR_OBJECT (comp->parent, "%s got error: %s (0x%08x)", comp->name,
+ gst_omx_error_to_string (error), error);
+
+ /* We only set the first error ever from which
+ * we can't recover anymore.
+ */
+ if (comp->last_error == OMX_ErrorNone)
+ comp->last_error = error;
+ g_cond_broadcast (&comp->messages_cond);
+
+ break;
+ }
+ case GST_OMX_MESSAGE_PORT_ENABLE:{
+ GstOMXPort *port = NULL;
+ OMX_U32 index = msg->content.port_enable.port;
+ OMX_BOOL enable = msg->content.port_enable.enable;
+
+ port = gst_omx_component_get_port (comp, index);
+ if (!port)
+ break;
+
+ GST_DEBUG_OBJECT (comp->parent, "%s port %u %s", comp->name,
+ port->index, (enable ? "enabled" : "disabled"));
+
+ if (enable)
+ port->enabled_pending = FALSE;
+ else
+ port->disabled_pending = FALSE;
+ break;
+ }
+ case GST_OMX_MESSAGE_PORT_SETTINGS_CHANGED:{
+ gint i, n;
+ OMX_U32 index = msg->content.port_settings_changed.port;
+ GList *outports = NULL, *l, *k;
+
+ GST_DEBUG_OBJECT (comp->parent, "%s settings changed (port %u)",
+ comp->name, (guint) index);
+
+ /* FIXME: This probably can be done better */
+
+ /* Now update the ports' states */
+ n = (comp->ports ? comp->ports->len : 0);
+ for (i = 0; i < n; i++) {
+ GstOMXPort *port = g_ptr_array_index (comp->ports, i);
+
+ if (index == OMX_ALL || index == port->index) {
+ port->settings_cookie++;
+ gst_omx_port_update_port_definition (port, NULL);
+ if (port->port_def.eDir == OMX_DirOutput && !port->tunneled)
+ outports = g_list_prepend (outports, port);
+ }
+ }
+
+ for (k = outports; k; k = k->next) {
+ gboolean found = FALSE;
+
+ for (l = comp->pending_reconfigure_outports; l; l = l->next) {
+ if (l->data == k->data) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ comp->pending_reconfigure_outports =
+ g_list_prepend (comp->pending_reconfigure_outports, k->data);
+ }
+
+ g_list_free (outports);
+
+ break;
+ }
+ case GST_OMX_MESSAGE_BUFFER_FLAG:{
+ GstOMXPort *port = NULL;
+ OMX_U32 index = msg->content.buffer_flag.port;
+ OMX_U32 flags = msg->content.buffer_flag.flags;
+
+ port = gst_omx_component_get_port (comp, index);
+ if (!port)
+ break;
+
+ GST_DEBUG_OBJECT (comp->parent,
+ "%s port %u got buffer flags 0x%08x (%s)", comp->name, port->index,
+ (guint) flags, gst_omx_buffer_flags_to_string (flags));
+ if ((flags & OMX_BUFFERFLAG_EOS)
+ && port->port_def.eDir == OMX_DirOutput && !port->eos) {
+ GST_DEBUG_OBJECT (comp->parent, "%s port %u is EOS", comp->name,
+ port->index);
+ port->eos = TRUE;
+ }
+
+ break;
+ }
+ case GST_OMX_MESSAGE_BUFFER_DONE:{
+ GstOMXBuffer *buf = msg->content.buffer_done.buffer->pAppPrivate;
+ GstOMXPort *port;
+
+ port = buf->port;
+
+ buf->used = FALSE;
+
+ if (msg->content.buffer_done.empty) {
+ /* Input buffer is empty again and can be used to contain new input */
+ GST_LOG_OBJECT (port->comp->parent,
+ "%s port %u emptied buffer %p (%p)", port->comp->name,
+ port->index, buf, buf->omx_buf->pBuffer);
+
+ /* Reset all flags, some implementations don't
+ * reset them themselves and the flags are not
+ * valid anymore after the buffer was consumed
+ */
+ gst_omx_buffer_reset (buf);
+
+ /* Release and unmap the parent buffer, if any */
+ gst_omx_buffer_unmap (buf);
+ } else {
+ /* Output buffer contains output now or
+ * the port was flushed */
+ GST_LOG_OBJECT (port->comp->parent,
+ "%s port %u filled buffer %p (%p)", port->comp->name, port->index,
+ buf, buf->omx_buf->pBuffer);
+
+ if ((buf->omx_buf->nFlags & OMX_BUFFERFLAG_EOS)
+ && port->port_def.eDir == OMX_DirOutput && !port->eos) {
+ GST_DEBUG_OBJECT (comp->parent, "%s port %u is EOS", comp->name,
+ port->index);
+ port->eos = TRUE;
+ }
+ }
+
+ /* If an input port is managed by a pool, the buffer will be ready to be
+ * filled again once it's been released to the pool. */
+ if (port->port_def.eDir == OMX_DirOutput || !port->using_pool) {
+ g_queue_push_tail (&port->pending_buffers, buf);
+ }
+
+ break;
+ }
+ default:{
+ g_assert_not_reached ();
+ break;
+ }
+ }
+
+ g_slice_free (GstOMXMessage, msg);
+
+ g_mutex_lock (&comp->messages_lock);
+ }
+
+ g_mutex_unlock (&comp->messages_lock);
+}
+
+/* NOTE: comp->messages_lock will be used */
+static void
+gst_omx_component_send_message (GstOMXComponent * comp, GstOMXMessage * msg)
+{
+ g_mutex_lock (&comp->messages_lock);
+ if (msg)
+ g_queue_push_tail (&comp->messages, msg);
+ g_cond_broadcast (&comp->messages_cond);
+ g_mutex_unlock (&comp->messages_lock);
+}
+
+/* NOTE: Call with comp->lock, comp->messages_lock will be used */
+static gboolean
+gst_omx_component_wait_message (GstOMXComponent * comp, GstClockTime timeout)
+{
+ gboolean signalled;
+ gint64 wait_until = -1;
+
+ if (timeout != GST_CLOCK_TIME_NONE) {
+ gint64 add = timeout / (GST_SECOND / G_TIME_SPAN_SECOND);
+
+ if (add == 0)
+ return FALSE;
+
+ wait_until = g_get_monotonic_time () + add;
+ GST_DEBUG_OBJECT (comp->parent, "%s waiting for %" G_GINT64_FORMAT "us",
+ comp->name, add);
+ } else {
+ GST_DEBUG_OBJECT (comp->parent, "%s waiting for signal", comp->name);
+ }
+
+ g_mutex_lock (&comp->messages_lock);
+ g_mutex_unlock (&comp->lock);
+
+ if (!g_queue_is_empty (&comp->messages)) {
+ signalled = TRUE;
+ } else if (timeout == GST_CLOCK_TIME_NONE) {
+ g_cond_wait (&comp->messages_cond, &comp->messages_lock);
+ signalled = TRUE;
+ } else {
+ signalled =
+ g_cond_wait_until (&comp->messages_cond, &comp->messages_lock,
+ wait_until);
+ }
+
+ g_mutex_unlock (&comp->messages_lock);
+ g_mutex_lock (&comp->lock);
+
+ return signalled;
+}
+
+static const gchar *
+omx_event_type_to_str (OMX_EVENTTYPE event)
+{
+ switch (event) {
+ case OMX_EventCmdComplete:
+ return "EventCmdComplete";
+ case OMX_EventError:
+ return "EventError";
+ case OMX_EventMark:
+ return "EventMark";
+ case OMX_EventPortSettingsChanged:
+ return "EventPortSettingsChanged";
+ case OMX_EventBufferFlag:
+ return "EventBufferFlag";
+ case OMX_EventResourcesAcquired:
+ return "EventResourcesAcquired";
+ case OMX_EventComponentResumed:
+ return "EventComponentResumed";
+ case OMX_EventDynamicResourcesAvailable:
+ return "EventDynamicResourcesAvailable";
+ case OMX_EventPortFormatDetected:
+ return "EventPortFormatDetected";
+#ifdef OMX_EventIndexSettingChanged
+ case OMX_EventIndexSettingChanged:
+ return "EventIndexSettingChanged";
+#endif
+#ifdef OMX_EventPortNeedsDisable
+ case OMX_EventPortNeedsDisable:
+ return "EventPortNeedsDisable";
+#endif
+#ifdef OMX_EventPortNeedsFlush
+ case OMX_EventPortNeedsFlush:
+ return "EventPortNeedsFlush";
+#endif
+ case OMX_EventKhronosExtensions:
+ case OMX_EventVendorStartUnused:
+ case OMX_EventMax:
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+/* See "Table 3-11: Event Parameter Usage" */
+static GstStructure *
+omx_event_to_debug_struct (OMX_EVENTTYPE event,
+ guint32 data1, guint32 data2, gpointer event_data)
+{
+ const gchar *name;
+
+ name = omx_event_type_to_str (event);
+ switch (event) {
+ case OMX_EventCmdComplete:
+ {
+ const gchar *cmd = gst_omx_command_to_string (data1);
+
+ if (!cmd)
+ break;
+
+ switch (data1) {
+ case OMX_CommandStateSet:
+ return gst_structure_new (name,
+ "command", G_TYPE_STRING, cmd,
+ "state-reached", G_TYPE_STRING, gst_omx_state_to_string (data2),
+ NULL);
+ case OMX_CommandFlush:
+ case OMX_CommandPortDisable:
+ case OMX_CommandPortEnable:
+ case OMX_CommandMarkBuffer:
+ return gst_structure_new (name,
+ "command", G_TYPE_STRING, cmd, "port", G_TYPE_UINT, data2,
+ "error", G_TYPE_STRING,
+ gst_omx_error_to_string (GPOINTER_TO_UINT (event_data)), NULL);
+ case OMX_CommandKhronosExtensions:
+ case OMX_CommandVendorStartUnused:
+ case OMX_CommandMax:
+ break;
+ }
+ }
+ break;
+ case OMX_EventError:
+ return gst_structure_new (name, "error", G_TYPE_STRING,
+ gst_omx_error_to_string (data1), "extra-info", G_TYPE_STRING,
+ gst_omx_error_to_string (data2), NULL);
+ case OMX_EventMark:
+ case OMX_EventComponentResumed:
+ case OMX_EventResourcesAcquired:
+ case OMX_EventDynamicResourcesAvailable:
+ case OMX_EventPortFormatDetected:
+ return gst_structure_new_empty (name);
+ case OMX_EventPortSettingsChanged:
+#ifdef OMX_EventIndexSettingChanged
+ case OMX_EventIndexSettingChanged:
+#endif
+#ifdef OMX_EventPortNeedsDisable
+ case OMX_EventPortNeedsDisable:
+#endif
+#ifdef OMX_EventPortNeedsFlush
+ case OMX_EventPortNeedsFlush:
+#endif
+ return gst_structure_new (name, "port", G_TYPE_UINT,
+ data1, "param-config", G_TYPE_UINT, data2, NULL);
+ case OMX_EventBufferFlag:
+ return gst_structure_new (name, "port", G_TYPE_UINT,
+ data1, "flags", G_TYPE_STRING, gst_omx_buffer_flags_to_string (data2),
+ NULL);
+ case OMX_EventKhronosExtensions:
+ case OMX_EventVendorStartUnused:
+ case OMX_EventMax:
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static void
+log_omx_api_trace_event (GstOMXComponent * comp, OMX_EVENTTYPE event,
+ guint32 data1, guint32 data2, gpointer event_data)
+{
+#ifndef GST_DISABLE_GST_DEBUG
+ GstStructure *s;
+
+ /* Don't bother creating useless structs if not needed */
+ if (gst_debug_category_get_threshold (OMX_API_TRACE) < GST_LEVEL_DEBUG)
+ return;
+
+ s = omx_event_to_debug_struct (event, data1, data2, event_data);
+ if (!s) {
+ GST_CAT_WARNING_OBJECT (OMX_API_TRACE, comp->parent,
+ "invalid event 0x%08x Data1 %u Data2 %u EventData %p", event, data1,
+ data2, event_data);
+ return;
+ }
+
+ GST_CAT_DEBUG_OBJECT (OMX_API_TRACE, comp->parent, "%" GST_PTR_FORMAT, s);
+
+ gst_structure_free (s);
+#endif /* GST_DISABLE_GST_DEBUG */
+}
+
+static OMX_ERRORTYPE
+EventHandler (OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_EVENTTYPE eEvent,
+ OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData)
+{
+ GstOMXComponent *comp = (GstOMXComponent *) pAppData;
+
+ log_omx_api_trace_event (comp, eEvent, nData1, nData2, pEventData);
+
+ switch (eEvent) {
+ case OMX_EventCmdComplete:
+ {
+ OMX_COMMANDTYPE cmd = (OMX_COMMANDTYPE) nData1;
+
+ GST_DEBUG_OBJECT (comp->parent, "%s %s command complete (%d)",
+ comp->name, gst_omx_command_to_string (cmd), cmd);
+
+ switch (cmd) {
+ case OMX_CommandStateSet:{
+ GstOMXMessage *msg = g_slice_new (GstOMXMessage);
+
+ msg->type = GST_OMX_MESSAGE_STATE_SET;
+ msg->content.state_set.state = nData2;
+
+ GST_DEBUG_OBJECT (comp->parent, "%s state change to %s finished",
+ comp->name,
+ gst_omx_state_to_string (msg->content.state_set.state));
+
+ gst_omx_component_send_message (comp, msg);
+ break;
+ }
+ case OMX_CommandFlush:{
+ GstOMXMessage *msg = g_slice_new (GstOMXMessage);
+
+ msg->type = GST_OMX_MESSAGE_FLUSH;
+ msg->content.flush.port = nData2;
+ GST_DEBUG_OBJECT (comp->parent, "%s port %u flushed", comp->name,
+ (guint) msg->content.flush.port);
+
+ gst_omx_component_send_message (comp, msg);
+ break;
+ }
+ case OMX_CommandPortEnable:
+ case OMX_CommandPortDisable:{
+ GstOMXMessage *msg = g_slice_new (GstOMXMessage);
+
+ msg->type = GST_OMX_MESSAGE_PORT_ENABLE;
+ msg->content.port_enable.port = nData2;
+ msg->content.port_enable.enable = (cmd == OMX_CommandPortEnable);
+ GST_DEBUG_OBJECT (comp->parent, "%s port %u %s", comp->name,
+ (guint) msg->content.port_enable.port,
+ (msg->content.port_enable.enable ? "enabled" : "disabled"));
+
+ gst_omx_component_send_message (comp, msg);
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+ }
+ case OMX_EventError:
+ {
+ GstOMXMessage *msg;
+ OMX_ERRORTYPE error_type = nData1;
+
+ /* Yes, this really happens... */
+ if (error_type == OMX_ErrorNone)
+ break;
+
+ /* Always ignore PortUnpopulated error. This error is informational
+ * at best but it is useful for debugging some strange scenarios.
+ */
+ if (error_type == OMX_ErrorPortUnpopulated) {
+ GST_DEBUG_OBJECT (comp->parent, "%s got error: %s (0x%08x)",
+ comp->name, gst_omx_error_to_string (error_type), error_type);
+ break;
+ }
+
+ msg = g_slice_new (GstOMXMessage);
+
+ msg->type = GST_OMX_MESSAGE_ERROR;
+ msg->content.error.error = error_type;
+ GST_ERROR_OBJECT (comp->parent, "%s got error: %s (0x%08x)", comp->name,
+ gst_omx_error_to_string (msg->content.error.error),
+ msg->content.error.error);
+
+ gst_omx_component_send_message (comp, msg);
+ break;
+ }
+ case OMX_EventPortSettingsChanged:
+ {
+ GstOMXMessage *msg = g_slice_new (GstOMXMessage);
+ OMX_U32 index;
+
+ if (!(comp->hacks &
+ GST_OMX_HACK_EVENT_PORT_SETTINGS_CHANGED_NDATA_PARAMETER_SWAP)) {
+ index = nData1;
+ } else {
+ index = nData2;
+ }
+
+
+ if (index == 0
+ && (comp->hacks &
+ GST_OMX_HACK_EVENT_PORT_SETTINGS_CHANGED_PORT_0_TO_1))
+ index = 1;
+
+
+ msg->type = GST_OMX_MESSAGE_PORT_SETTINGS_CHANGED;
+ msg->content.port_settings_changed.port = index;
+ GST_DEBUG_OBJECT (comp->parent, "%s settings changed (port index: %u)",
+ comp->name, (guint) msg->content.port_settings_changed.port);
+
+ gst_omx_component_send_message (comp, msg);
+ break;
+ }
+ case OMX_EventBufferFlag:{
+ GstOMXMessage *msg;
+
+ msg = g_slice_new (GstOMXMessage);
+
+ msg->type = GST_OMX_MESSAGE_BUFFER_FLAG;
+ msg->content.buffer_flag.port = nData1;
+ msg->content.buffer_flag.flags = nData2;
+ GST_DEBUG_OBJECT (comp->parent, "%s port %u got buffer flags 0x%08x (%s)",
+ comp->name, (guint) msg->content.buffer_flag.port,
+ (guint) msg->content.buffer_flag.flags,
+ gst_omx_buffer_flags_to_string (msg->content.buffer_flag.flags));
+
+ gst_omx_component_send_message (comp, msg);
+ break;
+ }
+ case OMX_EventPortFormatDetected:
+ default:
+ GST_DEBUG_OBJECT (comp->parent, "%s unknown event 0x%08x", comp->name,
+ eEvent);
+ break;
+ }
+
+ return OMX_ErrorNone;
+}
+
+static void
+gst_omx_buffer_unmap (GstOMXBuffer * buffer)
+{
+ g_return_if_fail (buffer != NULL);
+
+ if (buffer->input_frame_mapped) {
+ g_assert (!buffer->input_mem);
+ g_assert (!buffer->input_buffer);
+ g_assert (!buffer->input_buffer_mapped);
+ gst_video_frame_unmap (&buffer->input_frame);
+ buffer->input_frame_mapped = FALSE;
+ } else if (buffer->input_mem) {
+ g_assert (!buffer->input_buffer);
+ g_assert (!buffer->input_buffer_mapped);
+ gst_memory_unmap (buffer->input_mem, &buffer->map);
+ g_clear_pointer (&buffer->input_mem, gst_memory_unref);
+ } else if (buffer->input_buffer) {
+ if (buffer->input_buffer_mapped)
+ gst_buffer_unmap (buffer->input_buffer, &buffer->map);
+ buffer->input_buffer_mapped = FALSE;
+ g_clear_pointer (&buffer->input_buffer, gst_buffer_unref);
+ }
+}
+
+static void
+log_omx_api_trace_buffer (GstOMXComponent * comp, const gchar * event,
+ GstOMXBuffer * buf)
+{
+#ifndef GST_DISABLE_GST_DEBUG
+ GstStructure *s;
+
+ /* Don't bother creating useless structs if not needed */
+ if (gst_debug_category_get_threshold (OMX_API_TRACE) < GST_LEVEL_TRACE)
+ return;
+
+ if (buf) {
+ gchar *buf_str, *omx_buf_str, *pbuffer_str;
+
+ /* GST_PTR_FORMAT won't serialize G_TYPE_POINTER fields so stringify pointers */
+ buf_str = g_strdup_printf ("%p", buf);
+ omx_buf_str = g_strdup_printf ("%p", buf->omx_buf);
+ pbuffer_str = g_strdup_printf ("%p", buf->omx_buf->pBuffer);
+
+ /* *INDENT-OFF* */
+ s = gst_structure_new (event,
+ "GstOMXBuffer", G_TYPE_STRING, buf_str,
+ "OMX-buffer", G_TYPE_STRING, omx_buf_str,
+ "pBuffer", G_TYPE_STRING, pbuffer_str,
+ "TimeStamp", G_TYPE_UINT64, GST_OMX_GET_TICKS (buf->omx_buf->nTimeStamp),
+ "AllocLen", G_TYPE_UINT, buf->omx_buf->nAllocLen,
+ "FilledLen", G_TYPE_UINT, buf->omx_buf->nFilledLen,
+ "flags", G_TYPE_UINT, buf->omx_buf->nFlags,
+ "flags-str", G_TYPE_STRING, gst_omx_buffer_flags_to_string (buf->omx_buf->nFlags),
+ NULL);
+ /* *INDENT-ON* */
+
+ g_free (buf_str);
+ g_free (omx_buf_str);
+ g_free (pbuffer_str);
+ } else {
+ s = gst_structure_new_empty (event);
+ }
+
+ GST_CAT_TRACE_OBJECT (OMX_API_TRACE, comp->parent, "%" GST_PTR_FORMAT, s);
+
+ gst_structure_free (s);
+#endif /* GST_DISABLE_GST_DEBUG */
+}
+
+static OMX_ERRORTYPE
+EmptyBufferDone (OMX_HANDLETYPE hComponent, OMX_PTR pAppData,
+ OMX_BUFFERHEADERTYPE * pBuffer)
+{
+ GstOMXBuffer *buf;
+ GstOMXComponent *comp;
+ GstOMXMessage *msg;
+
+ buf = pBuffer->pAppPrivate;
+ if (!buf) {
+ GST_ERROR ("Have unknown or deallocated buffer %p", pBuffer);
+ return OMX_ErrorNone;
+ }
+
+ g_assert (buf->omx_buf == pBuffer);
+
+ if (buf->port->tunneled) {
+ GST_ERROR ("EmptyBufferDone on tunneled port");
+ return OMX_ErrorBadParameter;
+ }
+
+ comp = buf->port->comp;
+
+ msg = g_slice_new (GstOMXMessage);
+ msg->type = GST_OMX_MESSAGE_BUFFER_DONE;
+ msg->content.buffer_done.component = hComponent;
+ msg->content.buffer_done.app_data = pAppData;
+ msg->content.buffer_done.buffer = pBuffer;
+ msg->content.buffer_done.empty = OMX_TRUE;
+
+ log_omx_api_trace_buffer (comp, "EmptyBufferDone", buf);
+ GST_LOG_OBJECT (comp->parent, "%s port %u emptied buffer %p (%p)",
+ comp->name, buf->port->index, buf, buf->omx_buf->pBuffer);
+
+ gst_omx_component_send_message (comp, msg);
+
+ return OMX_ErrorNone;
+}
+
+static OMX_ERRORTYPE
+FillBufferDone (OMX_HANDLETYPE hComponent, OMX_PTR pAppData,
+ OMX_BUFFERHEADERTYPE * pBuffer)
+{
+ GstOMXBuffer *buf;
+ GstOMXComponent *comp;
+ GstOMXMessage *msg;
+
+ buf = pBuffer->pAppPrivate;
+ if (!buf) {
+ GST_ERROR ("Have unknown or deallocated buffer %p", pBuffer);
+ return OMX_ErrorNone;
+ }
+
+ g_assert (buf->omx_buf == pBuffer);
+
+ if (buf->port->tunneled) {
+ GST_ERROR ("FillBufferDone on tunneled port");
+ return OMX_ErrorBadParameter;
+ }
+
+ comp = buf->port->comp;
+
+ msg = g_slice_new (GstOMXMessage);
+ msg->type = GST_OMX_MESSAGE_BUFFER_DONE;
+ msg->content.buffer_done.component = hComponent;
+ msg->content.buffer_done.app_data = pAppData;
+ msg->content.buffer_done.buffer = pBuffer;
+ msg->content.buffer_done.empty = OMX_FALSE;
+
+ log_omx_api_trace_buffer (comp, "FillBufferDone", buf);
+ GST_LOG_OBJECT (comp->parent, "%s port %u filled buffer %p (%p)", comp->name,
+ buf->port->index, buf, buf->omx_buf->pBuffer);
+
+ gst_omx_component_send_message (comp, msg);
+
+ return OMX_ErrorNone;
+}
+
+static OMX_CALLBACKTYPE callbacks =
+ { EventHandler, EmptyBufferDone, FillBufferDone };
+
+GST_DEFINE_MINI_OBJECT_TYPE (GstOMXComponent, gst_omx_component);
+
+static void gst_omx_component_free (GstOMXComponent * comp);
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+GstOMXComponent *
+gst_omx_component_new (GstObject * parent, const gchar * core_name,
+ const gchar * component_name, const gchar * component_role, guint64 hacks)
+{
+ OMX_ERRORTYPE err;
+ GstOMXCore *core;
+ GstOMXComponent *comp;
+ const gchar *dot;
+
+ core = gst_omx_core_acquire (core_name);
+ if (!core)
+ return NULL;
+
+ comp = g_slice_new0 (GstOMXComponent);
+ comp->core = core;
+
+ gst_mini_object_init (GST_MINI_OBJECT_CAST (comp), 0,
+ gst_omx_component_get_type (), NULL, NULL,
+ (GstMiniObjectFreeFunction) gst_omx_component_free);
+
+ if ((dot = g_strrstr (component_name, ".")))
+ comp->name = g_strdup (dot + 1);
+ else
+ comp->name = g_strdup (component_name);
+
+ err =
+ core->get_handle (&comp->handle, (OMX_STRING) component_name, comp,
+ &callbacks);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (parent,
+ "Failed to get component handle '%s' from core '%s': 0x%08x",
+ component_name, core_name, err);
+ gst_omx_core_release (core);
+ g_free (comp->name);
+ g_slice_free (GstOMXComponent, comp);
+ return NULL;
+ }
+ GST_DEBUG_OBJECT (parent,
+ "Successfully got component handle %p (%s) from core '%s'", comp->handle,
+ component_name, core_name);
+ comp->parent = gst_object_ref (parent);
+ comp->hacks = hacks;
+
+ comp->ports = g_ptr_array_new ();
+ comp->n_in_ports = 0;
+ comp->n_out_ports = 0;
+
+ g_mutex_init (&comp->lock);
+ g_mutex_init (&comp->messages_lock);
+ g_cond_init (&comp->messages_cond);
+
+ g_queue_init (&comp->messages);
+ comp->pending_state = OMX_StateInvalid;
+ comp->last_error = OMX_ErrorNone;
+
+ /* Set component role if any */
+ if (component_role && !(hacks & GST_OMX_HACK_NO_COMPONENT_ROLE)) {
+ OMX_PARAM_COMPONENTROLETYPE param;
+
+ GST_OMX_INIT_STRUCT (&param);
+
+ g_strlcpy ((gchar *) param.cRole, component_role, sizeof (param.cRole));
+ err =
+ gst_omx_component_set_parameter (comp,
+ OMX_IndexParamStandardComponentRole, &param);
+
+ DEBUG_IF_OK (comp->parent, err,
+ "Setting component role to '%s': %s (0x%08x)", component_role,
+ gst_omx_error_to_string (err), err);
+
+ /* If setting the role failed this component is unusable */
+ if (err != OMX_ErrorNone) {
+ gst_omx_component_free (comp);
+ return NULL;
+ }
+ }
+
+ OMX_GetState (comp->handle, &comp->state);
+
+ g_mutex_lock (&comp->lock);
+ gst_omx_component_handle_messages (comp);
+ g_mutex_unlock (&comp->lock);
+
+ return comp;
+}
+
+/* NOTE: Uses comp->messages_lock */
+static void
+gst_omx_component_free (GstOMXComponent * comp)
+{
+ gint i, n;
+
+ g_return_if_fail (comp != NULL);
+
+ GST_INFO_OBJECT (comp->parent, "Unloading component %p %s", comp, comp->name);
+
+ if (comp->ports) {
+ n = comp->ports->len;
+ for (i = 0; i < n; i++) {
+ GstOMXPort *port = g_ptr_array_index (comp->ports, i);
+
+ gst_omx_port_deallocate_buffers (port);
+ g_assert (port->buffers == NULL);
+ g_assert (g_queue_get_length (&port->pending_buffers) == 0);
+
+ g_slice_free (GstOMXPort, port);
+ }
+ g_ptr_array_unref (comp->ports);
+ comp->ports = NULL;
+ }
+
+ comp->core->free_handle (comp->handle);
+ gst_omx_core_release (comp->core);
+
+ gst_omx_component_flush_messages (comp);
+
+ g_cond_clear (&comp->messages_cond);
+ g_mutex_clear (&comp->messages_lock);
+ g_mutex_clear (&comp->lock);
+
+ gst_object_unref (comp->parent);
+
+ g_free (comp->name);
+ comp->name = NULL;
+
+ g_slice_free (GstOMXComponent, comp);
+}
+
+GstOMXComponent *
+gst_omx_component_ref (GstOMXComponent * comp)
+{
+ g_return_val_if_fail (comp, NULL);
+
+ gst_mini_object_ref (GST_MINI_OBJECT_CAST (comp));
+ return comp;
+}
+
+void
+gst_omx_component_unref (GstOMXComponent * comp)
+{
+ g_return_if_fail (comp);
+
+ gst_mini_object_unref (GST_MINI_OBJECT_CAST (comp));
+}
+
+static GstStructure *
+omx_command_to_debug_struct (OMX_COMMANDTYPE cmd,
+ guint32 param, gpointer cmd_data)
+{
+ const gchar *cmd_str;
+
+ cmd_str = gst_omx_command_to_string (cmd);
+
+ switch (cmd) {
+ case OMX_CommandStateSet:
+ return gst_structure_new ("SendCommand",
+ "command", G_TYPE_STRING, cmd_str,
+ "state", G_TYPE_STRING, gst_omx_state_to_string (param), NULL);
+ case OMX_CommandFlush:
+ case OMX_CommandPortDisable:
+ case OMX_CommandPortEnable:
+ return gst_structure_new ("SendCommand",
+ "command", G_TYPE_STRING, cmd_str, "port", G_TYPE_UINT, param, NULL);
+ case OMX_CommandMarkBuffer:
+ return gst_structure_new ("SendCommand",
+ "command", G_TYPE_STRING, cmd_str,
+ "mark-type", G_TYPE_POINTER, cmd_data, NULL);
+ case OMX_CommandKhronosExtensions:
+ case OMX_CommandVendorStartUnused:
+ case OMX_CommandMax:
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static void
+log_omx_api_trace_send_command (GstOMXComponent * comp, OMX_COMMANDTYPE cmd,
+ guint32 param, gpointer cmd_data)
+{
+#ifndef GST_DISABLE_GST_DEBUG
+ GstStructure *s;
+
+ /* Don't bother creating useless structs if not needed */
+ if (gst_debug_category_get_threshold (OMX_API_TRACE) < GST_LEVEL_DEBUG)
+ return;
+
+ s = omx_command_to_debug_struct (cmd, param, cmd_data);
+ if (!s) {
+ GST_CAT_WARNING_OBJECT (OMX_API_TRACE, comp->parent,
+ "invalid command 0x%08x Param %u CmdData %p", cmd, param, cmd_data);
+ return;
+ }
+
+ GST_CAT_DEBUG_OBJECT (OMX_API_TRACE, comp->parent, "%" GST_PTR_FORMAT, s);
+
+ gst_structure_free (s);
+#endif /* GST_DISABLE_GST_DEBUG */
+}
+
+static OMX_ERRORTYPE
+gst_omx_component_send_command (GstOMXComponent * comp, OMX_COMMANDTYPE cmd,
+ guint32 param, gpointer cmd_data)
+{
+ OMX_ERRORTYPE err;
+
+ log_omx_api_trace_send_command (comp, cmd, param, cmd_data);
+ err = OMX_SendCommand (comp->handle, cmd, param, cmd_data);
+
+ return err;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_component_set_state (GstOMXComponent * comp, OMX_STATETYPE state)
+{
+ OMX_STATETYPE old_state;
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+
+ g_return_val_if_fail (comp != NULL, OMX_ErrorUndefined);
+
+ g_mutex_lock (&comp->lock);
+
+ gst_omx_component_handle_messages (comp);
+
+ old_state = comp->state;
+ GST_INFO_OBJECT (comp->parent, "Setting %s state from %s to %s", comp->name,
+ gst_omx_state_to_string (old_state), gst_omx_state_to_string (state));
+
+ if ((err = comp->last_error) != OMX_ErrorNone && state > old_state) {
+ GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
+ comp->name, gst_omx_error_to_string (err), err);
+ goto done;
+ }
+
+ if (old_state == state || comp->pending_state == state) {
+ GST_DEBUG_OBJECT (comp->parent, "Component %s already in state %s",
+ comp->name, gst_omx_state_to_string (state));
+ goto done;
+ }
+
+ comp->pending_state = state;
+
+ /* Reset some things */
+ if ((old_state == OMX_StateExecuting || old_state == OMX_StatePause)
+ && state < old_state) {
+ g_list_free (comp->pending_reconfigure_outports);
+ comp->pending_reconfigure_outports = NULL;
+ /* Notify all inports that are still waiting */
+ gst_omx_component_send_message (comp, NULL);
+ }
+
+ err = gst_omx_component_send_command (comp, OMX_CommandStateSet, state, NULL);
+ /* No need to check if anything has changed here */
+
+done:
+
+ gst_omx_component_handle_messages (comp);
+
+ if (err != OMX_ErrorNone && comp->last_error == OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent,
+ "Last operation returned an error. Setting last_error manually.");
+ comp->last_error = err;
+ }
+
+ g_mutex_unlock (&comp->lock);
+
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent,
+ "Error setting %s state from %s to %s: %s (0x%08x)", comp->name,
+ gst_omx_state_to_string (old_state), gst_omx_state_to_string (state),
+ gst_omx_error_to_string (err), err);
+ }
+ return err;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_STATETYPE
+gst_omx_component_get_state (GstOMXComponent * comp, GstClockTime timeout)
+{
+ OMX_STATETYPE ret;
+ gboolean signalled = TRUE;
+
+ g_return_val_if_fail (comp != NULL, OMX_StateInvalid);
+
+ GST_DEBUG_OBJECT (comp->parent, "Getting state of %s", comp->name);
+
+ g_mutex_lock (&comp->lock);
+
+ gst_omx_component_handle_messages (comp);
+
+ if (comp->last_error != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
+ comp->name, gst_omx_error_to_string (comp->last_error),
+ comp->last_error);
+ ret = OMX_StateInvalid;
+ goto done;
+ }
+
+ ret = comp->state;
+ if (comp->pending_state == OMX_StateInvalid)
+ goto done;
+
+ while (signalled && comp->last_error == OMX_ErrorNone
+ && comp->pending_state != OMX_StateInvalid) {
+
+ signalled = gst_omx_component_wait_message (comp, timeout);
+ if (signalled)
+ gst_omx_component_handle_messages (comp);
+ };
+
+ if (signalled) {
+ if (comp->last_error != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent,
+ "%s got error while waiting for state change: %s (0x%08x)",
+ comp->name, gst_omx_error_to_string (comp->last_error),
+ comp->last_error);
+ ret = OMX_StateInvalid;
+ } else if (comp->pending_state == OMX_StateInvalid) {
+ /* State change finished and everything's fine */
+ ret = comp->state;
+ } else {
+ ret = OMX_StateInvalid;
+ g_assert_not_reached ();
+ }
+ } else {
+ ret = OMX_StateInvalid;
+ GST_WARNING_OBJECT (comp->parent, "%s timeout while waiting for state "
+ "change", comp->name);
+ }
+
+done:
+ g_mutex_unlock (&comp->lock);
+
+ GST_DEBUG_OBJECT (comp->parent, "%s returning state %s", comp->name,
+ gst_omx_state_to_string (ret));
+
+ return ret;
+}
+
+GstOMXPort *
+gst_omx_component_add_port (GstOMXComponent * comp, guint32 index)
+{
+ gint i, n;
+ GstOMXPort *port;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ OMX_ERRORTYPE err;
+
+ g_return_val_if_fail (comp != NULL, NULL);
+
+ /* Check if this port exists already */
+ n = comp->ports->len;
+ for (i = 0; i < n; i++) {
+ port = g_ptr_array_index (comp->ports, i);
+ g_return_val_if_fail (port->index != index, NULL);
+ }
+
+ GST_DEBUG_OBJECT (comp->parent, "%s adding port %u", comp->name, index);
+
+ GST_OMX_INIT_STRUCT (&port_def);
+ port_def.nPortIndex = index;
+
+ err = gst_omx_component_get_parameter (comp, OMX_IndexParamPortDefinition,
+ &port_def);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent, "%s failed to add port %u: %s (0x%08x)",
+ comp->name, index, gst_omx_error_to_string (err), err);
+ return NULL;
+ }
+
+ port = g_slice_new0 (GstOMXPort);
+ port->comp = comp;
+ port->index = index;
+
+ port->tunneled = FALSE;
+
+ port->port_def = port_def;
+
+ g_queue_init (&port->pending_buffers);
+ port->flushing = TRUE;
+ port->flushed = FALSE;
+ port->enabled_pending = FALSE;
+ port->disabled_pending = FALSE;
+ port->eos = FALSE;
+ port->using_pool = FALSE;
+
+ if (port->port_def.eDir == OMX_DirInput)
+ comp->n_in_ports++;
+ else
+ comp->n_out_ports++;
+
+ g_ptr_array_add (comp->ports, port);
+
+ return port;
+}
+
+GstOMXPort *
+gst_omx_component_get_port (GstOMXComponent * comp, guint32 index)
+{
+ gint i, n;
+
+ n = comp->ports->len;
+ for (i = 0; i < n; i++) {
+ GstOMXPort *tmp = g_ptr_array_index (comp->ports, i);
+
+ if (tmp->index == index)
+ return tmp;
+ }
+ return NULL;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_component_get_last_error (GstOMXComponent * comp)
+{
+ OMX_ERRORTYPE err;
+
+ g_return_val_if_fail (comp != NULL, OMX_ErrorUndefined);
+
+ g_mutex_lock (&comp->lock);
+ gst_omx_component_handle_messages (comp);
+ err = comp->last_error;
+ g_mutex_unlock (&comp->lock);
+
+ GST_DEBUG_OBJECT (comp->parent, "Returning last %s error: %s (0x%08x)",
+ comp->name, gst_omx_error_to_string (err), err);
+
+ return err;
+}
+
+const gchar *
+gst_omx_component_get_last_error_string (GstOMXComponent * comp)
+{
+ g_return_val_if_fail (comp != NULL, NULL);
+
+ return gst_omx_error_to_string (gst_omx_component_get_last_error (comp));
+}
+
+#ifndef GST_DISABLE_GST_DEBUG
+static const gchar *
+omx_index_type_to_str (OMX_INDEXTYPE index)
+{
+ switch (index) {
+ case OMX_IndexComponentStartUnused:
+ return "OMX_IndexComponentStartUnused";
+ case OMX_IndexParamPriorityMgmt:
+ return "OMX_IndexParamPriorityMgmt";
+ case OMX_IndexParamAudioInit:
+ return "OMX_IndexParamAudioInit";
+ case OMX_IndexParamImageInit:
+ return "OMX_IndexParamImageInit";
+ case OMX_IndexParamVideoInit:
+ return "OMX_IndexParamVideoInit";
+ case OMX_IndexParamOtherInit:
+ return "OMX_IndexParamOtherInit";
+ case OMX_IndexParamNumAvailableStreams:
+ return "OMX_IndexParamNumAvailableStreams";
+ case OMX_IndexParamActiveStream:
+ return "OMX_IndexParamActiveStream";
+ case OMX_IndexParamSuspensionPolicy:
+ return "OMX_IndexParamSuspensionPolicy";
+ case OMX_IndexParamComponentSuspended:
+ return "OMX_IndexParamComponentSuspended";
+ case OMX_IndexConfigCapturing:
+ return "OMX_IndexConfigCapturing";
+ case OMX_IndexConfigCaptureMode:
+ return "OMX_IndexConfigCaptureMode";
+ case OMX_IndexAutoPauseAfterCapture:
+ return "OMX_IndexAutoPauseAfterCapture";
+ case OMX_IndexParamContentURI:
+ return "OMX_IndexParamContentURI";
+ case OMX_IndexParamDisableResourceConcealment:
+ return "OMX_IndexParamDisableResourceConcealment";
+ case OMX_IndexConfigMetadataItemCount:
+ return "OMX_IndexConfigMetadataItemCount";
+ case OMX_IndexConfigContainerNodeCount:
+ return "OMX_IndexConfigContainerNodeCount";
+ case OMX_IndexConfigMetadataItem:
+ return "OMX_IndexConfigMetadataItem";
+ case OMX_IndexConfigCounterNodeID:
+ return "OMX_IndexConfigCounterNodeID";
+ case OMX_IndexParamMetadataFilterType:
+ return "OMX_IndexParamMetadataFilterType";
+ case OMX_IndexParamMetadataKeyFilter:
+ return "OMX_IndexParamMetadataKeyFilter";
+ case OMX_IndexConfigPriorityMgmt:
+ return "OMX_IndexConfigPriorityMgmt";
+ case OMX_IndexParamStandardComponentRole:
+ return "OMX_IndexParamStandardComponentRole";
+ case OMX_IndexPortStartUnused:
+ return "OMX_IndexPortStartUnused";
+ case OMX_IndexParamPortDefinition:
+ return "OMX_IndexParamPortDefinition";
+ case OMX_IndexParamCompBufferSupplier:
+ return "OMX_IndexParamCompBufferSupplier";
+ case OMX_IndexReservedStartUnused:
+ return "OMX_IndexReservedStartUnused";
+ case OMX_IndexAudioStartUnused:
+ return "OMX_IndexAudioStartUnused";
+ case OMX_IndexParamAudioPortFormat:
+ return "OMX_IndexParamAudioPortFormat";
+ case OMX_IndexParamAudioPcm:
+ return "OMX_IndexParamAudioPcm";
+ case OMX_IndexParamAudioAac:
+ return "OMX_IndexParamAudioAac";
+ case OMX_IndexParamAudioRa:
+ return "OMX_IndexParamAudioRa";
+ case OMX_IndexParamAudioMp3:
+ return "OMX_IndexParamAudioMp3";
+ case OMX_IndexParamAudioAdpcm:
+ return "OMX_IndexParamAudioAdpcm";
+ case OMX_IndexParamAudioG723:
+ return "OMX_IndexParamAudioG723";
+ case OMX_IndexParamAudioG729:
+ return "OMX_IndexParamAudioG729";
+ case OMX_IndexParamAudioAmr:
+ return "OMX_IndexParamAudioAmr";
+ case OMX_IndexParamAudioWma:
+ return "OMX_IndexParamAudioWma";
+ case OMX_IndexParamAudioSbc:
+ return "OMX_IndexParamAudioSbc";
+ case OMX_IndexParamAudioMidi:
+ return "OMX_IndexParamAudioMidi";
+ case OMX_IndexParamAudioGsm_FR:
+ return "OMX_IndexParamAudioGsm_FR";
+ case OMX_IndexParamAudioMidiLoadUserSound:
+ return "OMX_IndexParamAudioMidiLoadUserSound";
+ case OMX_IndexParamAudioG726:
+ return "OMX_IndexParamAudioG726";
+ case OMX_IndexParamAudioGsm_EFR:
+ return "OMX_IndexParamAudioGsm_EFR";
+ case OMX_IndexParamAudioGsm_HR:
+ return "OMX_IndexParamAudioGsm_HR";
+ case OMX_IndexParamAudioPdc_FR:
+ return "OMX_IndexParamAudioPdc_FR";
+ case OMX_IndexParamAudioPdc_EFR:
+ return "OMX_IndexParamAudioPdc_EFR";
+ case OMX_IndexParamAudioPdc_HR:
+ return "OMX_IndexParamAudioPdc_HR";
+ case OMX_IndexParamAudioTdma_FR:
+ return "OMX_IndexParamAudioTdma_FR";
+ case OMX_IndexParamAudioTdma_EFR:
+ return "OMX_IndexParamAudioTdma_EFR";
+ case OMX_IndexParamAudioQcelp8:
+ return "OMX_IndexParamAudioQcelp8";
+ case OMX_IndexParamAudioQcelp13:
+ return "OMX_IndexParamAudioQcelp13";
+ case OMX_IndexParamAudioEvrc:
+ return "OMX_IndexParamAudioEvrc";
+ case OMX_IndexParamAudioSmv:
+ return "OMX_IndexParamAudioSmv";
+ case OMX_IndexParamAudioVorbis:
+ return "OMX_IndexParamAudioVorbis";
+ case OMX_IndexConfigAudioMidiImmediateEvent:
+ return "OMX_IndexConfigAudioMidiImmediateEvent";
+ case OMX_IndexConfigAudioMidiControl:
+ return "OMX_IndexConfigAudioMidiControl";
+ case OMX_IndexConfigAudioMidiSoundBankProgram:
+ return "OMX_IndexConfigAudioMidiSoundBankProgram";
+ case OMX_IndexConfigAudioMidiStatus:
+ return "OMX_IndexConfigAudioMidiStatus";
+ case OMX_IndexConfigAudioMidiMetaEvent:
+ return "OMX_IndexConfigAudioMidiMetaEvent";
+ case OMX_IndexConfigAudioMidiMetaEventData:
+ return "OMX_IndexConfigAudioMidiMetaEventData";
+ case OMX_IndexConfigAudioVolume:
+ return "OMX_IndexConfigAudioVolume";
+ case OMX_IndexConfigAudioBalance:
+ return "OMX_IndexConfigAudioBalance";
+ case OMX_IndexConfigAudioChannelMute:
+ return "OMX_IndexConfigAudioChannelMute";
+ case OMX_IndexConfigAudioMute:
+ return "OMX_IndexConfigAudioMute";
+ case OMX_IndexConfigAudioLoudness:
+ return "OMX_IndexConfigAudioLoudness";
+ case OMX_IndexConfigAudioEchoCancelation:
+ return "OMX_IndexConfigAudioEchoCancelation";
+ case OMX_IndexConfigAudioNoiseReduction:
+ return "OMX_IndexConfigAudioNoiseReduction";
+ case OMX_IndexConfigAudioBass:
+ return "OMX_IndexConfigAudioBass";
+ case OMX_IndexConfigAudioTreble:
+ return "OMX_IndexConfigAudioTreble";
+ case OMX_IndexConfigAudioStereoWidening:
+ return "OMX_IndexConfigAudioStereoWidening";
+ case OMX_IndexConfigAudioChorus:
+ return "OMX_IndexConfigAudioChorus";
+ case OMX_IndexConfigAudioEqualizer:
+ return "OMX_IndexConfigAudioEqualizer";
+ case OMX_IndexConfigAudioReverberation:
+ return "OMX_IndexConfigAudioReverberation";
+ case OMX_IndexConfigAudioChannelVolume:
+ return "OMX_IndexConfigAudioChannelVolume";
+ case OMX_IndexImageStartUnused:
+ return "OMX_IndexImageStartUnused";
+ case OMX_IndexParamImagePortFormat:
+ return "OMX_IndexParamImagePortFormat";
+ case OMX_IndexParamFlashControl:
+ return "OMX_IndexParamFlashControl";
+ case OMX_IndexConfigFocusControl:
+ return "OMX_IndexConfigFocusControl";
+ case OMX_IndexParamQFactor:
+ return "OMX_IndexParamQFactor";
+ case OMX_IndexParamQuantizationTable:
+ return "OMX_IndexParamQuantizationTable";
+ case OMX_IndexParamHuffmanTable:
+ return "OMX_IndexParamHuffmanTable";
+ case OMX_IndexConfigFlashControl:
+ return "OMX_IndexConfigFlashControl";
+ case OMX_IndexVideoStartUnused:
+ return "OMX_IndexVideoStartUnused";
+ case OMX_IndexParamVideoPortFormat:
+ return "OMX_IndexParamVideoPortFormat";
+ case OMX_IndexParamVideoQuantization:
+ return "OMX_IndexParamVideoQuantization";
+ case OMX_IndexParamVideoFastUpdate:
+ return "OMX_IndexParamVideoFastUpdate";
+ case OMX_IndexParamVideoBitrate:
+ return "OMX_IndexParamVideoBitrate";
+ case OMX_IndexParamVideoMotionVector:
+ return "OMX_IndexParamVideoMotionVector";
+ case OMX_IndexParamVideoIntraRefresh:
+ return "OMX_IndexParamVideoIntraRefresh";
+ case OMX_IndexParamVideoErrorCorrection:
+ return "OMX_IndexParamVideoErrorCorrection";
+ case OMX_IndexParamVideoVBSMC:
+ return "OMX_IndexParamVideoVBSMC";
+ case OMX_IndexParamVideoMpeg2:
+ return "OMX_IndexParamVideoMpeg2";
+ case OMX_IndexParamVideoMpeg4:
+ return "OMX_IndexParamVideoMpeg4";
+ case OMX_IndexParamVideoWmv:
+ return "OMX_IndexParamVideoWmv";
+ case OMX_IndexParamVideoRv:
+ return "OMX_IndexParamVideoRv";
+ case OMX_IndexParamVideoAvc:
+ return "OMX_IndexParamVideoAvc";
+ case OMX_IndexParamVideoH263:
+ return "OMX_IndexParamVideoH263";
+ case OMX_IndexParamVideoProfileLevelQuerySupported:
+ return "OMX_IndexParamVideoProfileLevelQuerySupported";
+ case OMX_IndexParamVideoProfileLevelCurrent:
+ return "OMX_IndexParamVideoProfileLevelCurrent";
+ case OMX_IndexConfigVideoBitrate:
+ return "OMX_IndexConfigVideoBitrate";
+ case OMX_IndexConfigVideoFramerate:
+ return "OMX_IndexConfigVideoFramerate";
+ case OMX_IndexConfigVideoIntraVOPRefresh:
+ return "OMX_IndexConfigVideoIntraVOPRefresh";
+ case OMX_IndexConfigVideoIntraMBRefresh:
+ return "OMX_IndexConfigVideoIntraMBRefresh";
+ case OMX_IndexConfigVideoMBErrorReporting:
+ return "OMX_IndexConfigVideoMBErrorReporting";
+ case OMX_IndexParamVideoMacroblocksPerFrame:
+ return "OMX_IndexParamVideoMacroblocksPerFrame";
+ case OMX_IndexConfigVideoMacroBlockErrorMap:
+ return "OMX_IndexConfigVideoMacroBlockErrorMap";
+ case OMX_IndexParamVideoSliceFMO:
+ return "OMX_IndexParamVideoSliceFMO";
+ case OMX_IndexConfigVideoAVCIntraPeriod:
+ return "OMX_IndexConfigVideoAVCIntraPeriod";
+ case OMX_IndexConfigVideoNalSize:
+ return "OMX_IndexConfigVideoNalSize";
+ case OMX_IndexCommonStartUnused:
+ return "OMX_IndexCommonStartUnused";
+ case OMX_IndexParamCommonDeblocking:
+ return "OMX_IndexParamCommonDeblocking";
+ case OMX_IndexParamCommonSensorMode:
+ return "OMX_IndexParamCommonSensorMode";
+ case OMX_IndexParamCommonInterleave:
+ return "OMX_IndexParamCommonInterleave";
+ case OMX_IndexConfigCommonColorFormatConversion:
+ return "OMX_IndexConfigCommonColorFormatConversion";
+ case OMX_IndexConfigCommonScale:
+ return "OMX_IndexConfigCommonScale";
+ case OMX_IndexConfigCommonImageFilter:
+ return "OMX_IndexConfigCommonImageFilter";
+ case OMX_IndexConfigCommonColorEnhancement:
+ return "OMX_IndexConfigCommonColorEnhancement";
+ case OMX_IndexConfigCommonColorKey:
+ return "OMX_IndexConfigCommonColorKey";
+ case OMX_IndexConfigCommonColorBlend:
+ return "OMX_IndexConfigCommonColorBlend";
+ case OMX_IndexConfigCommonFrameStabilisation:
+ return "OMX_IndexConfigCommonFrameStabilisation";
+ case OMX_IndexConfigCommonRotate:
+ return "OMX_IndexConfigCommonRotate";
+ case OMX_IndexConfigCommonMirror:
+ return "OMX_IndexConfigCommonMirror";
+ case OMX_IndexConfigCommonOutputPosition:
+ return "OMX_IndexConfigCommonOutputPosition";
+ case OMX_IndexConfigCommonInputCrop:
+ return "OMX_IndexConfigCommonInputCrop";
+ case OMX_IndexConfigCommonOutputCrop:
+ return "OMX_IndexConfigCommonOutputCrop";
+ case OMX_IndexConfigCommonDigitalZoom:
+ return "OMX_IndexConfigCommonDigitalZoom";
+ case OMX_IndexConfigCommonOpticalZoom:
+ return "OMX_IndexConfigCommonOpticalZoom";
+ case OMX_IndexConfigCommonWhiteBalance:
+ return "OMX_IndexConfigCommonWhiteBalance";
+ case OMX_IndexConfigCommonExposure:
+ return "OMX_IndexConfigCommonExposure";
+ case OMX_IndexConfigCommonContrast:
+ return "OMX_IndexConfigCommonContrast";
+ case OMX_IndexConfigCommonBrightness:
+ return "OMX_IndexConfigCommonBrightness";
+ case OMX_IndexConfigCommonBacklight:
+ return "OMX_IndexConfigCommonBacklight";
+ case OMX_IndexConfigCommonGamma:
+ return "OMX_IndexConfigCommonGamma";
+ case OMX_IndexConfigCommonSaturation:
+ return "OMX_IndexConfigCommonSaturation";
+ case OMX_IndexConfigCommonLightness:
+ return "OMX_IndexConfigCommonLightness";
+ case OMX_IndexConfigCommonExclusionRect:
+ return "OMX_IndexConfigCommonExclusionRect";
+ case OMX_IndexConfigCommonDithering:
+ return "OMX_IndexConfigCommonDithering";
+ case OMX_IndexConfigCommonPlaneBlend:
+ return "OMX_IndexConfigCommonPlaneBlend";
+ case OMX_IndexConfigCommonExposureValue:
+ return "OMX_IndexConfigCommonExposureValue";
+ case OMX_IndexConfigCommonOutputSize:
+ return "OMX_IndexConfigCommonOutputSize";
+ case OMX_IndexParamCommonExtraQuantData:
+ return "OMX_IndexParamCommonExtraQuantData";
+ case OMX_IndexConfigCommonTransitionEffect:
+ return "OMX_IndexConfigCommonTransitionEffect";
+ case OMX_IndexOtherStartUnused:
+ return "OMX_IndexOtherStartUnused";
+ case OMX_IndexParamOtherPortFormat:
+ return "OMX_IndexParamOtherPortFormat";
+ case OMX_IndexConfigOtherPower:
+ return "OMX_IndexConfigOtherPower";
+ case OMX_IndexConfigOtherStats:
+ return "OMX_IndexConfigOtherStats";
+ case OMX_IndexTimeStartUnused:
+ return "OMX_IndexTimeStartUnused";
+ case OMX_IndexConfigTimeScale:
+ return "OMX_IndexConfigTimeScale";
+ case OMX_IndexConfigTimeClockState:
+ return "OMX_IndexConfigTimeClockState";
+ case OMX_IndexConfigTimeCurrentMediaTime:
+ return "OMX_IndexConfigTimeCurrentMediaTime";
+ case OMX_IndexConfigTimeCurrentWallTime:
+ return "OMX_IndexConfigTimeCurrentWallTime";
+ case OMX_IndexConfigTimeMediaTimeRequest:
+ return "OMX_IndexConfigTimeMediaTimeRequest";
+ case OMX_IndexConfigTimeClientStartTime:
+ return "OMX_IndexConfigTimeClientStartTime";
+ case OMX_IndexConfigTimePosition:
+ return "OMX_IndexConfigTimePosition";
+ case OMX_IndexConfigTimeSeekMode:
+ return "OMX_IndexConfigTimeSeekMode";
+ case OMX_IndexKhronosExtensions:
+ return "OMX_IndexKhronosExtensions";
+ case OMX_IndexVendorStartUnused:
+ return "OMX_IndexVendorStartUnused";
+ case OMX_IndexMax:
+ return "OMX_IndexMax";
+ default:
+ break;
+ }
+
+#if OMX_VERSION_MINOR == 1
+ switch (index) {
+ case OMX_IndexParamCustomContentPipe:
+ return "OMX_IndexParamCustomContentPipe";
+ case OMX_IndexConfigCommonFocusRegion:
+ return "OMX_IndexConfigCommonFocusRegion";
+ case OMX_IndexConfigCommonFocusStatus:
+ return "OMX_IndexConfigCommonFocusStatus";
+ case OMX_IndexConfigTimeActiveRefClock:
+ return "OMX_IndexConfigTimeActiveRefClock";
+ case OMX_IndexConfigTimeCurrentAudioReference:
+ return "OMX_IndexConfigTimeCurrentAudioReference";
+ case OMX_IndexConfigTimeCurrentVideoReference:
+ return "OMX_IndexConfigTimeCurrentVideoReference";
+ default:
+ break;
+ }
+#endif
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ switch ((OMX_ALG_INDEXTYPE) index) {
+ case OMX_ALG_IndexVendorComponentStartUnused:
+ return "OMX_ALG_IndexVendorComponentStartUnused";
+ case OMX_ALG_IndexParamReportedLatency:
+ return "OMX_ALG_IndexParamReportedLatency";
+ case OMX_ALG_IndexParamPreallocation:
+ return "OMX_ALG_IndexParamPreallocation";
+ case OMX_ALG_IndexVendorPortStartUnused:
+ return "OMX_ALG_IndexVendorPortStartUnused";
+ case OMX_ALG_IndexPortParamBufferMode:
+ return "OMX_ALG_IndexPortParamBufferMode";
+ case OMX_ALG_IndexParamVendorVideoStartUnused:
+ return "OMX_ALG_IndexParamVendorVideoStartUnused";
+ case OMX_ALG_IndexParamVideoHevc:
+ return "OMX_ALG_IndexParamVideoHevc";
+ case OMX_ALG_IndexParamVideoVp9:
+ return "OMX_ALG_IndexParamVideoVp9";
+ case OMX_ALG_IndexParamVideoGopControl:
+ return "OMX_ALG_IndexParamVideoGopControl";
+ case OMX_ALG_IndexParamVideoSlices:
+ return "OMX_ALG_IndexParamVideoSlices";
+ case OMX_ALG_IndexParamVideoSceneChangeResilience:
+ return "OMX_ALG_IndexParamVideoSceneChangeResilience";
+ case OMX_ALG_IndexParamVideoPrefetchBuffer:
+ return "OMX_ALG_IndexParamVideoPrefetchBuffer";
+ case OMX_ALG_IndexParamVideoCodedPictureBuffer:
+ return "OMX_ALG_IndexParamVideoCodedPictureBuffer";
+ case OMX_ALG_IndexParamVideoQuantizationControl:
+ return "OMX_ALG_IndexParamVideoQuantizationControl";
+ case OMX_ALG_IndexParamVideoQuantizationExtension:
+ return "OMX_ALG_IndexParamVideoQuantizationExtension";
+ case OMX_ALG_IndexParamVideoScalingList:
+ return "OMX_ALG_IndexParamVideoScalingList";
+ case OMX_ALG_IndexParamVideoDecodedPictureBuffer:
+ return "OMX_ALG_IndexParamVideoDecodedPictureBuffer";
+ case OMX_ALG_IndexParamVideoInternalEntropyBuffers:
+ return "OMX_ALG_IndexParamVideoInternalEntropyBuffers";
+ case OMX_ALG_IndexParamVideoLowBandwidth:
+ return "OMX_ALG_IndexParamVideoLowBandwidth";
+ case OMX_ALG_IndexParamVideoAspectRatio:
+ return "OMX_ALG_IndexParamVideoAspectRatio";
+ case OMX_ALG_IndexParamVideoSubframe:
+ return "OMX_ALG_IndexParamVideoSubframe";
+ case OMX_ALG_IndexParamVideoInstantaneousDecodingRefresh:
+ return "OMX_ALG_IndexParamVideoInstantaneousDecodingRefresh";
+ case OMX_ALG_IndexParamVideoMaxBitrate:
+ return "OMX_ALG_IndexParamVideoMaxBitrate";
+ case OMX_ALG_IndexParamVideoFillerData:
+ return "OMX_ALG_IndexParamVideoFillerData";
+ case OMX_ALG_IndexParamVideoBufferMode:
+ return "OMX_ALG_IndexParamVideoBufferMode";
+ case OMX_ALG_IndexParamVideoInterlaceFormatCurrent:
+ return "OMX_ALG_IndexParamVideoInterlaceFormatCurrent";
+ case OMX_ALG_IndexParamVideoLongTerm:
+ return "OMX_ALG_IndexParamVideoLongTerm";
+ case OMX_ALG_IndexParamVideoLookAhead:
+ return "OMX_ALG_IndexParamVideoLookAhead";
+ case OMX_ALG_IndexConfigVendorVideoStartUnused:
+ return "OMX_ALG_IndexConfigVendorVideoStartUnused";
+ case OMX_ALG_IndexConfigVideoInsertInstantaneousDecodingRefresh:
+ return "OMX_ALG_IndexConfigVideoInsertInstantaneousDecodingRefresh";
+ case OMX_ALG_IndexConfigVideoGroupOfPictures:
+ return "OMX_ALG_IndexConfigVideoGroupOfPictures";
+ case OMX_ALG_IndexConfigVideoRegionOfInterest:
+ return "OMX_ALG_IndexConfigVideoRegionOfInterest";
+ case OMX_ALG_IndexConfigVideoNotifySceneChange:
+ return "OMX_ALG_IndexConfigVideoNotifySceneChange";
+ case OMX_ALG_IndexConfigVideoInsertLongTerm:
+ return "OMX_ALG_IndexConfigVideoInsertLongTerm";
+ case OMX_ALG_IndexConfigVideoUseLongTerm:
+ return "OMX_ALG_IndexConfigVideoUseLongTerm";
+ case OMX_ALG_IndexVendorCommonStartUnused:
+ return "OMX_ALG_IndexVendorCommonStartUnused";
+ case OMX_ALG_IndexParamCommonSequencePictureModeCurrent:
+ return "OMX_ALG_IndexParamCommonSequencePictureModeCurrent";
+ case OMX_ALG_IndexParamCommonSequencePictureModeQuerySupported:
+ return "OMX_ALG_IndexParamCommonSequencePictureModeQuerySupported";
+ case OMX_ALG_IndexParamVideoTwoPass:
+ return "OMX_ALG_IndexParamVideoTwoPass";
+ case OMX_ALG_IndexParamVideoColorPrimaries:
+ return "OMX_ALG_IndexParamVideoColorPrimaries";
+ case OMX_ALG_IndexParamVideoSkipFrame:
+ return "OMX_ALG_IndexParamVideoSkipFrame";
+ case OMX_ALG_IndexConfigVideoNotifyResolutionChange:
+ return "OMX_ALG_IndexConfigVideoNotifyResolutionChange";
+ case OMX_ALG_IndexConfigVideoInsertPrefixSEI:
+ return "OMX_ALG_IndexConfigVideoInsertPrefixSEI";
+ case OMX_ALG_IndexConfigVideoInsertSuffixSEI:
+ return "OMX_ALG_IndexConfigVideoInsertSuffixSEI";
+ case OMX_ALG_IndexConfigVideoQuantizationParameterTable:
+ return "OMX_ALG_IndexConfigVideoQuantizationParameterTable";
+ case OMX_ALG_IndexParamVideoInputParsed:
+ return "OMX_ALG_IndexParamVideoInputParsed";
+ case OMX_ALG_IndexParamVideoMaxPictureSize:
+ return "OMX_ALG_IndexParamVideoMaxPictureSize";
+ case OMX_ALG_IndexParamVideoMaxPictureSizes:
+ return "OMX_ALG_IndexParamVideoMaxPictureSizes";
+ case OMX_ALG_IndexConfigVideoLoopFilterBeta:
+ return "OMX_ALG_IndexConfigVideoLoopFilterBeta";
+ case OMX_ALG_IndexConfigVideoLoopFilterTc:
+ return "OMX_ALG_IndexConfigVideoLoopFilterTc";
+ case OMX_ALG_IndexParamVideoLoopFilterBeta:
+ return "OMX_ALG_IndexParamVideoLoopFilterBeta";
+ case OMX_ALG_IndexParamVideoLoopFilterTc:
+ return "OMX_ALG_IndexParamVideoLoopFilterTc";
+ case OMX_ALG_IndexPortParamEarlyCallback:
+ return "OMX_ALG_IndexPortParamEarlyCallback";
+ case OMX_ALG_IndexParamVideoTransferCharacteristics:
+ return "OMX_ALG_IndexParamVideoTransferCharacteristics";
+ case OMX_ALG_IndexParamVideoColorMatrix:
+ return "OMX_ALG_IndexParamVideoColorMatrix";
+ case OMX_ALG_IndexConfigVideoTransferCharacteristics:
+ return "OMX_ALG_IndexConfigVideoTransferCharacteristics";
+ case OMX_ALG_IndexConfigVideoColorMatrix:
+ return "OMX_ALG_IndexConfigVideoColorMatrix";
+ case OMX_ALG_IndexConfigVideoHighDynamicRangeSEI:
+ return "OMX_ALG_IndexConfigVideoHighDynamicRangeSEI";
+ case OMX_ALG_IndexConfigVideoMaxResolutionChange:
+ return "OMX_ALG_IndexConfigVideoMaxResolutionChange";
+ case OMX_ALG_IndexParamVideoQuantizationTable:
+ return "OMX_ALG_IndexParamVideoQuantizationTable";
+ case OMX_ALG_IndexParamVideoAccessUnitDelimiter:
+ return "OMX_ALG_IndexParamVideoAccessUnitDelimiter";
+ case OMX_ALG_IndexParamVideoBufferingPeriodSEI:
+ return "OMX_ALG_IndexParamVideoBufferingPeriodSEI";
+ case OMX_ALG_IndexParamVideoPictureTimingSEI:
+ return "OMX_ALG_IndexParamVideoPictureTimingSEI";
+ case OMX_ALG_IndexParamVideoRecoveryPointSEI:
+ return "OMX_ALG_IndexParamVideoRecoveryPointSEI";
+ case OMX_ALG_IndexParamVideoMasteringDisplayColourVolumeSEI:
+ return "OMX_ALG_IndexParamVideoMasteringDisplayColourVolumeSEI";
+ case OMX_ALG_IndexParamVideoContentLightLevelSEI:
+ return "OMX_ALG_IndexParamVideoContentLightLevelSEI";
+ case OMX_ALG_IndexConfigVideoRegionOfInterestByValue:
+ return "OMX_ALG_IndexConfigVideoRegionOfInterestByValue";
+ case OMX_ALG_IndexConfigVideoColorPrimaries:
+ return "OMX_ALG_IndexConfigVideoColorPrimaries";
+ case OMX_ALG_IndexMaxEnum:
+ return "OMX_ALG_IndexMaxEnum";
+ }
+#endif
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ /* Not part of the enum in OMX_IndexAlg.h */
+ if (index == OMX_ALG_IndexParamVideoInterlaceFormatSupported)
+ return "OMX_ALG_IndexParamVideoInterlaceFormatSupported";
+#endif
+
+ return NULL;
+}
+#endif /* GST_DISABLE_GST_DEBUG */
+
+static void
+log_omx_api_trace_call (GstOMXComponent * comp, const gchar * function,
+ OMX_INDEXTYPE index, GstDebugLevel level)
+{
+#ifndef GST_DISABLE_GST_DEBUG
+ GstStructure *s;
+ const gchar *index_name;
+
+ /* Don't bother creating useless structs if not needed */
+ if (gst_debug_category_get_threshold (OMX_API_TRACE) < level)
+ return;
+
+ index_name = omx_index_type_to_str (index);
+ if (!index_name) {
+ GST_CAT_WARNING_OBJECT (OMX_API_TRACE, comp->parent,
+ "unknown call of %s with index 0x%08x", function, index);
+ return;
+ }
+
+ s = gst_structure_new (function, "index", G_TYPE_STRING, index_name, NULL);
+ GST_CAT_LEVEL_LOG (OMX_API_TRACE, level, comp->parent, "%" GST_PTR_FORMAT, s);
+ gst_structure_free (s);
+#endif /* GST_DISABLE_GST_DEBUG */
+}
+
+/* comp->lock must be unlocked while calling this */
+OMX_ERRORTYPE
+gst_omx_component_get_parameter (GstOMXComponent * comp, OMX_INDEXTYPE index,
+ gpointer param)
+{
+ OMX_ERRORTYPE err;
+
+ g_return_val_if_fail (comp != NULL, OMX_ErrorUndefined);
+ g_return_val_if_fail (param != NULL, OMX_ErrorUndefined);
+
+ GST_DEBUG_OBJECT (comp->parent, "Getting %s parameter at index 0x%08x",
+ comp->name, index);
+ log_omx_api_trace_call (comp, "GetParameter", index, GST_LEVEL_LOG);
+ err = OMX_GetParameter (comp->handle, index, param);
+ DEBUG_IF_OK (comp->parent, err, "Got %s parameter at index 0x%08x: %s "
+ "(0x%08x)", comp->name, index, gst_omx_error_to_string (err), err);
+
+ return err;
+}
+
+/* comp->lock must be unlocked while calling this */
+OMX_ERRORTYPE
+gst_omx_component_set_parameter (GstOMXComponent * comp, OMX_INDEXTYPE index,
+ gpointer param)
+{
+ OMX_ERRORTYPE err;
+
+ g_return_val_if_fail (comp != NULL, OMX_ErrorUndefined);
+ g_return_val_if_fail (param != NULL, OMX_ErrorUndefined);
+
+ GST_DEBUG_OBJECT (comp->parent, "Setting %s parameter at index 0x%08x",
+ comp->name, index);
+
+ log_omx_api_trace_call (comp, "SetParameter", index, GST_LEVEL_DEBUG);
+ err = OMX_SetParameter (comp->handle, index, param);
+ DEBUG_IF_OK (comp->parent, err, "Set %s parameter at index 0x%08x: %s "
+ "(0x%08x)", comp->name, index, gst_omx_error_to_string (err), err);
+
+ return err;
+}
+
+/* comp->lock must be unlocked while calling this */
+OMX_ERRORTYPE
+gst_omx_component_get_config (GstOMXComponent * comp, OMX_INDEXTYPE index,
+ gpointer config)
+{
+ OMX_ERRORTYPE err;
+
+ g_return_val_if_fail (comp != NULL, OMX_ErrorUndefined);
+ g_return_val_if_fail (config != NULL, OMX_ErrorUndefined);
+
+ GST_DEBUG_OBJECT (comp->parent, "Getting %s configuration at index 0x%08x",
+ comp->name, index);
+ log_omx_api_trace_call (comp, "GetConfig", index, GST_LEVEL_LOG);
+ err = OMX_GetConfig (comp->handle, index, config);
+ DEBUG_IF_OK (comp->parent, err, "Got %s parameter at index 0x%08x: %s "
+ "(0x%08x)", comp->name, index, gst_omx_error_to_string (err), err);
+
+ return err;
+}
+
+/* comp->lock must be unlocked while calling this */
+OMX_ERRORTYPE
+gst_omx_component_set_config (GstOMXComponent * comp, OMX_INDEXTYPE index,
+ gpointer config)
+{
+ OMX_ERRORTYPE err;
+
+ g_return_val_if_fail (comp != NULL, OMX_ErrorUndefined);
+ g_return_val_if_fail (config != NULL, OMX_ErrorUndefined);
+
+ GST_DEBUG_OBJECT (comp->parent, "Setting %s configuration at index 0x%08x",
+ comp->name, index);
+ log_omx_api_trace_call (comp, "SetConfig", index, GST_LEVEL_DEBUG);
+ err = OMX_SetConfig (comp->handle, index, config);
+ DEBUG_IF_OK (comp->parent, err, "Set %s parameter at index 0x%08x: %s "
+ "(0x%08x)", comp->name, index, gst_omx_error_to_string (err), err);
+
+ return err;
+}
+
+OMX_ERRORTYPE
+gst_omx_setup_tunnel (GstOMXPort * port1, GstOMXPort * port2)
+{
+ GstOMXComponent *comp1;
+ GstOMXComponent *comp2;
+ OMX_ERRORTYPE err;
+
+ g_return_val_if_fail (port1 != NULL, OMX_ErrorUndefined);
+ g_return_val_if_fail (port1->port_def.eDir == OMX_DirOutput,
+ OMX_ErrorUndefined);
+ comp1 = port1->comp;
+
+ g_return_val_if_fail (port2 != NULL, OMX_ErrorUndefined);
+ g_return_val_if_fail (port2->port_def.eDir == OMX_DirInput,
+ OMX_ErrorUndefined);
+ comp2 = port2->comp;
+
+ g_return_val_if_fail (comp1->core == comp2->core, OMX_ErrorUndefined);
+
+ g_mutex_lock (&comp1->lock);
+ g_mutex_lock (&comp2->lock);
+ GST_DEBUG_OBJECT (comp1->parent,
+ "Setup tunnel between %s port %u and %s port %u",
+ comp1->name, port1->index, comp2->name, port2->index);
+
+ err = comp1->core->setup_tunnel (comp1->handle, port1->index, comp2->handle,
+ port2->index);
+
+ if (err == OMX_ErrorNone) {
+ port1->tunneled = TRUE;
+ port2->tunneled = TRUE;
+ }
+
+ DEBUG_IF_OK (comp1->parent, err,
+ "Setup tunnel between %s port %u and %s port %u: %s (0x%08x)",
+ comp1->name, port1->index,
+ comp2->name, port2->index, gst_omx_error_to_string (err), err);
+
+ g_mutex_unlock (&comp2->lock);
+ g_mutex_unlock (&comp1->lock);
+
+ return err;
+}
+
+OMX_ERRORTYPE
+gst_omx_close_tunnel (GstOMXPort * port1, GstOMXPort * port2)
+{
+ GstOMXComponent *comp1;
+ GstOMXComponent *comp2;
+ OMX_ERRORTYPE err;
+
+ g_return_val_if_fail (port1 != NULL, OMX_ErrorUndefined);
+ g_return_val_if_fail (port1->port_def.eDir == OMX_DirOutput,
+ OMX_ErrorUndefined);
+ comp1 = port1->comp;
+
+ g_return_val_if_fail (port2 != NULL, OMX_ErrorUndefined);
+ g_return_val_if_fail (port2->port_def.eDir == OMX_DirInput,
+ OMX_ErrorUndefined);
+ comp2 = port2->comp;
+
+ g_return_val_if_fail (comp1->core == comp2->core, OMX_ErrorUndefined);
+ g_return_val_if_fail (port1->tunneled && port2->tunneled, OMX_ErrorUndefined);
+
+ g_mutex_lock (&comp1->lock);
+ g_mutex_lock (&comp2->lock);
+ GST_DEBUG_OBJECT (comp1->parent,
+ "Closing tunnel between %s port %u and %s port %u",
+ comp1->name, port1->index, comp2->name, port2->index);
+
+ err = comp1->core->setup_tunnel (comp1->handle, port1->index, 0, 0);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp1->parent,
+ "Failed to close tunnel on output side %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ }
+ err = comp2->core->setup_tunnel (0, 0, comp2->handle, port2->index);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp2->parent,
+ "Failed to close tunnel on input side %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ }
+
+ port1->tunneled = FALSE;
+ port2->tunneled = FALSE;
+
+ GST_DEBUG_OBJECT (comp1->parent,
+ "Closed tunnel between %s port %u and %s port %u",
+ comp1->name, port1->index, comp2->name, port2->index);
+
+ g_mutex_unlock (&comp2->lock);
+ g_mutex_unlock (&comp1->lock);
+
+ return err;
+}
+
+OMX_ERRORTYPE
+gst_omx_port_get_port_definition (GstOMXPort * port,
+ OMX_PARAM_PORTDEFINITIONTYPE * port_def)
+{
+ GstOMXComponent *comp;
+ OMX_ERRORTYPE err;
+
+ g_return_val_if_fail (port != NULL, OMX_ErrorBadParameter);
+
+ comp = port->comp;
+
+ GST_OMX_INIT_STRUCT (port_def);
+ port_def->nPortIndex = port->index;
+
+ err = gst_omx_component_get_parameter (comp, OMX_IndexParamPortDefinition,
+ port_def);
+
+ return err;
+}
+
+OMX_ERRORTYPE
+gst_omx_port_update_port_definition (GstOMXPort * port,
+ OMX_PARAM_PORTDEFINITIONTYPE * port_def)
+{
+ OMX_ERRORTYPE err_get, err_set = OMX_ErrorNone;
+ GstOMXComponent *comp;
+
+ g_return_val_if_fail (port != NULL, FALSE);
+
+ comp = port->comp;
+
+ if (port_def)
+ err_set =
+ gst_omx_component_set_parameter (comp, OMX_IndexParamPortDefinition,
+ port_def);
+ err_get = gst_omx_component_get_parameter (comp, OMX_IndexParamPortDefinition,
+ &port->port_def);
+
+ DEBUG_IF_OK (comp->parent, err_set,
+ "Updated %s port %u definition: %s (0x%08x)", comp->name, port->index,
+ gst_omx_error_to_string (err_set), err_set);
+
+ if (err_set != OMX_ErrorNone)
+ return err_set;
+ else
+ return err_get;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+GstOMXAcquireBufferReturn
+gst_omx_port_acquire_buffer (GstOMXPort * port, GstOMXBuffer ** buf,
+ GstOMXWait wait)
+{
+ GstOMXAcquireBufferReturn ret = GST_OMX_ACQUIRE_BUFFER_ERROR;
+ GstOMXComponent *comp;
+ OMX_ERRORTYPE err;
+ GstOMXBuffer *_buf = NULL;
+ gint64 timeout = GST_CLOCK_TIME_NONE;
+
+ g_return_val_if_fail (port != NULL, GST_OMX_ACQUIRE_BUFFER_ERROR);
+ g_return_val_if_fail (!port->tunneled, GST_OMX_ACQUIRE_BUFFER_ERROR);
+ g_return_val_if_fail (buf != NULL, GST_OMX_ACQUIRE_BUFFER_ERROR);
+
+ *buf = NULL;
+
+ comp = port->comp;
+
+ g_mutex_lock (&comp->lock);
+ GST_DEBUG_OBJECT (comp->parent, "Acquiring %s buffer from port %u",
+ comp->name, port->index);
+
+retry:
+ gst_omx_component_handle_messages (comp);
+
+ /* If we are in the case where we waited for a buffer after EOS,
+ * make sure we don't do that again */
+ if (timeout != -1)
+ timeout = -2;
+
+ /* Check if the component is in an error state */
+ if ((err = comp->last_error) != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent, "Component %s is in error state: %s",
+ comp->name, gst_omx_error_to_string (err));
+ ret = GST_OMX_ACQUIRE_BUFFER_ERROR;
+ goto done;
+ }
+
+ /* Check if the port is flushing */
+ if (port->flushing) {
+ GST_DEBUG_OBJECT (comp->parent, "Component %s port %d is flushing",
+ comp->name, port->index);
+ ret = GST_OMX_ACQUIRE_BUFFER_FLUSHING;
+ goto done;
+ }
+
+ /* If this is an input port and at least one of the output ports
+ * needs to be reconfigured, we wait until all output ports are
+ * reconfigured. Afterwards this port is reconfigured if required
+ * or buffers are returned to be filled as usual.
+ */
+ if (port->port_def.eDir == OMX_DirInput) {
+ if (comp->pending_reconfigure_outports) {
+ gst_omx_component_handle_messages (comp);
+ while (comp->pending_reconfigure_outports &&
+ (err = comp->last_error) == OMX_ErrorNone && !port->flushing) {
+ GST_DEBUG_OBJECT (comp->parent,
+ "Waiting for %s output ports to reconfigure", comp->name);
+ gst_omx_component_wait_message (comp, GST_CLOCK_TIME_NONE);
+ gst_omx_component_handle_messages (comp);
+ }
+ goto retry;
+ }
+
+ /* Only if this port needs to be reconfigured too notify
+ * the caller about it */
+ if (port->settings_cookie != port->configured_settings_cookie) {
+ GST_DEBUG_OBJECT (comp->parent,
+ "Component %s port %d needs reconfiguring", comp->name, port->index);
+ ret = GST_OMX_ACQUIRE_BUFFER_RECONFIGURE;
+ goto done;
+ }
+ }
+
+ /* If we have an output port that needs to be reconfigured
+ * and it still has buffers pending for the old configuration
+ * we first return them.
+ * NOTE: If buffers for this configuration arrive later
+ * we have to drop them... */
+ if (port->port_def.eDir == OMX_DirOutput &&
+ port->settings_cookie != port->configured_settings_cookie) {
+ if (!g_queue_is_empty (&port->pending_buffers)) {
+ GST_DEBUG_OBJECT (comp->parent,
+ "%s output port %u needs reconfiguration but has buffers pending",
+ comp->name, port->index);
+ _buf = g_queue_pop_head (&port->pending_buffers);
+
+ ret = GST_OMX_ACQUIRE_BUFFER_OK;
+ goto done;
+ }
+
+ GST_DEBUG_OBJECT (comp->parent, "Component %s port %d needs reconfiguring",
+ comp->name, port->index);
+ ret = GST_OMX_ACQUIRE_BUFFER_RECONFIGURE;
+ goto done;
+ }
+
+ if (port->port_def.eDir == OMX_DirOutput && port->eos) {
+ if (!g_queue_is_empty (&port->pending_buffers)) {
+ GST_DEBUG_OBJECT (comp->parent, "%s output port %u is EOS but has "
+ "%d buffers pending", comp->name, port->index,
+ g_queue_get_length (&port->pending_buffers));
+ _buf = g_queue_pop_head (&port->pending_buffers);
+
+ ret = GST_OMX_ACQUIRE_BUFFER_OK;
+ goto done;
+ }
+
+ if (comp->hacks & GST_OMX_HACK_SIGNALS_PREMATURE_EOS && timeout != -2) {
+ timeout = 33 * GST_MSECOND;
+
+ GST_DEBUG_OBJECT (comp->parent, "%s output port %u is EOS but waiting "
+ "in case it spits out more buffers", comp->name, port->index);
+ } else {
+ GST_DEBUG_OBJECT (comp->parent, "Component %s port %d signalled EOS",
+ comp->name, port->index);
+ ret = GST_OMX_ACQUIRE_BUFFER_EOS;
+ port->eos = FALSE;
+ goto done;
+ }
+ }
+
+ /*
+ * At this point we have no error or flushing/eos port
+ * and a properly configured port.
+ *
+ */
+
+ /* If the queue is empty we wait until a buffer
+ * arrives, an error happens, the port is flushing
+ * or the port needs to be reconfigured.
+ */
+ if (g_queue_is_empty (&port->pending_buffers)) {
+ GST_DEBUG_OBJECT (comp->parent, "Queue of %s port %u is empty",
+ comp->name, port->index);
+
+ if (wait == GST_OMX_WAIT) {
+ gst_omx_component_wait_message (comp,
+ timeout == -2 ? GST_CLOCK_TIME_NONE : timeout);
+
+ /* And now check everything again and maybe get a buffer */
+ goto retry;
+ } else {
+ ret = GST_OMX_ACQUIRE_BUFFER_NO_AVAILABLE;
+ goto done;
+ }
+ }
+
+ GST_DEBUG_OBJECT (comp->parent, "%s port %u has pending buffers",
+ comp->name, port->index);
+ _buf = g_queue_pop_head (&port->pending_buffers);
+ ret = GST_OMX_ACQUIRE_BUFFER_OK;
+
+done:
+ g_mutex_unlock (&comp->lock);
+
+ if (_buf) {
+ g_assert (_buf == _buf->omx_buf->pAppPrivate);
+ *buf = _buf;
+ }
+
+ GST_DEBUG_OBJECT (comp->parent, "Acquired buffer %p (%p) from %s port %u: %d",
+ _buf, (_buf ? _buf->omx_buf->pBuffer : NULL), comp->name, port->index,
+ ret);
+
+ return ret;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_release_buffer (GstOMXPort * port, GstOMXBuffer * buf)
+{
+ GstOMXComponent *comp;
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+
+ g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+ g_return_val_if_fail (!port->tunneled, OMX_ErrorUndefined);
+ g_return_val_if_fail (buf != NULL, OMX_ErrorUndefined);
+ g_return_val_if_fail (buf->port == port, OMX_ErrorUndefined);
+
+ comp = port->comp;
+
+ g_mutex_lock (&comp->lock);
+
+ GST_DEBUG_OBJECT (comp->parent, "Releasing buffer %p (%p) to %s port %u",
+ buf, buf->omx_buf->pBuffer, comp->name, port->index);
+
+ gst_omx_component_handle_messages (comp);
+
+ if (port->port_def.eDir == OMX_DirOutput) {
+ /* Reset all flags, some implementations don't
+ * reset them themselves and the flags are not
+ * valid anymore after the buffer was consumed
+ */
+ gst_omx_buffer_reset (buf);
+ }
+
+ if ((err = comp->last_error) != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent, "Component %s is in error state: %s "
+ "(0x%08x)", comp->name, gst_omx_error_to_string (err), err);
+ g_queue_push_tail (&port->pending_buffers, buf);
+ gst_omx_component_send_message (comp, NULL);
+ goto done;
+ }
+
+ if (port->flushing || port->disabled_pending || !port->port_def.bEnabled) {
+ GST_DEBUG_OBJECT (comp->parent,
+ "%s port %u is flushing or disabled, not releasing " "buffer",
+ comp->name, port->index);
+ g_queue_push_tail (&port->pending_buffers, buf);
+ gst_omx_component_send_message (comp, NULL);
+ goto done;
+ }
+
+ g_assert (buf == buf->omx_buf->pAppPrivate);
+
+ /* FIXME: What if the settings cookies don't match? */
+
+ buf->used = TRUE;
+
+ if (port->port_def.eDir == OMX_DirInput) {
+ log_omx_api_trace_buffer (comp, "EmptyThisBuffer", buf);
+ err = OMX_EmptyThisBuffer (comp->handle, buf->omx_buf);
+ } else {
+ log_omx_api_trace_buffer (comp, "FillThisBuffer", buf);
+ err = OMX_FillThisBuffer (comp->handle, buf->omx_buf);
+ }
+ DEBUG_IF_OK (comp->parent, err, "Released buffer %p to %s port %u: %s "
+ "(0x%08x)", buf, comp->name, port->index, gst_omx_error_to_string (err),
+ err);
+
+done:
+ gst_omx_component_handle_messages (comp);
+ g_mutex_unlock (&comp->lock);
+
+ return err;
+}
+
+/* NOTE: Must be called while holding comp->lock */
+static gboolean
+should_wait_until_flushed (GstOMXPort * port)
+{
+ if (!port->flushed)
+ /* Flush command hasn't been completed yet by OMX */
+ return TRUE;
+
+ if (port->buffers) {
+ guint i;
+
+ /* Wait for all the buffers used by OMX to be released */
+ for (i = 0; i < port->buffers->len; i++) {
+ GstOMXBuffer *buf = g_ptr_array_index (port->buffers, i);
+
+ if (buf->used)
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_set_flushing (GstOMXPort * port, GstClockTime timeout,
+ gboolean flush)
+{
+ GstOMXComponent *comp;
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+
+ g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+ comp = port->comp;
+
+ g_mutex_lock (&comp->lock);
+
+ GST_DEBUG_OBJECT (comp->parent, "Setting %s port %d to %sflushing",
+ comp->name, port->index, (flush ? "" : "not "));
+
+ gst_omx_component_handle_messages (comp);
+
+ if (flush == port->flushing) {
+ GST_DEBUG_OBJECT (comp->parent, "%s port %u was %sflushing already",
+ comp->name, port->index, (flush ? "" : "not "));
+ goto done;
+ }
+
+ if ((err = comp->last_error) != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent, "Component %s is in error state: %s "
+ "(0x%08x)", comp->name, gst_omx_error_to_string (err), err);
+ goto done;
+ }
+
+ port->flushing = flush;
+ if (flush) {
+ gboolean signalled;
+ OMX_ERRORTYPE last_error;
+
+ gst_omx_component_send_message (comp, NULL);
+
+ /* Now flush the port */
+ port->flushed = FALSE;
+
+ err =
+ gst_omx_component_send_command (comp, OMX_CommandFlush, port->index,
+ NULL);
+
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent,
+ "Error sending flush command to %s port %u: %s (0x%08x)", comp->name,
+ port->index, gst_omx_error_to_string (err), err);
+ goto done;
+ }
+
+ if ((err = comp->last_error) != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent,
+ "Component %s is in error state: %s (0x%08x)", comp->name,
+ gst_omx_error_to_string (err), err);
+ goto done;
+ }
+
+ if (port->flushing != flush) {
+ GST_ERROR_OBJECT (comp->parent, "%s: another flush happened in the "
+ " meantime", comp->name);
+ goto done;
+ }
+
+ if (timeout == 0) {
+ if (should_wait_until_flushed (port))
+ err = OMX_ErrorTimeout;
+ goto done;
+ }
+
+ /* Retry until timeout or until an error happend or
+ * until all buffers were released by the component and
+ * the flush command completed */
+ signalled = TRUE;
+ last_error = OMX_ErrorNone;
+ gst_omx_component_handle_messages (comp);
+ while (should_wait_until_flushed (port)) {
+ signalled = gst_omx_component_wait_message (comp, timeout);
+ if (signalled)
+ gst_omx_component_handle_messages (comp);
+
+ last_error = comp->last_error;
+
+ if (!signalled || last_error != OMX_ErrorNone)
+ /* Something gone wrong or we timed out */
+ break;
+ }
+ port->flushed = FALSE;
+
+ GST_DEBUG_OBJECT (comp->parent, "%s port %d flushed", comp->name,
+ port->index);
+ if (last_error != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent,
+ "Got error while flushing %s port %u: %s (0x%08x)", comp->name,
+ port->index, gst_omx_error_to_string (last_error), last_error);
+ err = last_error;
+ goto done;
+ } else if (!signalled) {
+ GST_ERROR_OBJECT (comp->parent, "Timeout while flushing %s port %u",
+ comp->name, port->index);
+ err = OMX_ErrorTimeout;
+ goto done;
+ }
+ }
+
+ /* Reset EOS flag */
+ port->eos = FALSE;
+
+done:
+ gst_omx_port_update_port_definition (port, NULL);
+
+ DEBUG_IF_OK (comp->parent, err, "Set %s port %u to %sflushing: %s (0x%08x)",
+ comp->name, port->index, (flush ? "" : "not "),
+ gst_omx_error_to_string (err), err);
+ gst_omx_component_handle_messages (comp);
+ g_mutex_unlock (&comp->lock);
+
+ return err;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+gboolean
+gst_omx_port_is_flushing (GstOMXPort * port)
+{
+ GstOMXComponent *comp;
+ gboolean flushing;
+
+ g_return_val_if_fail (port != NULL, FALSE);
+
+ comp = port->comp;
+
+ g_mutex_lock (&comp->lock);
+ gst_omx_component_handle_messages (port->comp);
+ flushing = port->flushing;
+ g_mutex_unlock (&comp->lock);
+
+ GST_DEBUG_OBJECT (comp->parent, "%s port %u is flushing: %d", comp->name,
+ port->index, flushing);
+
+ return flushing;
+}
+
+static OMX_ERRORTYPE gst_omx_port_deallocate_buffers_unlocked (GstOMXPort *
+ port);
+
+/* NOTE: Must be called while holding comp->lock, uses comp->messages_lock */
+static OMX_ERRORTYPE
+gst_omx_port_allocate_buffers_unlocked (GstOMXPort * port,
+ const GList * buffers, const GList * images, guint n)
+{
+ GstOMXComponent *comp;
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+ gint i;
+ const GList *l;
+
+ g_assert (!port->buffers || port->buffers->len == 0);
+
+ g_return_val_if_fail (!port->tunneled, OMX_ErrorBadParameter);
+
+ comp = port->comp;
+
+ gst_omx_component_handle_messages (port->comp);
+ if ((err = comp->last_error) != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
+ comp->name, gst_omx_error_to_string (err), err);
+ goto done;
+ }
+
+ /* Update the port definition to check if we need more
+ * buffers after the port configuration was done and to
+ * update the buffer size
+ */
+ gst_omx_port_update_port_definition (port, NULL);
+
+ g_return_val_if_fail (n != -1 || (!buffers
+ && !images), OMX_ErrorBadParameter);
+
+ if (n == -1)
+ n = port->port_def.nBufferCountActual;
+
+ g_return_val_if_fail (n == port->port_def.nBufferCountActual,
+ OMX_ErrorBadParameter);
+
+ GST_INFO_OBJECT (comp->parent,
+ "Allocating %d buffers of size %" G_GSIZE_FORMAT " for %s port %u", n,
+ (size_t) port->port_def.nBufferSize, comp->name, (guint) port->index);
+
+ if (!port->buffers)
+ port->buffers = g_ptr_array_sized_new (n);
+
+ l = (buffers ? buffers : images);
+ for (i = 0; i < n; i++) {
+ GstOMXBuffer *buf;
+
+ buf = g_slice_new0 (GstOMXBuffer);
+ buf->port = port;
+ buf->used = FALSE;
+ buf->settings_cookie = port->settings_cookie;
+ g_ptr_array_add (port->buffers, buf);
+
+ if (buffers) {
+ err =
+ OMX_UseBuffer (comp->handle, &buf->omx_buf, port->index, buf,
+ port->port_def.nBufferSize, l->data);
+ buf->eglimage = FALSE;
+ } else if (images) {
+ err =
+ OMX_UseEGLImage (comp->handle, &buf->omx_buf, port->index, buf,
+ l->data);
+ buf->eglimage = TRUE;
+ } else {
+ err =
+ OMX_AllocateBuffer (comp->handle, &buf->omx_buf, port->index, buf,
+ port->port_def.nBufferSize);
+ buf->eglimage = FALSE;
+ }
+
+ /* Let the caller decide to print an error when OMX_UseBuffer or
+ * OMX_UseEGLImage fail. Indeed it can be part of a trial path. So
+ * it is not necessary to warn the user if the fallback path succeeds.
+ */
+ if (err != OMX_ErrorNone) {
+ GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, (buffers
+ || images) ? GST_LEVEL_INFO : GST_LEVEL_ERROR, comp->parent,
+ "Failed to allocate buffer for %s port %u: %s (0x%08x)", comp->name,
+ port->index, gst_omx_error_to_string (err), err);
+ gst_omx_port_deallocate_buffers_unlocked (port);
+ goto done;
+ }
+
+ GST_DEBUG_OBJECT (comp->parent, "%s: allocated buffer %p (%p)",
+ comp->name, buf, buf->omx_buf->pBuffer);
+
+ g_assert (buf->omx_buf->pAppPrivate == buf);
+
+ /* In the beginning all buffers are not owned by the component */
+ g_queue_push_tail (&port->pending_buffers, buf);
+ if (buffers || images)
+ l = l->next;
+ }
+
+ gst_omx_component_handle_messages (comp);
+
+done:
+ gst_omx_port_update_port_definition (port, NULL);
+
+ INFO_IF_OK (comp->parent, err, "Allocated buffers for %s port %u: %s "
+ "(0x%08x)", comp->name, port->index, gst_omx_error_to_string (err), err);
+
+ return err;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_allocate_buffers (GstOMXPort * port)
+{
+ OMX_ERRORTYPE err;
+
+ g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+ g_mutex_lock (&port->comp->lock);
+ err = gst_omx_port_allocate_buffers_unlocked (port, NULL, NULL, -1);
+ port->allocation = GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER;
+ g_mutex_unlock (&port->comp->lock);
+
+ return err;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_use_buffers (GstOMXPort * port, const GList * buffers)
+{
+ OMX_ERRORTYPE err;
+ guint n;
+
+ g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+ g_mutex_lock (&port->comp->lock);
+ n = g_list_length ((GList *) buffers);
+ err = gst_omx_port_allocate_buffers_unlocked (port, buffers, NULL, n);
+ port->allocation = GST_OMX_BUFFER_ALLOCATION_USE_BUFFER;
+ g_mutex_unlock (&port->comp->lock);
+
+ return err;
+}
+
+gboolean
+gst_omx_is_dynamic_allocation_supported (void)
+{
+ /* The Zynqultrascaleplus stack implements OMX 1.1.0 but supports the dynamic
+ * allocation mode from 1.2.0 as an extension. */
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ return TRUE;
+#endif
+
+#if OMX_VERSION_MINOR == 2
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+/* OMX 1.2.0 introduced a dynamic allocation mode where only buffer headers are
+ * being allocated during component's initialization. The actual buffers are
+ * allocated upstream and passed to OMX by setting the pBuffer dynamically
+ * for each input buffer.
+ *
+ * This function takes care of allocating the buffer headers. Element should
+ * then use one of the gst_omx_buffer_map_*() method to update buffer's pBuffer
+ * pointers for each incoming buffer.
+ *
+ * NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_use_dynamic_buffers (GstOMXPort * port)
+{
+ OMX_ERRORTYPE err;
+ GList *buffers = NULL;
+ guint i, n;
+
+ g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+ n = port->port_def.nBufferCountActual;
+ for (i = 0; i < port->port_def.nBufferCountActual; i++)
+ /* Pass NULL to UseBuffer() as the buffer is dynamic and so its payload
+ * will be set each time before being passed to OMX. */
+ buffers = g_list_prepend (buffers, GUINT_TO_POINTER (NULL));
+
+ g_mutex_lock (&port->comp->lock);
+ err = gst_omx_port_allocate_buffers_unlocked (port, buffers, NULL, n);
+ port->allocation = GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC;
+ g_mutex_unlock (&port->comp->lock);
+
+ g_list_free (buffers);
+
+ return err;
+}
+
+/* gst_omx_buffer_map_* methods are used in dynamic buffer mode to map
+ * a frame/memory/buffer and update @buffer so its pBuffer points to the
+ * mapped data. It also ensures that the input will stay alive until
+ * gst_omx_buffer_unmap() is called.
+ * This is used in OMX 1.2.0 dynamic allocation mode so an OMX component can
+ * safely process @buffer's content without having to copy it.
+ * The input will be automatically unmapped when @buffer is released by OMX.
+ */
+gboolean
+gst_omx_buffer_map_frame (GstOMXBuffer * buffer, GstBuffer * input,
+ GstVideoInfo * info)
+{
+ g_return_val_if_fail (buffer != NULL, FALSE);
+ g_return_val_if_fail (!buffer->input_frame_mapped, FALSE);
+ g_return_val_if_fail (!buffer->input_mem, FALSE);
+ g_return_val_if_fail (!buffer->input_buffer, FALSE);
+ g_return_val_if_fail (!buffer->input_buffer_mapped, FALSE);
+
+ if (!gst_video_frame_map (&buffer->input_frame, info, input, GST_MAP_READ))
+ return FALSE;
+
+ buffer->input_frame_mapped = TRUE;
+ buffer->omx_buf->pBuffer =
+ GST_VIDEO_FRAME_PLANE_DATA (&buffer->input_frame, 0);
+ buffer->omx_buf->nAllocLen = gst_buffer_get_size (input);
+ buffer->omx_buf->nFilledLen = buffer->omx_buf->nAllocLen;
+
+ return TRUE;
+}
+
+gboolean
+gst_omx_buffer_map_memory (GstOMXBuffer * buffer, GstMemory * mem)
+{
+ g_return_val_if_fail (buffer != NULL, FALSE);
+ g_return_val_if_fail (mem != NULL, FALSE);
+ g_return_val_if_fail (!buffer->input_frame_mapped, FALSE);
+ g_return_val_if_fail (!buffer->input_mem, FALSE);
+ g_return_val_if_fail (!buffer->input_buffer, FALSE);
+ g_return_val_if_fail (!buffer->input_buffer_mapped, FALSE);
+
+ if (!gst_memory_map (mem, &buffer->map, GST_MAP_READ))
+ return FALSE;
+
+ buffer->input_mem = gst_memory_ref (mem);
+ buffer->omx_buf->pBuffer = buffer->map.data;
+ buffer->omx_buf->nAllocLen = buffer->map.size;
+ buffer->omx_buf->nFilledLen = buffer->omx_buf->nAllocLen;
+
+ return TRUE;
+}
+
+gboolean
+gst_omx_buffer_import_fd (GstOMXBuffer * buffer, GstBuffer * input)
+{
+ gint fd;
+ GstMemory *mem;
+
+ g_return_val_if_fail (buffer != NULL, FALSE);
+ g_return_val_if_fail (input != NULL, FALSE);
+ g_return_val_if_fail (!buffer->input_frame_mapped, FALSE);
+ g_return_val_if_fail (!buffer->input_mem, FALSE);
+ g_return_val_if_fail (!buffer->input_buffer, FALSE);
+ g_return_val_if_fail (!buffer->input_buffer_mapped, FALSE);
+
+ mem = gst_buffer_peek_memory (input, 0);
+ g_return_val_if_fail (gst_is_dmabuf_memory (mem), FALSE);
+
+ fd = gst_dmabuf_memory_get_fd (mem);
+
+ buffer->input_buffer = gst_buffer_ref (input);
+ buffer->omx_buf->pBuffer = GUINT_TO_POINTER (fd);
+ buffer->omx_buf->nAllocLen = gst_memory_get_sizes (mem, NULL, NULL);
+ buffer->omx_buf->nFilledLen = buffer->omx_buf->nAllocLen;
+
+ return TRUE;
+}
+
+gboolean
+gst_omx_buffer_map_buffer (GstOMXBuffer * buffer, GstBuffer * input)
+{
+ g_return_val_if_fail (buffer != NULL, FALSE);
+ g_return_val_if_fail (input != NULL, FALSE);
+ g_return_val_if_fail (!buffer->input_frame_mapped, FALSE);
+ g_return_val_if_fail (!buffer->input_mem, FALSE);
+ g_return_val_if_fail (!buffer->input_buffer, FALSE);
+ g_return_val_if_fail (!buffer->input_buffer_mapped, FALSE);
+
+ if (!gst_buffer_map (input, &buffer->map, GST_MAP_READ))
+ return FALSE;
+
+ buffer->input_buffer_mapped = TRUE;
+ buffer->input_buffer = gst_buffer_ref (input);
+ buffer->omx_buf->pBuffer = buffer->map.data;
+ buffer->omx_buf->nAllocLen = buffer->map.size;
+ buffer->omx_buf->nFilledLen = buffer->omx_buf->nAllocLen;
+
+ return TRUE;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_use_eglimages (GstOMXPort * port, const GList * images)
+{
+ OMX_ERRORTYPE err;
+ guint n;
+
+ g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+ g_mutex_lock (&port->comp->lock);
+ n = g_list_length ((GList *) images);
+ err = gst_omx_port_allocate_buffers_unlocked (port, NULL, images, n);
+ g_mutex_unlock (&port->comp->lock);
+
+ return err;
+}
+
+/* NOTE: Must be called while holding comp->lock, uses comp->messages_lock */
+static OMX_ERRORTYPE
+gst_omx_port_deallocate_buffers_unlocked (GstOMXPort * port)
+{
+ GstOMXComponent *comp;
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+ gint i, n;
+
+ g_return_val_if_fail (!port->tunneled, OMX_ErrorBadParameter);
+
+ comp = port->comp;
+
+ GST_INFO_OBJECT (comp->parent, "Deallocating buffers of %s port %u",
+ comp->name, port->index);
+
+ gst_omx_component_handle_messages (port->comp);
+
+ if (!port->buffers) {
+ GST_DEBUG_OBJECT (comp->parent, "No buffers allocated for %s port %u",
+ comp->name, port->index);
+ goto done;
+ }
+
+ if ((err = comp->last_error) != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
+ comp->name, gst_omx_error_to_string (err), err);
+ /* We still try to deallocate all buffers */
+ }
+
+ /* We only allow deallocation of buffers after they
+ * were all released from the port, either by flushing
+ * the port or by disabling it.
+ */
+ n = port->buffers->len;
+ for (i = 0; i < n; i++) {
+ GstOMXBuffer *buf = g_ptr_array_index (port->buffers, i);
+ OMX_ERRORTYPE tmp = OMX_ErrorNone;
+
+ if (buf->used) {
+ GST_ERROR_OBJECT (comp->parent, "Trying to free used buffer %p of %s "
+ "port %u", buf, comp->name, port->index);
+ }
+
+ /* omx_buf can be NULL if allocation failed earlier
+ * and we're just shutting down
+ *
+ * errors do not cause exiting this loop because we want
+ * to deallocate as much as possible.
+ */
+ if (buf->omx_buf) {
+ g_assert (buf == buf->omx_buf->pAppPrivate);
+ buf->omx_buf->pAppPrivate = NULL;
+ GST_DEBUG_OBJECT (comp->parent, "%s: deallocating buffer %p (%p)",
+ comp->name, buf, buf->omx_buf->pBuffer);
+
+ tmp = OMX_FreeBuffer (comp->handle, port->index, buf->omx_buf);
+
+ if (tmp != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent,
+ "Failed to deallocate buffer %d of %s port %u: %s (0x%08x)", i,
+ comp->name, port->index, gst_omx_error_to_string (tmp), tmp);
+ if (err == OMX_ErrorNone)
+ err = tmp;
+ }
+ }
+ g_slice_free (GstOMXBuffer, buf);
+ }
+ g_queue_clear (&port->pending_buffers);
+ g_ptr_array_unref (port->buffers);
+ port->buffers = NULL;
+
+ gst_omx_component_handle_messages (comp);
+
+done:
+ gst_omx_port_update_port_definition (port, NULL);
+
+ DEBUG_IF_OK (comp->parent, err, "Deallocated buffers of %s port %u: %s "
+ "(0x%08x)", comp->name, port->index, gst_omx_error_to_string (err), err);
+
+ return err;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_deallocate_buffers (GstOMXPort * port)
+{
+ OMX_ERRORTYPE err;
+
+ g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+ g_mutex_lock (&port->comp->lock);
+ err = gst_omx_port_deallocate_buffers_unlocked (port);
+ g_mutex_unlock (&port->comp->lock);
+
+ return err;
+}
+
+/* NOTE: Must be called while holding comp->lock, uses comp->messages_lock */
+static OMX_ERRORTYPE
+gst_omx_port_set_enabled_unlocked (GstOMXPort * port, gboolean enabled)
+{
+ GstOMXComponent *comp;
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+
+ comp = port->comp;
+
+ gst_omx_component_handle_messages (comp);
+
+ if ((err = comp->last_error) != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
+ comp->name, gst_omx_error_to_string (err), err);
+ goto done;
+ }
+
+ if (port->enabled_pending || port->disabled_pending) {
+ GST_ERROR_OBJECT (comp->parent, "%s port %d enabled/disabled pending "
+ "already", comp->name, port->index);
+#if OMX_VERSION_MINOR == 2
+ err = OMX_ErrorBadParameter;
+#else
+ err = OMX_ErrorInvalidState;
+#endif
+ goto done;
+ }
+
+ GST_INFO_OBJECT (comp->parent, "Setting %s port %u to %s", comp->name,
+ port->index, (enabled ? "enabled" : "disabled"));
+
+ /* Check if the port is already enabled/disabled first */
+ gst_omx_port_update_port_definition (port, NULL);
+ if (! !port->port_def.bEnabled == ! !enabled)
+ goto done;
+
+ if (enabled)
+ port->enabled_pending = TRUE;
+ else
+ port->disabled_pending = TRUE;
+
+ if (enabled)
+ err =
+ gst_omx_component_send_command (comp, OMX_CommandPortEnable,
+ port->index, NULL);
+ else
+ err =
+ gst_omx_component_send_command (comp, OMX_CommandPortDisable,
+ port->index, NULL);
+
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent,
+ "Failed to send enable/disable command to %s port %u: %s (0x%08x)",
+ comp->name, port->index, gst_omx_error_to_string (err), err);
+ goto done;
+ }
+
+ if ((err = comp->last_error) != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
+ comp->name, gst_omx_error_to_string (err), err);
+ goto done;
+ }
+
+done:
+ gst_omx_component_handle_messages (comp);
+
+ gst_omx_port_update_port_definition (port, NULL);
+
+ INFO_IF_OK (comp->parent, err, "Set %s port %u to %s%s: %s (0x%08x)",
+ comp->name, port->index, (err == OMX_ErrorNone ? "" : "not "),
+ (enabled ? "enabled" : "disabled"), gst_omx_error_to_string (err), err);
+
+ return err;
+}
+
+static OMX_ERRORTYPE
+gst_omx_port_wait_buffers_released_unlocked (GstOMXPort * port,
+ GstClockTime timeout)
+{
+ GstOMXComponent *comp;
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+ OMX_ERRORTYPE last_error;
+ gboolean signalled;
+
+ comp = port->comp;
+
+ gst_omx_component_handle_messages (comp);
+
+ if ((err = comp->last_error) != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
+ comp->name, gst_omx_error_to_string (err), err);
+ goto done;
+ }
+
+ GST_INFO_OBJECT (comp->parent, "Waiting for %s port %u to release all "
+ "buffers", comp->name, port->index);
+
+ if (timeout == 0) {
+ if (!port->flushed || (port->buffers
+ && port->buffers->len >
+ g_queue_get_length (&port->pending_buffers)))
+ err = OMX_ErrorTimeout;
+ goto done;
+ }
+
+ /* Wait until all buffers are released by the port */
+ signalled = TRUE;
+ last_error = OMX_ErrorNone;
+ gst_omx_component_handle_messages (comp);
+ while (signalled && last_error == OMX_ErrorNone && (port->buffers
+ && port->buffers->len >
+ g_queue_get_length (&port->pending_buffers))) {
+ signalled = gst_omx_component_wait_message (comp, timeout);
+ if (signalled)
+ gst_omx_component_handle_messages (comp);
+ last_error = comp->last_error;
+ }
+
+ if (last_error != OMX_ErrorNone) {
+ err = last_error;
+ GST_ERROR_OBJECT (comp->parent,
+ "Got error while waiting for %s port %u to release all buffers: %s "
+ "(0x%08x)", comp->name, port->index, gst_omx_error_to_string (err),
+ err);
+ goto done;
+ } else if (!signalled) {
+ GST_ERROR_OBJECT (comp->parent, "Timeout waiting for %s port %u to "
+ "release all buffers", comp->name, port->index);
+ err = OMX_ErrorTimeout;
+ goto done;
+ }
+
+done:
+ gst_omx_component_handle_messages (comp);
+
+ gst_omx_port_update_port_definition (port, NULL);
+
+ DEBUG_IF_OK (comp->parent, err,
+ "Waited for %s port %u to release all buffers: %s (0x%08x)", comp->name,
+ port->index, gst_omx_error_to_string (err), err);
+
+ return err;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_wait_buffers_released (GstOMXPort * port, GstClockTime timeout)
+{
+ OMX_ERRORTYPE err;
+
+ g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+ g_mutex_lock (&port->comp->lock);
+ err = gst_omx_port_wait_buffers_released_unlocked (port, timeout);
+ g_mutex_unlock (&port->comp->lock);
+
+ return err;
+}
+
+void
+gst_omx_port_requeue_buffer (GstOMXPort * port, GstOMXBuffer * buf)
+{
+ g_mutex_lock (&port->comp->lock);
+ g_queue_push_tail (&port->pending_buffers, buf);
+ g_mutex_unlock (&port->comp->lock);
+
+ /* awake gst_omx_port_acquire_buffer() */
+ gst_omx_component_send_message (port->comp, NULL);
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_set_enabled (GstOMXPort * port, gboolean enabled)
+{
+ OMX_ERRORTYPE err;
+
+ g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+ g_mutex_lock (&port->comp->lock);
+ err = gst_omx_port_set_enabled_unlocked (port, enabled);
+ g_mutex_unlock (&port->comp->lock);
+
+ return err;
+}
+
+static OMX_ERRORTYPE
+gst_omx_port_populate_unlocked (GstOMXPort * port)
+{
+ GstOMXComponent *comp;
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+ GstOMXBuffer *buf;
+
+ g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+ comp = port->comp;
+
+ GST_DEBUG_OBJECT (comp->parent, "Populating %s port %d", comp->name,
+ port->index);
+
+ gst_omx_component_handle_messages (comp);
+
+ if (port->flushing || port->disabled_pending || !port->port_def.bEnabled) {
+ GST_DEBUG_OBJECT (comp->parent, "%s port %u is flushing or disabled",
+ comp->name, port->index);
+ err = OMX_ErrorIncorrectStateOperation;
+ goto done;
+ }
+
+ if ((err = comp->last_error) != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent, "Component %s is in error state: %s"
+ "(0x%08x)", comp->name, gst_omx_error_to_string (err), err);
+ goto done;
+ }
+
+ if (port->port_def.eDir == OMX_DirOutput && port->buffers && !port->tunneled) {
+ /* Enqueue all buffers for the component to fill */
+ while ((buf = g_queue_pop_head (&port->pending_buffers))) {
+ g_assert (!buf->used);
+
+ /* Reset all flags, some implementations don't
+ * reset them themselves and the flags are not
+ * valid anymore after the buffer was consumed.
+ * Also reset nFilledLen as FillThisBuffer() expects an empty buffer.
+ */
+ gst_omx_buffer_reset (buf);
+
+ log_omx_api_trace_buffer (comp, "FillThisBuffer", buf);
+ err = OMX_FillThisBuffer (comp->handle, buf->omx_buf);
+
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent,
+ "Failed to pass buffer %p (%p) to %s port %u: %s (0x%08x)", buf,
+ buf->omx_buf->pBuffer, comp->name, port->index,
+ gst_omx_error_to_string (err), err);
+ goto done;
+ }
+ GST_DEBUG_OBJECT (comp->parent, "Passed buffer %p (%p) to component %s",
+ buf, buf->omx_buf->pBuffer, comp->name);
+ }
+ }
+
+done:
+ gst_omx_port_update_port_definition (port, NULL);
+
+ DEBUG_IF_OK (comp->parent, err, "Populated %s port %u: %s (0x%08x)",
+ comp->name, port->index, gst_omx_error_to_string (err), err);
+ gst_omx_component_handle_messages (comp);
+
+ return err;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_populate (GstOMXPort * port)
+{
+ OMX_ERRORTYPE err;
+
+ g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+ g_mutex_lock (&port->comp->lock);
+ err = gst_omx_port_populate_unlocked (port);
+ g_mutex_unlock (&port->comp->lock);
+
+ return err;
+}
+
+/* NOTE: Must be called while holding comp->lock, uses comp->messages_lock */
+static OMX_ERRORTYPE
+gst_omx_port_wait_enabled_unlocked (GstOMXPort * port, GstClockTime timeout)
+{
+ GstOMXComponent *comp;
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+ gboolean signalled;
+ OMX_ERRORTYPE last_error;
+ gboolean enabled;
+
+ comp = port->comp;
+
+ /* Check the current port status */
+ gst_omx_port_update_port_definition (port, NULL);
+
+ if (port->enabled_pending)
+ enabled = TRUE;
+ else if (port->disabled_pending)
+ enabled = FALSE;
+ else
+ enabled = port->port_def.bEnabled;
+
+ gst_omx_component_handle_messages (comp);
+
+ if ((err = comp->last_error) != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
+ comp->name, gst_omx_error_to_string (err), err);
+ goto done;
+ }
+
+ GST_INFO_OBJECT (comp->parent, "Waiting for %s port %u to be %s",
+ comp->name, port->index, (enabled ? "enabled" : "disabled"));
+
+ if (timeout == 0) {
+ if (port->enabled_pending || port->disabled_pending)
+ err = OMX_ErrorTimeout;
+ goto done;
+ }
+
+ /* And now wait until the enable/disable command is finished */
+ signalled = TRUE;
+ last_error = OMX_ErrorNone;
+ gst_omx_port_update_port_definition (port, NULL);
+ gst_omx_component_handle_messages (comp);
+ while (signalled && last_error == OMX_ErrorNone &&
+ (! !port->port_def.bEnabled != ! !enabled || port->enabled_pending
+ || port->disabled_pending)) {
+ signalled = gst_omx_component_wait_message (comp, timeout);
+ if (signalled)
+ gst_omx_component_handle_messages (comp);
+ last_error = comp->last_error;
+ gst_omx_port_update_port_definition (port, NULL);
+ }
+ port->enabled_pending = FALSE;
+ port->disabled_pending = FALSE;
+
+ if (!signalled) {
+ GST_ERROR_OBJECT (comp->parent,
+ "Timeout waiting for %s port %u to be %s", comp->name, port->index,
+ (enabled ? "enabled" : "disabled"));
+ err = OMX_ErrorTimeout;
+ goto done;
+ } else if (last_error != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (comp->parent,
+ "Got error while waiting for %s port %u to be %s: %s (0x%08x)",
+ comp->name, port->index, (enabled ? "enabled" : "disabled"),
+ gst_omx_error_to_string (err), err);
+ err = last_error;
+ } else {
+ if (enabled) {
+ /* Reset EOS flag */
+ port->eos = FALSE;
+ }
+ }
+
+ gst_omx_component_handle_messages (comp);
+
+done:
+ gst_omx_port_update_port_definition (port, NULL);
+
+ GST_INFO_OBJECT (comp->parent, "%s port %u is %s%s: %s (0x%08x)", comp->name,
+ port->index, (err == OMX_ErrorNone ? "" : "not "),
+ (enabled ? "enabled" : "disabled"), gst_omx_error_to_string (err), err);
+
+ return err;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_wait_enabled (GstOMXPort * port, GstClockTime timeout)
+{
+ OMX_ERRORTYPE err;
+
+ g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+ g_mutex_lock (&port->comp->lock);
+ err = gst_omx_port_wait_enabled_unlocked (port, timeout);
+ g_mutex_unlock (&port->comp->lock);
+
+ return err;
+}
+
+gboolean
+gst_omx_port_is_enabled (GstOMXPort * port)
+{
+ gboolean enabled;
+
+ g_return_val_if_fail (port != NULL, FALSE);
+
+ gst_omx_port_update_port_definition (port, NULL);
+ enabled = ! !port->port_def.bEnabled;
+
+ GST_DEBUG_OBJECT (port->comp->parent, "%s port %u is enabled: %d",
+ port->comp->name, port->index, enabled);
+
+ return enabled;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_mark_reconfigured (GstOMXPort * port)
+{
+ GstOMXComponent *comp;
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+
+ g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+ comp = port->comp;
+
+ g_mutex_lock (&comp->lock);
+ GST_INFO_OBJECT (comp->parent, "Marking %s port %u is reconfigured",
+ comp->name, port->index);
+
+ gst_omx_component_handle_messages (comp);
+
+ if ((err = comp->last_error) != OMX_ErrorNone)
+ goto done;
+
+ port->configured_settings_cookie = port->settings_cookie;
+
+ if (port->port_def.eDir == OMX_DirOutput) {
+ GList *l;
+
+ for (l = comp->pending_reconfigure_outports; l; l = l->next) {
+ if (l->data == (gpointer) port) {
+ comp->pending_reconfigure_outports =
+ g_list_delete_link (comp->pending_reconfigure_outports, l);
+ break;
+ }
+ }
+ if (!comp->pending_reconfigure_outports)
+ gst_omx_component_send_message (comp, NULL);
+ }
+
+done:
+ gst_omx_port_update_port_definition (port, NULL);
+
+ INFO_IF_OK (comp->parent, err, "Marked %s port %u as reconfigured: %s "
+ "(0x%08x)", comp->name, port->index, gst_omx_error_to_string (err), err);
+
+ g_mutex_unlock (&comp->lock);
+
+ return err;
+}
+
+/* The OMX specs states that the nBufferCountActual of a port has to default
+ * to its nBufferCountMin. If we don't change nBufferCountActual we purely rely
+ * on this default. But in some cases, OMX may change nBufferCountMin before we
+ * allocate buffers. Like for example when configuring the input ports with the
+ * actual format, it may decrease the number of minimal buffers required.
+ * This method checks this and update nBufferCountActual if needed so we'll use
+ * less buffers than the worst case in such scenarios.
+ */
+gboolean
+gst_omx_port_ensure_buffer_count_actual (GstOMXPort * port, guint extra)
+{
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ guint nb;
+
+ gst_omx_port_get_port_definition (port, &port_def);
+
+ nb = port_def.nBufferCountMin + extra;
+ if (port_def.nBufferCountActual != nb) {
+ port_def.nBufferCountActual = nb;
+
+ GST_DEBUG_OBJECT (port->comp->parent,
+ "set port %d nBufferCountActual to %d", (guint) port->index, nb);
+
+ if (gst_omx_port_update_port_definition (port, &port_def) != OMX_ErrorNone)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+gst_omx_port_update_buffer_count_actual (GstOMXPort * port, guint nb)
+{
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+
+ gst_omx_port_get_port_definition (port, &port_def);
+
+ if (nb < port_def.nBufferCountMin) {
+ GST_DEBUG_OBJECT (port->comp->parent,
+ "Requested to use %d buffers on port %d but it's minimum is %d", nb,
+ (guint) port->index, (guint) port_def.nBufferCountMin);
+
+ nb = port_def.nBufferCountMin;
+ }
+
+ if (port_def.nBufferCountActual != nb) {
+ port_def.nBufferCountActual = nb;
+
+ GST_DEBUG_OBJECT (port->comp->parent,
+ "set port %d nBufferCountActual to %d", (guint) port->index, nb);
+
+ if (gst_omx_port_update_port_definition (port, &port_def) != OMX_ErrorNone)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+gst_omx_port_set_dmabuf (GstOMXPort * port, gboolean dmabuf)
+{
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ OMX_ALG_PORT_PARAM_BUFFER_MODE buffer_mode;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&buffer_mode);
+ buffer_mode.nPortIndex = port->index;
+
+ if (dmabuf)
+ buffer_mode.eMode = OMX_ALG_BUF_DMA;
+ else
+ buffer_mode.eMode = OMX_ALG_BUF_NORMAL;
+
+ err =
+ gst_omx_component_set_parameter (port->comp,
+ (OMX_INDEXTYPE) OMX_ALG_IndexPortParamBufferMode, &buffer_mode);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (port->comp->parent,
+ "Failed to set port %d in %sdmabuf mode: %s (0x%08x)",
+ port->index, dmabuf ? "" : "non-", gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+#else
+ /* dmabuf not supported for this platform */
+ return FALSE;
+#endif
+}
+
+gboolean
+gst_omx_port_set_subframe (GstOMXPort * port, gboolean enabled)
+{
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ OMX_ALG_VIDEO_PARAM_SUBFRAME subframe_mode;
+ OMX_ERRORTYPE err;
+ GST_DEBUG_OBJECT (port->comp->parent, "%s subframe mode for Zynq",
+ enabled ? "Enable" : "Disable");
+ GST_OMX_INIT_STRUCT (&subframe_mode);
+ subframe_mode.nPortIndex = port->index;
+
+ subframe_mode.bEnableSubframe = enabled;
+
+ err = gst_omx_component_set_parameter (port->comp,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoSubframe, &subframe_mode);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (port->comp->parent,
+ "Failed to %s subframe mode on port %d: %s (0x%08x)",
+ enabled ? "enable" : "disable", port->index,
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+#else
+ /* subframe mode is not supported on this platform */
+ return FALSE;
+#endif
+}
+
+gboolean
+gst_omx_port_get_subframe (GstOMXPort * port)
+{
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ OMX_ALG_VIDEO_PARAM_SUBFRAME subframe_mode;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&subframe_mode);
+ subframe_mode.nPortIndex = port->index;
+
+ err = gst_omx_component_get_parameter (port->comp,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoSubframe, &subframe_mode);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (port->comp->parent,
+ "Failed to get subframe mode on port %d: %s (0x%08x)",
+ port->index, gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return subframe_mode.bEnableSubframe;
+#else
+ /* subframe mode is not supported on this platform */
+ return FALSE;
+#endif
+}
+
+typedef GType (*GGetTypeFunction) (void);
+
+static const GGetTypeFunction types[] = {
+ gst_omx_analog_audio_sink_get_type, gst_omx_hdmi_audio_sink_get_type,
+ gst_omx_mpeg2_video_dec_get_type, gst_omx_mpeg4_video_dec_get_type,
+ gst_omx_h264_dec_get_type, gst_omx_h263_dec_get_type,
+ gst_omx_wmv_dec_get_type, gst_omx_mpeg4_video_enc_get_type,
+ gst_omx_h264_enc_get_type, gst_omx_h263_enc_get_type,
+ gst_omx_aac_enc_get_type, gst_omx_mjpeg_dec_get_type,
+ gst_omx_aac_dec_get_type, gst_omx_mp3_dec_get_type,
+ gst_omx_aac_dec_get_type, gst_omx_mp3_enc_get_type,
+ gst_omx_amr_dec_get_type
+#ifdef HAVE_VP8
+ , gst_omx_vp8_dec_get_type
+#endif
+#ifdef HAVE_THEORA
+ , gst_omx_theora_dec_get_type
+#endif
+#ifdef HAVE_HEVC
+ , gst_omx_h265_enc_get_type, gst_omx_h265_dec_get_type
+#endif
+};
+
+struct TypeOffest
+{
+ GType (*get_type) (void);
+ glong offset;
+};
+
+static const struct TypeOffest base_types[] = {
+ {gst_omx_audio_sink_get_type, G_STRUCT_OFFSET (GstOMXAudioSinkClass, cdata)},
+ {gst_omx_video_dec_get_type, G_STRUCT_OFFSET (GstOMXVideoDecClass, cdata)},
+ {gst_omx_video_enc_get_type, G_STRUCT_OFFSET (GstOMXVideoEncClass, cdata)},
+ {gst_omx_audio_dec_get_type, G_STRUCT_OFFSET (GstOMXAudioDecClass, cdata)},
+ {gst_omx_audio_enc_get_type, G_STRUCT_OFFSET (GstOMXAudioEncClass, cdata)},
+};
+
+static GKeyFile *config = NULL;
+GKeyFile *
+gst_omx_get_configuration (void)
+{
+ return config;
+}
+
+const gchar *
+gst_omx_error_to_string (OMX_ERRORTYPE err)
+{
+ guint err_u = (guint) err;
+
+ switch (err_u) {
+ case OMX_ErrorNone:
+ return "None";
+ case OMX_ErrorInsufficientResources:
+ return "Insufficient resources";
+ case OMX_ErrorUndefined:
+ return "Undefined";
+ case OMX_ErrorInvalidComponentName:
+ return "Invalid component name";
+ case OMX_ErrorComponentNotFound:
+ return "Component not found";
+ case OMX_ErrorBadParameter:
+ return "Bad parameter";
+ case OMX_ErrorNotImplemented:
+ return "Not implemented";
+ case OMX_ErrorUnderflow:
+ return "Underflow";
+ case OMX_ErrorOverflow:
+ return "Overflow";
+ case OMX_ErrorHardware:
+ return "Hardware";
+ case OMX_ErrorStreamCorrupt:
+ return "Stream corrupt";
+ case OMX_ErrorPortsNotCompatible:
+ return "Ports not compatible";
+ case OMX_ErrorResourcesLost:
+ return "Resources lost";
+ case OMX_ErrorNoMore:
+ return "No more";
+ case OMX_ErrorVersionMismatch:
+ return "Version mismatch";
+ case OMX_ErrorNotReady:
+ return "Not ready";
+ case OMX_ErrorTimeout:
+ return "Timeout";
+ case OMX_ErrorSameState:
+ return "Same state";
+ case OMX_ErrorResourcesPreempted:
+ return "Resources preempted";
+ case OMX_ErrorIncorrectStateTransition:
+ return "Incorrect state transition";
+ case OMX_ErrorIncorrectStateOperation:
+ return "Incorrect state operation";
+ case OMX_ErrorUnsupportedSetting:
+ return "Unsupported setting";
+ case OMX_ErrorUnsupportedIndex:
+ return "Unsupported index";
+ case OMX_ErrorBadPortIndex:
+ return "Bad port index";
+ case OMX_ErrorPortUnpopulated:
+ return "Port unpopulated";
+ case OMX_ErrorComponentSuspended:
+ return "Component suspended";
+ case OMX_ErrorDynamicResourcesUnavailable:
+ return "Dynamic resources unavailable";
+ case OMX_ErrorMbErrorsInFrame:
+ return "Macroblock errors in frame";
+ case OMX_ErrorFormatNotDetected:
+ return "Format not detected";
+ case OMX_ErrorSeperateTablesUsed:
+ return "Separate tables used";
+ case OMX_ErrorTunnelingUnsupported:
+ return "Tunneling unsupported";
+#if OMX_VERSION_MINOR == 1
+ case OMX_ErrorInvalidComponent:
+ return "Invalid component";
+ case OMX_ErrorInvalidState:
+ return "Invalid state";
+ case OMX_ErrorPortUnresponsiveDuringAllocation:
+ return "Port unresponsive during allocation";
+ case OMX_ErrorPortUnresponsiveDuringDeallocation:
+ return "Port unresponsive during deallocation";
+ case OMX_ErrorPortUnresponsiveDuringStop:
+ return "Port unresponsive during stop";
+ case OMX_ErrorContentPipeOpenFailed:
+ return "Content pipe open failed";
+ case OMX_ErrorContentPipeCreationFailed:
+ return "Content pipe creation failed";
+#endif
+ default:
+ if (err_u >= (guint) OMX_ErrorKhronosExtensions
+ && err_u < (guint) OMX_ErrorVendorStartUnused) {
+ return "Khronos extension error";
+ } else if (err_u >= (guint) OMX_ErrorVendorStartUnused
+ && err_u < (guint) OMX_ErrorMax) {
+ return "Vendor specific error";
+ } else {
+ return "Unknown error";
+ }
+ }
+}
+
+const gchar *
+gst_omx_state_to_string (OMX_STATETYPE state)
+{
+ switch (state) {
+ case OMX_StateInvalid:
+ return "Invalid";
+ case OMX_StateLoaded:
+ return "Loaded";
+ case OMX_StateIdle:
+ return "Idle";
+ case OMX_StateExecuting:
+ return "Executing";
+ case OMX_StatePause:
+ return "Pause";
+ case OMX_StateWaitForResources:
+ return "WaitForResources";
+ default:
+ if (state >= OMX_StateKhronosExtensions
+ && state < OMX_StateVendorStartUnused)
+ return "KhronosExtensionState";
+ else if (state >= OMX_StateVendorStartUnused && state < OMX_StateMax)
+ return "CustomVendorState";
+ break;
+ }
+ return "Unknown state";
+}
+
+const gchar *
+gst_omx_command_to_string (OMX_COMMANDTYPE cmd)
+{
+ switch (cmd) {
+ case OMX_CommandStateSet:
+ return "SetState";
+ case OMX_CommandFlush:
+ return "Flush";
+ case OMX_CommandPortDisable:
+ return "DisablePort";
+ case OMX_CommandPortEnable:
+ return "EnablePort";
+ case OMX_CommandMarkBuffer:
+ return "MarkBuffer";
+ default:
+ if (cmd >= OMX_CommandKhronosExtensions
+ && cmd < OMX_CommandVendorStartUnused)
+ return "KhronosExtensionCommand";
+ if (cmd >= OMX_CommandVendorStartUnused && cmd < OMX_CommandMax)
+ return "VendorExtensionCommand";
+ break;
+ }
+ return "Unknown command";
+}
+
+struct BufferFlagString
+{
+ guint32 flag;
+ const gchar *str;
+};
+
+struct BufferFlagString buffer_flags_map[] = {
+ {OMX_BUFFERFLAG_EOS, "eos"},
+ {OMX_BUFFERFLAG_STARTTIME, "start-time"},
+ {OMX_BUFFERFLAG_DECODEONLY, "decode-only"},
+ {OMX_BUFFERFLAG_DATACORRUPT, "data-corrupt"},
+ {OMX_BUFFERFLAG_ENDOFFRAME, "end-of-frame"},
+ {OMX_BUFFERFLAG_SYNCFRAME, "sync-frame"},
+ {OMX_BUFFERFLAG_EXTRADATA, "extra-data"},
+ {OMX_BUFFERFLAG_CODECCONFIG, "codec-config"},
+ /* Introduced in OMX 1.2.0 */
+#ifdef OMX_BUFFERFLAG_TIMESTAMPINVALID
+ {OMX_BUFFERFLAG_TIMESTAMPINVALID, "timestamp-invalid"},
+#endif
+#ifdef OMX_BUFFERFLAG_READONLY
+ {OMX_BUFFERFLAG_READONLY, "read-only"},
+#endif
+#ifdef OMX_BUFFERFLAG_ENDOFSUBFRAME
+ {OMX_BUFFERFLAG_ENDOFSUBFRAME, "end-of-subframe"},
+#endif
+#ifdef OMX_BUFFERFLAG_SKIPFRAME
+ {OMX_BUFFERFLAG_SKIPFRAME, "skip-frame"},
+#endif
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ {OMX_ALG_BUFFERFLAG_TOP_FIELD, "top-field"},
+ {OMX_ALG_BUFFERFLAG_BOT_FIELD, "bottom-field"},
+#endif
+ {0, NULL},
+};
+
+
+const gchar *
+gst_omx_buffer_flags_to_string (guint32 flags)
+{
+ GString *s = NULL;
+ guint i;
+ const gchar *str;
+
+ if (flags == 0)
+ return "";
+
+ /* Keep a cache of the string representation of the flags so we don't allocate
+ * and free strings for each buffer. In practice we should only have a handfull
+ * of flags so the cache won't consume much memory. */
+ if (!buffer_flags_str) {
+ G_LOCK (buffer_flags_str);
+ buffer_flags_str = g_hash_table_new_full (NULL, NULL, NULL, g_free);
+ G_UNLOCK (buffer_flags_str);
+ }
+
+ str = g_hash_table_lookup (buffer_flags_str, GUINT_TO_POINTER (flags));
+ if (str)
+ return str;
+
+ for (i = 0; buffer_flags_map[i].str != NULL; i++) {
+ if ((flags & buffer_flags_map[i].flag) == 0)
+ continue;
+
+ if (!s)
+ s = g_string_new (buffer_flags_map[i].str);
+ else
+ g_string_append_printf (s, ", %s", buffer_flags_map[i].str);
+ }
+
+ if (!s)
+ return "<unknown>";
+
+ str = g_string_free (s, FALSE);
+
+ G_LOCK (buffer_flags_str);
+ /* Transfer ownership of str to hash table */
+ g_hash_table_insert (buffer_flags_str, GUINT_TO_POINTER (flags),
+ (gchar *) str);
+ G_UNLOCK (buffer_flags_str);
+
+ return str;
+}
+
+#if defined(USE_OMX_TARGET_RPI)
+#define DEFAULT_HACKS (GST_OMX_HACK_NO_COMPONENT_ROLE | GST_OMX_HACK_HEIGHT_MULTIPLE_16)
+#else
+#define DEFAULT_HACKS (0)
+#endif
+
+guint64
+gst_omx_parse_hacks (gchar ** hacks)
+{
+ guint64 hacks_flags = DEFAULT_HACKS;
+
+ if (!hacks)
+ return 0;
+
+ while (*hacks) {
+ if (g_str_equal (*hacks,
+ "event-port-settings-changed-ndata-parameter-swap"))
+ hacks_flags |=
+ GST_OMX_HACK_EVENT_PORT_SETTINGS_CHANGED_NDATA_PARAMETER_SWAP;
+ else if (g_str_equal (*hacks, "event-port-settings-changed-port-0-to-1"))
+ hacks_flags |= GST_OMX_HACK_EVENT_PORT_SETTINGS_CHANGED_PORT_0_TO_1;
+ else if (g_str_equal (*hacks, "video-framerate-integer"))
+ hacks_flags |= GST_OMX_HACK_VIDEO_FRAMERATE_INTEGER;
+ else if (g_str_equal (*hacks, "syncframe-flag-not-used"))
+ hacks_flags |= GST_OMX_HACK_SYNCFRAME_FLAG_NOT_USED;
+ else if (g_str_equal (*hacks, "no-component-reconfigure"))
+ hacks_flags |= GST_OMX_HACK_NO_COMPONENT_RECONFIGURE;
+ else if (g_str_equal (*hacks, "no-empty-eos-buffer"))
+ hacks_flags |= GST_OMX_HACK_NO_EMPTY_EOS_BUFFER;
+ else if (g_str_equal (*hacks, "drain-may-not-return"))
+ hacks_flags |= GST_OMX_HACK_DRAIN_MAY_NOT_RETURN;
+ else if (g_str_equal (*hacks, "no-component-role"))
+ hacks_flags |= GST_OMX_HACK_NO_COMPONENT_ROLE;
+ else if (g_str_equal (*hacks, "no-disable-outport"))
+ hacks_flags |= GST_OMX_HACK_NO_DISABLE_OUTPORT;
+ else if (g_str_equal (*hacks, "signals-premature-eos"))
+ hacks_flags |= GST_OMX_HACK_SIGNALS_PREMATURE_EOS;
+ else if (g_str_equal (*hacks, "height-multiple-16"))
+ hacks_flags |= GST_OMX_HACK_HEIGHT_MULTIPLE_16;
+ else if (g_str_equal (*hacks, "pass-profile-to-decoder"))
+ hacks_flags |= GST_OMX_HACK_PASS_PROFILE_TO_DECODER;
+ else if (g_str_equal (*hacks, "pass-color-format-to-decoder"))
+ hacks_flags |= GST_OMX_HACK_PASS_COLOR_FORMAT_TO_DECODER;
+ else if (g_str_equal (*hacks, "ensure-buffer-count-actual"))
+ hacks_flags |= GST_OMX_HACK_ENSURE_BUFFER_COUNT_ACTUAL;
+ else
+ GST_WARNING ("Unknown hack: %s", *hacks);
+ hacks++;
+ }
+
+ return hacks_flags;
+}
+
+
+void
+gst_omx_set_default_role (GstOMXClassData * class_data,
+ const gchar * default_role)
+{
+ if (!class_data->component_role)
+ class_data->component_role = default_role;
+}
+
+static void
+_class_init (gpointer g_class, gpointer data)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+ GstOMXClassData *class_data = NULL;
+ GKeyFile *config;
+ const gchar *element_name = data;
+ GError *err;
+ gchar *core_name, *component_name, *component_role;
+ gint in_port_index, out_port_index;
+ gchar *template_caps;
+ GstPadTemplate *templ;
+ GstCaps *caps;
+ gchar **hacks;
+ int i;
+
+ if (!element_name)
+ return;
+
+ /* Find the GstOMXClassData for this class */
+ for (i = 0; i < G_N_ELEMENTS (base_types); i++) {
+ GType gtype = base_types[i].get_type ();
+
+ if (G_TYPE_CHECK_CLASS_TYPE (g_class, gtype)) {
+ class_data = (GstOMXClassData *)
+ (((guint8 *) g_class) + base_types[i].offset);
+ break;
+ }
+ }
+
+ g_assert (class_data != NULL);
+
+ config = gst_omx_get_configuration ();
+
+ /* This will alwaxys succeed, see check in plugin_init */
+ core_name = g_key_file_get_string (config, element_name, "core-name", NULL);
+ g_assert (core_name != NULL);
+ class_data->core_name = core_name;
+ component_name =
+ g_key_file_get_string (config, element_name, "component-name", NULL);
+ g_assert (component_name != NULL);
+ class_data->component_name = component_name;
+
+ /* If this fails we simply don't set a role */
+ if ((component_role =
+ g_key_file_get_string (config, element_name, "component-role",
+ NULL))) {
+ GST_DEBUG ("Using component-role '%s' for element '%s'", component_role,
+ element_name);
+ class_data->component_role = component_role;
+ }
+
+
+ /* Now set the inport/outport indizes and assume sane defaults */
+ err = NULL;
+ in_port_index =
+ g_key_file_get_integer (config, element_name, "in-port-index", &err);
+ if (err != NULL) {
+ GST_DEBUG ("No 'in-port-index' set for element '%s', auto-detecting: %s",
+ element_name, err->message);
+ in_port_index = -1;
+ g_error_free (err);
+ }
+ class_data->in_port_index = in_port_index;
+
+ err = NULL;
+ out_port_index =
+ g_key_file_get_integer (config, element_name, "out-port-index", &err);
+ if (err != NULL) {
+ GST_DEBUG ("No 'out-port-index' set for element '%s', auto-detecting: %s",
+ element_name, err->message);
+ out_port_index = -1;
+ g_error_free (err);
+ }
+ class_data->out_port_index = out_port_index;
+
+ /* Add pad templates */
+ err = NULL;
+ if (class_data->type != GST_OMX_COMPONENT_TYPE_SOURCE) {
+ if (!(template_caps =
+ g_key_file_get_string (config, element_name, "sink-template-caps",
+ &err))) {
+ GST_DEBUG
+ ("No sink template caps specified for element '%s', using default '%s'",
+ element_name, class_data->default_sink_template_caps);
+ caps = gst_caps_from_string (class_data->default_sink_template_caps);
+ g_assert (caps != NULL);
+ g_error_free (err);
+ } else {
+ caps = gst_caps_from_string (template_caps);
+ if (!caps) {
+ GST_DEBUG
+ ("Could not parse sink template caps '%s' for element '%s', using default '%s'",
+ template_caps, element_name,
+ class_data->default_sink_template_caps);
+ caps = gst_caps_from_string (class_data->default_sink_template_caps);
+ g_assert (caps != NULL);
+ }
+ }
+ templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps);
+ g_free (template_caps);
+ gst_element_class_add_pad_template (element_class, templ);
+ gst_caps_unref (caps);
+ }
+
+ err = NULL;
+ if (class_data->type != GST_OMX_COMPONENT_TYPE_SINK) {
+ if (!(template_caps =
+ g_key_file_get_string (config, element_name, "src-template-caps",
+ &err))) {
+ GST_DEBUG
+ ("No src template caps specified for element '%s', using default '%s'",
+ element_name, class_data->default_src_template_caps);
+ caps = gst_caps_from_string (class_data->default_src_template_caps);
+ g_assert (caps != NULL);
+ g_error_free (err);
+ } else {
+ caps = gst_caps_from_string (template_caps);
+ if (!caps) {
+ GST_DEBUG
+ ("Could not parse src template caps '%s' for element '%s', using default '%s'",
+ template_caps, element_name, class_data->default_src_template_caps);
+ caps = gst_caps_from_string (class_data->default_src_template_caps);
+ g_assert (caps != NULL);
+ }
+ }
+ templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps);
+ g_free (template_caps);
+ gst_element_class_add_pad_template (element_class, templ);
+ gst_caps_unref (caps);
+ }
+
+ if ((hacks =
+ g_key_file_get_string_list (config, element_name, "hacks", NULL,
+ NULL))) {
+#ifndef GST_DISABLE_GST_DEBUG
+ gchar **walk = hacks;
+
+ while (*walk) {
+ GST_DEBUG ("Using hack: %s", *walk);
+ walk++;
+ }
+#endif
+
+ class_data->hacks = gst_omx_parse_hacks (hacks);
+ g_strfreev (hacks);
+ }
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ GError *err = NULL;
+ gchar **config_dirs;
+ gchar **elements;
+ gchar *env_config_dir;
+ const gchar *user_config_dir;
+ const gchar *const *system_config_dirs;
+ gint i, j;
+ gsize n_elements;
+ static const gchar *config_name[] = { "gstomx.conf", NULL };
+ static const gchar *env_config_name[] = { "GST_OMX_CONFIG_DIR", NULL };
+ static const gchar *gst_omx_config_dir = GST_OMX_CONFIG_DIR;
+
+ GST_DEBUG_CATEGORY_INIT (gstomx_debug, "omx", 0, "gst-omx");
+ GST_DEBUG_CATEGORY_INIT (gst_omx_video_debug_category, "omxvideo", 0,
+ "gst-omx-video");
+ GST_DEBUG_CATEGORY_INIT (OMX_API_TRACE, "OMX_API_TRACE", 0,
+ "gst-omx performace");
+
+ /* Read configuration file gstomx.conf from the preferred
+ * configuration directories */
+ env_config_dir = g_strdup (g_getenv (*env_config_name));
+ user_config_dir = g_get_user_config_dir ();
+ system_config_dirs = g_get_system_config_dirs ();
+ config_dirs =
+ g_new (gchar *, g_strv_length ((gchar **) system_config_dirs) + 4);
+
+ i = 0;
+ j = 0;
+ if (env_config_dir)
+ config_dirs[i++] = (gchar *) env_config_dir;
+ config_dirs[i++] = (gchar *) user_config_dir;
+ while (system_config_dirs[j])
+ config_dirs[i++] = (gchar *) system_config_dirs[j++];
+ config_dirs[i++] = (gchar *) gst_omx_config_dir;
+ config_dirs[i++] = NULL;
+
+ gst_plugin_add_dependency (plugin, env_config_name,
+ (const gchar **) (config_dirs + (env_config_dir ? 1 : 0)), config_name,
+ GST_PLUGIN_DEPENDENCY_FLAG_NONE);
+
+ config = g_key_file_new ();
+ if (!g_key_file_load_from_dirs (config, *config_name,
+ (const gchar **) config_dirs, NULL, G_KEY_FILE_NONE, &err)) {
+#ifdef USE_OMX_TARGET_GENERIC
+ GST_INFO ("No configuration file found; "
+ "ignore as gst-omx has been built with the generic target used only for testing");
+#else
+ {
+ gchar *paths;
+
+ paths = g_strjoinv (":", config_dirs);
+ GST_ERROR
+ ("Failed to load configuration file: %s (searched in: %s as per "
+ "GST_OMX_CONFIG_DIR environment variable, the xdg user config "
+ "directory (or XDG_CONFIG_HOME) and the system config directory "
+ "(or XDG_CONFIG_DIRS)", err->message, paths);
+ g_free (paths);
+ }
+#endif /* USE_OMX_TARGET_GENERIC */
+
+ g_error_free (err);
+ goto done;
+ }
+
+ /* Initialize all types */
+ for (i = 0; i < G_N_ELEMENTS (types); i++)
+ types[i] ();
+
+ elements = g_key_file_get_groups (config, &n_elements);
+ for (i = 0; i < n_elements; i++) {
+ GTypeQuery type_query;
+ GTypeInfo type_info = { 0, };
+ GType type, subtype;
+ gchar *type_name, *core_name, *component_name;
+ gint rank;
+
+ GST_DEBUG ("Registering element '%s'", elements[i]);
+
+ err = NULL;
+ if (!(type_name =
+ g_key_file_get_string (config, elements[i], "type-name", &err))) {
+ GST_ERROR
+ ("Unable to read 'type-name' configuration for element '%s': %s",
+ elements[i], err->message);
+ g_error_free (err);
+ continue;
+ }
+
+ type = g_type_from_name (type_name);
+ if (type == G_TYPE_INVALID) {
+ GST_ERROR ("Invalid type name '%s' for element '%s'", type_name,
+ elements[i]);
+ g_free (type_name);
+ continue;
+ }
+ if (!g_type_is_a (type, GST_TYPE_ELEMENT)) {
+ GST_ERROR ("Type '%s' is no GstElement subtype for element '%s'",
+ type_name, elements[i]);
+ g_free (type_name);
+ continue;
+ }
+ g_free (type_name);
+
+ /* And now some sanity checking */
+ err = NULL;
+ if (!(core_name =
+ g_key_file_get_string (config, elements[i], "core-name", &err))) {
+ GST_ERROR
+ ("Unable to read 'core-name' configuration for element '%s': %s",
+ elements[i], err->message);
+ g_error_free (err);
+ continue;
+ }
+ if (!g_file_test (core_name, G_FILE_TEST_IS_REGULAR)) {
+ GST_ERROR ("Core '%s' does not exist for element '%s'", core_name,
+ elements[i]);
+ g_free (core_name);
+ continue;
+ }
+ g_free (core_name);
+
+ err = NULL;
+ if (!(component_name =
+ g_key_file_get_string (config, elements[i], "component-name",
+ &err))) {
+ GST_ERROR
+ ("Unable to read 'component-name' configuration for element '%s': %s",
+ elements[i], err->message);
+ g_error_free (err);
+ continue;
+ }
+ g_free (component_name);
+
+ err = NULL;
+ rank = g_key_file_get_integer (config, elements[i], "rank", &err);
+ if (err != NULL) {
+ GST_ERROR ("No rank set for element '%s': %s", elements[i], err->message);
+ g_error_free (err);
+ continue;
+ }
+
+ /* And now register the type, all other configuration will
+ * be handled by the type itself */
+ g_type_query (type, &type_query);
+ memset (&type_info, 0, sizeof (type_info));
+ type_info.class_size = type_query.class_size;
+ type_info.instance_size = type_query.instance_size;
+ type_info.class_init = _class_init;
+ type_info.class_data = g_strdup (elements[i]);
+ type_name = g_strdup_printf ("%s-%s", g_type_name (type), elements[i]);
+ if (g_type_from_name (type_name) != G_TYPE_INVALID) {
+ GST_ERROR ("Type '%s' already exists for element '%s'", type_name,
+ elements[i]);
+ g_free (type_name);
+ continue;
+ }
+ subtype = g_type_register_static (type, type_name, &type_info, 0);
+ g_free (type_name);
+ gst_element_register (plugin, elements[i], rank, subtype);
+ }
+ g_strfreev (elements);
+
+done:
+ g_free (env_config_dir);
+ g_free (config_dirs);
+
+ return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ omx,
+ "GStreamer OpenMAX Plug-ins",
+ plugin_init,
+ PACKAGE_VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/subprojects/gst-omx/omx/gstomx.h b/subprojects/gst-omx/omx/gstomx.h
new file mode 100644
index 0000000000..68624632df
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomx.h
@@ -0,0 +1,493 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ * Copyright (C) 2013, Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * 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_OMX_H__
+#define __GST_OMX_H__
+
+#include <gmodule.h>
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef GST_OMX_STRUCT_PACKING
+# if GST_OMX_STRUCT_PACKING == 1
+# pragma pack(1)
+# elif GST_OMX_STRUCT_PACKING == 2
+# pragma pack(2)
+# elif GST_OMX_STRUCT_PACKING == 4
+# pragma pack(4)
+# elif GST_OMX_STRUCT_PACKING == 8
+# pragma pack(8)
+# else
+# error "Unsupported struct packing value"
+# endif
+#endif
+
+/* If the component may signal EOS before it has finished pushing
+ * out all of its buffers. Happens with egl_render on the rpi.
+ */
+#define GST_OMX_HACK_SIGNALS_PREMATURE_EOS G_GUINT64_CONSTANT (0x0000000000000400)
+
+#include <OMX_Core.h>
+#include <OMX_Component.h>
+
+#ifdef USE_OMX_TARGET_RPI
+#include <OMX_Broadcom.h>
+#endif
+
+#ifdef HAVE_VIDEO_EXT
+#include <OMX_VideoExt.h>
+#endif
+
+#ifdef HAVE_INDEX_EXT
+#include <OMX_IndexExt.h>
+#endif
+
+#ifdef HAVE_COMPONENT_EXT
+#include <OMX_ComponentExt.h>
+#endif
+
+#ifdef HAVE_CORE_EXT
+#include <OMX_CoreExt.h>
+#endif
+
+#ifdef HAVE_AUDIO_EXT
+#include <OMX_AudioExt.h>
+#endif
+
+#ifdef HAVE_IV_COMMON_EXT
+#include <OMX_IVCommonExt.h>
+#endif
+
+#ifdef HAVE_IMAGE_EXT
+#include <OMX_ImageExt.h>
+#endif
+
+#ifdef HAVE_OTHER_EXT
+#include <OMX_OtherExt.h>
+#endif
+
+#ifdef GST_OMX_STRUCT_PACKING
+#pragma pack()
+#endif
+
+G_BEGIN_DECLS
+
+#define GST_OMX_INIT_STRUCT(st) G_STMT_START { \
+ memset ((st), 0, sizeof (*(st))); \
+ (st)->nSize = sizeof (*(st)); \
+ (st)->nVersion.s.nVersionMajor = OMX_VERSION_MAJOR; \
+ (st)->nVersion.s.nVersionMinor = OMX_VERSION_MINOR; \
+ (st)->nVersion.s.nRevision = OMX_VERSION_REVISION; \
+ (st)->nVersion.s.nStep = OMX_VERSION_STEP; \
+} G_STMT_END
+
+#ifdef OMX_SKIP64BIT
+#define GST_OMX_GET_TICKS(ticks) ((((guint64) (ticks).nHighPart) << 32) | ((ticks).nLowPart))
+#define GST_OMX_SET_TICKS(ticks, i) G_STMT_START { \
+ ticks.nLowPart = ((guint64) (i)) & 0xffffffff; \
+ ticks.nHighPart = ((guint64) (i)) >> 32; \
+} G_STMT_END
+#else
+#define GST_OMX_GET_TICKS(ticks) (ticks)
+#define GST_OMX_SET_TICKS(ticks, i) G_STMT_START { \
+ ticks = i; \
+} G_STMT_END
+#endif
+
+/* If set on an element property means "use the OMX default value".
+ * If set on a default_* variable means that the default values hasn't been
+ * retrieved from OMX yet. */
+#define GST_OMX_PROP_OMX_DEFAULT G_MAXUINT32
+
+/* OMX_StateInvalid does not exist in 1.2.0 spec. The initial state is now
+ * StateLoaded. Problem is that gst-omx still needs an initial state different
+ * than StateLoaded. Otherwise gst_omx_component_set_state(StateLoaded) will
+ * early return because it will think it is already in StateLoaded. Also note
+ * that there is no call to gst_omx_component_set_state(StateInvalid) so this
+ * also shows that StateInvalid is used as a helper in gst-omx.
+ */
+#if OMX_VERSION_MINOR == 2
+#define OMX_StateInvalid OMX_StateReserved_0x00000000
+#endif
+
+/* Different hacks that are required to work around
+ * bugs in different OpenMAX implementations
+ */
+/* In the EventSettingsChanged callback use nData2 instead of nData1 for
+ * the port index. Happens with Bellagio.
+ */
+#define GST_OMX_HACK_EVENT_PORT_SETTINGS_CHANGED_NDATA_PARAMETER_SWAP G_GUINT64_CONSTANT (0x0000000000000001)
+/* In the EventSettingsChanged callback assume that port index 0 really
+ * means port index 1. Happens with the Bellagio ffmpegdist video decoder.
+ */
+#define GST_OMX_HACK_EVENT_PORT_SETTINGS_CHANGED_PORT_0_TO_1 G_GUINT64_CONSTANT (0x0000000000000002)
+/* If the video framerate is not specified as fraction (Q.16) but as
+ * integer number. Happens with the Bellagio ffmpegdist video encoder.
+ */
+#define GST_OMX_HACK_VIDEO_FRAMERATE_INTEGER G_GUINT64_CONSTANT (0x0000000000000004)
+/* If the SYNCFRAME flag on encoder output buffers is not used and we
+ * have to assume that all frames are sync frames.
+ * Happens with the Bellagio ffmpegdist video encoder.
+ */
+#define GST_OMX_HACK_SYNCFRAME_FLAG_NOT_USED G_GUINT64_CONSTANT (0x0000000000000008)
+/* If the component needs to be re-created if the caps change.
+ * Happens with Qualcomm's OpenMAX implementation.
+ */
+#define GST_OMX_HACK_NO_COMPONENT_RECONFIGURE G_GUINT64_CONSTANT (0x0000000000000010)
+
+/* If the component does not accept empty EOS buffers.
+ * Happens with Qualcomm's OpenMAX implementation.
+ */
+#define GST_OMX_HACK_NO_EMPTY_EOS_BUFFER G_GUINT64_CONSTANT (0x0000000000000020)
+
+/* If the component might not acknowledge a drain.
+ * Happens with TI's Ducati OpenMAX implementation.
+ */
+#define GST_OMX_HACK_DRAIN_MAY_NOT_RETURN G_GUINT64_CONSTANT (0x0000000000000040)
+
+/* If the component doesn't allow any component role to be set.
+ * Happens with Broadcom's OpenMAX implementation.
+ */
+#define GST_OMX_HACK_NO_COMPONENT_ROLE G_GUINT64_CONSTANT (0x0000000000000080)
+
+/* If the component doesn't allow disabling the outport while
+ * when setting the format until the output format is known.
+ */
+#define GST_OMX_HACK_NO_DISABLE_OUTPORT G_GUINT64_CONSTANT (0x0000000000000100)
+
+/* If the encoder requires input buffers that have a height
+ * which is a multiple of 16 pixels
+ */
+#define GST_OMX_HACK_HEIGHT_MULTIPLE_16 G_GUINT64_CONSTANT (0x0000000000000200)
+
+/* If we should pass the profile/level information from upstream to the
+ * OMX decoder. This is a violation of the OMX spec as
+ * OMX_IndexParamVideoProfileLevelCurrent is supposed to be r-o so
+ * do it as a platform specific hack.
+ */
+#define GST_OMX_HACK_PASS_PROFILE_TO_DECODER G_GUINT64_CONSTANT (0x0000000000000800)
+
+/* If we should pass the color format information from upstream to the
+ * OMX decoder input. This is a violation of the OMX spec as
+ * the eColorFormat field is supposed to only be used if eCompressionFormat is
+ * set to OMX_IMAGE_CodingUnused.
+ * Do this as a platform specific hack for OMX implementation which may use
+ * this information to pre-allocate internal buffers for example.
+ */
+#define GST_OMX_HACK_PASS_COLOR_FORMAT_TO_DECODER G_GUINT64_CONSTANT (0x0000000000001000)
+
+/* If set, automatically update nBufferCountActual to nBufferCountMin before
+ * allocating buffers. This can be used on OMX implementation decreasing
+ * nBufferCountMin depending of the format and so can reduce the number
+ * of allocated buffers.
+ */
+#define GST_OMX_HACK_ENSURE_BUFFER_COUNT_ACTUAL G_GUINT64_CONSTANT (0x0000000000002000)
+
+typedef struct _GstOMXCore GstOMXCore;
+typedef struct _GstOMXPort GstOMXPort;
+typedef enum _GstOMXPortDirection GstOMXPortDirection;
+typedef struct _GstOMXComponent GstOMXComponent;
+typedef struct _GstOMXBuffer GstOMXBuffer;
+typedef struct _GstOMXClassData GstOMXClassData;
+typedef struct _GstOMXMessage GstOMXMessage;
+
+typedef enum {
+ /* Everything good and the buffer is valid */
+ GST_OMX_ACQUIRE_BUFFER_OK = 0,
+ /* The port is flushing, exit ASAP */
+ GST_OMX_ACQUIRE_BUFFER_FLUSHING,
+ /* The port must be reconfigured */
+ GST_OMX_ACQUIRE_BUFFER_RECONFIGURE,
+ /* The port is EOS */
+ GST_OMX_ACQUIRE_BUFFER_EOS,
+ /* A fatal error happened */
+ GST_OMX_ACQUIRE_BUFFER_ERROR,
+ /* No buffer is currently available (used when calling gst_omx_port_acquire_buffer() in not waiting mode) */
+ GST_OMX_ACQUIRE_BUFFER_NO_AVAILABLE,
+} GstOMXAcquireBufferReturn;
+
+struct _GstOMXCore {
+ /* Handle to the OpenMAX IL core shared library */
+ GModule *module;
+
+ /* Current number of users, transitions from/to 0
+ * call init/deinit */
+ GMutex lock;
+ gint user_count; /* LOCK */
+
+ /* OpenMAX core library functions, protected with LOCK */
+ OMX_ERRORTYPE (*init) (void);
+ OMX_ERRORTYPE (*deinit) (void);
+ OMX_ERRORTYPE (*get_handle) (OMX_HANDLETYPE * handle,
+ OMX_STRING name, OMX_PTR data, OMX_CALLBACKTYPE * callbacks);
+ OMX_ERRORTYPE (*free_handle) (OMX_HANDLETYPE handle);
+ OMX_ERRORTYPE (*setup_tunnel) (OMX_HANDLETYPE output, OMX_U32 outport, OMX_HANDLETYPE input, OMX_U32 inport);
+};
+
+typedef enum {
+ GST_OMX_MESSAGE_STATE_SET,
+ GST_OMX_MESSAGE_FLUSH,
+ GST_OMX_MESSAGE_ERROR,
+ GST_OMX_MESSAGE_PORT_ENABLE,
+ GST_OMX_MESSAGE_PORT_SETTINGS_CHANGED,
+ GST_OMX_MESSAGE_BUFFER_FLAG,
+ GST_OMX_MESSAGE_BUFFER_DONE,
+} GstOMXMessageType;
+
+typedef enum {
+ GST_OMX_COMPONENT_TYPE_SINK,
+ GST_OMX_COMPONENT_TYPE_SOURCE,
+ GST_OMX_COMPONENT_TYPE_FILTER
+} GstOmxComponentType;
+
+/* How the port's buffers are allocated */
+typedef enum {
+ GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER,
+ GST_OMX_BUFFER_ALLOCATION_USE_BUFFER,
+ GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC, /* Only supported by OMX 1.2.0 */
+} GstOMXBufferAllocation;
+
+typedef enum {
+ GST_OMX_WAIT,
+ GST_OMX_DONT_WAIT,
+} GstOMXWait;
+
+struct _GstOMXMessage {
+ GstOMXMessageType type;
+
+ union {
+ struct {
+ OMX_STATETYPE state;
+ } state_set;
+ struct {
+ OMX_U32 port;
+ } flush;
+ struct {
+ OMX_ERRORTYPE error;
+ } error;
+ struct {
+ OMX_U32 port;
+ OMX_BOOL enable;
+ } port_enable;
+ struct {
+ OMX_U32 port;
+ } port_settings_changed;
+ struct {
+ OMX_U32 port;
+ OMX_U32 flags;
+ } buffer_flag;
+ struct {
+ OMX_HANDLETYPE component;
+ OMX_PTR app_data;
+ OMX_BUFFERHEADERTYPE *buffer;
+ OMX_BOOL empty;
+ } buffer_done;
+ } content;
+};
+
+struct _GstOMXPort {
+ GstOMXComponent *comp;
+ guint32 index;
+
+ gboolean tunneled;
+
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ GPtrArray *buffers; /* Contains GstOMXBuffer* */
+ GQueue pending_buffers; /* Contains GstOMXBuffer* */
+ gboolean flushing;
+ gboolean flushed; /* TRUE after OMX_CommandFlush was done */
+ gboolean enabled_pending; /* TRUE after OMX_Command{En,Dis}able */
+ gboolean disabled_pending; /* was done until it took effect */
+ gboolean eos; /* TRUE after a buffer with EOS flag was received */
+ GstOMXBufferAllocation allocation;
+ gboolean using_pool; /* TRUE if the buffers of this port are managed by a pool */
+
+ /* Increased whenever the settings of these port change.
+ * If settings_cookie != configured_settings_cookie
+ * the port has to be reconfigured.
+ */
+ gint settings_cookie;
+ gint configured_settings_cookie;
+};
+
+struct _GstOMXComponent {
+ GstMiniObject mini_object;
+
+ GstObject *parent;
+
+ gchar *name; /* for debugging mostly */
+
+ OMX_HANDLETYPE handle;
+ GstOMXCore *core;
+
+ guint64 hacks; /* Flags, GST_OMX_HACK_* */
+
+ /* Added once, never changed. No locks necessary */
+ GPtrArray *ports; /* Contains GstOMXPort* */
+ gint n_in_ports, n_out_ports;
+
+ /* Locking order: lock -> messages_lock
+ *
+ * Never hold lock while waiting for messages_cond
+ * Always check that messages is empty before waiting */
+ GMutex lock;
+
+ GQueue messages; /* Queue of GstOMXMessages */
+ GMutex messages_lock;
+ GCond messages_cond;
+
+ OMX_STATETYPE state;
+ /* OMX_StateInvalid if no pending state */
+ OMX_STATETYPE pending_state;
+ /* OMX_ErrorNone usually, if different nothing will work */
+ OMX_ERRORTYPE last_error;
+
+ GList *pending_reconfigure_outports;
+};
+
+struct _GstOMXBuffer {
+ GstOMXPort *port;
+ OMX_BUFFERHEADERTYPE *omx_buf;
+
+ /* TRUE if the buffer is used by the port, i.e.
+ * between {Empty,Fill}ThisBuffer and the callback
+ */
+ gboolean used;
+
+ /* Cookie of the settings when this buffer was allocated */
+ gint settings_cookie;
+
+ /* TRUE if this is an EGLImage */
+ gboolean eglimage;
+
+ /* Used in dynamic buffer mode to keep track of the mapped content while it's
+ * being processed by the OMX component. */
+ GstVideoFrame input_frame;
+ gboolean input_frame_mapped; /* TRUE if input_frame is valid */
+ GstMemory *input_mem;
+ GstBuffer *input_buffer;
+ gboolean input_buffer_mapped;
+ GstMapInfo map;
+};
+
+struct _GstOMXClassData {
+ const gchar *core_name;
+ const gchar *component_name;
+ const gchar *component_role;
+
+ const gchar *default_src_template_caps;
+ const gchar *default_sink_template_caps;
+
+ guint32 in_port_index, out_port_index;
+
+ guint64 hacks;
+
+ GstOmxComponentType type;
+};
+
+GKeyFile * gst_omx_get_configuration (void);
+
+const gchar * gst_omx_error_to_string (OMX_ERRORTYPE err);
+const gchar * gst_omx_state_to_string (OMX_STATETYPE state);
+const gchar * gst_omx_command_to_string (OMX_COMMANDTYPE cmd);
+const gchar * gst_omx_buffer_flags_to_string (guint32 flags);
+
+guint64 gst_omx_parse_hacks (gchar ** hacks);
+
+GstOMXCore * gst_omx_core_acquire (const gchar * filename);
+void gst_omx_core_release (GstOMXCore * core);
+
+GType gst_omx_component_get_type (void);
+
+GstOMXComponent * gst_omx_component_new (GstObject * parent, const gchar *core_name, const gchar *component_name, const gchar * component_role, guint64 hacks);
+GstOMXComponent * gst_omx_component_ref (GstOMXComponent * comp);
+void gst_omx_component_unref (GstOMXComponent * comp);
+
+OMX_ERRORTYPE gst_omx_component_set_state (GstOMXComponent * comp, OMX_STATETYPE state);
+OMX_STATETYPE gst_omx_component_get_state (GstOMXComponent * comp, GstClockTime timeout);
+
+OMX_ERRORTYPE gst_omx_component_get_last_error (GstOMXComponent * comp);
+const gchar * gst_omx_component_get_last_error_string (GstOMXComponent * comp);
+
+GstOMXPort * gst_omx_component_add_port (GstOMXComponent * comp, guint32 index);
+GstOMXPort * gst_omx_component_get_port (GstOMXComponent * comp, guint32 index);
+
+OMX_ERRORTYPE gst_omx_component_get_parameter (GstOMXComponent * comp, OMX_INDEXTYPE index, gpointer param);
+OMX_ERRORTYPE gst_omx_component_set_parameter (GstOMXComponent * comp, OMX_INDEXTYPE index, gpointer param);
+
+OMX_ERRORTYPE gst_omx_component_get_config (GstOMXComponent * comp, OMX_INDEXTYPE index, gpointer config);
+OMX_ERRORTYPE gst_omx_component_set_config (GstOMXComponent * comp, OMX_INDEXTYPE index, gpointer config);
+
+OMX_ERRORTYPE gst_omx_setup_tunnel (GstOMXPort * port1, GstOMXPort * port2);
+OMX_ERRORTYPE gst_omx_close_tunnel (GstOMXPort * port1, GstOMXPort * port2);
+
+
+OMX_ERRORTYPE gst_omx_port_get_port_definition (GstOMXPort * port, OMX_PARAM_PORTDEFINITIONTYPE * port_def);
+OMX_ERRORTYPE gst_omx_port_update_port_definition (GstOMXPort *port, OMX_PARAM_PORTDEFINITIONTYPE *port_definition);
+
+GstOMXAcquireBufferReturn gst_omx_port_acquire_buffer (GstOMXPort *port, GstOMXBuffer **buf, GstOMXWait wait);
+OMX_ERRORTYPE gst_omx_port_release_buffer (GstOMXPort *port, GstOMXBuffer *buf);
+
+OMX_ERRORTYPE gst_omx_port_set_flushing (GstOMXPort *port, GstClockTime timeout, gboolean flush);
+gboolean gst_omx_port_is_flushing (GstOMXPort *port);
+
+OMX_ERRORTYPE gst_omx_port_allocate_buffers (GstOMXPort *port);
+OMX_ERRORTYPE gst_omx_port_use_buffers (GstOMXPort *port, const GList *buffers);
+OMX_ERRORTYPE gst_omx_port_use_eglimages (GstOMXPort *port, const GList *images);
+OMX_ERRORTYPE gst_omx_port_deallocate_buffers (GstOMXPort *port);
+OMX_ERRORTYPE gst_omx_port_populate (GstOMXPort *port);
+OMX_ERRORTYPE gst_omx_port_wait_buffers_released (GstOMXPort * port, GstClockTime timeout);
+void gst_omx_port_requeue_buffer (GstOMXPort * port, GstOMXBuffer * buf);
+
+OMX_ERRORTYPE gst_omx_port_mark_reconfigured (GstOMXPort * port);
+
+OMX_ERRORTYPE gst_omx_port_set_enabled (GstOMXPort * port, gboolean enabled);
+OMX_ERRORTYPE gst_omx_port_wait_enabled (GstOMXPort * port, GstClockTime timeout);
+gboolean gst_omx_port_is_enabled (GstOMXPort * port);
+gboolean gst_omx_port_ensure_buffer_count_actual (GstOMXPort * port, guint extra);
+gboolean gst_omx_port_update_buffer_count_actual (GstOMXPort * port, guint nb);
+
+gboolean gst_omx_port_set_dmabuf (GstOMXPort * port, gboolean dmabuf);
+gboolean gst_omx_port_set_subframe (GstOMXPort * port, gboolean enabled);
+gboolean gst_omx_port_get_subframe (GstOMXPort * port);
+
+/* OMX 1.2.0 dynamic allocation mode */
+gboolean gst_omx_is_dynamic_allocation_supported (void);
+OMX_ERRORTYPE gst_omx_port_use_dynamic_buffers (GstOMXPort * port);
+gboolean gst_omx_buffer_map_frame (GstOMXBuffer * buffer, GstBuffer * input, GstVideoInfo * info);
+gboolean gst_omx_buffer_map_memory (GstOMXBuffer * buffer, GstMemory * mem);
+gboolean gst_omx_buffer_map_buffer (GstOMXBuffer * buffer, GstBuffer * input);
+gboolean gst_omx_buffer_import_fd (GstOMXBuffer * buffer, GstBuffer * input);
+
+void gst_omx_set_default_role (GstOMXClassData *class_data, const gchar *default_role);
+
+/* refered by plugin_init */
+GST_DEBUG_CATEGORY_EXTERN (gst_omx_video_debug_category);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_H__ */
diff --git a/subprojects/gst-omx/omx/gstomxaacdec.c b/subprojects/gst-omx/omx/gstomxaacdec.c
new file mode 100644
index 0000000000..9606b7fd33
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxaacdec.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxaacdec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_aac_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_aac_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_aac_dec_set_format (GstOMXAudioDec * dec,
+ GstOMXPort * port, GstCaps * caps);
+static gboolean gst_omx_aac_dec_is_format_change (GstOMXAudioDec * dec,
+ GstOMXPort * port, GstCaps * caps);
+static gint gst_omx_aac_dec_get_samples_per_frame (GstOMXAudioDec * dec,
+ GstOMXPort * port);
+static gboolean gst_omx_aac_dec_get_channel_positions (GstOMXAudioDec * dec,
+ GstOMXPort * port, GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS]);
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_aac_dec_debug_category, "omxaacdec", 0, \
+ "debug category for gst-omx aac audio decoder");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXAACDec, gst_omx_aac_dec,
+ GST_TYPE_OMX_AUDIO_DEC, DEBUG_INIT);
+
+static void
+gst_omx_aac_dec_class_init (GstOMXAACDecClass * klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstOMXAudioDecClass *audiodec_class = GST_OMX_AUDIO_DEC_CLASS (klass);
+
+ audiodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_aac_dec_set_format);
+ audiodec_class->is_format_change =
+ GST_DEBUG_FUNCPTR (gst_omx_aac_dec_is_format_change);
+ audiodec_class->get_samples_per_frame =
+ GST_DEBUG_FUNCPTR (gst_omx_aac_dec_get_samples_per_frame);
+ audiodec_class->get_channel_positions =
+ GST_DEBUG_FUNCPTR (gst_omx_aac_dec_get_channel_positions);
+
+ audiodec_class->cdata.default_sink_template_caps = "audio/mpeg, "
+ "mpegversion=(int){2, 4}, "
+ "stream-format=(string) { raw, adts, adif, loas }, "
+ "rate=(int)[8000,48000], "
+ "channels=(int)[1,9], " "framed=(boolean) true";
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX AAC Audio Decoder",
+ "Codec/Decoder/Audio/Hardware",
+ "Decode AAC audio streams",
+ "Sebastian Dröge <sebastian@centricular.com>");
+
+ gst_omx_set_default_role (&audiodec_class->cdata, "audio_decoder.aac");
+}
+
+static void
+gst_omx_aac_dec_init (GstOMXAACDec * self)
+{
+ /* FIXME: Other values exist too! */
+ self->spf = 1024;
+}
+
+static gboolean
+gst_omx_aac_dec_set_format (GstOMXAudioDec * dec, GstOMXPort * port,
+ GstCaps * caps)
+{
+ GstOMXAACDec *self = GST_OMX_AAC_DEC (dec);
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ OMX_AUDIO_PARAM_AACPROFILETYPE aac_param;
+ OMX_ERRORTYPE err;
+ GstStructure *s;
+ gint rate, channels, mpegversion;
+ const gchar *stream_format;
+
+ gst_omx_port_get_port_definition (port, &port_def);
+ port_def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
+ err = gst_omx_port_update_port_definition (port, &port_def);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to set AAC format on component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ GST_OMX_INIT_STRUCT (&aac_param);
+ aac_param.nPortIndex = port->index;
+
+ err =
+ gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioAac,
+ &aac_param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to get AAC parameters from component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ s = gst_caps_get_structure (caps, 0);
+
+ if (!gst_structure_get_int (s, "mpegversion", &mpegversion) ||
+ !gst_structure_get_int (s, "rate", &rate) ||
+ !gst_structure_get_int (s, "channels", &channels)) {
+ GST_ERROR_OBJECT (self, "Incomplete caps");
+ return FALSE;
+ }
+
+ stream_format = gst_structure_get_string (s, "stream-format");
+ if (!stream_format) {
+ GST_ERROR_OBJECT (self, "Incomplete caps");
+ return FALSE;
+ }
+
+ aac_param.nChannels = channels;
+ aac_param.nSampleRate = rate;
+ aac_param.nBitRate = 0; /* unknown */
+ aac_param.nAudioBandWidth = 0; /* decoder decision */
+ aac_param.eChannelMode = 0; /* FIXME */
+ if (mpegversion == 2)
+ aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP2ADTS;
+ else if (strcmp (stream_format, "adts") == 0)
+ aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
+ else if (strcmp (stream_format, "loas") == 0)
+ aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4LOAS;
+ else if (strcmp (stream_format, "adif") == 0)
+ aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatADIF;
+ else if (strcmp (stream_format, "raw") == 0)
+ aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatRAW;
+ else {
+ GST_ERROR_OBJECT (self, "Unexpected format: %s", stream_format);
+ return FALSE;
+ }
+
+ err =
+ gst_omx_component_set_parameter (dec->dec, OMX_IndexParamAudioAac,
+ &aac_param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Error setting AAC parameters: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_aac_dec_is_format_change (GstOMXAudioDec * dec, GstOMXPort * port,
+ GstCaps * caps)
+{
+ GstOMXAACDec *self = GST_OMX_AAC_DEC (dec);
+ OMX_AUDIO_PARAM_AACPROFILETYPE aac_param;
+ OMX_ERRORTYPE err;
+ GstStructure *s;
+ gint rate, channels, mpegversion;
+ const gchar *stream_format;
+
+ GST_OMX_INIT_STRUCT (&aac_param);
+ aac_param.nPortIndex = port->index;
+
+ err =
+ gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioAac,
+ &aac_param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to get AAC parameters from component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ s = gst_caps_get_structure (caps, 0);
+
+ if (!gst_structure_get_int (s, "mpegversion", &mpegversion) ||
+ !gst_structure_get_int (s, "rate", &rate) ||
+ !gst_structure_get_int (s, "channels", &channels)) {
+ GST_ERROR_OBJECT (self, "Incomplete caps");
+ return FALSE;
+ }
+
+ stream_format = gst_structure_get_string (s, "stream-format");
+ if (!stream_format) {
+ GST_ERROR_OBJECT (self, "Incomplete caps");
+ return FALSE;
+ }
+
+ if (aac_param.nChannels != channels)
+ return TRUE;
+
+ if (aac_param.nSampleRate != rate)
+ return TRUE;
+
+ if (mpegversion == 2
+ && aac_param.eAACStreamFormat != OMX_AUDIO_AACStreamFormatMP2ADTS)
+ return TRUE;
+ if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4ADTS &&
+ strcmp (stream_format, "adts") != 0)
+ return TRUE;
+ if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4LOAS &&
+ strcmp (stream_format, "loas") != 0)
+ return TRUE;
+ if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatADIF &&
+ strcmp (stream_format, "adif") != 0)
+ return TRUE;
+ if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatRAW &&
+ strcmp (stream_format, "raw") != 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+static gint
+gst_omx_aac_dec_get_samples_per_frame (GstOMXAudioDec * dec, GstOMXPort * port)
+{
+ return GST_OMX_AAC_DEC (dec)->spf;
+}
+
+static gboolean
+gst_omx_aac_dec_get_channel_positions (GstOMXAudioDec * dec,
+ GstOMXPort * port, GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS])
+{
+ OMX_AUDIO_PARAM_PCMMODETYPE pcm_param;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&pcm_param);
+ pcm_param.nPortIndex = port->index;
+ err =
+ gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioPcm,
+ &pcm_param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (dec, "Failed to get PCM parameters: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ /* FIXME: Rather arbitrary values here, based on what we do in gstfaac.c */
+ switch (pcm_param.nChannels) {
+ case 1:
+ position[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
+ break;
+ case 2:
+ position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
+ position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
+ break;
+ case 3:
+ position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
+ position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
+ position[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
+ break;
+ case 4:
+ position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
+ position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
+ position[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
+ position[3] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
+ break;
+ case 5:
+ position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
+ position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
+ position[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
+ position[3] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
+ position[4] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
+ break;
+ case 6:
+ position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
+ position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
+ position[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
+ position[3] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
+ position[4] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
+ position[5] = GST_AUDIO_CHANNEL_POSITION_LFE1;
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/subprojects/gst-omx/omx/gstomxaacdec.h b/subprojects/gst-omx/omx/gstomxaacdec.h
new file mode 100644
index 0000000000..891589b01e
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxaacdec.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_AAC_DEC_H__
+#define __GST_OMX_AAC_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxaudiodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_AAC_DEC \
+ (gst_omx_aac_dec_get_type())
+#define GST_OMX_AAC_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_AAC_DEC,GstOMXAACDec))
+#define GST_OMX_AAC_DEC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_AAC_DEC,GstOMXAACDecClass))
+#define GST_OMX_AAC_DEC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_AAC_DEC,GstOMXAACDecClass))
+#define GST_IS_OMX_AAC_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_AAC_DEC))
+#define GST_IS_OMX_AAC_DEC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_AAC_DEC))
+
+typedef struct _GstOMXAACDec GstOMXAACDec;
+typedef struct _GstOMXAACDecClass GstOMXAACDecClass;
+
+struct _GstOMXAACDec
+{
+ GstOMXAudioDec parent;
+ gint spf;
+};
+
+struct _GstOMXAACDecClass
+{
+ GstOMXAudioDecClass parent_class;
+};
+
+GType gst_omx_aac_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_AAC_DEC_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxaacenc.c b/subprojects/gst-omx/omx/gstomxaacenc.c
new file mode 100644
index 0000000000..c568ddd184
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxaacenc.c
@@ -0,0 +1,511 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxaacenc.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_aac_enc_debug_category);
+#define GST_CAT_DEFAULT gst_omx_aac_enc_debug_category
+
+/* prototypes */
+static void gst_omx_aac_enc_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_omx_aac_enc_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+static gboolean gst_omx_aac_enc_set_format (GstOMXAudioEnc * enc,
+ GstOMXPort * port, GstAudioInfo * info);
+static GstCaps *gst_omx_aac_enc_get_caps (GstOMXAudioEnc * enc,
+ GstOMXPort * port, GstAudioInfo * info);
+static guint gst_omx_aac_enc_get_num_samples (GstOMXAudioEnc * enc,
+ GstOMXPort * port, GstAudioInfo * info, GstOMXBuffer * buf);
+
+enum
+{
+ PROP_0,
+ PROP_BITRATE,
+ PROP_AAC_TOOLS,
+ PROP_AAC_ERROR_RESILIENCE_TOOLS
+};
+
+#define DEFAULT_BITRATE (128000)
+#define DEFAULT_AAC_TOOLS (OMX_AUDIO_AACToolMS | OMX_AUDIO_AACToolIS | OMX_AUDIO_AACToolTNS | OMX_AUDIO_AACToolPNS | OMX_AUDIO_AACToolLTP)
+#define DEFAULT_AAC_ER_TOOLS (OMX_AUDIO_AACERNone)
+
+#define GST_TYPE_OMX_AAC_TOOLS (gst_omx_aac_tools_get_type ())
+static GType
+gst_omx_aac_tools_get_type (void)
+{
+ static gsize id = 0;
+ static const GFlagsValue values[] = {
+ {OMX_AUDIO_AACToolMS, "Mid/side joint coding", "ms"},
+ {OMX_AUDIO_AACToolIS, "Intensity stereo", "is"},
+ {OMX_AUDIO_AACToolTNS, "Temporal noise shaping", "tns"},
+ {OMX_AUDIO_AACToolPNS, "Perceptual noise substitution", "pns"},
+ {OMX_AUDIO_AACToolLTP, "Long term prediction", "ltp"},
+ {0, NULL, NULL}
+ };
+
+ if (g_once_init_enter (&id)) {
+ GType tmp = g_flags_register_static ("GstOMXAACTools", values);
+ g_once_init_leave (&id, tmp);
+ }
+
+ return (GType) id;
+}
+
+#define GST_TYPE_OMX_AAC_ER_TOOLS (gst_omx_aac_er_tools_get_type ())
+static GType
+gst_omx_aac_er_tools_get_type (void)
+{
+ static gsize id = 0;
+ static const GFlagsValue values[] = {
+ {OMX_AUDIO_AACERVCB11, "Virtual code books", "vcb11"},
+ {OMX_AUDIO_AACERRVLC, "Reversible variable length coding", "rvlc"},
+ {OMX_AUDIO_AACERHCR, "Huffman codeword reordering", "hcr"},
+ {0, NULL, NULL}
+ };
+
+ if (g_once_init_enter (&id)) {
+ GType tmp = g_flags_register_static ("GstOMXAACERTools", values);
+ g_once_init_leave (&id, tmp);
+ }
+
+ return (GType) id;
+}
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_aac_enc_debug_category, "omxaacenc", 0, \
+ "debug category for gst-omx audio encoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXAACEnc, gst_omx_aac_enc,
+ GST_TYPE_OMX_AUDIO_ENC, DEBUG_INIT);
+
+
+static void
+gst_omx_aac_enc_class_init (GstOMXAACEncClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstOMXAudioEncClass *audioenc_class = GST_OMX_AUDIO_ENC_CLASS (klass);
+
+ gobject_class->set_property = gst_omx_aac_enc_set_property;
+ gobject_class->get_property = gst_omx_aac_enc_get_property;
+
+ g_object_class_install_property (gobject_class, PROP_BITRATE,
+ g_param_spec_uint ("bitrate", "Bitrate",
+ "Bitrate",
+ 0, G_MAXUINT, DEFAULT_BITRATE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_AAC_TOOLS,
+ g_param_spec_flags ("aac-tools", "AAC Tools",
+ "Allowed AAC tools",
+ GST_TYPE_OMX_AAC_TOOLS,
+ DEFAULT_AAC_TOOLS,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class,
+ PROP_AAC_ERROR_RESILIENCE_TOOLS,
+ g_param_spec_flags ("aac-error-resilience-tools",
+ "AAC Error Resilience Tools", "Allowed AAC error resilience tools",
+ GST_TYPE_OMX_AAC_ER_TOOLS, DEFAULT_AAC_ER_TOOLS,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ audioenc_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_aac_enc_set_format);
+ audioenc_class->get_caps = GST_DEBUG_FUNCPTR (gst_omx_aac_enc_get_caps);
+ audioenc_class->get_num_samples =
+ GST_DEBUG_FUNCPTR (gst_omx_aac_enc_get_num_samples);
+
+ audioenc_class->cdata.default_src_template_caps = "audio/mpeg, "
+ "mpegversion=(int){2, 4}, "
+ "stream-format=(string){raw, adts, adif, loas, latm}";
+
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX AAC Audio Encoder",
+ "Codec/Encoder/Audio/Hardware",
+ "Encode AAC audio streams",
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+ gst_omx_set_default_role (&audioenc_class->cdata, "audio_encoder.aac");
+}
+
+static void
+gst_omx_aac_enc_init (GstOMXAACEnc * self)
+{
+ self->bitrate = DEFAULT_BITRATE;
+ self->aac_tools = DEFAULT_AAC_TOOLS;
+ self->aac_er_tools = DEFAULT_AAC_ER_TOOLS;
+}
+
+static void
+gst_omx_aac_enc_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstOMXAACEnc *self = GST_OMX_AAC_ENC (object);
+
+ switch (prop_id) {
+ case PROP_BITRATE:
+ self->bitrate = g_value_get_uint (value);
+ break;
+ case PROP_AAC_TOOLS:
+ self->aac_tools = g_value_get_flags (value);
+ break;
+ case PROP_AAC_ERROR_RESILIENCE_TOOLS:
+ self->aac_er_tools = g_value_get_flags (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_omx_aac_enc_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec)
+{
+ GstOMXAACEnc *self = GST_OMX_AAC_ENC (object);
+
+ switch (prop_id) {
+ case PROP_BITRATE:
+ g_value_set_uint (value, self->bitrate);
+ break;
+ case PROP_AAC_TOOLS:
+ g_value_set_flags (value, self->aac_tools);
+ break;
+ case PROP_AAC_ERROR_RESILIENCE_TOOLS:
+ g_value_set_flags (value, self->aac_er_tools);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static gboolean
+gst_omx_aac_enc_set_format (GstOMXAudioEnc * enc, GstOMXPort * port,
+ GstAudioInfo * info)
+{
+ GstOMXAACEnc *self = GST_OMX_AAC_ENC (enc);
+ OMX_AUDIO_PARAM_AACPROFILETYPE aac_profile;
+ GstCaps *peercaps;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&aac_profile);
+ aac_profile.nPortIndex = enc->enc_out_port->index;
+
+ err =
+ gst_omx_component_get_parameter (enc->enc, OMX_IndexParamAudioAac,
+ &aac_profile);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to get AAC parameters from component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ peercaps = gst_pad_peer_query_caps (GST_AUDIO_ENCODER_SRC_PAD (self),
+ gst_pad_get_pad_template_caps (GST_AUDIO_ENCODER_SRC_PAD (self)));
+ if (peercaps) {
+ GstStructure *s;
+ gint mpegversion = 0;
+ const gchar *profile_string, *stream_format_string;
+
+ if (gst_caps_is_empty (peercaps)) {
+ gst_caps_unref (peercaps);
+ GST_ERROR_OBJECT (self, "Empty caps");
+ return FALSE;
+ }
+
+ s = gst_caps_get_structure (peercaps, 0);
+
+ if (gst_structure_get_int (s, "mpegversion", &mpegversion)) {
+ profile_string =
+ gst_structure_get_string (s,
+ ((mpegversion == 2) ? "profile" : "base-profile"));
+
+ if (profile_string) {
+ if (g_str_equal (profile_string, "main")) {
+ aac_profile.eAACProfile = OMX_AUDIO_AACObjectMain;
+ } else if (g_str_equal (profile_string, "lc")) {
+ aac_profile.eAACProfile = OMX_AUDIO_AACObjectLC;
+ } else if (g_str_equal (profile_string, "ssr")) {
+ aac_profile.eAACProfile = OMX_AUDIO_AACObjectSSR;
+ } else if (g_str_equal (profile_string, "ltp")) {
+ aac_profile.eAACProfile = OMX_AUDIO_AACObjectLTP;
+ } else {
+ GST_ERROR_OBJECT (self, "Unsupported profile '%s'", profile_string);
+ gst_caps_unref (peercaps);
+ return FALSE;
+ }
+ }
+ }
+
+ stream_format_string = gst_structure_get_string (s, "stream-format");
+ if (stream_format_string) {
+ if (g_str_equal (stream_format_string, "raw")) {
+ aac_profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatRAW;
+ } else if (g_str_equal (stream_format_string, "adts")) {
+ if (mpegversion == 2) {
+ aac_profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP2ADTS;
+ } else {
+ aac_profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
+ }
+ } else if (g_str_equal (stream_format_string, "loas")) {
+ aac_profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4LOAS;
+ } else if (g_str_equal (stream_format_string, "latm")) {
+ aac_profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4LATM;
+ } else if (g_str_equal (stream_format_string, "adif")) {
+ aac_profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatADIF;
+ } else {
+ GST_ERROR_OBJECT (self, "Unsupported stream-format '%s'",
+ stream_format_string);
+ gst_caps_unref (peercaps);
+ return FALSE;
+ }
+ }
+
+ gst_caps_unref (peercaps);
+
+ aac_profile.nSampleRate = info->rate;
+ aac_profile.nChannels = info->channels;
+ }
+
+ aac_profile.nAACtools = self->aac_tools;
+ aac_profile.nAACERtools = self->aac_er_tools;
+
+ aac_profile.nBitRate = self->bitrate;
+
+ err =
+ gst_omx_component_set_parameter (enc->enc, OMX_IndexParamAudioAac,
+ &aac_profile);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Error setting AAC parameters: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+typedef enum adts_sample_index__
+{
+ ADTS_SAMPLE_INDEX_96000 = 0x0,
+ ADTS_SAMPLE_INDEX_88200,
+ ADTS_SAMPLE_INDEX_64000,
+ ADTS_SAMPLE_INDEX_48000,
+ ADTS_SAMPLE_INDEX_44100,
+ ADTS_SAMPLE_INDEX_32000,
+ ADTS_SAMPLE_INDEX_24000,
+ ADTS_SAMPLE_INDEX_22050,
+ ADTS_SAMPLE_INDEX_16000,
+ ADTS_SAMPLE_INDEX_12000,
+ ADTS_SAMPLE_INDEX_11025,
+ ADTS_SAMPLE_INDEX_8000,
+ ADTS_SAMPLE_INDEX_7350,
+ ADTS_SAMPLE_INDEX_MAX
+} adts_sample_index;
+
+static adts_sample_index
+map_adts_sample_index (guint32 srate)
+{
+ adts_sample_index ret;
+
+ switch (srate) {
+
+ case 96000:
+ ret = ADTS_SAMPLE_INDEX_96000;
+ break;
+ case 88200:
+ ret = ADTS_SAMPLE_INDEX_88200;
+ break;
+ case 64000:
+ ret = ADTS_SAMPLE_INDEX_64000;
+ break;
+ case 48000:
+ ret = ADTS_SAMPLE_INDEX_48000;
+ break;
+ case 44100:
+ ret = ADTS_SAMPLE_INDEX_44100;
+ break;
+ case 32000:
+ ret = ADTS_SAMPLE_INDEX_32000;
+ break;
+ case 24000:
+ ret = ADTS_SAMPLE_INDEX_24000;
+ break;
+ case 22050:
+ ret = ADTS_SAMPLE_INDEX_22050;
+ break;
+ case 16000:
+ ret = ADTS_SAMPLE_INDEX_16000;
+ break;
+ case 12000:
+ ret = ADTS_SAMPLE_INDEX_12000;
+ break;
+ case 11025:
+ ret = ADTS_SAMPLE_INDEX_11025;
+ break;
+ case 8000:
+ ret = ADTS_SAMPLE_INDEX_8000;
+ break;
+ case 7350:
+ ret = ADTS_SAMPLE_INDEX_7350;
+ break;
+ default:
+ ret = ADTS_SAMPLE_INDEX_44100;
+ break;
+ }
+ return ret;
+}
+
+static GstCaps *
+gst_omx_aac_enc_get_caps (GstOMXAudioEnc * enc, GstOMXPort * port,
+ GstAudioInfo * info)
+{
+ GstCaps *caps;
+ OMX_ERRORTYPE err;
+ OMX_AUDIO_PARAM_AACPROFILETYPE aac_profile;
+ gint mpegversion = 4;
+ const gchar *stream_format = NULL, *profile = NULL;
+
+ GST_OMX_INIT_STRUCT (&aac_profile);
+ aac_profile.nPortIndex = enc->enc_out_port->index;
+
+ err =
+ gst_omx_component_get_parameter (enc->enc, OMX_IndexParamAudioAac,
+ &aac_profile);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (enc,
+ "Failed to get AAC parameters from component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return NULL;
+ }
+
+ switch (aac_profile.eAACProfile) {
+ case OMX_AUDIO_AACObjectMain:
+ profile = "main";
+ break;
+ case OMX_AUDIO_AACObjectLC:
+ profile = "lc";
+ break;
+ case OMX_AUDIO_AACObjectSSR:
+ profile = "ssr";
+ break;
+ case OMX_AUDIO_AACObjectLTP:
+ profile = "ltp";
+ break;
+ case OMX_AUDIO_AACObjectHE:
+ case OMX_AUDIO_AACObjectScalable:
+ case OMX_AUDIO_AACObjectERLC:
+ case OMX_AUDIO_AACObjectLD:
+ case OMX_AUDIO_AACObjectHE_PS:
+ default:
+ GST_ERROR_OBJECT (enc, "Unsupported profile %d", aac_profile.eAACProfile);
+ break;
+ }
+
+ switch (aac_profile.eAACStreamFormat) {
+ case OMX_AUDIO_AACStreamFormatMP2ADTS:
+ mpegversion = 2;
+ stream_format = "adts";
+ break;
+ case OMX_AUDIO_AACStreamFormatMP4ADTS:
+ mpegversion = 4;
+ stream_format = "adts";
+ break;
+ case OMX_AUDIO_AACStreamFormatMP4LOAS:
+ mpegversion = 4;
+ stream_format = "loas";
+ break;
+ case OMX_AUDIO_AACStreamFormatMP4LATM:
+ mpegversion = 4;
+ stream_format = "latm";
+ break;
+ case OMX_AUDIO_AACStreamFormatADIF:
+ mpegversion = 4;
+ stream_format = "adif";
+ break;
+ case OMX_AUDIO_AACStreamFormatRAW:
+ mpegversion = 4;
+ stream_format = "raw";
+ break;
+ case OMX_AUDIO_AACStreamFormatMP4FF:
+ default:
+ GST_ERROR_OBJECT (enc, "Unsupported stream-format %u",
+ aac_profile.eAACStreamFormat);
+ break;
+ }
+
+ caps = gst_caps_new_empty_simple ("audio/mpeg");
+
+ if (mpegversion != 0)
+ gst_caps_set_simple (caps, "mpegversion", G_TYPE_INT, mpegversion,
+ "stream-format", G_TYPE_STRING, stream_format, NULL);
+ if (profile != NULL && (mpegversion == 2 || mpegversion == 4))
+ gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
+ if (profile != NULL && mpegversion == 4)
+ gst_caps_set_simple (caps, "base-profile", G_TYPE_STRING, profile, NULL);
+ if (aac_profile.nChannels != 0)
+ gst_caps_set_simple (caps, "channels", G_TYPE_INT, aac_profile.nChannels,
+ NULL);
+ if (aac_profile.nSampleRate != 0)
+ gst_caps_set_simple (caps, "rate", G_TYPE_INT, aac_profile.nSampleRate,
+ NULL);
+
+ if (aac_profile.eAACStreamFormat == OMX_AUDIO_AACStreamFormatRAW) {
+ GstBuffer *codec_data;
+ adts_sample_index sr_idx;
+ GstMapInfo map = GST_MAP_INFO_INIT;
+
+ codec_data = gst_buffer_new_and_alloc (2);
+ gst_buffer_map (codec_data, &map, GST_MAP_WRITE);
+ sr_idx = map_adts_sample_index (aac_profile.nSampleRate);
+ map.data[0] = ((aac_profile.eAACProfile & 0x1F) << 3) |
+ ((sr_idx & 0xE) >> 1);
+ map.data[1] = ((sr_idx & 0x1) << 7) | ((aac_profile.nChannels & 0xF) << 3);
+ gst_buffer_unmap (codec_data, &map);
+
+ GST_DEBUG_OBJECT (enc, "setting new codec_data");
+ gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, codec_data, NULL);
+
+ gst_buffer_unref (codec_data);
+ }
+ return caps;
+
+}
+
+static guint
+gst_omx_aac_enc_get_num_samples (GstOMXAudioEnc * enc, GstOMXPort * port,
+ GstAudioInfo * info, GstOMXBuffer * buf)
+{
+ /* FIXME: Depends on the profile at least */
+ return 1024;
+}
diff --git a/subprojects/gst-omx/omx/gstomxaacenc.h b/subprojects/gst-omx/omx/gstomxaacenc.h
new file mode 100644
index 0000000000..b6c3daa9b7
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxaacenc.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_AAC_ENC_H__
+#define __GST_OMX_AAC_ENC_H__
+
+#include <gst/gst.h>
+#include "gstomxaudioenc.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_AAC_ENC \
+ (gst_omx_aac_enc_get_type())
+#define GST_OMX_AAC_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_AAC_ENC,GstOMXAACEnc))
+#define GST_OMX_AAC_ENC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_AAC_ENC,GstOMXAACEncClass))
+#define GST_OMX_AAC_ENC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_AAC_ENC,GstOMXAACEncClass))
+#define GST_IS_OMX_AAC_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_AAC_ENC))
+#define GST_IS_OMX_AAC_ENC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_AAC_ENC))
+
+typedef struct _GstOMXAACEnc GstOMXAACEnc;
+typedef struct _GstOMXAACEncClass GstOMXAACEncClass;
+
+struct _GstOMXAACEnc
+{
+ GstOMXAudioEnc parent;
+
+ /* properties */
+ guint bitrate;
+ guint aac_tools;
+ guint aac_er_tools;
+};
+
+struct _GstOMXAACEncClass
+{
+ GstOMXAudioEncClass parent_class;
+};
+
+GType gst_omx_aac_enc_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_AAC_ENC_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxallocator.c b/subprojects/gst-omx/omx/gstomxallocator.c
new file mode 100644
index 0000000000..a180669791
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxallocator.c
@@ -0,0 +1,554 @@
+/*
+ * Copyright (C) 2019, Collabora Ltd.
+ * Author: George Kiagiadakis <george.kiagiadakis@collabora.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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstomxallocator.h"
+#include <gst/allocators/gstdmabuf.h>
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_allocator_debug_category);
+#define GST_CAT_DEFAULT gst_omx_allocator_debug_category
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_allocator_debug_category, "omxallocator", 0, \
+ "debug category for gst-omx allocator class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXAllocator, gst_omx_allocator, GST_TYPE_ALLOCATOR,
+ DEBUG_INIT);
+
+enum
+{
+ SIG_OMXBUF_RELEASED,
+ SIG_FOREIGN_MEM_RELEASED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/* Custom allocator for memory associated with OpenMAX buffers
+ *
+ * The main purpose of this allocator is to track memory that is associated
+ * with OpenMAX buffers, so that we know when the buffers can be released
+ * back to OpenMAX.
+ *
+ * This allocator looks and behaves more like a buffer pool. It allocates
+ * the memory objects before starting and sets a miniobject dispose function
+ * on them, which allows them to return when their last ref count is dropped.
+ *
+ * The type of memory that this allocator manages is GstOMXMemory. However, it
+ * is possible to manage a different type of memory, in which case the
+ * GstOMXMemory object is used only internally. There are two supported cases:
+ * - Allocate memory from the dmabuf allocator
+ * - Take memory that was allocated externally and manage it here
+ *
+ * In both cases, this allocator will replace the miniobject dispose function
+ * of these memory objects, so if they were acquired from here, they will also
+ * return here on their last unref.
+ *
+ * The caller initially needs to configure how many memory objects will be
+ * managed here by calling configure(). After that it needs to call
+ * set_active(TRUE) and finally allocate() for each memory. Allocation is done
+ * like this to facilitate calling allocate() from the alloc() function of
+ * the buffer pool for each OMX buffer on the port.
+ *
+ * After the allocator has been activated and all buffers have been allocated,
+ * the acquire() method can be called to retrieve a memory object. acquire() can
+ * be given an OMX buffer index or pointer to locate and return the memory
+ * object that corresponds to this OMX buffer. If the buffer is already
+ * acquired, this will result in a GST_FLOW_ERROR.
+ *
+ * When the last reference count is dropped on a memory that was acquired from
+ * here, its dispose function will ref it again and allow it to be acquired
+ * again. In addition, the omxbuf-released signal is fired to let the caller
+ * know that it can return this OMX buffer to the port, as it is no longer
+ * used outside this allocator.
+ */
+
+/******************/
+/** GstOMXMemory **/
+/******************/
+
+#define GST_OMX_MEMORY_TYPE "openmax"
+
+GQuark
+gst_omx_memory_quark (void)
+{
+ static GQuark quark = 0;
+
+ if (quark == 0)
+ quark = g_quark_from_static_string ("GstOMXMemory");
+
+ return quark;
+}
+
+static GstOMXMemory *
+gst_omx_memory_new (GstOMXAllocator * allocator, GstOMXBuffer * omx_buf,
+ GstMemoryFlags flags, GstMemory * parent, gssize offset, gssize size)
+{
+ GstOMXMemory *mem;
+ gint align;
+ gsize maxsize;
+
+ /* GStreamer uses a bitmask for the alignment while
+ * OMX uses the alignment itself. So we have to convert
+ * here */
+ align = allocator->port->port_def.nBufferAlignment;
+ if (align > 0)
+ align -= 1;
+ if (((align + 1) & align) != 0) {
+ GST_WARNING ("Invalid alignment that is not a power of two: %u",
+ (guint) allocator->port->port_def.nBufferAlignment);
+ align = 0;
+ }
+
+ maxsize = omx_buf->omx_buf->nAllocLen;
+
+ if (size == -1) {
+ size = maxsize - offset;
+ }
+
+ mem = g_slice_new0 (GstOMXMemory);
+ gst_memory_init (GST_MEMORY_CAST (mem), flags, (GstAllocator *) allocator,
+ parent, maxsize, align, offset, size);
+
+ mem->buf = omx_buf;
+
+ return mem;
+}
+
+static gpointer
+gst_omx_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
+{
+ GstOMXMemory *omem = (GstOMXMemory *) mem;
+
+ /* if we are using foreign_mem, the GstOMXMemory should never appear
+ * anywhere outside this allocator, therefore it should never be mapped */
+ g_return_val_if_fail (!omem->foreign_mem, NULL);
+
+ return omem->buf->omx_buf->pBuffer;
+}
+
+static void
+gst_omx_memory_unmap (GstMemory * mem)
+{
+}
+
+static GstMemory *
+gst_omx_memory_share (GstMemory * mem, gssize offset, gssize size)
+{
+ GstOMXMemory *omem = (GstOMXMemory *) mem;
+ GstOMXMemory *sub;
+ GstMemory *parent;
+
+ /* find the real parent */
+ if ((parent = mem->parent) == NULL)
+ parent = mem;
+
+ if (size == -1)
+ size = mem->size - offset;
+
+ /* the shared memory is always readonly */
+ sub = gst_omx_memory_new ((GstOMXAllocator *) mem->allocator, omem->buf,
+ GST_MINI_OBJECT_FLAGS (parent) | GST_MINI_OBJECT_FLAG_LOCK_READONLY,
+ parent, offset, size);
+
+ return (GstMemory *) sub;
+}
+
+GstOMXBuffer *
+gst_omx_memory_get_omx_buf (GstMemory * mem)
+{
+ GstOMXMemory *omx_mem;
+
+ if (GST_IS_OMX_ALLOCATOR (mem->allocator))
+ omx_mem = (GstOMXMemory *) mem;
+ else
+ omx_mem = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
+ GST_OMX_MEMORY_QUARK);
+
+ if (!omx_mem)
+ return NULL;
+
+ return omx_mem->buf;
+}
+
+/*********************/
+/** GstOMXAllocator **/
+/*********************/
+
+static void
+gst_omx_allocator_init (GstOMXAllocator * allocator)
+{
+ GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
+
+ alloc->mem_type = GST_OMX_MEMORY_TYPE;
+
+ alloc->mem_map = gst_omx_memory_map;
+ alloc->mem_unmap = gst_omx_memory_unmap;
+ alloc->mem_share = gst_omx_memory_share;
+ /* default copy & is_span */
+
+ GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
+
+ g_mutex_init (&allocator->lock);
+ g_cond_init (&allocator->cond);
+}
+
+GstOMXAllocator *
+gst_omx_allocator_new (GstOMXComponent * component, GstOMXPort * port)
+{
+ GstOMXAllocator *allocator;
+
+ allocator = g_object_new (gst_omx_allocator_get_type (), NULL);
+ allocator->component = gst_omx_component_ref (component);
+ allocator->port = port;
+
+ return allocator;
+}
+
+static void
+gst_omx_allocator_finalize (GObject * object)
+{
+ GstOMXAllocator *allocator = GST_OMX_ALLOCATOR (object);
+
+ gst_omx_component_unref (allocator->component);
+ g_mutex_clear (&allocator->lock);
+ g_cond_clear (&allocator->cond);
+
+ G_OBJECT_CLASS (gst_omx_allocator_parent_class)->finalize (object);
+}
+
+gboolean
+gst_omx_allocator_configure (GstOMXAllocator * allocator, guint count,
+ GstOMXAllocatorForeignMemMode mode)
+{
+ /* check if already configured */
+ if (allocator->n_memories > 0)
+ return FALSE;
+
+ allocator->n_memories = count;
+ allocator->foreign_mode = mode;
+ if (mode == GST_OMX_ALLOCATOR_FOREIGN_MEM_DMABUF)
+ allocator->foreign_allocator = gst_dmabuf_allocator_new ();
+
+ return TRUE;
+}
+
+/* must be protected with allocator->lock */
+static void
+gst_omx_allocator_dealloc (GstOMXAllocator * allocator)
+{
+ /* might be called more than once */
+ if (!allocator->memories)
+ return;
+
+ /* return foreign memory back to whoever lended it to us.
+ * the signal handler is expected to increase the ref count of foreign_mem */
+ if (allocator->foreign_mode == GST_OMX_ALLOCATOR_FOREIGN_MEM_OTHER_POOL) {
+ gint i;
+ GstOMXMemory *m;
+
+ for (i = 0; i < allocator->memories->len; i++) {
+ m = g_ptr_array_index (allocator->memories, i);
+
+ /* this should not happen, but let's not crash for this */
+ if (!m->foreign_mem) {
+ GST_WARNING_OBJECT (allocator, "no foreign_mem to release");
+ continue;
+ }
+
+ /* restore the original dispose function */
+ GST_MINI_OBJECT_CAST (m->foreign_mem)->dispose =
+ (GstMiniObjectDisposeFunction) m->foreign_dispose;
+
+ g_signal_emit (allocator, signals[SIG_FOREIGN_MEM_RELEASED], 0, i,
+ m->foreign_mem);
+ }
+ }
+
+ g_ptr_array_foreach (allocator->memories, (GFunc) gst_memory_unref, NULL);
+ g_ptr_array_free (allocator->memories, TRUE);
+ allocator->memories = NULL;
+ allocator->n_memories = 0;
+ allocator->foreign_mode = GST_OMX_ALLOCATOR_FOREIGN_MEM_NONE;
+ if (allocator->foreign_allocator) {
+ g_object_unref (allocator->foreign_allocator);
+ allocator->foreign_allocator = NULL;
+ }
+
+ g_cond_broadcast (&allocator->cond);
+}
+
+gboolean
+gst_omx_allocator_set_active (GstOMXAllocator * allocator, gboolean active)
+{
+ gboolean changed = FALSE;
+
+ /* on activation, _configure() must be called first */
+ g_return_val_if_fail (!active || allocator->n_memories > 0, FALSE);
+
+ g_mutex_lock (&allocator->lock);
+
+ if (allocator->active != active)
+ changed = TRUE;
+
+ if (changed) {
+ if (active) {
+ allocator->memories = g_ptr_array_sized_new (allocator->n_memories);
+ g_ptr_array_set_size (allocator->memories, allocator->n_memories);
+ } else {
+ if (g_atomic_int_get (&allocator->n_outstanding) == 0)
+ gst_omx_allocator_dealloc (allocator);
+ }
+ }
+
+ allocator->active = active;
+ g_mutex_unlock (&allocator->lock);
+
+ return changed;
+}
+
+void
+gst_omx_allocator_wait_inactive (GstOMXAllocator * allocator)
+{
+ g_mutex_lock (&allocator->lock);
+ while (allocator->memories)
+ g_cond_wait (&allocator->cond, &allocator->lock);
+ g_mutex_unlock (&allocator->lock);
+}
+
+static inline void
+dec_outstanding (GstOMXAllocator * allocator)
+{
+ if (g_atomic_int_dec_and_test (&allocator->n_outstanding)) {
+ /* keep a ref to the allocator because _dealloc() will free
+ * all the memories and the memories might be the only thing holding
+ * a reference to the allocator; we need to keep it alive until the
+ * end of this function call */
+ g_object_ref (allocator);
+
+ /* take the lock so that _set_active() is not run concurrently */
+ g_mutex_lock (&allocator->lock);
+
+ /* now that we have the lock, check if we have been de-activated with
+ * outstanding buffers */
+ if (!allocator->active)
+ gst_omx_allocator_dealloc (allocator);
+
+ g_mutex_unlock (&allocator->lock);
+ g_object_unref (allocator);
+ }
+}
+
+GstFlowReturn
+gst_omx_allocator_acquire (GstOMXAllocator * allocator, GstMemory ** memory,
+ gint index, GstOMXBuffer * omx_buf)
+{
+ GstFlowReturn ret = GST_FLOW_OK;
+ GstOMXMemory *omx_mem = NULL;
+
+ /* ensure memories are not going to disappear concurrently */
+ g_atomic_int_inc (&allocator->n_outstanding);
+
+ if (!allocator->active) {
+ ret = GST_FLOW_FLUSHING;
+ goto beach;
+ }
+
+ if (index >= 0 && index < allocator->n_memories)
+ omx_mem = g_ptr_array_index (allocator->memories, index);
+ else if (omx_buf) {
+ for (index = 0; index < allocator->n_memories; index++) {
+ omx_mem = g_ptr_array_index (allocator->memories, index);
+ if (omx_mem->buf == omx_buf)
+ break;
+ }
+ }
+
+ if (G_UNLIKELY (!omx_mem || index >= allocator->n_memories)) {
+ GST_ERROR_OBJECT (allocator, "Failed to find OMX memory");
+ ret = GST_FLOW_ERROR;
+ goto beach;
+ }
+
+ if (G_UNLIKELY (omx_mem->buf->used)) {
+ GST_ERROR_OBJECT (allocator,
+ "Trying to acquire a buffer that is being used by the OMX port");
+ ret = GST_FLOW_ERROR;
+ goto beach;
+ }
+
+ omx_mem->acquired = TRUE;
+
+ if (omx_mem->foreign_mem)
+ *memory = omx_mem->foreign_mem;
+ else
+ *memory = GST_MEMORY_CAST (omx_mem);
+
+beach:
+ if (ret != GST_FLOW_OK)
+ dec_outstanding (allocator);
+ return ret;
+}
+
+/* installed as the GstMiniObject::dispose function of the acquired GstMemory */
+static gboolean
+gst_omx_allocator_memory_dispose (GstMemory * mem)
+{
+ GstOMXMemory *omx_mem;
+ GstOMXAllocator *allocator;
+
+ /* memory may be from our allocator, but
+ * may as well be from the dmabuf allocator */
+ if (GST_IS_OMX_ALLOCATOR (mem->allocator))
+ omx_mem = (GstOMXMemory *) mem;
+ else
+ omx_mem = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
+ GST_OMX_MEMORY_QUARK);
+
+ if (omx_mem->acquired) {
+ /* keep the memory alive */
+ gst_memory_ref (mem);
+
+ omx_mem->acquired = FALSE;
+
+ allocator = GST_OMX_ALLOCATOR (GST_MEMORY_CAST (omx_mem)->allocator);
+
+ /* inform the upper layer that we are no longer using this GstOMXBuffer */
+ g_signal_emit (allocator, signals[SIG_OMXBUF_RELEASED], 0, omx_mem->buf);
+
+ dec_outstanding (allocator);
+
+ /* be careful here, both the memory and the allocator
+ * may have been free'd as part of the call to dec_outstanding() */
+
+ return FALSE;
+ }
+
+ /* if the foreign memory had a dispose function, let that one decide
+ * the fate of this memory. We are no longer going to be using it here */
+ if (omx_mem->foreign_dispose)
+ return omx_mem->foreign_dispose (GST_MINI_OBJECT_CAST (mem));
+
+ return TRUE;
+}
+
+static inline void
+install_mem_dispose (GstOMXMemory * mem)
+{
+ GstMemory *managed_mem = (GstMemory *) mem;
+
+ if (mem->foreign_mem) {
+ managed_mem = mem->foreign_mem;
+ mem->foreign_dispose = GST_MINI_OBJECT_CAST (managed_mem)->dispose;
+ }
+
+ GST_MINI_OBJECT_CAST (managed_mem)->dispose =
+ (GstMiniObjectDisposeFunction) gst_omx_allocator_memory_dispose;
+}
+
+/* the returned memory is transfer:none, ref still belongs to the allocator */
+GstMemory *
+gst_omx_allocator_allocate (GstOMXAllocator * allocator, gint index,
+ GstMemory * foreign_mem)
+{
+ GstOMXMemory *mem;
+ GstOMXBuffer *omx_buf;
+
+ g_return_val_if_fail (allocator->port->buffers, NULL);
+ g_return_val_if_fail (allocator->memories, NULL);
+ g_return_val_if_fail (index >= 0 && index < allocator->n_memories, NULL);
+ g_return_val_if_fail ((foreign_mem == NULL &&
+ allocator->foreign_mode != GST_OMX_ALLOCATOR_FOREIGN_MEM_OTHER_POOL)
+ || (foreign_mem != NULL
+ && allocator->foreign_mode ==
+ GST_OMX_ALLOCATOR_FOREIGN_MEM_OTHER_POOL), NULL);
+
+ omx_buf = g_ptr_array_index (allocator->port->buffers, index);
+ g_return_val_if_fail (omx_buf != NULL, NULL);
+
+ mem = gst_omx_memory_new (allocator, omx_buf, 0, NULL, 0, -1);
+
+ switch (allocator->foreign_mode) {
+ case GST_OMX_ALLOCATOR_FOREIGN_MEM_NONE:
+ install_mem_dispose (mem);
+ break;
+ case GST_OMX_ALLOCATOR_FOREIGN_MEM_DMABUF:
+ {
+ gint fd = GPOINTER_TO_INT (omx_buf->omx_buf->pBuffer);
+ mem->foreign_mem =
+ gst_dmabuf_allocator_alloc (allocator->foreign_allocator, fd,
+ omx_buf->omx_buf->nAllocLen);
+ gst_mini_object_set_qdata (GST_MINI_OBJECT (mem->foreign_mem),
+ GST_OMX_MEMORY_QUARK, mem, NULL);
+ install_mem_dispose (mem);
+ break;
+ }
+ case GST_OMX_ALLOCATOR_FOREIGN_MEM_OTHER_POOL:
+ mem->foreign_mem = foreign_mem;
+ gst_mini_object_set_qdata (GST_MINI_OBJECT (mem->foreign_mem),
+ GST_OMX_MEMORY_QUARK, mem, NULL);
+ install_mem_dispose (mem);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ g_ptr_array_index (allocator->memories, index) = mem;
+ return mem->foreign_mem ? mem->foreign_mem : (GstMemory *) mem;
+}
+
+static void
+gst_omx_allocator_free (GstAllocator * allocator, GstMemory * mem)
+{
+ GstOMXMemory *omem = (GstOMXMemory *) mem;
+
+ g_warn_if_fail (!omem->acquired);
+
+ if (omem->foreign_mem)
+ gst_memory_unref (omem->foreign_mem);
+
+ g_slice_free (GstOMXMemory, omem);
+}
+
+static void
+gst_omx_allocator_class_init (GstOMXAllocatorClass * klass)
+{
+ GObjectClass *object_class;
+ GstAllocatorClass *allocator_class;
+
+ object_class = (GObjectClass *) klass;
+ allocator_class = (GstAllocatorClass *) klass;
+
+ object_class->finalize = gst_omx_allocator_finalize;
+ allocator_class->alloc = NULL;
+ allocator_class->free = gst_omx_allocator_free;
+
+ signals[SIG_OMXBUF_RELEASED] = g_signal_new ("omxbuf-released",
+ G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0,
+ NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+ signals[SIG_FOREIGN_MEM_RELEASED] = g_signal_new ("foreign-mem-released",
+ G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0,
+ NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_POINTER);
+}
diff --git a/subprojects/gst-omx/omx/gstomxallocator.h b/subprojects/gst-omx/omx/gstomxallocator.h
new file mode 100644
index 0000000000..5c94584ec2
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxallocator.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2019, Collabora Ltd.
+ * Author: George Kiagiadakis <george.kiagiadakis@collabora.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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_ALLOCATOR_H__
+#define __GST_OMX_ALLOCATOR_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomx.h"
+
+G_BEGIN_DECLS
+
+#define GST_OMX_MEMORY_QUARK gst_omx_memory_quark ()
+
+#define GST_TYPE_OMX_ALLOCATOR (gst_omx_allocator_get_type())
+#define GST_IS_OMX_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_OMX_ALLOCATOR))
+#define GST_OMX_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_OMX_ALLOCATOR, GstOMXAllocator))
+
+typedef struct _GstOMXMemory GstOMXMemory;
+typedef struct _GstOMXAllocator GstOMXAllocator;
+typedef struct _GstOMXAllocatorClass GstOMXAllocatorClass;
+
+typedef enum {
+ GST_OMX_ALLOCATOR_FOREIGN_MEM_NONE,
+ GST_OMX_ALLOCATOR_FOREIGN_MEM_DMABUF,
+ GST_OMX_ALLOCATOR_FOREIGN_MEM_OTHER_POOL,
+} GstOMXAllocatorForeignMemMode;
+
+struct _GstOMXMemory
+{
+ GstMemory mem;
+ GstOMXBuffer *buf;
+
+ /* TRUE if the memory is in use outside the allocator */
+ gboolean acquired;
+
+ /* memory allocated from the foreign_allocator
+ * or planted externally when using a foreign buffer pool */
+ GstMemory *foreign_mem;
+ /* the original dispose function of foreign_mem */
+ GstMiniObjectDisposeFunction foreign_dispose;
+};
+
+struct _GstOMXAllocator
+{
+ GstAllocator parent;
+
+ GstOMXComponent *component;
+ GstOMXPort *port;
+
+ GstOMXAllocatorForeignMemMode foreign_mode;
+ GstAllocator *foreign_allocator;
+
+ /* array of GstOMXMemory */
+ GPtrArray *memories;
+ guint n_memories;
+
+ guint n_outstanding;
+ gboolean active;
+
+ GMutex lock;
+ GCond cond;
+};
+
+struct _GstOMXAllocatorClass
+{
+ GstAllocatorClass parent_class;
+};
+
+GType gst_omx_allocator_get_type (void);
+
+GQuark gst_omx_memory_quark (void);
+
+GstOMXBuffer * gst_omx_memory_get_omx_buf (GstMemory * mem);
+
+GstOMXAllocator * gst_omx_allocator_new (GstOMXComponent * component,
+ GstOMXPort * port);
+
+gboolean gst_omx_allocator_configure (GstOMXAllocator * allocator, guint count,
+ GstOMXAllocatorForeignMemMode mode);
+gboolean gst_omx_allocator_set_active (GstOMXAllocator * allocator,
+ gboolean active);
+void gst_omx_allocator_wait_inactive (GstOMXAllocator * allocator);
+
+GstFlowReturn gst_omx_allocator_acquire (GstOMXAllocator * allocator,
+ GstMemory ** memory, gint index, GstOMXBuffer * omx_buf);
+
+GstMemory * gst_omx_allocator_allocate (GstOMXAllocator * allocator, gint index,
+ GstMemory * foreign_mem);
+
+G_END_DECLS
+
+#endif
diff --git a/subprojects/gst-omx/omx/gstomxamrdec.c b/subprojects/gst-omx/omx/gstomxamrdec.c
new file mode 100644
index 0000000000..d7e468fbbf
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxamrdec.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.com>
+ * Copyright (C) 2014, LG Electronics, Inc. <jun.ji@lge.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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxamrdec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_amr_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_amr_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_amr_dec_set_format (GstOMXAudioDec * dec,
+ GstOMXPort * port, GstCaps * caps);
+static gboolean gst_omx_amr_dec_is_format_change (GstOMXAudioDec * dec,
+ GstOMXPort * port, GstCaps * caps);
+static gint gst_omx_amr_dec_get_samples_per_frame (GstOMXAudioDec * dec,
+ GstOMXPort * port);
+static gboolean gst_omx_amr_dec_get_channel_positions (GstOMXAudioDec * dec,
+ GstOMXPort * port, GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS]);
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_amr_dec_debug_category, "omxamrdec", 0, \
+ "debug category for gst-omx amr audio decoder");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXAMRDec, gst_omx_amr_dec,
+ GST_TYPE_OMX_AUDIO_DEC, DEBUG_INIT);
+
+static void
+gst_omx_amr_dec_class_init (GstOMXAMRDecClass * klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstOMXAudioDecClass *audiodec_class = GST_OMX_AUDIO_DEC_CLASS (klass);
+
+ audiodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_amr_dec_set_format);
+ audiodec_class->is_format_change =
+ GST_DEBUG_FUNCPTR (gst_omx_amr_dec_is_format_change);
+ audiodec_class->get_samples_per_frame =
+ GST_DEBUG_FUNCPTR (gst_omx_amr_dec_get_samples_per_frame);
+ audiodec_class->get_channel_positions =
+ GST_DEBUG_FUNCPTR (gst_omx_amr_dec_get_channel_positions);
+
+ audiodec_class->cdata.default_sink_template_caps =
+ "audio/AMR, rate=(int)8000, channels=(int)1; "
+ "audio/AMR-WB, rate=(int)16000, channels=(int)1";
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX AMR Audio Decoder",
+ "Codec/Decoder/Audio/Hardware",
+ "Decode AMR audio streams",
+ "Sebastian Dröge <sebastian@centricular.com>");
+
+ gst_omx_set_default_role (&audiodec_class->cdata, "audio_decoder.amrnb");
+}
+
+static void
+gst_omx_amr_dec_init (GstOMXAMRDec * self)
+{
+ self->spf = -1;
+}
+
+static gboolean
+gst_omx_amr_dec_set_format (GstOMXAudioDec * dec, GstOMXPort * port,
+ GstCaps * caps)
+{
+ GstOMXAMRDec *self = GST_OMX_AMR_DEC (dec);
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ OMX_AUDIO_PARAM_AMRTYPE amr_param;
+ OMX_ERRORTYPE err;
+ GstStructure *s;
+ gint rate, channels;
+
+ gst_omx_port_get_port_definition (port, &port_def);
+ port_def.format.audio.eEncoding = OMX_AUDIO_CodingAMR; /* not tested for AMRWB */
+ err = gst_omx_port_update_port_definition (port, &port_def);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to set AMR format on component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ GST_OMX_INIT_STRUCT (&amr_param);
+ amr_param.nPortIndex = port->index;
+
+ err =
+ gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioAmr,
+ &amr_param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to get AMR parameters from component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ s = gst_caps_get_structure (caps, 0);
+
+ if (!gst_structure_get_int (s, "rate", &rate) ||
+ !gst_structure_get_int (s, "channels", &channels)) {
+ GST_ERROR_OBJECT (self, "Incomplete caps");
+ return FALSE;
+ }
+
+ self->rate = rate;
+
+ if (rate == 8000)
+ self->spf = 160; /* (8000/50) */
+ else if (rate == 16000)
+ self->spf = 320; /* (16000/50) */
+
+ amr_param.nChannels = channels;
+ amr_param.eAMRBandMode = 0; /*FIXME: It may require a specific value */
+ amr_param.eAMRDTXMode = 0;
+ amr_param.eAMRFrameFormat = 0;
+
+ err =
+ gst_omx_component_set_parameter (dec->dec, OMX_IndexParamAudioAmr,
+ &amr_param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Error setting AMR parameters: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_amr_dec_is_format_change (GstOMXAudioDec * dec, GstOMXPort * port,
+ GstCaps * caps)
+{
+ GstOMXAMRDec *self = GST_OMX_AMR_DEC (dec);
+ OMX_AUDIO_PARAM_AMRTYPE amr_param;
+ OMX_ERRORTYPE err;
+ GstStructure *s;
+ gint rate, channels;
+
+ GST_OMX_INIT_STRUCT (&amr_param);
+ amr_param.nPortIndex = port->index;
+
+ err =
+ gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioAmr,
+ &amr_param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to get AMR parameters from component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ s = gst_caps_get_structure (caps, 0);
+
+ if (!gst_structure_get_int (s, "rate", &rate) ||
+ !gst_structure_get_int (s, "channels", &channels)) {
+ GST_ERROR_OBJECT (self, "Incomplete caps");
+ return FALSE;
+ }
+
+ if (self->rate != rate)
+ return TRUE;
+
+ if (amr_param.nChannels != channels)
+ return TRUE;
+
+ return FALSE;
+}
+
+static gint
+gst_omx_amr_dec_get_samples_per_frame (GstOMXAudioDec * dec, GstOMXPort * port)
+{
+ return GST_OMX_AMR_DEC (dec)->spf;
+}
+
+static gboolean
+gst_omx_amr_dec_get_channel_positions (GstOMXAudioDec * dec,
+ GstOMXPort * port, GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS])
+{
+ OMX_AUDIO_PARAM_PCMMODETYPE pcm_param;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&pcm_param);
+ pcm_param.nPortIndex = port->index;
+ err =
+ gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioPcm,
+ &pcm_param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (dec, "Failed to get PCM parameters: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+
+ g_return_val_if_fail (pcm_param.nChannels == 1, FALSE); /* AMR supports only mono */
+
+ position[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
+
+ return TRUE;
+}
diff --git a/subprojects/gst-omx/omx/gstomxamrdec.h b/subprojects/gst-omx/omx/gstomxamrdec.h
new file mode 100644
index 0000000000..7a2df33050
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxamrdec.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_AMR_DEC_H__
+#define __GST_OMX_AMR_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxaudiodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_AMR_DEC \
+ (gst_omx_amr_dec_get_type())
+#define GST_OMX_AMR_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_AMR_DEC,GstOMXAMRDec))
+#define GST_OMX_AMR_DEC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_AMR_DEC,GstOMXAMRDecClass))
+#define GST_OMX_AMR_DEC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_AMR_DEC,GstOMXAMRDecClass))
+#define GST_IS_OMX_AMR_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_AMR_DEC))
+#define GST_IS_OMX_AMR_DEC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_AMR_DEC))
+
+typedef struct _GstOMXAMRDec GstOMXAMRDec;
+typedef struct _GstOMXAMRDecClass GstOMXAMRDecClass;
+
+struct _GstOMXAMRDec
+{
+ GstOMXAudioDec parent;
+ gint spf;
+ gint rate;
+};
+
+struct _GstOMXAMRDecClass
+{
+ GstOMXAudioDecClass parent_class;
+};
+
+GType gst_omx_amr_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_AMR_DEC_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxanalogaudiosink.c b/subprojects/gst-omx/omx/gstomxanalogaudiosink.c
new file mode 100644
index 0000000000..7c8c885273
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxanalogaudiosink.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2014, Fluendo, S.A.
+ * Copyright (C) 2014, Metrological Media Innovations B.V.
+ * Author: Josep Torra <josep@fluendo.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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxanalogaudiosink.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_analog_audio_sink_debug_category);
+#define GST_CAT_DEFAULT gst_omx_analog_audio_sink_debug_category
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_analog_audio_sink_debug_category, \
+ "omxanalogaudiosink", 0, "debug category for gst-omx analog audio sink");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXAnalogAudioSink, gst_omx_analog_audio_sink,
+ GST_TYPE_OMX_AUDIO_SINK, DEBUG_INIT);
+
+static void
+gst_omx_analog_audio_sink_class_init (GstOMXAnalogAudioSinkClass * klass)
+{
+ GstOMXAudioSinkClass *audiosink_class = GST_OMX_AUDIO_SINK_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ audiosink_class->cdata.default_sink_template_caps = "audio/x-raw, "
+ "format = (string) " GST_AUDIO_FORMATS_ALL ", "
+ "layout = (string) interleaved, "
+ "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ] ";
+ audiosink_class->destination = "local";
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX Analog Audio Sink",
+ "Sink/Audio", "Output analog audio", "Josep Torra <josep@fluendo.com>");
+
+ gst_omx_set_default_role (&audiosink_class->cdata, "audio_render.local");
+}
+
+static void
+gst_omx_analog_audio_sink_init (GstOMXAnalogAudioSink * self)
+{
+}
diff --git a/subprojects/gst-omx/omx/gstomxanalogaudiosink.h b/subprojects/gst-omx/omx/gstomxanalogaudiosink.h
new file mode 100644
index 0000000000..7f5704812f
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxanalogaudiosink.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2014, Fluendo, S.A.
+ * Copyright (C) 2014, Metrological Media Innovations B.V.
+ * Author: Josep Torra <josep@fluendo.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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_ANALOG_AUDIO_SINK_H__
+#define __GST_OMX_ANALOG_AUDIO_SINK_H__
+
+#include <gst/gst.h>
+#include "gstomxaudiosink.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_ANALOG_AUDIO_SINK \
+ (gst_omx_analog_audio_sink_get_type())
+#define GST_OMX_ANALOG_AUDIO_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_ANALOG_AUDIO_SINK,GstOMXAnalogAudioSink))
+#define GST_OMX_ANALOG_AUDIO_SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_ANALOG_AUDIO_SINK,GstOMXAnalogAudioSinkClass))
+#define GST_OMX_ANALOG_AUDIO_SINK_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_ANALOG_AUDIO_SINK,GstOMXAnalogAudioSinkClass))
+#define GST_IS_OMX_ANALOG_AUDIO_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_ANALOG_AUDIO_SINK))
+#define GST_IS_OMX_ANALOG_AUDIO_SINK_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_ANALOG_AUDIO_SINK))
+
+typedef struct _GstOMXAnalogAudioSink GstOMXAnalogAudioSink;
+typedef struct _GstOMXAnalogAudioSinkClass GstOMXAnalogAudioSinkClass;
+
+struct _GstOMXAnalogAudioSink
+{
+ GstOMXAudioSink parent;
+};
+
+struct _GstOMXAnalogAudioSinkClass
+{
+ GstOMXAudioSinkClass parent_class;
+};
+
+GType gst_omx_analog_audio_sink_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_ANALOG_AUDIO_SINK_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxaudiodec.c b/subprojects/gst-omx/omx/gstomxaudiodec.c
new file mode 100644
index 0000000000..8275b7204f
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxaudiodec.c
@@ -0,0 +1,1404 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ * Copyright (C) 2013, Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include <string.h>
+
+#include "gstomxaudiodec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_audio_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_audio_dec_debug_category
+
+/* prototypes */
+static void gst_omx_audio_dec_finalize (GObject * object);
+
+static GstStateChangeReturn
+gst_omx_audio_dec_change_state (GstElement * element,
+ GstStateChange transition);
+
+static gboolean gst_omx_audio_dec_open (GstAudioDecoder * decoder);
+static gboolean gst_omx_audio_dec_close (GstAudioDecoder * decoder);
+static gboolean gst_omx_audio_dec_start (GstAudioDecoder * decoder);
+static gboolean gst_omx_audio_dec_stop (GstAudioDecoder * decoder);
+static gboolean gst_omx_audio_dec_set_format (GstAudioDecoder * decoder,
+ GstCaps * caps);
+static void gst_omx_audio_dec_flush (GstAudioDecoder * decoder, gboolean hard);
+static GstFlowReturn gst_omx_audio_dec_handle_frame (GstAudioDecoder * decoder,
+ GstBuffer * buffer);
+static GstFlowReturn gst_omx_audio_dec_drain (GstOMXAudioDec * self);
+
+enum
+{
+ PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_audio_dec_debug_category, "omxaudiodec", 0, \
+ "debug category for gst-omx audio decoder base class");
+
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstOMXAudioDec, gst_omx_audio_dec,
+ GST_TYPE_AUDIO_DECODER, DEBUG_INIT);
+
+static void
+gst_omx_audio_dec_class_init (GstOMXAudioDecClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstAudioDecoderClass *audio_decoder_class = GST_AUDIO_DECODER_CLASS (klass);
+
+ gobject_class->finalize = gst_omx_audio_dec_finalize;
+
+ element_class->change_state =
+ GST_DEBUG_FUNCPTR (gst_omx_audio_dec_change_state);
+
+ audio_decoder_class->open = GST_DEBUG_FUNCPTR (gst_omx_audio_dec_open);
+ audio_decoder_class->close = GST_DEBUG_FUNCPTR (gst_omx_audio_dec_close);
+ audio_decoder_class->start = GST_DEBUG_FUNCPTR (gst_omx_audio_dec_start);
+ audio_decoder_class->stop = GST_DEBUG_FUNCPTR (gst_omx_audio_dec_stop);
+ audio_decoder_class->flush = GST_DEBUG_FUNCPTR (gst_omx_audio_dec_flush);
+ audio_decoder_class->set_format =
+ GST_DEBUG_FUNCPTR (gst_omx_audio_dec_set_format);
+ audio_decoder_class->handle_frame =
+ GST_DEBUG_FUNCPTR (gst_omx_audio_dec_handle_frame);
+
+ klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
+ klass->cdata.default_src_template_caps =
+ "audio/x-raw, "
+ "rate = (int) [ 1, MAX ], "
+ "channels = (int) [ 1, " G_STRINGIFY (OMX_AUDIO_MAXCHANNELS) " ], "
+ "format = (string) " GST_AUDIO_FORMATS_ALL;
+}
+
+static void
+gst_omx_audio_dec_init (GstOMXAudioDec * self)
+{
+ gst_audio_decoder_set_needs_format (GST_AUDIO_DECODER (self), TRUE);
+ gst_audio_decoder_set_drainable (GST_AUDIO_DECODER (self), TRUE);
+ gst_audio_decoder_set_use_default_pad_acceptcaps (GST_AUDIO_DECODER_CAST
+ (self), TRUE);
+ GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_DECODER_SINK_PAD (self));
+
+ g_mutex_init (&self->drain_lock);
+ g_cond_init (&self->drain_cond);
+
+ self->output_adapter = gst_adapter_new ();
+}
+
+static gboolean
+gst_omx_audio_dec_open (GstAudioDecoder * decoder)
+{
+ GstOMXAudioDec *self = GST_OMX_AUDIO_DEC (decoder);
+ GstOMXAudioDecClass *klass = GST_OMX_AUDIO_DEC_GET_CLASS (self);
+ gint in_port_index, out_port_index;
+
+ GST_DEBUG_OBJECT (self, "Opening decoder");
+
+ self->dec =
+ gst_omx_component_new (GST_OBJECT_CAST (self), klass->cdata.core_name,
+ klass->cdata.component_name, klass->cdata.component_role,
+ klass->cdata.hacks);
+ self->started = FALSE;
+
+ if (!self->dec)
+ return FALSE;
+
+ if (gst_omx_component_get_state (self->dec,
+ GST_CLOCK_TIME_NONE) != OMX_StateLoaded)
+ return FALSE;
+
+ in_port_index = klass->cdata.in_port_index;
+ out_port_index = klass->cdata.out_port_index;
+
+ if (in_port_index == -1 || out_port_index == -1) {
+ OMX_PORT_PARAM_TYPE param;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&param);
+
+ err =
+ gst_omx_component_get_parameter (self->dec, OMX_IndexParamAudioInit,
+ &param);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self, "Couldn't get port information: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ /* Fallback */
+ in_port_index = 0;
+ out_port_index = 1;
+ } else {
+ GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u",
+ (guint) param.nPorts, (guint) param.nStartPortNumber);
+ in_port_index = param.nStartPortNumber + 0;
+ out_port_index = param.nStartPortNumber + 1;
+ }
+ }
+ self->dec_in_port = gst_omx_component_add_port (self->dec, in_port_index);
+ self->dec_out_port = gst_omx_component_add_port (self->dec, out_port_index);
+
+ if (!self->dec_in_port || !self->dec_out_port)
+ return FALSE;
+
+ GST_DEBUG_OBJECT (self, "Opened decoder");
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_audio_dec_shutdown (GstOMXAudioDec * self)
+{
+ OMX_STATETYPE state;
+
+ GST_DEBUG_OBJECT (self, "Shutting down decoder");
+
+ state = gst_omx_component_get_state (self->dec, 0);
+ if (state > OMX_StateLoaded || state == OMX_StateInvalid) {
+ if (state > OMX_StateIdle) {
+ gst_omx_component_set_state (self->dec, OMX_StateIdle);
+ gst_omx_component_get_state (self->dec, 5 * GST_SECOND);
+ }
+ gst_omx_component_set_state (self->dec, OMX_StateLoaded);
+ gst_omx_port_deallocate_buffers (self->dec_in_port);
+ gst_omx_port_deallocate_buffers (self->dec_out_port);
+ if (state > OMX_StateLoaded)
+ gst_omx_component_get_state (self->dec, 5 * GST_SECOND);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_audio_dec_close (GstAudioDecoder * decoder)
+{
+ GstOMXAudioDec *self = GST_OMX_AUDIO_DEC (decoder);
+
+ GST_DEBUG_OBJECT (self, "Closing decoder");
+
+ if (!gst_omx_audio_dec_shutdown (self))
+ return FALSE;
+
+ self->dec_in_port = NULL;
+ self->dec_out_port = NULL;
+ if (self->dec)
+ gst_omx_component_unref (self->dec);
+ self->dec = NULL;
+
+ self->started = FALSE;
+
+ GST_DEBUG_OBJECT (self, "Closed decoder");
+
+ return TRUE;
+}
+
+static void
+gst_omx_audio_dec_finalize (GObject * object)
+{
+ GstOMXAudioDec *self = GST_OMX_AUDIO_DEC (object);
+
+ g_mutex_clear (&self->drain_lock);
+ g_cond_clear (&self->drain_cond);
+
+ if (self->output_adapter)
+ gst_object_unref (self->output_adapter);
+ self->output_adapter = NULL;
+
+ G_OBJECT_CLASS (gst_omx_audio_dec_parent_class)->finalize (object);
+}
+
+static GstStateChangeReturn
+gst_omx_audio_dec_change_state (GstElement * element, GstStateChange transition)
+{
+ GstOMXAudioDec *self;
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+
+ g_return_val_if_fail (GST_IS_OMX_AUDIO_DEC (element),
+ GST_STATE_CHANGE_FAILURE);
+ self = GST_OMX_AUDIO_DEC (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ break;
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ self->downstream_flow_ret = GST_FLOW_OK;
+ self->draining = FALSE;
+ self->started = FALSE;
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ if (self->dec_in_port)
+ gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
+ if (self->dec_out_port)
+ gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
+
+ g_mutex_lock (&self->drain_lock);
+ self->draining = FALSE;
+ g_cond_broadcast (&self->drain_cond);
+ g_mutex_unlock (&self->drain_lock);
+ break;
+ default:
+ break;
+ }
+
+ ret =
+ GST_ELEMENT_CLASS (gst_omx_audio_dec_parent_class)->change_state
+ (element, transition);
+
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ return ret;
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ self->downstream_flow_ret = GST_FLOW_FLUSHING;
+ self->started = FALSE;
+
+ if (!gst_omx_audio_dec_shutdown (self))
+ ret = GST_STATE_CHANGE_FAILURE;
+ break;
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static void
+gst_omx_audio_dec_loop (GstOMXAudioDec * self)
+{
+ GstOMXAudioDecClass *klass = GST_OMX_AUDIO_DEC_GET_CLASS (self);
+ GstOMXPort *port = self->dec_out_port;
+ GstOMXBuffer *buf = NULL;
+ GstFlowReturn flow_ret = GST_FLOW_OK;
+ GstOMXAcquireBufferReturn acq_return;
+ OMX_ERRORTYPE err;
+ gint spf;
+
+ acq_return = gst_omx_port_acquire_buffer (port, &buf, GST_OMX_WAIT);
+ if (acq_return == GST_OMX_ACQUIRE_BUFFER_ERROR) {
+ goto component_error;
+ } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
+ goto flushing;
+ } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_EOS) {
+ goto eos;
+ }
+
+ if (!gst_pad_has_current_caps (GST_AUDIO_DECODER_SRC_PAD (self)) ||
+ acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ OMX_AUDIO_PARAM_PCMMODETYPE pcm_param;
+ GstAudioChannelPosition omx_position[OMX_AUDIO_MAXCHANNELS];
+ GstOMXAudioDecClass *klass = GST_OMX_AUDIO_DEC_GET_CLASS (self);
+ gint i;
+
+ GST_DEBUG_OBJECT (self, "Port settings have changed, updating caps");
+
+ /* Reallocate all buffers */
+ if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE
+ && gst_omx_port_is_enabled (port)) {
+ err = gst_omx_port_set_enabled (port, FALSE);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_wait_buffers_released (port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_deallocate_buffers (port);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_wait_enabled (port, 1 * GST_SECOND);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+ }
+
+ /* Just update caps */
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+
+ gst_omx_port_get_port_definition (port, &port_def);
+ g_assert (port_def.format.audio.eEncoding == OMX_AUDIO_CodingPCM);
+
+ GST_OMX_INIT_STRUCT (&pcm_param);
+ pcm_param.nPortIndex = self->dec_out_port->index;
+ err =
+ gst_omx_component_get_parameter (self->dec, OMX_IndexParamAudioPcm,
+ &pcm_param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to get PCM parameters: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto caps_failed;
+ }
+
+ g_assert (pcm_param.ePCMMode == OMX_AUDIO_PCMModeLinear);
+ g_assert (pcm_param.bInterleaved == OMX_TRUE);
+
+ gst_audio_info_init (&self->info);
+
+ for (i = 0; i < pcm_param.nChannels; i++) {
+ switch (pcm_param.eChannelMapping[i]) {
+ case OMX_AUDIO_ChannelLF:
+ omx_position[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
+ break;
+ case OMX_AUDIO_ChannelRF:
+ omx_position[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
+ break;
+ case OMX_AUDIO_ChannelCF:
+ omx_position[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
+ break;
+ case OMX_AUDIO_ChannelLS:
+ omx_position[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT;
+ break;
+ case OMX_AUDIO_ChannelRS:
+ omx_position[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT;
+ break;
+ case OMX_AUDIO_ChannelLFE:
+ omx_position[i] = GST_AUDIO_CHANNEL_POSITION_LFE1;
+ break;
+ case OMX_AUDIO_ChannelCS:
+ omx_position[i] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
+ break;
+ case OMX_AUDIO_ChannelLR:
+ omx_position[i] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
+ break;
+ case OMX_AUDIO_ChannelRR:
+ omx_position[i] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
+ break;
+ case OMX_AUDIO_ChannelNone:
+ default:
+ /* This will break the outer loop too as the
+ * i == pcm_param.nChannels afterwards */
+ for (i = 0; i < pcm_param.nChannels; i++)
+ omx_position[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
+ break;
+ }
+ }
+ if (pcm_param.nChannels == 1
+ && omx_position[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER)
+ omx_position[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
+
+ if (omx_position[0] == GST_AUDIO_CHANNEL_POSITION_NONE
+ && klass->get_channel_positions) {
+ GST_WARNING_OBJECT (self,
+ "Failed to get a valid channel layout, trying fallback");
+ klass->get_channel_positions (self, self->dec_out_port, omx_position);
+ }
+
+ memcpy (self->position, omx_position, sizeof (omx_position));
+ gst_audio_channel_positions_to_valid_order (self->position,
+ pcm_param.nChannels);
+ self->needs_reorder =
+ (memcmp (self->position, omx_position,
+ sizeof (GstAudioChannelPosition) * pcm_param.nChannels) != 0);
+ if (self->needs_reorder)
+ gst_audio_get_channel_reorder_map (pcm_param.nChannels, self->position,
+ omx_position, self->reorder_map);
+
+ gst_audio_info_set_format (&self->info,
+ gst_audio_format_build_integer (pcm_param.eNumData ==
+ OMX_NumericalDataSigned,
+ pcm_param.eEndian ==
+ OMX_EndianLittle ? G_LITTLE_ENDIAN : G_BIG_ENDIAN,
+ pcm_param.nBitPerSample, pcm_param.nBitPerSample),
+ pcm_param.nSamplingRate, pcm_param.nChannels, self->position);
+
+ GST_DEBUG_OBJECT (self,
+ "Setting output state: format %s, rate %u, channels %u",
+ gst_audio_format_to_string (self->info.finfo->format),
+ (guint) pcm_param.nSamplingRate, (guint) pcm_param.nChannels);
+
+ if (!gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (self),
+ &self->info)
+ || !gst_audio_decoder_negotiate (GST_AUDIO_DECODER (self))) {
+ if (buf)
+ gst_omx_port_release_buffer (port, buf);
+ goto caps_failed;
+ }
+
+ GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+
+ if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+ err = gst_omx_port_set_enabled (port, TRUE);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_allocate_buffers (port);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_wait_enabled (port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_populate (port);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_mark_reconfigured (port);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+ }
+
+ /* Now get a buffer */
+ if (acq_return != GST_OMX_ACQUIRE_BUFFER_OK) {
+ return;
+ }
+ }
+
+ g_assert (acq_return == GST_OMX_ACQUIRE_BUFFER_OK);
+ if (!buf) {
+ g_assert ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER));
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+ goto eos;
+ }
+
+ /* This prevents a deadlock between the srcpad stream
+ * lock and the audiocodec stream lock, if ::reset()
+ * is called at the wrong time
+ */
+ if (gst_omx_port_is_flushing (port)) {
+ GST_DEBUG_OBJECT (self, "Flushing");
+ gst_omx_port_release_buffer (port, buf);
+ goto flushing;
+ }
+
+ GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %" G_GUINT64_FORMAT,
+ (guint) buf->omx_buf->nFlags,
+ (guint64) GST_OMX_GET_TICKS (buf->omx_buf->nTimeStamp));
+
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+
+ spf = klass->get_samples_per_frame (self, self->dec_out_port);
+
+ if (buf->omx_buf->nFilledLen > 0) {
+ GstBuffer *outbuf;
+ GstMapInfo minfo;
+
+ GST_DEBUG_OBJECT (self, "Handling output data");
+
+ if (buf->omx_buf->nFilledLen % self->info.bpf != 0) {
+ gst_omx_port_release_buffer (port, buf);
+ goto invalid_buffer;
+ }
+
+ outbuf =
+ gst_audio_decoder_allocate_output_buffer (GST_AUDIO_DECODER (self),
+ buf->omx_buf->nFilledLen);
+
+ gst_buffer_map (outbuf, &minfo, GST_MAP_WRITE);
+ if (self->needs_reorder) {
+ gint i, n_samples, c, n_channels;
+ gint *reorder_map = self->reorder_map;
+ gint16 *dest, *source;
+
+ dest = (gint16 *) minfo.data;
+ source = (gint16 *) (buf->omx_buf->pBuffer + buf->omx_buf->nOffset);
+ n_samples = buf->omx_buf->nFilledLen / self->info.bpf;
+ n_channels = self->info.channels;
+
+ for (i = 0; i < n_samples; i++) {
+ for (c = 0; c < n_channels; c++) {
+ dest[i * n_channels + reorder_map[c]] = source[i * n_channels + c];
+ }
+ }
+ } else {
+ memcpy (minfo.data, buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+ buf->omx_buf->nFilledLen);
+ }
+ gst_buffer_unmap (outbuf, &minfo);
+
+ if (spf != -1) {
+ gst_adapter_push (self->output_adapter, outbuf);
+ } else {
+ flow_ret =
+ gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (self), outbuf, 1);
+ }
+ }
+
+ GST_DEBUG_OBJECT (self, "Read frame from component");
+
+ if (spf != -1) {
+ GstBuffer *outbuf;
+ guint avail = gst_adapter_available (self->output_adapter);
+ guint nframes;
+
+ /* We take a multiple of codec frames and push
+ * them downstream
+ */
+ avail /= self->info.bpf;
+ nframes = avail / spf;
+ avail = nframes * spf;
+ avail *= self->info.bpf;
+
+ if (avail > 0) {
+ outbuf = gst_adapter_take_buffer (self->output_adapter, avail);
+ flow_ret =
+ gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (self), outbuf,
+ nframes);
+ }
+ }
+
+ GST_DEBUG_OBJECT (self, "Finished frame: %s", gst_flow_get_name (flow_ret));
+
+ if (buf) {
+ err = gst_omx_port_release_buffer (port, buf);
+ if (err != OMX_ErrorNone)
+ goto release_error;
+ }
+
+ self->downstream_flow_ret = flow_ret;
+
+ if (flow_ret != GST_FLOW_OK)
+ goto flow_error;
+
+ GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+
+ return;
+
+component_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+ ("OpenMAX component in error state %s (0x%08x)",
+ gst_omx_component_get_last_error_string (self->dec),
+ gst_omx_component_get_last_error (self->dec)));
+ gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
+ gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+ self->downstream_flow_ret = GST_FLOW_ERROR;
+ self->started = FALSE;
+ return;
+ }
+
+flushing:
+ {
+ GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
+ g_mutex_lock (&self->drain_lock);
+ if (self->draining) {
+ self->draining = FALSE;
+ g_cond_broadcast (&self->drain_cond);
+ }
+ gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+ self->downstream_flow_ret = GST_FLOW_FLUSHING;
+ self->started = FALSE;
+ g_mutex_unlock (&self->drain_lock);
+ return;
+ }
+
+eos:
+ {
+ spf = klass->get_samples_per_frame (self, self->dec_out_port);
+ if (spf != -1) {
+ GstBuffer *outbuf;
+ guint avail = gst_adapter_available (self->output_adapter);
+ guint nframes;
+
+ /* On EOS we take the complete adapter content, no matter
+ * if it is a multiple of the codec frame size or not.
+ */
+ avail /= self->info.bpf;
+ nframes = (avail + spf - 1) / spf;
+ avail *= self->info.bpf;
+
+ if (avail > 0) {
+ outbuf = gst_adapter_take_buffer (self->output_adapter, avail);
+ flow_ret =
+ gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (self), outbuf,
+ nframes);
+ }
+ }
+
+ g_mutex_lock (&self->drain_lock);
+ if (self->draining) {
+ GST_DEBUG_OBJECT (self, "Drained");
+ self->draining = FALSE;
+ g_cond_broadcast (&self->drain_cond);
+ flow_ret = GST_FLOW_OK;
+ gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+ } else {
+ GST_DEBUG_OBJECT (self, "Component signalled EOS");
+ flow_ret = GST_FLOW_EOS;
+ }
+ g_mutex_unlock (&self->drain_lock);
+
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+ self->downstream_flow_ret = flow_ret;
+
+ /* Here we fallback and pause the task for the EOS case */
+ if (flow_ret != GST_FLOW_OK)
+ goto flow_error;
+
+ GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+
+ return;
+ }
+
+flow_error:
+ {
+ if (flow_ret == GST_FLOW_EOS) {
+ GST_DEBUG_OBJECT (self, "EOS");
+
+ gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self),
+ gst_event_new_eos ());
+ gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+ self->started = FALSE;
+ } else if (flow_ret < GST_FLOW_EOS) {
+ GST_ELEMENT_ERROR (self, STREAM, FAILED,
+ ("Internal data stream error."), ("stream stopped, reason %s",
+ gst_flow_get_name (flow_ret)));
+
+ gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self),
+ gst_event_new_eos ());
+ gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+ self->started = FALSE;
+ } else if (flow_ret == GST_FLOW_FLUSHING) {
+ GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
+ g_mutex_lock (&self->drain_lock);
+ if (self->draining) {
+ self->draining = FALSE;
+ g_cond_broadcast (&self->drain_cond);
+ }
+ gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+ self->started = FALSE;
+ g_mutex_unlock (&self->drain_lock);
+ }
+ GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+ return;
+ }
+
+reconfigure_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Unable to reconfigure output port"));
+ gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
+ gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+ self->downstream_flow_ret = GST_FLOW_ERROR;
+ self->started = FALSE;
+ return;
+ }
+
+invalid_buffer:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Invalid sized input buffer"));
+ gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
+ gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+ self->downstream_flow_ret = GST_FLOW_NOT_NEGOTIATED;
+ self->started = FALSE;
+ GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+ return;
+ }
+
+caps_failed:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL), ("Failed to set caps"));
+ gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
+ gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+ GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+ self->downstream_flow_ret = GST_FLOW_NOT_NEGOTIATED;
+ self->started = FALSE;
+ return;
+ }
+release_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Failed to relase output buffer to component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err));
+ gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
+ gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+ self->downstream_flow_ret = GST_FLOW_ERROR;
+ self->started = FALSE;
+ GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+ return;
+ }
+}
+
+static gboolean
+gst_omx_audio_dec_start (GstAudioDecoder * decoder)
+{
+ GstOMXAudioDec *self;
+
+ self = GST_OMX_AUDIO_DEC (decoder);
+
+ self->last_upstream_ts = 0;
+ self->downstream_flow_ret = GST_FLOW_OK;
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_audio_dec_stop (GstAudioDecoder * decoder)
+{
+ GstOMXAudioDec *self;
+
+ self = GST_OMX_AUDIO_DEC (decoder);
+
+ GST_DEBUG_OBJECT (self, "Stopping decoder");
+
+ gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
+ gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
+
+ gst_pad_stop_task (GST_AUDIO_DECODER_SRC_PAD (decoder));
+
+ if (gst_omx_component_get_state (self->dec, 0) > OMX_StateIdle)
+ gst_omx_component_set_state (self->dec, OMX_StateIdle);
+
+ self->downstream_flow_ret = GST_FLOW_FLUSHING;
+ self->started = FALSE;
+
+ g_mutex_lock (&self->drain_lock);
+ self->draining = FALSE;
+ g_cond_broadcast (&self->drain_cond);
+ g_mutex_unlock (&self->drain_lock);
+
+ gst_adapter_flush (self->output_adapter,
+ gst_adapter_available (self->output_adapter));
+
+ gst_omx_component_get_state (self->dec, 5 * GST_SECOND);
+
+ gst_buffer_replace (&self->codec_data, NULL);
+
+ GST_DEBUG_OBJECT (self, "Stopped decoder");
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_audio_dec_set_format (GstAudioDecoder * decoder, GstCaps * caps)
+{
+ GstOMXAudioDec *self;
+ GstOMXAudioDecClass *klass;
+ GstStructure *s;
+ const GValue *codec_data;
+ gboolean is_format_change = FALSE;
+ gboolean needs_disable = FALSE;
+
+ self = GST_OMX_AUDIO_DEC (decoder);
+ klass = GST_OMX_AUDIO_DEC_GET_CLASS (decoder);
+
+ GST_DEBUG_OBJECT (self, "Setting new caps %" GST_PTR_FORMAT, caps);
+
+ /* Check if the caps change is a real format change or if only irrelevant
+ * parts of the caps have changed or nothing at all.
+ */
+ if (klass->is_format_change)
+ is_format_change = klass->is_format_change (self, self->dec_in_port, caps);
+
+ needs_disable =
+ gst_omx_component_get_state (self->dec,
+ GST_CLOCK_TIME_NONE) != OMX_StateLoaded;
+ /* If the component is not in Loaded state and a real format change happens
+ * we have to disable the port and re-allocate all buffers. If no real
+ * format change happened we can just exit here.
+ */
+ if (needs_disable && !is_format_change) {
+ GST_DEBUG_OBJECT (self,
+ "Already running and caps did not change the format");
+ return TRUE;
+ }
+
+ if (needs_disable && is_format_change) {
+ GstOMXPort *out_port = self->dec_out_port;
+
+ GST_DEBUG_OBJECT (self, "Need to disable and drain decoder");
+
+ gst_omx_audio_dec_drain (self);
+ gst_omx_audio_dec_flush (decoder, FALSE);
+ gst_omx_port_set_flushing (out_port, 5 * GST_SECOND, TRUE);
+
+ if (klass->cdata.hacks & GST_OMX_HACK_NO_COMPONENT_RECONFIGURE) {
+ GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+ gst_omx_audio_dec_stop (GST_AUDIO_DECODER (self));
+ gst_omx_audio_dec_close (GST_AUDIO_DECODER (self));
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+
+ if (!gst_omx_audio_dec_open (GST_AUDIO_DECODER (self)))
+ return FALSE;
+ needs_disable = FALSE;
+ } else {
+ /* Disabling at the same time input port and output port is only
+ * required when a buffer is shared between the ports. This cannot
+ * be the case for a decoder because its input and output buffers
+ * are of different nature. So let's disable ports sequencially.
+ * Starting from IL 1.2.0, this point has been clarified.
+ * OMX_SendCommand will return an error if the IL client attempts to
+ * call it when there is already an on-going command being processed.
+ * The exception is for buffer sharing above and the event
+ * OMX_EventPortNeedsDisable will be sent to request disabling the
+ * other port at the same time. */
+ if (gst_omx_port_set_enabled (self->dec_in_port, FALSE) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_wait_buffers_released (self->dec_in_port,
+ 5 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_deallocate_buffers (self->dec_in_port) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_wait_enabled (self->dec_in_port,
+ 1 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+
+ if (gst_omx_port_set_enabled (out_port, FALSE) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_wait_buffers_released (out_port,
+ 1 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_deallocate_buffers (out_port) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_wait_enabled (out_port, 1 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ }
+
+ GST_DEBUG_OBJECT (self, "Decoder drained and disabled");
+ }
+
+ if (klass->set_format) {
+ if (!klass->set_format (self, self->dec_in_port, caps)) {
+ GST_ERROR_OBJECT (self, "Subclass failed to set the new format");
+ return FALSE;
+ }
+ }
+
+ GST_DEBUG_OBJECT (self, "Updating outport port definition");
+ if (gst_omx_port_update_port_definition (self->dec_out_port,
+ NULL) != OMX_ErrorNone)
+ return FALSE;
+
+ /* Get codec data from caps */
+ gst_buffer_replace (&self->codec_data, NULL);
+ s = gst_caps_get_structure (caps, 0);
+ codec_data = gst_structure_get_value (s, "codec_data");
+ if (codec_data) {
+ /* Vorbis and some other codecs have multiple buffers in
+ * the stream-header field */
+ self->codec_data = gst_value_get_buffer (codec_data);
+ if (self->codec_data)
+ gst_buffer_ref (self->codec_data);
+ }
+
+ GST_DEBUG_OBJECT (self, "Enabling component");
+
+ if (needs_disable) {
+ if (gst_omx_port_set_enabled (self->dec_in_port, TRUE) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone)
+ return FALSE;
+
+ if ((klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
+ if (gst_omx_port_set_enabled (self->dec_out_port, TRUE) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_allocate_buffers (self->dec_out_port) != OMX_ErrorNone)
+ return FALSE;
+
+ if (gst_omx_port_wait_enabled (self->dec_out_port,
+ 5 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ }
+
+ if (gst_omx_port_wait_enabled (self->dec_in_port,
+ 5 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_mark_reconfigured (self->dec_in_port) != OMX_ErrorNone)
+ return FALSE;
+ } else {
+ if (!(klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
+ /* Disable output port */
+ if (gst_omx_port_set_enabled (self->dec_out_port, FALSE) != OMX_ErrorNone)
+ return FALSE;
+
+ if (gst_omx_port_wait_enabled (self->dec_out_port,
+ 1 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+
+ if (gst_omx_component_set_state (self->dec,
+ OMX_StateIdle) != OMX_ErrorNone)
+ return FALSE;
+
+ /* Need to allocate buffers to reach Idle state */
+ if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone)
+ return FALSE;
+ } else {
+ if (gst_omx_component_set_state (self->dec,
+ OMX_StateIdle) != OMX_ErrorNone)
+ return FALSE;
+
+ /* Need to allocate buffers to reach Idle state */
+ if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_allocate_buffers (self->dec_out_port) != OMX_ErrorNone)
+ return FALSE;
+ }
+
+ if (gst_omx_component_get_state (self->dec,
+ GST_CLOCK_TIME_NONE) != OMX_StateIdle)
+ return FALSE;
+
+ if (gst_omx_component_set_state (self->dec,
+ OMX_StateExecuting) != OMX_ErrorNone)
+ return FALSE;
+
+ if (gst_omx_component_get_state (self->dec,
+ GST_CLOCK_TIME_NONE) != OMX_StateExecuting)
+ return FALSE;
+ }
+
+ /* Unset flushing to allow ports to accept data again */
+ gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, FALSE);
+ gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, FALSE);
+
+ if (gst_omx_component_get_last_error (self->dec) != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Component in error state: %s (0x%08x)",
+ gst_omx_component_get_last_error_string (self->dec),
+ gst_omx_component_get_last_error (self->dec));
+ return FALSE;
+ }
+
+ self->downstream_flow_ret = GST_FLOW_OK;
+
+ return TRUE;
+}
+
+static void
+gst_omx_audio_dec_flush (GstAudioDecoder * decoder, gboolean hard)
+{
+ GstOMXAudioDec *self = GST_OMX_AUDIO_DEC (decoder);
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+
+ GST_DEBUG_OBJECT (self, "Flushing decoder");
+
+ if (gst_omx_component_get_state (self->dec, 0) == OMX_StateLoaded)
+ return;
+
+ /* 0) Pause the components */
+ if (gst_omx_component_get_state (self->dec, 0) == OMX_StateExecuting) {
+ gst_omx_component_set_state (self->dec, OMX_StatePause);
+ gst_omx_component_get_state (self->dec, GST_CLOCK_TIME_NONE);
+ }
+
+ /* 1) Flush the ports */
+ GST_DEBUG_OBJECT (self, "flushing ports");
+ gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
+ gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
+
+ /* 2) Wait until the srcpad loop is stopped,
+ * unlock GST_AUDIO_DECODER_STREAM_LOCK to prevent deadlocks
+ * caused by using this lock from inside the loop function */
+ GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+ gst_pad_stop_task (GST_AUDIO_DECODER_SRC_PAD (decoder));
+ GST_DEBUG_OBJECT (self, "Flushing -- task stopped");
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+
+ /* 3) Resume components */
+ gst_omx_component_set_state (self->dec, OMX_StateExecuting);
+ gst_omx_component_get_state (self->dec, GST_CLOCK_TIME_NONE);
+
+ /* 4) Unset flushing to allow ports to accept data again */
+ gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, FALSE);
+ gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, FALSE);
+
+ err = gst_omx_port_populate (self->dec_out_port);
+
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self, "Failed to populate output port: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ }
+
+ /* Reset our state */
+ gst_adapter_flush (self->output_adapter,
+ gst_adapter_available (self->output_adapter));
+ self->last_upstream_ts = 0;
+ self->downstream_flow_ret = GST_FLOW_OK;
+ self->started = FALSE;
+ GST_DEBUG_OBJECT (self, "Flush finished");
+}
+
+static GstFlowReturn
+gst_omx_audio_dec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf)
+{
+ GstOMXAcquireBufferReturn acq_ret = GST_OMX_ACQUIRE_BUFFER_ERROR;
+ GstOMXAudioDec *self;
+ GstOMXPort *port;
+ GstOMXBuffer *buf;
+ GstBuffer *codec_data = NULL;
+ guint offset = 0;
+ GstClockTime timestamp, duration;
+ OMX_ERRORTYPE err;
+ GstMapInfo minfo;
+
+ self = GST_OMX_AUDIO_DEC (decoder);
+
+ GST_DEBUG_OBJECT (self, "Handling frame");
+
+ if (self->downstream_flow_ret != GST_FLOW_OK) {
+ return self->downstream_flow_ret;
+ }
+
+ if (!self->started) {
+ GST_DEBUG_OBJECT (self, "Starting task");
+ gst_pad_start_task (GST_AUDIO_DECODER_SRC_PAD (self),
+ (GstTaskFunction) gst_omx_audio_dec_loop, decoder, NULL);
+ }
+
+ if (inbuf == NULL)
+ return gst_omx_audio_dec_drain (self);
+
+ /* Make sure to keep a reference to the input here,
+ * it can be unreffed from the other thread if
+ * finish_frame() is called */
+ gst_buffer_ref (inbuf);
+
+ timestamp = GST_BUFFER_TIMESTAMP (inbuf);
+ duration = GST_BUFFER_DURATION (inbuf);
+
+ port = self->dec_in_port;
+
+ gst_buffer_map (inbuf, &minfo, GST_MAP_READ);
+
+ while (offset < minfo.size) {
+ /* Make sure to release the base class stream lock, otherwise
+ * _loop() can't call _finish_frame() and we might block forever
+ * because no input buffers are released */
+ GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+ acq_ret = gst_omx_port_acquire_buffer (port, &buf, GST_OMX_WAIT);
+
+ if (acq_ret == GST_OMX_ACQUIRE_BUFFER_ERROR) {
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+ goto component_error;
+ } else if (acq_ret == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+ goto flushing;
+ } else if (acq_ret == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+ /* Reallocate all buffers */
+ err = gst_omx_port_set_enabled (port, FALSE);
+ if (err != OMX_ErrorNone) {
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_wait_buffers_released (port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_deallocate_buffers (port);
+ if (err != OMX_ErrorNone) {
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_wait_enabled (port, 1 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_set_enabled (port, TRUE);
+ if (err != OMX_ErrorNone) {
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_allocate_buffers (port);
+ if (err != OMX_ErrorNone) {
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_wait_enabled (port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_mark_reconfigured (port);
+ if (err != OMX_ErrorNone) {
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ /* Now get a new buffer and fill it */
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+ continue;
+ }
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+
+ g_assert (acq_ret == GST_OMX_ACQUIRE_BUFFER_OK && buf != NULL);
+
+ if (buf->omx_buf->nAllocLen - buf->omx_buf->nOffset <= 0) {
+ gst_omx_port_release_buffer (port, buf);
+ goto full_buffer;
+ }
+
+ if (self->downstream_flow_ret != GST_FLOW_OK) {
+ gst_omx_port_release_buffer (port, buf);
+ goto flow_error;
+ }
+
+ if (self->codec_data) {
+ GST_DEBUG_OBJECT (self, "Passing codec data to the component");
+
+ codec_data = self->codec_data;
+
+ if (buf->omx_buf->nAllocLen - buf->omx_buf->nOffset <
+ gst_buffer_get_size (codec_data)) {
+ gst_omx_port_release_buffer (port, buf);
+ goto too_large_codec_data;
+ }
+
+ buf->omx_buf->nFlags |= OMX_BUFFERFLAG_CODECCONFIG;
+ buf->omx_buf->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
+ buf->omx_buf->nFilledLen = gst_buffer_get_size (codec_data);
+ gst_buffer_extract (codec_data, 0,
+ buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+ buf->omx_buf->nFilledLen);
+
+ if (GST_CLOCK_TIME_IS_VALID (timestamp))
+ GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp,
+ gst_util_uint64_scale (timestamp, OMX_TICKS_PER_SECOND,
+ GST_SECOND));
+ else
+ GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp, G_GUINT64_CONSTANT (0));
+ buf->omx_buf->nTickCount = 0;
+
+ self->started = TRUE;
+ err = gst_omx_port_release_buffer (port, buf);
+ gst_buffer_replace (&self->codec_data, NULL);
+ if (err != OMX_ErrorNone)
+ goto release_error;
+ /* Acquire new buffer for the actual frame */
+ continue;
+ }
+
+ /* Now handle the frame */
+ GST_DEBUG_OBJECT (self, "Passing frame offset %d to the component", offset);
+
+ /* Copy the buffer content in chunks of size as requested
+ * by the port */
+ buf->omx_buf->nFilledLen =
+ MIN (minfo.size - offset,
+ buf->omx_buf->nAllocLen - buf->omx_buf->nOffset);
+ gst_buffer_extract (inbuf, offset,
+ buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+ buf->omx_buf->nFilledLen);
+
+ if (timestamp != GST_CLOCK_TIME_NONE) {
+ GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp,
+ gst_util_uint64_scale (timestamp, OMX_TICKS_PER_SECOND, GST_SECOND));
+ self->last_upstream_ts = timestamp;
+ } else {
+ GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp, G_GUINT64_CONSTANT (0));
+ }
+
+ if (duration != GST_CLOCK_TIME_NONE && offset == 0) {
+ buf->omx_buf->nTickCount =
+ gst_util_uint64_scale (duration, OMX_TICKS_PER_SECOND, GST_SECOND);
+ self->last_upstream_ts += duration;
+ } else {
+ buf->omx_buf->nTickCount = 0;
+ }
+
+ if (offset == 0)
+ buf->omx_buf->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
+
+ /* TODO: Set flags
+ * - OMX_BUFFERFLAG_DECODEONLY for buffers that are outside
+ * the segment
+ */
+
+ offset += buf->omx_buf->nFilledLen;
+
+ if (offset == minfo.size)
+ buf->omx_buf->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
+
+ self->started = TRUE;
+ err = gst_omx_port_release_buffer (port, buf);
+ if (err != OMX_ErrorNone)
+ goto release_error;
+ }
+ gst_buffer_unmap (inbuf, &minfo);
+ gst_buffer_unref (inbuf);
+
+ GST_DEBUG_OBJECT (self, "Passed frame to component");
+
+ return self->downstream_flow_ret;
+
+full_buffer:
+ {
+ gst_buffer_unmap (inbuf, &minfo);
+ gst_buffer_unref (inbuf);
+
+ GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+ ("Got OpenMAX buffer with no free space (%p, %u/%u)", buf,
+ (guint) buf->omx_buf->nOffset, (guint) buf->omx_buf->nAllocLen));
+ return GST_FLOW_ERROR;
+ }
+
+flow_error:
+ {
+ gst_buffer_unmap (inbuf, &minfo);
+ gst_buffer_unref (inbuf);
+
+ return self->downstream_flow_ret;
+ }
+
+too_large_codec_data:
+ {
+ gst_buffer_unmap (inbuf, &minfo);
+ gst_buffer_unref (inbuf);
+
+ GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL),
+ ("codec_data larger than supported by OpenMAX port "
+ "(%" G_GSIZE_FORMAT " > %u)", gst_buffer_get_size (codec_data),
+ (guint) self->dec_in_port->port_def.nBufferSize));
+ return GST_FLOW_ERROR;
+ }
+
+component_error:
+ {
+ gst_buffer_unmap (inbuf, &minfo);
+ gst_buffer_unref (inbuf);
+
+ GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+ ("OpenMAX component in error state %s (0x%08x)",
+ gst_omx_component_get_last_error_string (self->dec),
+ gst_omx_component_get_last_error (self->dec)));
+ return GST_FLOW_ERROR;
+ }
+
+flushing:
+ {
+ gst_buffer_unmap (inbuf, &minfo);
+ gst_buffer_unref (inbuf);
+
+ GST_DEBUG_OBJECT (self, "Flushing -- returning FLUSHING");
+ return GST_FLOW_FLUSHING;
+ }
+reconfigure_error:
+ {
+ gst_buffer_unmap (inbuf, &minfo);
+ gst_buffer_unref (inbuf);
+
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Unable to reconfigure input port"));
+ return GST_FLOW_ERROR;
+ }
+release_error:
+ {
+ gst_buffer_unmap (inbuf, &minfo);
+ gst_buffer_unref (inbuf);
+
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Failed to relase input buffer to component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err));
+
+ return GST_FLOW_ERROR;
+ }
+}
+
+static GstFlowReturn
+gst_omx_audio_dec_drain (GstOMXAudioDec * self)
+{
+ GstOMXAudioDecClass *klass;
+ GstOMXBuffer *buf;
+ GstOMXAcquireBufferReturn acq_ret;
+ OMX_ERRORTYPE err;
+
+ GST_DEBUG_OBJECT (self, "Draining component");
+
+ klass = GST_OMX_AUDIO_DEC_GET_CLASS (self);
+
+ if (!self->started) {
+ GST_DEBUG_OBJECT (self, "Component not started yet");
+ return GST_FLOW_OK;
+ }
+ self->started = FALSE;
+
+ if ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
+ GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
+ return GST_FLOW_OK;
+ }
+
+ /* Make sure to release the base class stream lock, otherwise
+ * _loop() can't call _finish_frame() and we might block forever
+ * because no input buffers are released */
+ GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+
+ /* Send an EOS buffer to the component and let the base
+ * class drop the EOS event. We will send it later when
+ * the EOS buffer arrives on the output port. */
+ acq_ret = gst_omx_port_acquire_buffer (self->dec_in_port, &buf, GST_OMX_WAIT);
+ if (acq_ret != GST_OMX_ACQUIRE_BUFFER_OK) {
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+ GST_ERROR_OBJECT (self, "Failed to acquire buffer for draining: %d",
+ acq_ret);
+ return GST_FLOW_ERROR;
+ }
+
+ g_mutex_lock (&self->drain_lock);
+ self->draining = TRUE;
+ buf->omx_buf->nFilledLen = 0;
+ GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp,
+ gst_util_uint64_scale (self->last_upstream_ts, OMX_TICKS_PER_SECOND,
+ GST_SECOND));
+ buf->omx_buf->nTickCount = 0;
+ buf->omx_buf->nFlags |= OMX_BUFFERFLAG_EOS;
+ err = gst_omx_port_release_buffer (self->dec_in_port, buf);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to drain component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ g_mutex_unlock (&self->drain_lock);
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+ return GST_FLOW_ERROR;
+ }
+
+ GST_DEBUG_OBJECT (self, "Waiting until component is drained");
+
+ if (G_UNLIKELY (self->dec->hacks & GST_OMX_HACK_DRAIN_MAY_NOT_RETURN)) {
+ gint64 wait_until = g_get_monotonic_time () + G_TIME_SPAN_SECOND / 2;
+
+ if (!g_cond_wait_until (&self->drain_cond, &self->drain_lock, wait_until))
+ GST_WARNING_OBJECT (self, "Drain timed out");
+ else
+ GST_DEBUG_OBJECT (self, "Drained component");
+
+ } else {
+ g_cond_wait (&self->drain_cond, &self->drain_lock);
+ GST_DEBUG_OBJECT (self, "Drained component");
+ }
+
+ g_mutex_unlock (&self->drain_lock);
+ GST_AUDIO_DECODER_STREAM_LOCK (self);
+
+ gst_adapter_flush (self->output_adapter,
+ gst_adapter_available (self->output_adapter));
+ self->started = FALSE;
+
+ return GST_FLOW_OK;
+}
diff --git a/subprojects/gst-omx/omx/gstomxaudiodec.h b/subprojects/gst-omx/omx/gstomxaudiodec.h
new file mode 100644
index 0000000000..0f4adc693e
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxaudiodec.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_AUDIO_DEC_H__
+#define __GST_OMX_AUDIO_DEC_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiodecoder.h>
+
+#include "gstomx.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_AUDIO_DEC \
+ (gst_omx_audio_dec_get_type())
+#define GST_OMX_AUDIO_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_AUDIO_DEC,GstOMXAudioDec))
+#define GST_OMX_AUDIO_DEC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_AUDIO_DEC,GstOMXAudioDecClass))
+#define GST_OMX_AUDIO_DEC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_AUDIO_DEC,GstOMXAudioDecClass))
+#define GST_IS_OMX_AUDIO_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_AUDIO_DEC))
+#define GST_IS_OMX_AUDIO_DEC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_AUDIO_DEC))
+
+typedef struct _GstOMXAudioDec GstOMXAudioDec;
+typedef struct _GstOMXAudioDecClass GstOMXAudioDecClass;
+
+struct _GstOMXAudioDec
+{
+ GstAudioDecoder parent;
+
+ /* < protected > */
+ GstOMXComponent *dec;
+ GstOMXPort *dec_in_port, *dec_out_port;
+
+ GstBufferPool *in_port_pool, *out_port_pool;
+
+ /* < private > */
+ GstAudioInfo info;
+ GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS];
+ gint reorder_map[OMX_AUDIO_MAXCHANNELS];
+ gboolean needs_reorder;
+ GstBuffer *codec_data;
+ /* TRUE if the component is configured and saw
+ * the first buffer */
+ gboolean started;
+
+ GstClockTime last_upstream_ts;
+
+ /* Draining state */
+ GMutex drain_lock;
+ GCond drain_cond;
+ /* TRUE if EOS buffers shouldn't be forwarded */
+ gboolean draining;
+
+ GstAdapter *output_adapter;
+
+ GstFlowReturn downstream_flow_ret;
+};
+
+struct _GstOMXAudioDecClass
+{
+ GstAudioDecoderClass parent_class;
+
+ GstOMXClassData cdata;
+
+ gboolean (*is_format_change) (GstOMXAudioDec * self, GstOMXPort * port, GstCaps * caps);
+ gboolean (*set_format) (GstOMXAudioDec * self, GstOMXPort * port, GstCaps * caps);
+ gint (*get_samples_per_frame) (GstOMXAudioDec * self, GstOMXPort * port);
+ gboolean (*get_channel_positions) (GstOMXAudioDec * self, GstOMXPort * port, GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS]);
+};
+
+GType gst_omx_audio_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_AUDIO_DEC_H__ */
diff --git a/subprojects/gst-omx/omx/gstomxaudioenc.c b/subprojects/gst-omx/omx/gstomxaudioenc.c
new file mode 100644
index 0000000000..c5c1d6fffd
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxaudioenc.c
@@ -0,0 +1,1181 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <string.h>
+
+#include "gstomxaudioenc.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_audio_enc_debug_category);
+#define GST_CAT_DEFAULT gst_omx_audio_enc_debug_category
+
+/* prototypes */
+static void gst_omx_audio_enc_finalize (GObject * object);
+
+static GstStateChangeReturn
+gst_omx_audio_enc_change_state (GstElement * element,
+ GstStateChange transition);
+
+static gboolean gst_omx_audio_enc_open (GstAudioEncoder * encoder);
+static gboolean gst_omx_audio_enc_close (GstAudioEncoder * encoder);
+static gboolean gst_omx_audio_enc_start (GstAudioEncoder * encoder);
+static gboolean gst_omx_audio_enc_stop (GstAudioEncoder * encoder);
+static gboolean gst_omx_audio_enc_set_format (GstAudioEncoder * encoder,
+ GstAudioInfo * info);
+static GstFlowReturn gst_omx_audio_enc_handle_frame (GstAudioEncoder *
+ encoder, GstBuffer * buffer);
+static void gst_omx_audio_enc_flush (GstAudioEncoder * encoder);
+
+static GstFlowReturn gst_omx_audio_enc_drain (GstOMXAudioEnc * self);
+
+enum
+{
+ PROP_0
+};
+
+/* class initialization */
+#define do_init \
+{ \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_audio_enc_debug_category, "omxaudioenc", 0, \
+ "debug category for gst-omx audio encoder base class"); \
+ G_IMPLEMENT_INTERFACE (GST_TYPE_PRESET, NULL); \
+}
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstOMXAudioEnc, gst_omx_audio_enc,
+ GST_TYPE_AUDIO_ENCODER, do_init);
+
+static void
+gst_omx_audio_enc_class_init (GstOMXAudioEncClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstAudioEncoderClass *audio_encoder_class = GST_AUDIO_ENCODER_CLASS (klass);
+
+ gobject_class->finalize = gst_omx_audio_enc_finalize;
+
+ element_class->change_state =
+ GST_DEBUG_FUNCPTR (gst_omx_audio_enc_change_state);
+
+ audio_encoder_class->open = GST_DEBUG_FUNCPTR (gst_omx_audio_enc_open);
+ audio_encoder_class->close = GST_DEBUG_FUNCPTR (gst_omx_audio_enc_close);
+ audio_encoder_class->start = GST_DEBUG_FUNCPTR (gst_omx_audio_enc_start);
+ audio_encoder_class->stop = GST_DEBUG_FUNCPTR (gst_omx_audio_enc_stop);
+ audio_encoder_class->flush = GST_DEBUG_FUNCPTR (gst_omx_audio_enc_flush);
+ audio_encoder_class->set_format =
+ GST_DEBUG_FUNCPTR (gst_omx_audio_enc_set_format);
+ audio_encoder_class->handle_frame =
+ GST_DEBUG_FUNCPTR (gst_omx_audio_enc_handle_frame);
+
+ klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
+ klass->cdata.default_sink_template_caps = "audio/x-raw, "
+ "rate = (int) [ 1, MAX ], "
+ "channels = (int) [ 1, " G_STRINGIFY (OMX_AUDIO_MAXCHANNELS) " ], "
+ "format = (string) { S8, U8, S16LE, S16BE, U16LE, U16BE, "
+ "S24LE, S24BE, U24LE, U24BE, S32LE, S32BE, U32LE, U32BE }";
+}
+
+static void
+gst_omx_audio_enc_init (GstOMXAudioEnc * self)
+{
+ g_mutex_init (&self->drain_lock);
+ g_cond_init (&self->drain_cond);
+}
+
+static gboolean
+gst_omx_audio_enc_open (GstAudioEncoder * encoder)
+{
+ GstOMXAudioEnc *self = GST_OMX_AUDIO_ENC (encoder);
+ GstOMXAudioEncClass *klass = GST_OMX_AUDIO_ENC_GET_CLASS (self);
+ gint in_port_index, out_port_index;
+
+ self->enc =
+ gst_omx_component_new (GST_OBJECT_CAST (self), klass->cdata.core_name,
+ klass->cdata.component_name, klass->cdata.component_role,
+ klass->cdata.hacks);
+ self->started = FALSE;
+
+ if (!self->enc)
+ return FALSE;
+
+ if (gst_omx_component_get_state (self->enc,
+ GST_CLOCK_TIME_NONE) != OMX_StateLoaded)
+ return FALSE;
+
+ in_port_index = klass->cdata.in_port_index;
+ out_port_index = klass->cdata.out_port_index;
+
+ if (in_port_index == -1 || out_port_index == -1) {
+ OMX_PORT_PARAM_TYPE param;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&param);
+
+ err =
+ gst_omx_component_get_parameter (self->enc, OMX_IndexParamAudioInit,
+ &param);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self, "Couldn't get port information: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ /* Fallback */
+ in_port_index = 0;
+ out_port_index = 1;
+ } else {
+ GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u",
+ (guint) param.nPorts, (guint) param.nStartPortNumber);
+ in_port_index = param.nStartPortNumber + 0;
+ out_port_index = param.nStartPortNumber + 1;
+ }
+ }
+
+ self->enc_in_port = gst_omx_component_add_port (self->enc, in_port_index);
+ self->enc_out_port = gst_omx_component_add_port (self->enc, out_port_index);
+
+ if (!self->enc_in_port || !self->enc_out_port)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+static gboolean
+gst_omx_audio_enc_shutdown (GstOMXAudioEnc * self)
+{
+ OMX_STATETYPE state;
+
+ GST_DEBUG_OBJECT (self, "Shutting down encoder");
+
+ state = gst_omx_component_get_state (self->enc, 0);
+ if (state > OMX_StateLoaded || state == OMX_StateInvalid) {
+ if (state > OMX_StateIdle) {
+ gst_omx_component_set_state (self->enc, OMX_StateIdle);
+ gst_omx_component_get_state (self->enc, 5 * GST_SECOND);
+ }
+ gst_omx_component_set_state (self->enc, OMX_StateLoaded);
+ gst_omx_port_deallocate_buffers (self->enc_in_port);
+ gst_omx_port_deallocate_buffers (self->enc_out_port);
+ if (state > OMX_StateLoaded)
+ gst_omx_component_get_state (self->enc, 5 * GST_SECOND);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_audio_enc_close (GstAudioEncoder * encoder)
+{
+ GstOMXAudioEnc *self = GST_OMX_AUDIO_ENC (encoder);
+
+ GST_DEBUG_OBJECT (self, "Closing encoder");
+
+ if (!gst_omx_audio_enc_shutdown (self))
+ return FALSE;
+
+ self->enc_in_port = NULL;
+ self->enc_out_port = NULL;
+ if (self->enc)
+ gst_omx_component_unref (self->enc);
+ self->enc = NULL;
+
+ return TRUE;
+}
+
+static void
+gst_omx_audio_enc_finalize (GObject * object)
+{
+ GstOMXAudioEnc *self = GST_OMX_AUDIO_ENC (object);
+
+ g_mutex_clear (&self->drain_lock);
+ g_cond_clear (&self->drain_cond);
+
+ G_OBJECT_CLASS (gst_omx_audio_enc_parent_class)->finalize (object);
+}
+
+static GstStateChangeReturn
+gst_omx_audio_enc_change_state (GstElement * element, GstStateChange transition)
+{
+ GstOMXAudioEnc *self;
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+
+ g_return_val_if_fail (GST_IS_OMX_AUDIO_ENC (element),
+ GST_STATE_CHANGE_FAILURE);
+ self = GST_OMX_AUDIO_ENC (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ break;
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ self->downstream_flow_ret = GST_FLOW_OK;
+
+ self->draining = FALSE;
+ self->started = FALSE;
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ if (self->enc_in_port)
+ gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, TRUE);
+ if (self->enc_out_port)
+ gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE);
+
+ g_mutex_lock (&self->drain_lock);
+ self->draining = FALSE;
+ g_cond_broadcast (&self->drain_cond);
+ g_mutex_unlock (&self->drain_lock);
+ break;
+ default:
+ break;
+ }
+
+ ret =
+ GST_ELEMENT_CLASS (gst_omx_audio_enc_parent_class)->change_state (element,
+ transition);
+
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ return ret;
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ self->downstream_flow_ret = GST_FLOW_FLUSHING;
+ self->started = FALSE;
+
+ if (!gst_omx_audio_enc_shutdown (self))
+ ret = GST_STATE_CHANGE_FAILURE;
+ break;
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static void
+gst_omx_audio_enc_loop (GstOMXAudioEnc * self)
+{
+ GstOMXAudioEncClass *klass;
+ GstOMXPort *port = self->enc_out_port;
+ GstOMXBuffer *buf = NULL;
+ GstFlowReturn flow_ret = GST_FLOW_OK;
+ GstOMXAcquireBufferReturn acq_return;
+ OMX_ERRORTYPE err;
+
+ klass = GST_OMX_AUDIO_ENC_GET_CLASS (self);
+
+ acq_return = gst_omx_port_acquire_buffer (port, &buf, GST_OMX_WAIT);
+ if (acq_return == GST_OMX_ACQUIRE_BUFFER_ERROR) {
+ goto component_error;
+ } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
+ goto flushing;
+ } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_EOS) {
+ goto eos;
+ }
+
+ if (!gst_pad_has_current_caps (GST_AUDIO_ENCODER_SRC_PAD (self))
+ || acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+ GstAudioInfo *info =
+ gst_audio_encoder_get_audio_info (GST_AUDIO_ENCODER (self));
+ GstCaps *caps;
+
+ GST_DEBUG_OBJECT (self, "Port settings have changed, updating caps");
+
+ /* Reallocate all buffers */
+ if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+ err = gst_omx_port_set_enabled (port, FALSE);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_wait_buffers_released (port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_deallocate_buffers (port);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_wait_enabled (port, 1 * GST_SECOND);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ }
+
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+
+ caps = klass->get_caps (self, self->enc_out_port, info);
+ if (!caps) {
+ if (buf)
+ gst_omx_port_release_buffer (self->enc_out_port, buf);
+ GST_AUDIO_ENCODER_STREAM_UNLOCK (self);
+ goto caps_failed;
+ }
+
+ GST_DEBUG_OBJECT (self, "Setting output caps: %" GST_PTR_FORMAT, caps);
+
+ if (!gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (self), caps)) {
+ gst_caps_unref (caps);
+ if (buf)
+ gst_omx_port_release_buffer (self->enc_out_port, buf);
+ GST_AUDIO_ENCODER_STREAM_UNLOCK (self);
+ goto caps_failed;
+ }
+ gst_caps_unref (caps);
+
+ GST_AUDIO_ENCODER_STREAM_UNLOCK (self);
+
+ if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+ err = gst_omx_port_set_enabled (port, TRUE);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_allocate_buffers (port);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_wait_enabled (port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_populate (port);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_mark_reconfigured (port);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+ }
+
+ /* Now get a buffer */
+ if (acq_return != GST_OMX_ACQUIRE_BUFFER_OK) {
+ return;
+ }
+ }
+
+ g_assert (acq_return == GST_OMX_ACQUIRE_BUFFER_OK);
+ if (!buf) {
+ g_assert ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER));
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+ goto eos;
+ }
+
+ GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %" G_GUINT64_FORMAT,
+ (guint) buf->omx_buf->nFlags,
+ (guint64) GST_OMX_GET_TICKS (buf->omx_buf->nTimeStamp));
+
+ /* This prevents a deadlock between the srcpad stream
+ * lock and the videocodec stream lock, if ::reset()
+ * is called at the wrong time
+ */
+ if (gst_omx_port_is_flushing (self->enc_out_port)) {
+ GST_DEBUG_OBJECT (self, "Flushing");
+ gst_omx_port_release_buffer (self->enc_out_port, buf);
+ goto flushing;
+ }
+
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+
+ if ((buf->omx_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG)
+ && buf->omx_buf->nFilledLen > 0) {
+ GstCaps *caps;
+ GstBuffer *codec_data;
+ GstMapInfo map = GST_MAP_INFO_INIT;
+
+ GST_DEBUG_OBJECT (self, "Handling codec data");
+ caps =
+ gst_caps_copy (gst_pad_get_current_caps (GST_AUDIO_ENCODER_SRC_PAD
+ (self)));
+ codec_data = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
+
+ gst_buffer_map (codec_data, &map, GST_MAP_WRITE);
+ memcpy (map.data,
+ buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+ buf->omx_buf->nFilledLen);
+ gst_buffer_unmap (codec_data, &map);
+
+ gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, codec_data, NULL);
+ if (!gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (self), caps)) {
+ gst_caps_unref (caps);
+ if (buf)
+ gst_omx_port_release_buffer (self->enc_out_port, buf);
+ GST_AUDIO_ENCODER_STREAM_UNLOCK (self);
+ goto caps_failed;
+ }
+ gst_caps_unref (caps);
+ flow_ret = GST_FLOW_OK;
+ } else if (buf->omx_buf->nFilledLen > 0) {
+ GstBuffer *outbuf;
+ guint n_samples;
+
+ GST_DEBUG_OBJECT (self, "Handling output data");
+
+ n_samples =
+ klass->get_num_samples (self, self->enc_out_port,
+ gst_audio_encoder_get_audio_info (GST_AUDIO_ENCODER (self)), buf);
+
+ if (buf->omx_buf->nFilledLen > 0) {
+ GstMapInfo map = GST_MAP_INFO_INIT;
+ outbuf = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
+
+ gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
+
+ memcpy (map.data,
+ buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+ buf->omx_buf->nFilledLen);
+ gst_buffer_unmap (outbuf, &map);
+
+ } else {
+ outbuf = gst_buffer_new ();
+ }
+
+ GST_BUFFER_TIMESTAMP (outbuf) =
+ gst_util_uint64_scale (GST_OMX_GET_TICKS (buf->omx_buf->nTimeStamp),
+ GST_SECOND, OMX_TICKS_PER_SECOND);
+ if (buf->omx_buf->nTickCount != 0)
+ GST_BUFFER_DURATION (outbuf) =
+ gst_util_uint64_scale (buf->omx_buf->nTickCount, GST_SECOND,
+ OMX_TICKS_PER_SECOND);
+
+ flow_ret =
+ gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (self),
+ outbuf, n_samples);
+ }
+
+ GST_DEBUG_OBJECT (self, "Handled output data");
+
+ GST_DEBUG_OBJECT (self, "Finished frame: %s", gst_flow_get_name (flow_ret));
+
+ err = gst_omx_port_release_buffer (port, buf);
+ if (err != OMX_ErrorNone)
+ goto release_error;
+
+ self->downstream_flow_ret = flow_ret;
+
+ if (flow_ret != GST_FLOW_OK)
+ goto flow_error;
+
+ GST_AUDIO_ENCODER_STREAM_UNLOCK (self);
+
+ return;
+
+component_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+ ("OpenMAX component in error state %s (0x%08x)",
+ gst_omx_component_get_last_error_string (self->enc),
+ gst_omx_component_get_last_error (self->enc)));
+ gst_pad_push_event (GST_AUDIO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
+ gst_pad_pause_task (GST_AUDIO_ENCODER_SRC_PAD (self));
+ self->downstream_flow_ret = GST_FLOW_ERROR;
+ self->started = FALSE;
+ return;
+ }
+flushing:
+ {
+ GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
+ g_mutex_lock (&self->drain_lock);
+ if (self->draining) {
+ self->draining = FALSE;
+ g_cond_broadcast (&self->drain_cond);
+ }
+ gst_pad_pause_task (GST_AUDIO_ENCODER_SRC_PAD (self));
+ self->downstream_flow_ret = GST_FLOW_FLUSHING;
+ self->started = FALSE;
+ g_mutex_unlock (&self->drain_lock);
+ return;
+ }
+eos:
+ {
+ g_mutex_lock (&self->drain_lock);
+ if (self->draining) {
+ GST_DEBUG_OBJECT (self, "Drained");
+ self->draining = FALSE;
+ g_cond_broadcast (&self->drain_cond);
+ flow_ret = GST_FLOW_OK;
+ gst_pad_pause_task (GST_AUDIO_ENCODER_SRC_PAD (self));
+ } else {
+ GST_DEBUG_OBJECT (self, "Component signalled EOS");
+ flow_ret = GST_FLOW_EOS;
+ }
+ g_mutex_unlock (&self->drain_lock);
+
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+ self->downstream_flow_ret = flow_ret;
+
+ /* Here we fallback and pause the task for the EOS case */
+ if (flow_ret != GST_FLOW_OK)
+ goto flow_error;
+
+ GST_AUDIO_ENCODER_STREAM_UNLOCK (self);
+
+ return;
+ }
+flow_error:
+ {
+ if (flow_ret == GST_FLOW_EOS) {
+ GST_DEBUG_OBJECT (self, "EOS");
+
+ gst_pad_push_event (GST_AUDIO_ENCODER_SRC_PAD (self),
+ gst_event_new_eos ());
+ gst_pad_pause_task (GST_AUDIO_ENCODER_SRC_PAD (self));
+ self->started = FALSE;
+ } else if (flow_ret < GST_FLOW_EOS) {
+ GST_ELEMENT_ERROR (self, STREAM, FAILED, ("Internal data stream error."),
+ ("stream stopped, reason %s", gst_flow_get_name (flow_ret)));
+
+ gst_pad_push_event (GST_AUDIO_ENCODER_SRC_PAD (self),
+ gst_event_new_eos ());
+ gst_pad_pause_task (GST_AUDIO_ENCODER_SRC_PAD (self));
+ self->started = FALSE;
+ } else if (flow_ret == GST_FLOW_FLUSHING) {
+ GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
+ g_mutex_lock (&self->drain_lock);
+ if (self->draining) {
+ self->draining = FALSE;
+ g_cond_broadcast (&self->drain_cond);
+ }
+ gst_pad_pause_task (GST_AUDIO_ENCODER_SRC_PAD (self));
+ self->started = FALSE;
+ g_mutex_unlock (&self->drain_lock);
+ }
+ GST_AUDIO_ENCODER_STREAM_UNLOCK (self);
+ return;
+ }
+reconfigure_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Unable to reconfigure output port"));
+ gst_pad_push_event (GST_AUDIO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
+ gst_pad_pause_task (GST_AUDIO_ENCODER_SRC_PAD (self));
+ self->downstream_flow_ret = GST_FLOW_NOT_NEGOTIATED;
+ self->started = FALSE;
+ return;
+ }
+caps_failed:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL), ("Failed to set caps"));
+ gst_pad_push_event (GST_AUDIO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
+ gst_pad_pause_task (GST_AUDIO_ENCODER_SRC_PAD (self));
+ self->downstream_flow_ret = GST_FLOW_NOT_NEGOTIATED;
+ self->started = FALSE;
+ return;
+ }
+release_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Failed to relase output buffer to component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err));
+ gst_pad_push_event (GST_AUDIO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
+ gst_pad_pause_task (GST_AUDIO_ENCODER_SRC_PAD (self));
+ self->downstream_flow_ret = GST_FLOW_ERROR;
+ self->started = FALSE;
+ GST_AUDIO_ENCODER_STREAM_UNLOCK (self);
+ return;
+ }
+}
+
+static gboolean
+gst_omx_audio_enc_start (GstAudioEncoder * encoder)
+{
+ GstOMXAudioEnc *self;
+
+ self = GST_OMX_AUDIO_ENC (encoder);
+
+ self->last_upstream_ts = 0;
+ self->downstream_flow_ret = GST_FLOW_OK;
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_audio_enc_stop (GstAudioEncoder * encoder)
+{
+ GstOMXAudioEnc *self;
+
+ self = GST_OMX_AUDIO_ENC (encoder);
+
+ GST_DEBUG_OBJECT (self, "Stopping encoder");
+
+ gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, TRUE);
+ gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE);
+
+ gst_pad_stop_task (GST_AUDIO_ENCODER_SRC_PAD (encoder));
+
+ if (gst_omx_component_get_state (self->enc, 0) > OMX_StateIdle)
+ gst_omx_component_set_state (self->enc, OMX_StateIdle);
+
+ self->downstream_flow_ret = GST_FLOW_FLUSHING;
+ self->started = FALSE;
+
+ g_mutex_lock (&self->drain_lock);
+ self->draining = FALSE;
+ g_cond_broadcast (&self->drain_cond);
+ g_mutex_unlock (&self->drain_lock);
+
+ gst_omx_component_get_state (self->enc, 5 * GST_SECOND);
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_audio_enc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
+{
+ GstOMXAudioEnc *self;
+ GstOMXAudioEncClass *klass;
+ gboolean needs_disable = FALSE;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ OMX_AUDIO_PARAM_PCMMODETYPE pcm_param;
+ gint i;
+ OMX_ERRORTYPE err;
+
+ self = GST_OMX_AUDIO_ENC (encoder);
+ klass = GST_OMX_AUDIO_ENC_GET_CLASS (encoder);
+
+ GST_DEBUG_OBJECT (self, "Setting new caps");
+
+ /* Set audio encoder base class properties */
+ gst_audio_encoder_set_frame_samples_min (encoder,
+ gst_util_uint64_scale_ceil (OMX_MIN_PCMPAYLOAD_MSEC,
+ GST_MSECOND * info->rate, GST_SECOND));
+ gst_audio_encoder_set_frame_samples_max (encoder, 0);
+
+ gst_omx_port_get_port_definition (self->enc_in_port, &port_def);
+
+ needs_disable =
+ gst_omx_component_get_state (self->enc,
+ GST_CLOCK_TIME_NONE) != OMX_StateLoaded;
+ /* If the component is not in Loaded state and a real format change happens
+ * we have to disable the port and re-allocate all buffers. If no real
+ * format change happened we can just exit here.
+ */
+ if (needs_disable) {
+ GST_DEBUG_OBJECT (self, "Need to disable and drain encoder");
+ gst_omx_audio_enc_drain (self);
+ gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE);
+
+ /* Wait until the srcpad loop is finished,
+ * unlock GST_AUDIO_ENCODER_STREAM_LOCK to prevent deadlocks
+ * caused by using this lock from inside the loop function */
+ GST_AUDIO_ENCODER_STREAM_UNLOCK (self);
+ gst_pad_stop_task (GST_AUDIO_ENCODER_SRC_PAD (encoder));
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+
+ if (klass->cdata.hacks & GST_OMX_HACK_NO_COMPONENT_RECONFIGURE) {
+ GST_AUDIO_ENCODER_STREAM_UNLOCK (self);
+ gst_omx_audio_enc_stop (GST_AUDIO_ENCODER (self));
+ gst_omx_audio_enc_close (GST_AUDIO_ENCODER (self));
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+
+ if (!gst_omx_audio_enc_open (GST_AUDIO_ENCODER (self)))
+ return FALSE;
+ needs_disable = FALSE;
+
+ /* The local port_def is now obsolete so get it again. */
+ gst_omx_port_get_port_definition (self->enc_in_port, &port_def);
+ } else {
+ /* Disabling at the same time input port and output port is only
+ * required when a buffer is shared between the ports. This cannot
+ * be the case for a encoder because its input and output buffers
+ * are of different nature. So let's disable ports sequencially.
+ * Starting from IL 1.2.0, this point has been clarified.
+ * OMX_SendCommand will return an error if the IL client attempts to
+ * call it when there is already an on-going command being processed.
+ * The exception is for buffer sharing above and the event
+ * OMX_EventPortNeedsDisable will be sent to request disabling the
+ * other port at the same time. */
+ if (gst_omx_port_set_enabled (self->enc_in_port, FALSE) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_wait_buffers_released (self->enc_in_port,
+ 5 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_deallocate_buffers (self->enc_in_port) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_wait_enabled (self->enc_in_port,
+ 1 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+
+ if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_wait_buffers_released (self->enc_out_port,
+ 1 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_deallocate_buffers (self->enc_out_port) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_wait_enabled (self->enc_out_port,
+ 1 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ }
+
+ GST_DEBUG_OBJECT (self, "Encoder drained and disabled");
+ }
+
+ port_def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+ GST_DEBUG_OBJECT (self, "Setting inport port definition");
+ if (gst_omx_port_update_port_definition (self->enc_in_port,
+ &port_def) != OMX_ErrorNone)
+ return FALSE;
+
+ GST_OMX_INIT_STRUCT (&pcm_param);
+ pcm_param.nPortIndex = self->enc_in_port->index;
+ pcm_param.nChannels = info->channels;
+ pcm_param.eNumData =
+ ((info->finfo->flags & GST_AUDIO_FORMAT_FLAG_SIGNED) ?
+ OMX_NumericalDataSigned : OMX_NumericalDataUnsigned);
+ pcm_param.eEndian =
+ ((info->finfo->endianness == G_LITTLE_ENDIAN) ?
+ OMX_EndianLittle : OMX_EndianBig);
+ pcm_param.bInterleaved = OMX_TRUE;
+ pcm_param.nBitPerSample = info->finfo->width;
+ pcm_param.nSamplingRate = info->rate;
+ pcm_param.ePCMMode = OMX_AUDIO_PCMModeLinear;
+
+ for (i = 0; i < pcm_param.nChannels; i++) {
+ OMX_AUDIO_CHANNELTYPE pos;
+
+ switch (info->position[i]) {
+ case GST_AUDIO_CHANNEL_POSITION_MONO:
+ case GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER:
+ pos = OMX_AUDIO_ChannelCF;
+ break;
+ case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT:
+ pos = OMX_AUDIO_ChannelLF;
+ break;
+ case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT:
+ pos = OMX_AUDIO_ChannelRF;
+ break;
+ case GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT:
+ pos = OMX_AUDIO_ChannelLS;
+ break;
+ case GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT:
+ pos = OMX_AUDIO_ChannelRS;
+ break;
+ case GST_AUDIO_CHANNEL_POSITION_LFE1:
+ pos = OMX_AUDIO_ChannelLFE;
+ break;
+ case GST_AUDIO_CHANNEL_POSITION_REAR_CENTER:
+ pos = OMX_AUDIO_ChannelCS;
+ break;
+ case GST_AUDIO_CHANNEL_POSITION_REAR_LEFT:
+ pos = OMX_AUDIO_ChannelLR;
+ break;
+ case GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT:
+ pos = OMX_AUDIO_ChannelRR;
+ break;
+ default:
+ pos = OMX_AUDIO_ChannelNone;
+ break;
+ }
+ pcm_param.eChannelMapping[i] = pos;
+ }
+
+ GST_DEBUG_OBJECT (self, "Setting PCM parameters");
+ err =
+ gst_omx_component_set_parameter (self->enc, OMX_IndexParamAudioPcm,
+ &pcm_param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to set PCM parameters: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ if (klass->set_format) {
+ if (!klass->set_format (self, self->enc_in_port, info)) {
+ GST_ERROR_OBJECT (self, "Subclass failed to set the new format");
+ return FALSE;
+ }
+ }
+
+ GST_DEBUG_OBJECT (self, "Updating outport port definition");
+ if (gst_omx_port_update_port_definition (self->enc_out_port,
+ NULL) != OMX_ErrorNone)
+ return FALSE;
+
+ GST_DEBUG_OBJECT (self, "Enabling component");
+ if (needs_disable) {
+ if (gst_omx_port_set_enabled (self->enc_in_port, TRUE) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
+ return FALSE;
+
+ if ((klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
+ if (gst_omx_port_set_enabled (self->enc_out_port, TRUE) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_allocate_buffers (self->enc_out_port) != OMX_ErrorNone)
+ return FALSE;
+
+ if (gst_omx_port_wait_enabled (self->enc_out_port,
+ 5 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ }
+
+ if (gst_omx_port_wait_enabled (self->enc_in_port,
+ 5 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_mark_reconfigured (self->enc_in_port) != OMX_ErrorNone)
+ return FALSE;
+ } else {
+ if (!(klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
+ /* Disable output port */
+ if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone)
+ return FALSE;
+
+ if (gst_omx_port_wait_enabled (self->enc_out_port,
+ 1 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+
+ if (gst_omx_component_set_state (self->enc,
+ OMX_StateIdle) != OMX_ErrorNone)
+ return FALSE;
+
+ /* Need to allocate buffers to reach Idle state */
+ if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
+ return FALSE;
+ } else {
+ if (gst_omx_component_set_state (self->enc,
+ OMX_StateIdle) != OMX_ErrorNone)
+ return FALSE;
+
+ /* Need to allocate buffers to reach Idle state */
+ if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_allocate_buffers (self->enc_out_port) != OMX_ErrorNone)
+ return FALSE;
+ }
+
+ if (gst_omx_component_get_state (self->enc,
+ GST_CLOCK_TIME_NONE) != OMX_StateIdle)
+ return FALSE;
+
+ if (gst_omx_component_set_state (self->enc,
+ OMX_StateExecuting) != OMX_ErrorNone)
+ return FALSE;
+
+ if (gst_omx_component_get_state (self->enc,
+ GST_CLOCK_TIME_NONE) != OMX_StateExecuting)
+ return FALSE;
+ }
+
+ /* Unset flushing to allow ports to accept data again */
+ gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, FALSE);
+ gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, FALSE);
+
+ if (gst_omx_component_get_last_error (self->enc) != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Component in error state: %s (0x%08x)",
+ gst_omx_component_get_last_error_string (self->enc),
+ gst_omx_component_get_last_error (self->enc));
+ return FALSE;
+ }
+
+ /* Start the srcpad loop again */
+ GST_DEBUG_OBJECT (self, "Starting task again");
+ self->downstream_flow_ret = GST_FLOW_OK;
+ gst_pad_start_task (GST_AUDIO_ENCODER_SRC_PAD (self),
+ (GstTaskFunction) gst_omx_audio_enc_loop, encoder, NULL);
+
+ return TRUE;
+}
+
+static void
+gst_omx_audio_enc_flush (GstAudioEncoder * encoder)
+{
+ GstOMXAudioEnc *self;
+
+ self = GST_OMX_AUDIO_ENC (encoder);
+
+ GST_DEBUG_OBJECT (self, "Resetting encoder");
+
+ gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, TRUE);
+ gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE);
+
+ /* Wait until the srcpad loop is finished */
+ GST_AUDIO_ENCODER_STREAM_UNLOCK (self);
+ GST_PAD_STREAM_LOCK (GST_AUDIO_ENCODER_SRC_PAD (self));
+ GST_PAD_STREAM_UNLOCK (GST_AUDIO_ENCODER_SRC_PAD (self));
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+
+ gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, FALSE);
+ gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, FALSE);
+ gst_omx_port_populate (self->enc_out_port);
+
+ /* Start the srcpad loop again */
+ self->last_upstream_ts = 0;
+ self->downstream_flow_ret = GST_FLOW_OK;
+ self->started = FALSE;
+ gst_pad_start_task (GST_AUDIO_ENCODER_SRC_PAD (self),
+ (GstTaskFunction) gst_omx_audio_enc_loop, encoder, NULL);
+}
+
+static GstFlowReturn
+gst_omx_audio_enc_handle_frame (GstAudioEncoder * encoder, GstBuffer * inbuf)
+{
+ GstOMXAcquireBufferReturn acq_ret = GST_OMX_ACQUIRE_BUFFER_ERROR;
+ GstOMXAudioEnc *self;
+ GstOMXPort *port;
+ GstOMXBuffer *buf;
+ gsize size;
+ guint offset = 0;
+ GstClockTime timestamp, duration, timestamp_offset = 0;
+ OMX_ERRORTYPE err;
+
+ self = GST_OMX_AUDIO_ENC (encoder);
+
+ if (self->downstream_flow_ret != GST_FLOW_OK) {
+ return self->downstream_flow_ret;
+ }
+
+ if (inbuf == NULL)
+ return gst_omx_audio_enc_drain (self);
+
+ GST_DEBUG_OBJECT (self, "Handling frame");
+
+ timestamp = GST_BUFFER_TIMESTAMP (inbuf);
+ duration = GST_BUFFER_DURATION (inbuf);
+
+ port = self->enc_in_port;
+
+ size = gst_buffer_get_size (inbuf);
+ while (offset < size) {
+ /* Make sure to release the base class stream lock, otherwise
+ * _loop() can't call _finish_frame() and we might block forever
+ * because no input buffers are released */
+ GST_AUDIO_ENCODER_STREAM_UNLOCK (self);
+ acq_ret = gst_omx_port_acquire_buffer (port, &buf, GST_OMX_WAIT);
+
+ if (acq_ret == GST_OMX_ACQUIRE_BUFFER_ERROR) {
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+ goto component_error;
+ } else if (acq_ret == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+ goto flushing;
+ } else if (acq_ret == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+ /* Reallocate all buffers */
+ err = gst_omx_port_set_enabled (port, FALSE);
+ if (err != OMX_ErrorNone) {
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_wait_buffers_released (port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_deallocate_buffers (port);
+ if (err != OMX_ErrorNone) {
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_wait_enabled (port, 1 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_set_enabled (port, TRUE);
+ if (err != OMX_ErrorNone) {
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_allocate_buffers (port);
+ if (err != OMX_ErrorNone) {
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_wait_enabled (port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_mark_reconfigured (port);
+ if (err != OMX_ErrorNone) {
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ /* Now get a new buffer and fill it */
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+ continue;
+ }
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+
+ g_assert (acq_ret == GST_OMX_ACQUIRE_BUFFER_OK && buf != NULL);
+
+ if (self->downstream_flow_ret != GST_FLOW_OK) {
+ gst_omx_port_release_buffer (port, buf);
+ return self->downstream_flow_ret;
+ }
+
+ if (buf->omx_buf->nAllocLen - buf->omx_buf->nOffset <= 0) {
+ gst_omx_port_release_buffer (port, buf);
+ goto full_buffer;
+ }
+
+ GST_DEBUG_OBJECT (self, "Handling frame at offset %d", offset);
+
+ /* Copy the buffer content in chunks of size as requested
+ * by the port */
+ buf->omx_buf->nFilledLen =
+ MIN (size - offset, buf->omx_buf->nAllocLen - buf->omx_buf->nOffset);
+ gst_buffer_extract (inbuf, offset,
+ buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+ buf->omx_buf->nFilledLen);
+
+ /* Interpolate timestamps if we're passing the buffer
+ * in multiple chunks */
+ if (offset != 0 && duration != GST_CLOCK_TIME_NONE) {
+ timestamp_offset = gst_util_uint64_scale (offset, duration, size);
+ }
+
+ if (timestamp != GST_CLOCK_TIME_NONE) {
+ GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp,
+ gst_util_uint64_scale (timestamp + timestamp_offset,
+ OMX_TICKS_PER_SECOND, GST_SECOND));
+ self->last_upstream_ts = timestamp + timestamp_offset;
+ }
+ if (duration != GST_CLOCK_TIME_NONE) {
+ buf->omx_buf->nTickCount =
+ gst_util_uint64_scale (buf->omx_buf->nFilledLen, duration, size);
+ buf->omx_buf->nTickCount =
+ gst_util_uint64_scale (buf->omx_buf->nTickCount,
+ OMX_TICKS_PER_SECOND, GST_SECOND);
+ self->last_upstream_ts += duration;
+ }
+
+ offset += buf->omx_buf->nFilledLen;
+ self->started = TRUE;
+ err = gst_omx_port_release_buffer (port, buf);
+ if (err != OMX_ErrorNone)
+ goto release_error;
+ }
+
+ GST_DEBUG_OBJECT (self, "Passed frame to component");
+
+ return self->downstream_flow_ret;
+
+full_buffer:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+ ("Got OpenMAX buffer with no free space (%p, %u/%u)", buf,
+ (guint) buf->omx_buf->nOffset, (guint) buf->omx_buf->nAllocLen));
+ return GST_FLOW_ERROR;
+ }
+component_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+ ("OpenMAX component in error state %s (0x%08x)",
+ gst_omx_component_get_last_error_string (self->enc),
+ gst_omx_component_get_last_error (self->enc)));
+ return GST_FLOW_ERROR;
+ }
+
+flushing:
+ {
+ GST_DEBUG_OBJECT (self, "Flushing -- returning FLUSHING");
+ return GST_FLOW_FLUSHING;
+ }
+reconfigure_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Unable to reconfigure input port"));
+ return GST_FLOW_ERROR;
+ }
+release_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Failed to relase input buffer to component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err));
+ return GST_FLOW_ERROR;
+ }
+}
+
+static GstFlowReturn
+gst_omx_audio_enc_drain (GstOMXAudioEnc * self)
+{
+ GstOMXAudioEncClass *klass;
+ GstOMXBuffer *buf;
+ GstOMXAcquireBufferReturn acq_ret;
+ OMX_ERRORTYPE err;
+
+ GST_DEBUG_OBJECT (self, "Draining component");
+
+ klass = GST_OMX_AUDIO_ENC_GET_CLASS (self);
+
+ if (!self->started) {
+ GST_DEBUG_OBJECT (self, "Component not started yet");
+ return GST_FLOW_OK;
+ }
+ self->started = FALSE;
+
+ if ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
+ GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
+ return GST_FLOW_OK;
+ }
+
+ /* Make sure to release the base class stream lock, otherwise
+ * _loop() can't call _finish_frame() and we might block forever
+ * because no input buffers are released */
+ GST_AUDIO_ENCODER_STREAM_UNLOCK (self);
+
+ /* Send an EOS buffer to the component and let the base
+ * class drop the EOS event. We will send it later when
+ * the EOS buffer arrives on the output port. */
+ acq_ret = gst_omx_port_acquire_buffer (self->enc_in_port, &buf, GST_OMX_WAIT);
+ if (acq_ret != GST_OMX_ACQUIRE_BUFFER_OK) {
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+ GST_ERROR_OBJECT (self, "Failed to acquire buffer for draining: %d",
+ acq_ret);
+ return GST_FLOW_ERROR;
+ }
+
+ g_mutex_lock (&self->drain_lock);
+ self->draining = TRUE;
+ buf->omx_buf->nFilledLen = 0;
+ GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp,
+ gst_util_uint64_scale (self->last_upstream_ts, OMX_TICKS_PER_SECOND,
+ GST_SECOND));
+ buf->omx_buf->nTickCount = 0;
+ buf->omx_buf->nFlags |= OMX_BUFFERFLAG_EOS;
+ err = gst_omx_port_release_buffer (self->enc_in_port, buf);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to drain component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ g_mutex_unlock (&self->drain_lock);
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+ return GST_FLOW_ERROR;
+ }
+ GST_DEBUG_OBJECT (self, "Waiting until component is drained");
+ g_cond_wait (&self->drain_cond, &self->drain_lock);
+ GST_DEBUG_OBJECT (self, "Drained component");
+ g_mutex_unlock (&self->drain_lock);
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+
+ self->started = FALSE;
+
+ return GST_FLOW_OK;
+}
diff --git a/subprojects/gst-omx/omx/gstomxaudioenc.h b/subprojects/gst-omx/omx/gstomxaudioenc.h
new file mode 100644
index 0000000000..8fe5369cdf
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxaudioenc.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_AUDIO_ENC_H__
+#define __GST_OMX_AUDIO_ENC_H__
+
+#include <gst/gst.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudioencoder.h>
+
+#include "gstomx.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_AUDIO_ENC \
+ (gst_omx_audio_enc_get_type())
+#define GST_OMX_AUDIO_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_AUDIO_ENC,GstOMXAudioEnc))
+#define GST_OMX_AUDIO_ENC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_AUDIO_ENC,GstOMXAudioEncClass))
+#define GST_OMX_AUDIO_ENC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_AUDIO_ENC,GstOMXAudioEncClass))
+#define GST_IS_OMX_AUDIO_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_AUDIO_ENC))
+#define GST_IS_OMX_AUDIO_ENC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_AUDIO_ENC))
+
+typedef struct _GstOMXAudioEnc GstOMXAudioEnc;
+typedef struct _GstOMXAudioEncClass GstOMXAudioEncClass;
+
+struct _GstOMXAudioEnc
+{
+ GstAudioEncoder parent;
+
+ /* < protected > */
+ GstOMXComponent *enc;
+ GstOMXPort *enc_in_port, *enc_out_port;
+
+ /* < private > */
+ /* TRUE if the component is configured and saw
+ * the first buffer */
+ gboolean started;
+
+ GstClockTime last_upstream_ts;
+
+ /* Draining state */
+ GMutex drain_lock;
+ GCond drain_cond;
+ /* TRUE if EOS buffers shouldn't be forwarded */
+ gboolean draining;
+
+ GstFlowReturn downstream_flow_ret;
+};
+
+struct _GstOMXAudioEncClass
+{
+ GstAudioEncoderClass parent_class;
+
+ GstOMXClassData cdata;
+
+ gboolean (*set_format) (GstOMXAudioEnc * self, GstOMXPort * port, GstAudioInfo * info);
+ GstCaps *(*get_caps) (GstOMXAudioEnc * self, GstOMXPort * port, GstAudioInfo * info);
+ guint (*get_num_samples) (GstOMXAudioEnc * self, GstOMXPort * port, GstAudioInfo * info, GstOMXBuffer * buffer);
+};
+
+GType gst_omx_audio_enc_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_AUDIO_ENC_H__ */
diff --git a/subprojects/gst-omx/omx/gstomxaudiosink.c b/subprojects/gst-omx/omx/gstomxaudiosink.c
new file mode 100644
index 0000000000..d4e684f3b5
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxaudiosink.c
@@ -0,0 +1,1228 @@
+/*
+ * Copyright (C) 2014, Fluendo, S.A.
+ * Copyright (C) 2014, Metrological Media Innovations B.V.
+ * Author: Josep Torra <josep@fluendo.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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include <gst/gst.h>
+#include <gst/audio/audio.h>
+
+#include <math.h>
+
+#include "gstomxaudiosink.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_audio_sink_debug_category);
+#define GST_CAT_DEFAULT gst_omx_audio_sink_debug_category
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_audio_sink_debug_category, "omxaudiosink", \
+ 0, "debug category for gst-omx audio sink base class");
+
+#define DEFAULT_PROP_MUTE FALSE
+#define DEFAULT_PROP_VOLUME 1.0
+
+#define VOLUME_MAX_DOUBLE 10.0
+#define OUT_CHANNELS(num_channels) ((num_channels) > 4 ? 8: (num_channels) > 2 ? 4: (num_channels))
+
+enum
+{
+ PROP_0,
+ PROP_MUTE,
+ PROP_VOLUME
+};
+
+#define gst_omx_audio_sink_parent_class parent_class
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstOMXAudioSink, gst_omx_audio_sink,
+ GST_TYPE_AUDIO_SINK, G_IMPLEMENT_INTERFACE (GST_TYPE_STREAM_VOLUME, NULL);
+ DEBUG_INIT);
+
+#define transform_3_4(type) \
+static inline void \
+transform_3_4_##type (gpointer psrc, gpointer pdst, guint len) \
+{ \
+ g##type *src = (g##type *) psrc; \
+ g##type *dst = (g##type *) pdst; \
+ for (; len > 0; len--) { \
+ dst[0] = src[0]; \
+ dst[1] = src[1]; \
+ dst[2] = src[2]; \
+ dst[3] = 0; \
+ src += 3; \
+ dst += 4; \
+ } \
+}
+
+#define transform_5_8(type) \
+static inline void \
+transform_5_8_##type (gpointer psrc, gpointer pdst, guint len) \
+{ \
+ g##type *src = (g##type *) psrc; \
+ g##type *dst = (g##type *) pdst; \
+ for (; len > 0; len--) { \
+ dst[0] = src[0]; \
+ dst[1] = src[1]; \
+ dst[2] = src[2]; \
+ dst[3] = src[3]; \
+ dst[4] = src[4]; \
+ dst[5] = 0; \
+ dst[6] = 0; \
+ dst[7] = 0; \
+ src += 5; \
+ dst += 8; \
+ } \
+}
+
+#define transform_6_8(type) \
+static inline void \
+transform_6_8_##type (gpointer psrc, gpointer pdst, guint len) \
+{ \
+ g##type *src = (g##type *) psrc; \
+ g##type *dst = (g##type *) pdst; \
+ for (; len > 0; len--) { \
+ dst[0] = src[0]; \
+ dst[1] = src[1]; \
+ dst[2] = src[2]; \
+ dst[3] = src[3]; \
+ dst[4] = src[4]; \
+ dst[5] = src[5]; \
+ dst[6] = 0; \
+ dst[7] = 0; \
+ src += 6; \
+ dst += 8; \
+ } \
+}
+
+#define transform_7_8(type) \
+static inline void \
+transform_7_8_##type (gpointer psrc, gpointer pdst, guint len) \
+{ \
+ g##type *src = (g##type *) psrc; \
+ g##type *dst = (g##type *) pdst; \
+ for (; len > 0; len--) { \
+ dst[0] = src[0]; \
+ dst[1] = src[1]; \
+ dst[2] = src[2]; \
+ dst[3] = src[3]; \
+ dst[4] = src[4]; \
+ dst[5] = src[5]; \
+ dst[6] = src[6]; \
+ dst[7] = 0; \
+ src += 7; \
+ dst += 8; \
+ } \
+}
+
+transform_3_4 (int16);
+transform_5_8 (int16);
+transform_6_8 (int16);
+transform_7_8 (int16);
+
+transform_3_4 (int32);
+transform_5_8 (int32);
+transform_6_8 (int32);
+transform_7_8 (int32);
+
+static void inline
+transform (guint in_chan, guint width, gpointer psrc, gpointer pdst, guint len)
+{
+ guint out_chan = OUT_CHANNELS (in_chan);
+ if (width == 16) {
+ switch (out_chan) {
+ case 4:
+ if (in_chan == 3) {
+ transform_3_4_int16 (psrc, pdst, len);
+ } else {
+ g_assert (FALSE);
+ }
+ break;
+ case 8:
+ switch (in_chan) {
+ case 5:
+ transform_5_8_int16 (psrc, pdst, len);
+ break;
+ case 6:
+ transform_6_8_int16 (psrc, pdst, len);
+ break;
+ case 7:
+ transform_7_8_int16 (psrc, pdst, len);
+ break;
+ default:
+ g_assert (FALSE);
+ }
+ break;
+ default:
+ g_assert (FALSE);
+ }
+ } else if (width == 32) {
+ switch (out_chan) {
+ case 4:
+ if (in_chan == 3) {
+ transform_3_4_int32 (psrc, pdst, len);
+ } else {
+ g_assert (FALSE);
+ }
+ break;
+ case 8:
+ switch (in_chan) {
+ case 5:
+ transform_5_8_int32 (psrc, pdst, len);
+ break;
+ case 6:
+ transform_6_8_int32 (psrc, pdst, len);
+ break;
+ case 7:
+ transform_7_8_int32 (psrc, pdst, len);
+ break;
+ default:
+ g_assert (FALSE);
+ }
+ break;
+ default:
+ g_assert (FALSE);
+ }
+ } else {
+ g_assert (FALSE);
+ }
+}
+
+static void
+gst_omx_audio_sink_mute_set (GstOMXAudioSink * self, gboolean mute)
+{
+ if (self->comp) {
+ OMX_ERRORTYPE err;
+ OMX_AUDIO_CONFIG_MUTETYPE param;
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = self->in_port->index;
+ param.bMute = (mute ? OMX_TRUE : OMX_FALSE);
+ err = gst_omx_component_set_config (self->comp,
+ OMX_IndexConfigAudioMute, &param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to set mute to %d: %s (0x%08x)",
+ param.bMute, gst_omx_error_to_string (err), err);
+ }
+ }
+ self->mute = mute;
+}
+
+static void
+gst_omx_audio_sink_volume_set (GstOMXAudioSink * self, gdouble volume)
+{
+ if (self->comp) {
+ OMX_ERRORTYPE err;
+ OMX_AUDIO_CONFIG_VOLUMETYPE param;
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = self->in_port->index;
+ param.bLinear = OMX_TRUE;
+ param.sVolume.nValue = volume * 100;
+ err = gst_omx_component_set_config (self->comp,
+ OMX_IndexConfigAudioVolume, &param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to set volume to %d: %s (0x%08x)",
+ (gint) param.sVolume.nValue, gst_omx_error_to_string (err), err);
+ }
+ }
+ self->volume = volume;
+}
+
+static gboolean
+gst_omx_audio_sink_open (GstAudioSink * audiosink)
+{
+ GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (audiosink);
+ GstOMXAudioSinkClass *klass = GST_OMX_AUDIO_SINK_GET_CLASS (self);
+ gint port_index;
+ OMX_ERRORTYPE err;
+
+ GST_DEBUG_OBJECT (self, "Opening audio sink");
+
+ self->comp =
+ gst_omx_component_new (GST_OBJECT_CAST (self), klass->cdata.core_name,
+ klass->cdata.component_name, klass->cdata.component_role,
+ klass->cdata.hacks);
+
+ if (!self->comp)
+ return FALSE;
+
+ if (gst_omx_component_get_state (self->comp,
+ GST_CLOCK_TIME_NONE) != OMX_StateLoaded)
+ return FALSE;
+
+ port_index = klass->cdata.in_port_index;
+
+ if (port_index == -1) {
+ OMX_PORT_PARAM_TYPE param;
+
+ GST_OMX_INIT_STRUCT (&param);
+
+ err =
+ gst_omx_component_get_parameter (self->comp, OMX_IndexParamAudioInit,
+ &param);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self, "Couldn't get port information: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ /* Fallback */
+ port_index = 0;
+ } else {
+ GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u",
+ (guint) param.nPorts, (guint) param.nStartPortNumber);
+ port_index = param.nStartPortNumber + 0;
+ }
+ }
+ self->in_port = gst_omx_component_add_port (self->comp, port_index);
+
+ port_index = klass->cdata.out_port_index;
+
+ if (port_index == -1) {
+ OMX_PORT_PARAM_TYPE param;
+
+ GST_OMX_INIT_STRUCT (&param);
+
+ err =
+ gst_omx_component_get_parameter (self->comp, OMX_IndexParamAudioInit,
+ &param);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self, "Couldn't get port information: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ /* Fallback */
+ port_index = 0;
+ } else {
+ GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u",
+ (guint) param.nPorts, (guint) param.nStartPortNumber);
+ port_index = param.nStartPortNumber + 1;
+ }
+ }
+ self->out_port = gst_omx_component_add_port (self->comp, port_index);
+
+ if (!self->in_port || !self->out_port)
+ return FALSE;
+
+ err = gst_omx_port_set_enabled (self->in_port, FALSE);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to disable port: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ err = gst_omx_port_set_enabled (self->out_port, FALSE);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to disable port: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ GST_DEBUG_OBJECT (self, "Opened audio sink");
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_audio_sink_close (GstAudioSink * audiosink)
+{
+ GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (audiosink);
+ OMX_STATETYPE state;
+
+ GST_DEBUG_OBJECT (self, "Closing audio sink");
+
+ state = gst_omx_component_get_state (self->comp, 0);
+ if (state > OMX_StateLoaded || state == OMX_StateInvalid) {
+ if (state > OMX_StateIdle) {
+ gst_omx_component_set_state (self->comp, OMX_StateIdle);
+ gst_omx_component_get_state (self->comp, 5 * GST_SECOND);
+ }
+ gst_omx_component_set_state (self->comp, OMX_StateLoaded);
+ gst_omx_port_deallocate_buffers (self->in_port);
+ if (state > OMX_StateLoaded)
+ gst_omx_component_get_state (self->comp, 5 * GST_SECOND);
+ }
+
+ self->in_port = NULL;
+ self->out_port = NULL;
+ if (self->comp)
+ gst_omx_component_unref (self->comp);
+ self->comp = NULL;
+
+ GST_DEBUG_OBJECT (self, "Closed audio sink");
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_audio_sink_parse_spec (GstOMXAudioSink * self,
+ GstAudioRingBufferSpec * spec)
+{
+ self->iec61937 = FALSE;
+ self->endianness = GST_AUDIO_INFO_ENDIANNESS (&spec->info);
+ self->rate = GST_AUDIO_INFO_RATE (&spec->info);
+ self->channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
+ self->width = GST_AUDIO_INFO_WIDTH (&spec->info);
+ self->is_signed = GST_AUDIO_INFO_IS_SIGNED (&spec->info);
+ self->is_float = GST_AUDIO_INFO_IS_FLOAT (&spec->info);
+
+ switch (spec->type) {
+ case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW:
+ {
+ guint out_channels = OUT_CHANNELS (self->channels);
+
+ self->samples = spec->segsize / self->channels / (self->width >> 3);
+ if (self->channels == out_channels) {
+ self->buffer_size = spec->segsize;
+ } else {
+ self->buffer_size = (spec->segsize / self->channels) * out_channels;
+ }
+ break;
+ }
+ case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_AC3:
+ case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_EAC3:
+ case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_DTS:
+ case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG:
+ self->iec61937 = TRUE;
+ self->endianness = G_LITTLE_ENDIAN;
+ self->channels = 2;
+ self->width = 16;
+ self->is_signed = TRUE;
+ self->is_float = FALSE;
+ self->buffer_size = spec->segsize;
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static inline void
+channel_mapping (GstAudioRingBufferSpec * spec,
+ OMX_AUDIO_CHANNELTYPE * eChannelMapping)
+{
+ gint i, nchan = GST_AUDIO_INFO_CHANNELS (&spec->info);
+
+ for (i = 0; i < nchan; i++) {
+ OMX_AUDIO_CHANNELTYPE pos;
+
+ switch (GST_AUDIO_INFO_POSITION (&spec->info, i)) {
+ case GST_AUDIO_CHANNEL_POSITION_MONO:
+ case GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER:
+ pos = OMX_AUDIO_ChannelCF;
+ break;
+ case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT:
+ pos = OMX_AUDIO_ChannelLF;
+ break;
+ case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT:
+ pos = OMX_AUDIO_ChannelRF;
+ break;
+ case GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT:
+ pos = OMX_AUDIO_ChannelLS;
+ break;
+ case GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT:
+ pos = OMX_AUDIO_ChannelRS;
+ break;
+ case GST_AUDIO_CHANNEL_POSITION_LFE1:
+ pos = OMX_AUDIO_ChannelLFE;
+ break;
+ case GST_AUDIO_CHANNEL_POSITION_REAR_CENTER:
+ pos = OMX_AUDIO_ChannelCS;
+ break;
+ case GST_AUDIO_CHANNEL_POSITION_REAR_LEFT:
+ pos = OMX_AUDIO_ChannelLR;
+ break;
+ case GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT:
+ pos = OMX_AUDIO_ChannelRR;
+ break;
+ default:
+ pos = OMX_AUDIO_ChannelNone;
+ break;
+ }
+ eChannelMapping[i] = pos;
+ }
+}
+
+static inline const gchar *
+ch2str (OMX_AUDIO_CHANNELTYPE ch)
+{
+ switch (ch) {
+ case OMX_AUDIO_ChannelNone:
+ return "OMX_AUDIO_ChannelNone";
+ case OMX_AUDIO_ChannelLF:
+ return "OMX_AUDIO_ChannelLF";
+ case OMX_AUDIO_ChannelRF:
+ return "OMX_AUDIO_ChannelRF";
+ case OMX_AUDIO_ChannelCF:
+ return "OMX_AUDIO_ChannelCF";
+ case OMX_AUDIO_ChannelLS:
+ return "OMX_AUDIO_ChannelLS";
+ case OMX_AUDIO_ChannelRS:
+ return "OMX_AUDIO_ChannelRS";
+ case OMX_AUDIO_ChannelLFE:
+ return "OMX_AUDIO_ChannelLFE";
+ case OMX_AUDIO_ChannelCS:
+ return "OMX_AUDIO_ChannelCS";
+ case OMX_AUDIO_ChannelLR:
+ return "OMX_AUDIO_ChannelLR";
+ case OMX_AUDIO_ChannelRR:
+ return "OMX_AUDIO_ChannelRR";
+ default:
+ return "Invalid value";
+ }
+}
+
+static inline gboolean
+gst_omx_audio_sink_configure_pcm (GstOMXAudioSink * self,
+ GstAudioRingBufferSpec * spec)
+{
+ OMX_AUDIO_PARAM_PCMMODETYPE param;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = self->in_port->index;
+ param.nChannels = OUT_CHANNELS (self->channels);
+ param.eNumData =
+ (self->is_signed ? OMX_NumericalDataSigned : OMX_NumericalDataUnsigned);
+ param.eEndian =
+ ((self->endianness ==
+ G_LITTLE_ENDIAN) ? OMX_EndianLittle : OMX_EndianBig);
+ param.bInterleaved = OMX_TRUE;
+ param.nBitPerSample = self->width;
+ param.nSamplingRate = self->rate;
+
+ if (self->is_float) {
+ /* This is cherrypicked from xbmc but it doesn't seems to be valid on my RPI.
+ * https://github.com/xbmc/xbmc/blob/master/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp
+ */
+ param.ePCMMode = (OMX_AUDIO_PCMMODETYPE) 0x8000;
+ } else {
+ param.ePCMMode = OMX_AUDIO_PCMModeLinear;
+ }
+
+ if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW) {
+ channel_mapping (spec, &param.eChannelMapping[0]);
+ }
+
+ GST_DEBUG_OBJECT (self, "Setting PCM parameters");
+ GST_DEBUG_OBJECT (self, " nChannels: %u", (guint) param.nChannels);
+ GST_DEBUG_OBJECT (self, " eNumData: %s",
+ (param.eNumData == OMX_NumericalDataSigned ? "signed" : "unsigned"));
+ GST_DEBUG_OBJECT (self, " eEndian: %s",
+ (param.eEndian == OMX_EndianLittle ? "little endian" : "big endian"));
+ GST_DEBUG_OBJECT (self, " bInterleaved: %d", param.bInterleaved);
+ GST_DEBUG_OBJECT (self, " nBitPerSample: %u", (guint) param.nBitPerSample);
+ GST_DEBUG_OBJECT (self, " nSamplingRate: %u", (guint) param.nSamplingRate);
+ GST_DEBUG_OBJECT (self, " ePCMMode: %04x", param.ePCMMode);
+ GST_DEBUG_OBJECT (self, " eChannelMapping: {%s, %s, %s, %s, %s, %s, %s, %s}",
+ ch2str (param.eChannelMapping[0]), ch2str (param.eChannelMapping[1]),
+ ch2str (param.eChannelMapping[2]), ch2str (param.eChannelMapping[3]),
+ ch2str (param.eChannelMapping[4]), ch2str (param.eChannelMapping[5]),
+ ch2str (param.eChannelMapping[6]), ch2str (param.eChannelMapping[7]));
+
+ err =
+ gst_omx_component_set_parameter (self->comp, OMX_IndexParamAudioPcm,
+ &param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to set PCM parameters: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_audio_sink_prepare (GstAudioSink * audiosink,
+ GstAudioRingBufferSpec * spec)
+{
+ GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (audiosink);
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ OMX_ERRORTYPE err;
+
+ if (!gst_omx_audio_sink_parse_spec (self, spec))
+ goto spec_parse;
+
+ gst_omx_port_get_port_definition (self->in_port, &port_def);
+
+ port_def.nBufferSize = self->buffer_size;
+ /* Only allocate a min number of buffers for transfers from our ringbuffer to
+ * the hw ringbuffer as we want to keep our small */
+ port_def.nBufferCountActual = MAX (port_def.nBufferCountMin, 2);
+ port_def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+
+ GST_DEBUG_OBJECT (self, "Updating outport port definition");
+ GST_DEBUG_OBJECT (self, " nBufferSize: %u", (guint) port_def.nBufferSize);
+ GST_DEBUG_OBJECT (self, " nBufferCountActual: %u", (guint)
+ port_def.nBufferCountActual);
+ GST_DEBUG_OBJECT (self, " audio.eEncoding: 0x%08x",
+ port_def.format.audio.eEncoding);
+
+ err = gst_omx_port_update_port_definition (self->in_port, &port_def);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to configure port: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto configuration;
+ }
+
+ if (!gst_omx_audio_sink_configure_pcm (self, spec)) {
+ goto configuration;
+ }
+
+ err = gst_omx_component_set_state (self->comp, OMX_StateIdle);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to set state idle: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto activation;
+ }
+
+ err = gst_omx_port_set_flushing (self->in_port, 5 * GST_SECOND, FALSE);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to set port not flushing: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto activation;
+ }
+
+ err = gst_omx_port_set_enabled (self->in_port, TRUE);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to enable port: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto activation;
+ }
+
+ GST_DEBUG_OBJECT (self, "Allocate buffers");
+ err = gst_omx_port_allocate_buffers (self->in_port);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed on buffer allocation: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto activation;
+ }
+
+ err = gst_omx_port_wait_enabled (self->in_port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "port not enabled: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto activation;
+ }
+
+ err = gst_omx_port_mark_reconfigured (self->in_port);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Couln't mark port as reconfigured: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto activation;
+ }
+
+ err = gst_omx_component_set_state (self->comp, OMX_StatePause);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to set state paused: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto activation;
+ }
+
+ if (gst_omx_component_get_state (self->comp,
+ GST_CLOCK_TIME_NONE) != OMX_StatePause)
+ goto activation;
+
+ /* Configure some parameters */
+ GST_OBJECT_LOCK (self);
+ gst_omx_audio_sink_mute_set (self, self->mute);
+ gst_omx_audio_sink_volume_set (self, self->volume);
+ GST_OBJECT_UNLOCK (self);
+
+#if defined (USE_OMX_TARGET_RPI)
+ {
+ GstOMXAudioSinkClass *klass = GST_OMX_AUDIO_SINK_GET_CLASS (self);
+ OMX_ERRORTYPE err;
+ OMX_CONFIG_BRCMAUDIODESTINATIONTYPE param;
+
+ if (klass->destination
+ && strlen (klass->destination) < sizeof (param.sName)) {
+ GST_DEBUG_OBJECT (self, "Setting destination: %s", klass->destination);
+ GST_OMX_INIT_STRUCT (&param);
+ strcpy ((char *) param.sName, klass->destination);
+ err = gst_omx_component_set_config (self->comp,
+ OMX_IndexConfigBrcmAudioDestination, &param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to configuring destination: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto activation;
+ }
+ }
+ }
+#endif
+
+ return TRUE;
+
+ /* ERRORS */
+spec_parse:
+ {
+ GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS, (NULL),
+ ("Error parsing spec"));
+ return FALSE;
+ }
+
+configuration:
+ {
+ GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS, (NULL),
+ ("Configuration failed"));
+ return FALSE;
+ }
+activation:
+ {
+ GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS, (NULL),
+ ("Component activation failed"));
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_omx_audio_sink_unprepare (GstAudioSink * audiosink)
+{
+ GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (audiosink);
+ OMX_ERRORTYPE err;
+
+ if (gst_omx_component_get_state (self->comp, 0) == OMX_StateIdle)
+ return TRUE;
+
+ err = gst_omx_port_set_flushing (self->in_port, 5 * GST_SECOND, TRUE);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to set port flushing: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto failed;
+ }
+
+ err = gst_omx_component_set_state (self->comp, OMX_StateIdle);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to set state idle: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto failed;
+ }
+
+ err = gst_omx_port_set_enabled (self->in_port, FALSE);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to set port disabled: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto failed;
+ }
+
+ err = gst_omx_port_wait_buffers_released (self->in_port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ goto failed;
+ }
+
+ err = gst_omx_port_deallocate_buffers (self->in_port);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Couldn't deallocate buffers: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto failed;
+ }
+
+ err = gst_omx_port_wait_enabled (self->in_port, 1 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ goto failed;
+ }
+
+ gst_omx_component_get_state (self->comp, GST_CLOCK_TIME_NONE);
+
+ return TRUE;
+
+ /* ERRORS */
+failed:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+ ("OpenMAX component in error state %s (0x%08x)",
+ gst_omx_component_get_last_error_string (self->comp),
+ gst_omx_component_get_last_error (self->comp)));
+ return FALSE;
+ }
+}
+
+static GstOMXBuffer *
+gst_omx_audio_sink_acquire_buffer (GstOMXAudioSink * self)
+{
+ GstOMXAcquireBufferReturn acq_ret = GST_OMX_ACQUIRE_BUFFER_ERROR;
+ GstOMXPort *port = self->in_port;
+ OMX_ERRORTYPE err;
+ GstOMXBuffer *buf = NULL;
+
+ while (!buf) {
+ acq_ret = gst_omx_port_acquire_buffer (port, &buf, GST_OMX_WAIT);
+ if (acq_ret == GST_OMX_ACQUIRE_BUFFER_ERROR) {
+ goto component_error;
+ } else if (acq_ret == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
+ GST_DEBUG_OBJECT (self, "Flushing...");
+ goto flushing;
+ } else if (acq_ret == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+ GST_DEBUG_OBJECT (self, "Reconfigure...");
+ /* Reallocate all buffers */
+ err = gst_omx_port_set_enabled (port, FALSE);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to set port disabled: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_wait_buffers_released (port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_deallocate_buffers (port);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Couldn't deallocate buffers: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_wait_enabled (port, 1 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_set_enabled (port, TRUE);
+ if (err != OMX_ErrorNone) {
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_allocate_buffers (port);
+ if (err != OMX_ErrorNone) {
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_wait_enabled (port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_mark_reconfigured (port);
+ if (err != OMX_ErrorNone) {
+ goto reconfigure_error;
+ }
+ continue;
+ }
+ }
+
+ return buf;
+
+ /* ERRORS */
+component_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+ ("OpenMAX component in error state %s (0x%08x)",
+ gst_omx_component_get_last_error_string (self->comp),
+ gst_omx_component_get_last_error (self->comp)));
+ return NULL;
+ }
+reconfigure_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Unable to reconfigure input port"));
+ return NULL;
+ }
+flushing:
+ {
+ return NULL;
+ }
+}
+
+static gint
+gst_omx_audio_sink_write (GstAudioSink * audiosink, gpointer data, guint length)
+{
+ GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (audiosink);
+ GstOMXBuffer *buf;
+ OMX_ERRORTYPE err;
+
+ GST_LOG_OBJECT (self, "received audio samples buffer of %u bytes", length);
+
+ GST_OMX_AUDIO_SINK_LOCK (self);
+
+ if (!(buf = gst_omx_audio_sink_acquire_buffer (self))) {
+ goto beach;
+ }
+
+ if (buf->omx_buf->nAllocLen == length) {
+ memcpy (buf->omx_buf->pBuffer + buf->omx_buf->nOffset, data, length);
+ } else {
+ transform (self->channels, self->width, data,
+ buf->omx_buf->pBuffer + buf->omx_buf->nOffset, self->samples);
+ }
+ buf->omx_buf->nFilledLen = buf->omx_buf->nAllocLen;
+
+ err = gst_omx_port_release_buffer (self->in_port, buf);
+ if (err != OMX_ErrorNone)
+ goto release_error;
+
+beach:
+
+ GST_OMX_AUDIO_SINK_UNLOCK (self);
+
+ return length;
+
+ /* ERRORS */
+release_error:
+ {
+ GST_OMX_AUDIO_SINK_UNLOCK (self);
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Failed to relase input buffer to component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err));
+ return 0;
+ }
+}
+
+static guint
+gst_omx_audio_sink_delay (GstAudioSink * audiosink)
+{
+#if defined (USE_OMX_TARGET_RPI)
+ GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (audiosink);
+ OMX_PARAM_U32TYPE param;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = self->in_port->index;
+ param.nU32 = 0;
+ err = gst_omx_component_get_config (self->comp,
+ OMX_IndexConfigAudioRenderingLatency, &param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to get rendering latency: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ param.nU32 = 0;
+ }
+
+ GST_DEBUG_OBJECT (self, "reported delay %u samples", (guint) param.nU32);
+ return param.nU32;
+#else
+ return 0;
+#endif
+}
+
+static void
+gst_omx_audio_sink_reset (GstAudioSink * audiosink)
+{
+ GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (audiosink);
+ OMX_STATETYPE state;
+
+ GST_DEBUG_OBJECT (self, "Flushing sink");
+
+ gst_omx_port_set_flushing (self->in_port, 5 * GST_SECOND, TRUE);
+
+ GST_OMX_AUDIO_SINK_LOCK (self);
+ if ((state = gst_omx_component_get_state (self->comp, 0)) > OMX_StatePause) {
+ gst_omx_component_set_state (self->comp, OMX_StatePause);
+ gst_omx_component_get_state (self->comp, GST_CLOCK_TIME_NONE);
+ }
+
+ gst_omx_component_set_state (self->comp, state);
+ gst_omx_component_get_state (self->comp, GST_CLOCK_TIME_NONE);
+
+ gst_omx_port_set_flushing (self->in_port, 5 * GST_SECOND, FALSE);
+
+ GST_OMX_AUDIO_SINK_UNLOCK (self);
+}
+
+static GstBuffer *
+gst_omx_audio_sink_payload (GstAudioBaseSink * audiobasesink, GstBuffer * buf)
+{
+ GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (audiobasesink);
+
+ if (self->iec61937) {
+ GstBuffer *out;
+ gint framesize;
+ GstMapInfo iinfo, oinfo;
+ GstAudioRingBufferSpec *spec = &audiobasesink->ringbuffer->spec;
+
+ framesize = gst_audio_iec61937_frame_size (spec);
+ if (framesize <= 0)
+ return NULL;
+
+ out = gst_buffer_new_and_alloc (framesize);
+
+ gst_buffer_map (buf, &iinfo, GST_MAP_READ);
+ gst_buffer_map (out, &oinfo, GST_MAP_WRITE);
+
+ if (!gst_audio_iec61937_payload (iinfo.data, iinfo.size,
+ oinfo.data, oinfo.size, spec, G_BIG_ENDIAN)) {
+ gst_buffer_unref (out);
+ return NULL;
+ }
+
+ gst_buffer_unmap (buf, &iinfo);
+ gst_buffer_unmap (out, &oinfo);
+
+ gst_buffer_copy_into (out, buf, GST_BUFFER_COPY_METADATA, 0, -1);
+ return out;
+ }
+
+ return gst_buffer_ref (buf);
+}
+
+static gboolean
+gst_omx_audio_sink_accept_caps (GstOMXAudioSink * self, GstCaps * caps)
+{
+ GstPad *pad = GST_BASE_SINK (self)->sinkpad;
+ GstCaps *pad_caps;
+ GstStructure *st;
+ gboolean ret = FALSE;
+ GstAudioRingBufferSpec spec = { 0 };
+
+ pad_caps = gst_pad_query_caps (pad, caps);
+ if (!pad_caps || gst_caps_is_empty (pad_caps)) {
+ if (pad_caps)
+ gst_caps_unref (pad_caps);
+ ret = FALSE;
+ goto done;
+ }
+ gst_caps_unref (pad_caps);
+
+ /* If we've not got fixed caps, creating a stream might fail, so let's just
+ * return from here with default acceptcaps behaviour */
+ if (!gst_caps_is_fixed (caps))
+ goto done;
+
+ /* parse helper expects this set, so avoid nasty warning
+ * will be set properly later on anyway */
+ spec.latency_time = GST_SECOND;
+ if (!gst_audio_ring_buffer_parse_caps (&spec, caps))
+ goto done;
+
+ /* Make sure input is framed (one frame per buffer) and can be payloaded */
+ switch (spec.type) {
+ case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_AC3:
+ case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_EAC3:
+ case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_DTS:
+ case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG:
+ {
+ gboolean framed = FALSE, parsed = FALSE;
+ st = gst_caps_get_structure (caps, 0);
+
+ gst_structure_get_boolean (st, "framed", &framed);
+ gst_structure_get_boolean (st, "parsed", &parsed);
+ if ((!framed && !parsed) || gst_audio_iec61937_frame_size (&spec) <= 0)
+ goto done;
+ }
+ default:{
+ }
+ }
+ ret = TRUE;
+
+done:
+ gst_caps_replace (&spec.caps, NULL);
+ return ret;
+}
+
+static gboolean
+gst_omx_audio_sink_query (GstBaseSink * basesink, GstQuery * query)
+{
+ GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (basesink);
+ gboolean ret;
+
+ switch (GST_QUERY_TYPE (query)) {
+ case GST_QUERY_ACCEPT_CAPS:
+ {
+ GstCaps *caps;
+
+ gst_query_parse_accept_caps (query, &caps);
+ ret = gst_omx_audio_sink_accept_caps (self, caps);
+ gst_query_set_accept_caps_result (query, ret);
+ ret = TRUE;
+ break;
+ }
+ default:
+ ret = GST_BASE_SINK_CLASS (parent_class)->query (basesink, query);
+ break;
+ }
+ return ret;
+}
+
+static void
+gst_omx_audio_sink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (object);
+
+ switch (prop_id) {
+ case PROP_MUTE:
+ {
+ gboolean mute = g_value_get_boolean (value);
+ GST_OBJECT_LOCK (self);
+ if (self->mute != mute) {
+ gst_omx_audio_sink_mute_set (self, mute);
+ }
+ GST_OBJECT_UNLOCK (self);
+ break;
+ }
+ case PROP_VOLUME:
+ {
+ gdouble volume = g_value_get_double (value);
+ GST_OBJECT_LOCK (self);
+ if (volume != self->volume) {
+ gst_omx_audio_sink_volume_set (self, volume);
+ }
+ GST_OBJECT_UNLOCK (self);
+ break;
+ }
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_omx_audio_sink_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (object);
+
+ switch (prop_id) {
+ case PROP_MUTE:
+ GST_OBJECT_LOCK (self);
+ g_value_set_boolean (value, self->mute);
+ GST_OBJECT_UNLOCK (self);
+ break;
+ case PROP_VOLUME:
+ GST_OBJECT_LOCK (self);
+ g_value_set_double (value, self->volume);
+ GST_OBJECT_UNLOCK (self);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GstStateChangeReturn
+gst_omx_audio_sink_change_state (GstElement * element,
+ GstStateChange transition)
+{
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+ GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (element);
+ OMX_ERRORTYPE err;
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ {
+ GST_DEBUG_OBJECT (self, "going to PLAYING state");
+ err = gst_omx_component_set_state (self->comp, OMX_StateExecuting);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to set state executing: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return GST_STATE_CHANGE_FAILURE;
+ }
+
+ if (gst_omx_component_get_state (self->comp,
+ GST_CLOCK_TIME_NONE) != OMX_StateExecuting) {
+ return GST_STATE_CHANGE_FAILURE;
+ }
+ GST_DEBUG_OBJECT (self, "in PLAYING state");
+ break;
+ }
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ {
+ GST_DEBUG_OBJECT (self, "going to PAUSED state");
+ err = gst_omx_component_set_state (self->comp, OMX_StatePause);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to set state paused: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return GST_STATE_CHANGE_FAILURE;
+ }
+
+ if (gst_omx_component_get_state (self->comp,
+ GST_CLOCK_TIME_NONE) != OMX_StatePause) {
+ return GST_STATE_CHANGE_FAILURE;
+ }
+ GST_DEBUG_OBJECT (self, "in PAUSED state");
+ break;
+ }
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static void
+gst_omx_audio_sink_finalize (GObject * object)
+{
+ GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (object);
+
+ g_mutex_clear (&self->lock);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_omx_audio_sink_class_init (GstOMXAudioSinkClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstBaseSinkClass *basesink_class = GST_BASE_SINK_CLASS (klass);
+ GstAudioBaseSinkClass *baudiosink_class = GST_AUDIO_BASE_SINK_CLASS (klass);
+ GstAudioSinkClass *audiosink_class = GST_AUDIO_SINK_CLASS (klass);
+
+ gobject_class->set_property = gst_omx_audio_sink_set_property;
+ gobject_class->get_property = gst_omx_audio_sink_get_property;
+ gobject_class->finalize = gst_omx_audio_sink_finalize;
+
+ g_object_class_install_property (gobject_class, PROP_MUTE,
+ g_param_spec_boolean ("mute", "Mute", "mute channel",
+ DEFAULT_PROP_MUTE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_VOLUME,
+ g_param_spec_double ("volume", "Volume", "volume factor, 1.0=100%",
+ 0.0, VOLUME_MAX_DOUBLE, DEFAULT_PROP_VOLUME,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ element_class->change_state =
+ GST_DEBUG_FUNCPTR (gst_omx_audio_sink_change_state);
+
+ basesink_class->query = GST_DEBUG_FUNCPTR (gst_omx_audio_sink_query);
+
+ baudiosink_class->payload = GST_DEBUG_FUNCPTR (gst_omx_audio_sink_payload);
+
+ audiosink_class->open = GST_DEBUG_FUNCPTR (gst_omx_audio_sink_open);
+ audiosink_class->close = GST_DEBUG_FUNCPTR (gst_omx_audio_sink_close);
+ audiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_omx_audio_sink_prepare);
+ audiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_omx_audio_sink_unprepare);
+ audiosink_class->write = GST_DEBUG_FUNCPTR (gst_omx_audio_sink_write);
+ audiosink_class->delay = GST_DEBUG_FUNCPTR (gst_omx_audio_sink_delay);
+ audiosink_class->reset = GST_DEBUG_FUNCPTR (gst_omx_audio_sink_reset);
+
+
+ klass->cdata.type = GST_OMX_COMPONENT_TYPE_SINK;
+}
+
+static void
+gst_omx_audio_sink_init (GstOMXAudioSink * self)
+{
+ g_mutex_init (&self->lock);
+
+ self->mute = DEFAULT_PROP_MUTE;
+ self->volume = DEFAULT_PROP_VOLUME;
+
+ /* For the Raspberry PI there's a big hw buffer and 400 ms seems a good
+ * size for our ringbuffer. OpenSL ES Sink also allocates a buffer of 400 ms
+ * in Android so I guess that this should be a sane value for OpenMax in
+ * general. */
+ GST_AUDIO_BASE_SINK (self)->buffer_time = 400000;
+ gst_audio_base_sink_set_provide_clock (GST_AUDIO_BASE_SINK (self), TRUE);
+}
diff --git a/subprojects/gst-omx/omx/gstomxaudiosink.h b/subprojects/gst-omx/omx/gstomxaudiosink.h
new file mode 100644
index 0000000000..481b18a513
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxaudiosink.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2014, Fluendo, S.A.
+ * Copyright (C) 2014, Metrological Media Innovations B.V.
+ * Author: Josep Torra <josep@fluendo.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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_AUDIO_SINK_H__
+#define __GST_OMX_AUDIO_SINK_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/audio/audio.h>
+
+#include "gstomx.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_AUDIO_SINK \
+ (gst_omx_audio_sink_get_type())
+#define GST_OMX_AUDIO_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_AUDIO_SINK,GstOMXAudioSink))
+#define GST_OMX_AUDIO_SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_AUDIO_SINK,GstOMXAudioSinkClass))
+#define GST_OMX_AUDIO_SINK_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_AUDIO_SINK,GstOMXAudioSinkClass))
+#define GST_IS_OMX_AUDIO_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_AUDIO_SINK))
+#define GST_IS_OMX_AUDIO_SINK_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_AUDIO_SINK))
+#define GST_OMX_AUDIO_SINK_CAST(obj) ((GstOMXAudioSink *) (obj))
+
+#define GST_OMX_AUDIO_SINK_GET_LOCK(obj) (&GST_OMX_AUDIO_SINK_CAST (obj)->lock)
+#define GST_OMX_AUDIO_SINK_LOCK(obj) (g_mutex_lock (GST_OMX_AUDIO_SINK_GET_LOCK (obj)))
+#define GST_OMX_AUDIO_SINK_UNLOCK(obj) (g_mutex_unlock (GST_OMX_AUDIO_SINK_GET_LOCK (obj)))
+
+#define PASSTHROUGH_CAPS \
+ "audio/x-ac3, framed = (boolean) true;" \
+ "audio/x-eac3, framed = (boolean) true; " \
+ "audio/x-dts, framed = (boolean) true, " \
+ "block-size = (int) { 512, 1024, 2048 }; " \
+ "audio/mpeg, mpegversion = (int) 1, " \
+ "mpegaudioversion = (int) [ 1, 2 ], parsed = (boolean) true;"
+
+typedef struct _GstOMXAudioSink GstOMXAudioSink;
+typedef struct _GstOMXAudioSinkClass GstOMXAudioSinkClass;
+
+struct _GstOMXAudioSink
+{
+ GstAudioSink parent;
+
+ /* < protected > */
+ GstOMXComponent *comp;
+ GstOMXPort *in_port, *out_port;
+
+ gboolean mute;
+ gdouble volume;
+
+ gboolean iec61937;
+ guint endianness;
+ guint rate;
+ guint channels;
+ guint width;
+ gboolean is_signed;
+ gboolean is_float;
+
+ guint buffer_size;
+ guint samples;
+
+ GMutex lock;
+};
+
+struct _GstOMXAudioSinkClass
+{
+ GstAudioSinkClass parent_class;
+
+ GstOMXClassData cdata;
+ const gchar * destination;
+};
+
+GType gst_omx_audio_sink_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_AUDIO_SINK_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxbufferpool.c b/subprojects/gst-omx/omx/gstomxbufferpool.c
new file mode 100644
index 0000000000..b88568524c
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxbufferpool.c
@@ -0,0 +1,674 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ * Copyright (C) 2013-2019, Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ * George Kiagiadakis <george.kiagiadakis@collabora.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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstomxbufferpool.h"
+#include "gstomxvideo.h"
+
+#include <gst/allocators/gstdmabuf.h>
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_buffer_pool_debug_category);
+#define GST_CAT_DEFAULT gst_omx_buffer_pool_debug_category
+
+enum
+{
+ SIG_ALLOCATE,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/* Buffer pool for the buffers of an OpenMAX port.
+ *
+ * This pool is only used if we either passed buffers from another
+ * pool to the OMX port or provide the OMX buffers directly to other
+ * elements.
+ *
+ * An output buffer is in the pool if it is currently owned by the port,
+ * i.e. after OMX_FillThisBuffer(). An output buffer is outside
+ * the pool after it was taken from the port after it was handled
+ * by the port, i.e. FillBufferDone.
+ *
+ * An input buffer is in the pool if it is currently available to be filled
+ * upstream. It will be put back into the pool when it has been processed by
+ * OMX, (EmptyBufferDone).
+ *
+ * Buffers can be allocated by us (OMX_AllocateBuffer()) or allocated
+ * by someone else and (temporarily) passed to this pool
+ * (OMX_UseBuffer(), OMX_UseEGLImage()). In the latter case the pool of
+ * the buffer will be overriden, and restored in free_buffer(). Other
+ * buffers are just freed there.
+ *
+ * The pool always has a fixed number of minimum and maximum buffers
+ * and these are allocated while starting the pool and released afterwards.
+ * They correspond 1:1 to the OMX buffers of the port, which are allocated
+ * before the pool is started.
+ *
+ * Acquiring an output buffer from this pool happens after the OMX buffer has
+ * been acquired from the port. gst_buffer_pool_acquire_buffer() is
+ * supposed to return the buffer that corresponds to the OMX buffer.
+ *
+ * For buffers provided to upstream, the buffer will be passed to
+ * the component manually when it arrives and then unreffed. If the
+ * buffer is released before reaching the component it will be just put
+ * back into the pool as if EmptyBufferDone has happened. If it was
+ * passed to the component, it will be back into the pool when it was
+ * released and EmptyBufferDone has happened.
+ *
+ * For buffers provided to downstream, the buffer will be returned
+ * back to the component (OMX_FillThisBuffer()) when it is released.
+ *
+ * This pool uses a special allocator object, GstOMXAllocator. The main purpose
+ * of this allocator is to track GstMemory objects in the same way that a
+ * GstBufferPool tracks buffers. When a buffer is inserted into this pool
+ * (either because it was just allocated or because it was released back to
+ * the pool), its memory is ripped off and is tracked separately by the
+ * allocator. When a buffer is then acquired, we acquire the corresponding
+ * GstMemory from the allocator and put it back in the buffer.
+ *
+ * This allocator mechanism allows us to track memory that has been shared
+ * with buffers that are not part of this pool. When a memory is shared, then
+ * its ref count is > 1, which means it will not be released to the allocator
+ * until the sub-memory is destroyed.
+ *
+ * When a memory returns to the allocator, the allocator fires the
+ * omxbuf-released signal, which is handled by the buffer pool to return the
+ * omx buffer to the port or the queue.
+ */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_buffer_pool_debug_category, "omxbufferpool", 0, \
+ "debug category for gst-omx buffer pool base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXBufferPool, gst_omx_buffer_pool,
+ GST_TYPE_BUFFER_POOL, DEBUG_INIT);
+
+static void gst_omx_buffer_pool_free_buffer (GstBufferPool * bpool,
+ GstBuffer * buffer);
+
+static gboolean
+gst_omx_buffer_pool_start (GstBufferPool * bpool)
+{
+ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
+ gboolean has_buffers;
+ GstStructure *config;
+ guint min, max;
+ GstOMXAllocatorForeignMemMode mode;
+
+ /* Only allow to start the pool if we still are attached
+ * to a component and port */
+ GST_OBJECT_LOCK (pool);
+ if (!pool->component || !pool->port) {
+ GST_OBJECT_UNLOCK (pool);
+ return FALSE;
+ }
+
+ pool->port->using_pool = TRUE;
+
+ has_buffers = (pool->port->buffers != NULL);
+ GST_OBJECT_UNLOCK (pool);
+
+ config = gst_buffer_pool_get_config (bpool);
+ gst_buffer_pool_config_get_params (config, NULL, NULL, &min, &max);
+ gst_structure_free (config);
+ if (max > min) {
+ GST_WARNING_OBJECT (bpool,
+ "max (%d) cannot be higher than min (%d) as pool cannot allocate buffers on the fly",
+ max, min);
+ return FALSE;
+ }
+
+ if (!has_buffers) {
+ gboolean result = FALSE;
+
+ GST_DEBUG_OBJECT (bpool, "Buffers not yet allocated on port %d of %s",
+ pool->port->index, pool->component->name);
+
+ g_signal_emit (pool, signals[SIG_ALLOCATE], 0, &result);
+
+ if (!result) {
+ GST_WARNING_OBJECT (bpool,
+ "Element failed to allocate buffers, can't start pool");
+ return FALSE;
+ }
+ }
+
+ g_assert (pool->port->buffers);
+
+ if (pool->other_pool)
+ /* Importing buffers from downstream, either normal or dmabuf ones */
+ mode = GST_OMX_ALLOCATOR_FOREIGN_MEM_OTHER_POOL;
+ else if (pool->output_mode == GST_OMX_BUFFER_MODE_DMABUF)
+ /* Exporting dmabuf */
+ mode = GST_OMX_ALLOCATOR_FOREIGN_MEM_DMABUF;
+ else
+ /* Exporting normal buffers */
+ mode = GST_OMX_ALLOCATOR_FOREIGN_MEM_NONE;
+
+ if (!gst_omx_allocator_configure (pool->allocator, min, mode))
+ return FALSE;
+
+ if (!gst_omx_allocator_set_active (pool->allocator, TRUE))
+ return FALSE;
+
+ return
+ GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->start (bpool);
+}
+
+static gboolean
+gst_omx_buffer_pool_stop (GstBufferPool * bpool)
+{
+ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
+
+ /* Remove any buffers that are there */
+ g_ptr_array_set_size (pool->buffers, 0);
+
+ GST_DEBUG_OBJECT (pool, "deactivating OMX allocator");
+ gst_omx_allocator_set_active (pool->allocator, FALSE);
+
+ /* ensure all memories have been deallocated;
+ * this may take a while if some memories are being shared
+ * and therefore are in use somewhere else in the pipeline */
+ gst_omx_allocator_wait_inactive (pool->allocator);
+
+ GST_DEBUG_OBJECT (pool, "deallocate OMX buffers");
+ gst_omx_port_deallocate_buffers (pool->port);
+
+ if (pool->caps)
+ gst_caps_unref (pool->caps);
+ pool->caps = NULL;
+
+ pool->add_videometa = FALSE;
+ pool->deactivated = TRUE;
+ pool->port->using_pool = TRUE;
+
+ return GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->stop (bpool);
+}
+
+static const gchar **
+gst_omx_buffer_pool_get_options (GstBufferPool * bpool)
+{
+ static const gchar *raw_video_options[] =
+ { GST_BUFFER_POOL_OPTION_VIDEO_META, NULL };
+ static const gchar *options[] = { NULL };
+ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
+
+ GST_OBJECT_LOCK (pool);
+ if (pool->port && pool->port->port_def.eDomain == OMX_PortDomainVideo
+ && pool->port->port_def.format.video.eCompressionFormat ==
+ OMX_VIDEO_CodingUnused) {
+ GST_OBJECT_UNLOCK (pool);
+ return raw_video_options;
+ }
+ GST_OBJECT_UNLOCK (pool);
+
+ return options;
+}
+
+static gboolean
+gst_omx_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
+{
+ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
+ GstCaps *caps;
+ guint size, min;
+ GstStructure *fake_config;
+ gboolean ret;
+
+ GST_OBJECT_LOCK (pool);
+
+ if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min, NULL))
+ goto wrong_config;
+
+ if (caps == NULL)
+ goto no_caps;
+
+ if (pool->port && pool->port->port_def.eDomain == OMX_PortDomainVideo
+ && pool->port->port_def.format.video.eCompressionFormat ==
+ OMX_VIDEO_CodingUnused) {
+ GstVideoInfo info;
+
+ /* now parse the caps from the config */
+ if (!gst_video_info_from_caps (&info, caps))
+ goto wrong_video_caps;
+
+ /* enable metadata based on config of the pool */
+ pool->add_videometa =
+ gst_buffer_pool_config_has_option (config,
+ GST_BUFFER_POOL_OPTION_VIDEO_META);
+
+ pool->video_info = info;
+ }
+
+ if (pool->caps)
+ gst_caps_unref (pool->caps);
+ pool->caps = gst_caps_ref (caps);
+
+ /* Ensure max=min as the pool won't be able to allocate more buffers while active */
+ gst_buffer_pool_config_set_params (config, caps, size, min, min);
+
+ GST_OBJECT_UNLOCK (pool);
+
+ /* give a fake config to the parent default_set_config() with size == 0
+ * this prevents default_release_buffer() from free'ing the buffers, since
+ * we release them with no memory */
+ fake_config = gst_structure_copy (config);
+ gst_buffer_pool_config_set_params (fake_config, caps, 0, min, min);
+
+ ret = GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->set_config
+ (bpool, fake_config);
+ gst_structure_free (fake_config);
+
+ return ret;
+
+ /* ERRORS */
+wrong_config:
+ {
+ GST_OBJECT_UNLOCK (pool);
+ GST_WARNING_OBJECT (pool, "invalid config");
+ return FALSE;
+ }
+no_caps:
+ {
+ GST_OBJECT_UNLOCK (pool);
+ GST_WARNING_OBJECT (pool, "no caps in config");
+ return FALSE;
+ }
+wrong_video_caps:
+ {
+ GST_OBJECT_UNLOCK (pool);
+ GST_WARNING_OBJECT (pool,
+ "failed getting geometry from caps %" GST_PTR_FORMAT, caps);
+ return FALSE;
+ }
+}
+
+static GstFlowReturn
+gst_omx_buffer_pool_alloc_buffer (GstBufferPool * bpool,
+ GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
+{
+ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
+ GstBuffer *buf;
+ GstMemory *mem;
+ GstMemory *foreign_mem = NULL;
+
+ if (pool->other_pool) {
+ guint n;
+
+ buf = g_ptr_array_index (pool->buffers, pool->current_buffer_index);
+ g_assert (pool->other_pool == buf->pool);
+ gst_object_replace ((GstObject **) & buf->pool, NULL);
+
+ n = gst_buffer_n_memory (buf);
+ g_return_val_if_fail (n == 1, GST_FLOW_ERROR);
+
+ /* rip the memory out of the buffer;
+ * we like to keep them separate in this pool */
+ foreign_mem = gst_buffer_get_memory (buf, 0);
+ gst_buffer_remove_all_memory (buf);
+
+ if (pool->add_videometa) {
+ GstVideoMeta *meta;
+
+ meta = gst_buffer_get_video_meta (buf);
+ if (!meta) {
+ gst_buffer_add_video_meta (buf, GST_VIDEO_FRAME_FLAG_NONE,
+ GST_VIDEO_INFO_FORMAT (&pool->video_info),
+ GST_VIDEO_INFO_WIDTH (&pool->video_info),
+ GST_VIDEO_INFO_HEIGHT (&pool->video_info));
+ }
+ }
+
+ pool->need_copy = FALSE;
+ } else {
+ const guint nstride = pool->port->port_def.format.video.nStride;
+ const guint nslice = pool->port->port_def.format.video.nSliceHeight;
+ gsize offset[GST_VIDEO_MAX_PLANES] = { 0, };
+ gint stride[GST_VIDEO_MAX_PLANES] = { nstride, 0, };
+
+ buf = gst_buffer_new ();
+
+ switch (GST_VIDEO_INFO_FORMAT (&pool->video_info)) {
+ case GST_VIDEO_FORMAT_ABGR:
+ case GST_VIDEO_FORMAT_ARGB:
+ case GST_VIDEO_FORMAT_RGB16:
+ case GST_VIDEO_FORMAT_BGR16:
+ case GST_VIDEO_FORMAT_YUY2:
+ case GST_VIDEO_FORMAT_UYVY:
+ case GST_VIDEO_FORMAT_YVYU:
+ case GST_VIDEO_FORMAT_GRAY8:
+ break;
+ case GST_VIDEO_FORMAT_I420:
+ stride[1] = nstride / 2;
+ offset[1] = offset[0] + stride[0] * nslice;
+ stride[2] = nstride / 2;
+ offset[2] = offset[1] + (stride[1] * nslice / 2);
+ break;
+ case GST_VIDEO_FORMAT_NV12:
+ case GST_VIDEO_FORMAT_NV12_10LE32:
+ case GST_VIDEO_FORMAT_NV16:
+ case GST_VIDEO_FORMAT_NV16_10LE32:
+ stride[1] = nstride;
+ offset[1] = offset[0] + stride[0] * nslice;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ if (pool->add_videometa) {
+ pool->need_copy = FALSE;
+ } else {
+ GstVideoInfo info;
+ gboolean need_copy = FALSE;
+ gint i;
+
+ gst_video_info_init (&info);
+ gst_video_info_set_format (&info,
+ GST_VIDEO_INFO_FORMAT (&pool->video_info),
+ GST_VIDEO_INFO_WIDTH (&pool->video_info),
+ GST_VIDEO_INFO_HEIGHT (&pool->video_info));
+
+ for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&pool->video_info); i++) {
+ if (info.stride[i] != stride[i] || info.offset[i] != offset[i]) {
+ GST_DEBUG_OBJECT (pool,
+ "Need to copy output frames because of stride/offset mismatch: plane %d stride %d (expected: %d) offset %"
+ G_GSIZE_FORMAT " (expected: %" G_GSIZE_FORMAT
+ ") nStride: %d nSliceHeight: %d ", i, stride[i], info.stride[i],
+ offset[i], info.offset[i], nstride, nslice);
+
+ need_copy = TRUE;
+ break;
+ }
+ }
+
+ pool->need_copy = need_copy;
+ }
+
+ if (pool->need_copy || pool->add_videometa) {
+ /* We always add the videometa. It's the job of the user
+ * to copy the buffer if pool->need_copy is TRUE
+ */
+ GstVideoMeta *meta;
+ GstVideoAlignment align;
+
+ meta = gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE,
+ GST_VIDEO_INFO_FORMAT (&pool->video_info),
+ GST_VIDEO_INFO_WIDTH (&pool->video_info),
+ GST_VIDEO_INFO_HEIGHT (&pool->video_info),
+ GST_VIDEO_INFO_N_PLANES (&pool->video_info), offset, stride);
+
+ if (gst_omx_video_get_port_padding (pool->port, &pool->video_info,
+ &align))
+ gst_video_meta_set_alignment (meta, align);
+ }
+ }
+
+ mem = gst_omx_allocator_allocate (pool->allocator, pool->current_buffer_index,
+ foreign_mem);
+ if (!mem)
+ return GST_FLOW_ERROR;
+
+ if (pool->output_mode == GST_OMX_BUFFER_MODE_DMABUF) {
+ GstMapInfo map;
+
+ if (!gst_caps_features_contains (gst_caps_get_features (pool->caps, 0),
+ GST_CAPS_FEATURE_MEMORY_DMABUF)) {
+ /* Check if the memory is actually mappable */
+ if (!gst_memory_map (mem, &map, GST_MAP_READWRITE)) {
+ GST_ERROR_OBJECT (pool,
+ "dmabuf memory is not mappable but caps does not have the 'memory:DMABuf' feature");
+ gst_memory_unref (mem);
+ return GST_FLOW_ERROR;
+ }
+
+ gst_memory_unmap (mem, &map);
+ }
+ }
+
+ /* mem still belongs to the allocator; do not add it in the buffer just yet */
+
+ *buffer = buf;
+
+ pool->current_buffer_index++;
+
+ return GST_FLOW_OK;
+}
+
+/* called by the allocator when we are using other_pool in order
+ * to restore the foreign GstMemory back to its original GstBuffer */
+static void
+on_allocator_foreign_mem_released (GstOMXAllocator * allocator,
+ gint index, GstMemory * mem, GstOMXBufferPool * pool)
+{
+ GstBuffer *buf;
+
+ buf = g_ptr_array_index (pool->buffers, index);
+ gst_buffer_append_memory (buf, mem);
+
+ /* the buffer consumed the passed reference.
+ * we still need one more reference for the allocator */
+ gst_memory_ref (mem);
+}
+
+static void
+gst_omx_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer)
+{
+ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
+
+ /* If the buffers belong to another pool, restore them now */
+ GST_OBJECT_LOCK (pool);
+ if (pool->other_pool) {
+ gst_object_replace ((GstObject **) & buffer->pool,
+ (GstObject *) pool->other_pool);
+ }
+ GST_OBJECT_UNLOCK (pool);
+
+ GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->free_buffer (bpool,
+ buffer);
+}
+
+static GstFlowReturn
+gst_omx_buffer_pool_acquire_buffer (GstBufferPool * bpool,
+ GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
+{
+ GstFlowReturn ret;
+ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
+ GstMemory *mem;
+
+ if (pool->port->port_def.eDir == OMX_DirOutput) {
+ g_return_val_if_fail (pool->current_buffer_index != -1, GST_FLOW_ERROR);
+
+ ret = gst_omx_allocator_acquire (pool->allocator, &mem,
+ pool->current_buffer_index, NULL);
+ if (ret != GST_FLOW_OK)
+ return ret;
+
+ /* If it's our own memory we have to set the sizes */
+ if (!pool->other_pool) {
+ GstOMXBuffer *omx_buf = gst_omx_memory_get_omx_buf (mem);
+ mem->size = omx_buf->omx_buf->nFilledLen;
+ mem->offset = omx_buf->omx_buf->nOffset;
+ }
+ } else {
+ /* Acquire any buffer that is available to be filled by upstream */
+ GstOMXBuffer *omx_buf;
+ GstOMXAcquireBufferReturn r;
+ GstOMXWait wait = GST_OMX_WAIT;
+
+ if (params && (params->flags & GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT))
+ wait = GST_OMX_DONT_WAIT;
+
+ r = gst_omx_port_acquire_buffer (pool->port, &omx_buf, wait);
+ if (r == GST_OMX_ACQUIRE_BUFFER_OK) {
+ ret = gst_omx_allocator_acquire (pool->allocator, &mem, -1, omx_buf);
+ if (ret != GST_FLOW_OK)
+ return ret;
+ } else if (r == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
+ return GST_FLOW_FLUSHING;
+ } else {
+ return GST_FLOW_ERROR;
+ }
+ }
+
+ /* get some GstBuffer available in this pool */
+ ret = GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->acquire_buffer
+ (bpool, buffer, params);
+
+ if (ret == GST_FLOW_OK) {
+ /* attach the acquired memory on it */
+ gst_buffer_append_memory (*buffer, mem);
+ } else {
+ gst_memory_unref (mem);
+ }
+
+ return ret;
+}
+
+static void
+gst_omx_buffer_pool_reset_buffer (GstBufferPool * bpool, GstBuffer * buffer)
+{
+ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
+ guint n;
+
+ n = gst_buffer_n_memory (buffer);
+ if (G_UNLIKELY (n != 1)) {
+ GST_ERROR_OBJECT (pool, "Released buffer does not have 1 memory... "
+ "(n = %u) something went terribly wrong", n);
+ }
+
+ /* rip the memory out of the buffer;
+ * we like to keep them separate in this pool.
+ * if this was the last ref count of the memory, it will be returned
+ * to the allocator, otherwise it will be returned later */
+ gst_buffer_remove_all_memory (buffer);
+
+ /* reset before removing the TAG_MEMORY flag so that the parent impl
+ * doesn't try to restore the original buffer size */
+ GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->reset_buffer
+ (bpool, buffer);
+
+ /* pretend nothing happened to the memory to avoid discarding the buffer */
+ GST_MINI_OBJECT_FLAG_UNSET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
+}
+
+static void
+on_allocator_omxbuf_released (GstOMXAllocator * allocator,
+ GstOMXBuffer * omx_buf, GstOMXBufferPool * pool)
+{
+ OMX_ERRORTYPE err;
+
+ if (pool->port->port_def.eDir == OMX_DirOutput && !omx_buf->used &&
+ !pool->deactivated) {
+ /* Release back to the port, can be filled again */
+ err = gst_omx_port_release_buffer (pool->port, omx_buf);
+
+ if (err != OMX_ErrorNone) {
+ GST_ELEMENT_ERROR (pool->element, LIBRARY, SETTINGS, (NULL),
+ ("Failed to relase output buffer to component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err));
+ }
+ } else if (pool->port->port_def.eDir == OMX_DirInput) {
+ gst_omx_port_requeue_buffer (pool->port, omx_buf);
+ }
+}
+
+static void
+gst_omx_buffer_pool_finalize (GObject * object)
+{
+ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (object);
+
+ if (pool->element)
+ gst_object_unref (pool->element);
+ pool->element = NULL;
+
+ if (pool->buffers)
+ g_ptr_array_unref (pool->buffers);
+ pool->buffers = NULL;
+
+ if (pool->other_pool)
+ gst_object_unref (pool->other_pool);
+ pool->other_pool = NULL;
+
+ if (pool->allocator)
+ gst_object_unref (pool->allocator);
+ pool->allocator = NULL;
+
+ if (pool->caps)
+ gst_caps_unref (pool->caps);
+ pool->caps = NULL;
+
+ g_clear_pointer (&pool->component, gst_omx_component_unref);
+
+ G_OBJECT_CLASS (gst_omx_buffer_pool_parent_class)->finalize (object);
+}
+
+static void
+gst_omx_buffer_pool_class_init (GstOMXBufferPoolClass * klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
+
+ gobject_class->finalize = gst_omx_buffer_pool_finalize;
+ gstbufferpool_class->start = gst_omx_buffer_pool_start;
+ gstbufferpool_class->stop = gst_omx_buffer_pool_stop;
+ gstbufferpool_class->get_options = gst_omx_buffer_pool_get_options;
+ gstbufferpool_class->set_config = gst_omx_buffer_pool_set_config;
+ gstbufferpool_class->alloc_buffer = gst_omx_buffer_pool_alloc_buffer;
+ gstbufferpool_class->free_buffer = gst_omx_buffer_pool_free_buffer;
+ gstbufferpool_class->acquire_buffer = gst_omx_buffer_pool_acquire_buffer;
+ gstbufferpool_class->reset_buffer = gst_omx_buffer_pool_reset_buffer;
+
+ signals[SIG_ALLOCATE] = g_signal_new ("allocate",
+ G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
+ G_TYPE_BOOLEAN, 0);
+}
+
+static void
+gst_omx_buffer_pool_init (GstOMXBufferPool * pool)
+{
+ pool->buffers = g_ptr_array_new ();
+}
+
+GstBufferPool *
+gst_omx_buffer_pool_new (GstElement * element, GstOMXComponent * component,
+ GstOMXPort * port, GstOMXBufferMode output_mode)
+{
+ GstOMXBufferPool *pool;
+
+ pool = g_object_new (gst_omx_buffer_pool_get_type (), NULL);
+ pool->element = gst_object_ref (element);
+ pool->component = gst_omx_component_ref (component);
+ pool->port = port;
+ pool->output_mode = output_mode;
+ pool->allocator = gst_omx_allocator_new (component, port);
+
+ g_signal_connect_object (pool->allocator, "omxbuf-released",
+ (GCallback) on_allocator_omxbuf_released, pool, 0);
+ g_signal_connect_object (pool->allocator, "foreign-mem-released",
+ (GCallback) on_allocator_foreign_mem_released, pool, 0);
+
+ return GST_BUFFER_POOL (pool);
+}
diff --git a/subprojects/gst-omx/omx/gstomxbufferpool.h b/subprojects/gst-omx/omx/gstomxbufferpool.h
new file mode 100644
index 0000000000..bc5ac60588
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxbufferpool.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ * Author: Christian König <christian.koenig@amd.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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_BUFFER_POOL_H__
+#define __GST_OMX_BUFFER_POOL_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/video/gstvideometa.h>
+#include <gst/video/gstvideopool.h>
+
+#include "gstomx.h"
+#include "gstomxallocator.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_BUFFER_POOL \
+ (gst_omx_buffer_pool_get_type())
+#define GST_OMX_BUFFER_POOL(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_BUFFER_POOL,GstOMXBufferPool))
+#define GST_IS_OMX_BUFFER_POOL(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_BUFFER_POOL))
+
+typedef struct _GstOMXBufferPool GstOMXBufferPool;
+typedef struct _GstOMXBufferPoolClass GstOMXBufferPoolClass;
+
+typedef enum {
+ GST_OMX_BUFFER_MODE_SYSTEM_MEMORY,
+ GST_OMX_BUFFER_MODE_DMABUF,
+} GstOMXBufferMode;
+
+struct _GstOMXBufferPool
+{
+ GstVideoBufferPool parent;
+
+ GstElement *element;
+
+ GstCaps *caps;
+ gboolean add_videometa;
+ gboolean need_copy;
+ GstVideoInfo video_info;
+
+ /* Owned by element, element has to stop this pool before
+ * it destroys component or port */
+ GstOMXComponent *component;
+ GstOMXPort *port;
+
+ /* For handling OpenMAX allocated memory */
+ GstOMXAllocator *allocator;
+
+ /* Set from outside this pool */
+ /* TRUE if the pool is not used anymore */
+ gboolean deactivated;
+
+ /* For populating the pool from another one */
+ GstBufferPool *other_pool;
+ GPtrArray *buffers;
+
+ /* Used during acquire for output ports to
+ * specify which buffer has to be retrieved
+ * and during alloc, which buffer has to be
+ * wrapped
+ */
+ gint current_buffer_index;
+
+ /* The type of buffers produced by the decoder */
+ GstOMXBufferMode output_mode;
+};
+
+struct _GstOMXBufferPoolClass
+{
+ GstVideoBufferPoolClass parent_class;
+};
+
+GType gst_omx_buffer_pool_get_type (void);
+
+GstBufferPool *gst_omx_buffer_pool_new (GstElement * element, GstOMXComponent * component, GstOMXPort * port, GstOMXBufferMode output_mode);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_BUFFER_POOL_H__ */
diff --git a/subprojects/gst-omx/omx/gstomxh263dec.c b/subprojects/gst-omx/omx/gstomxh263dec.c
new file mode 100644
index 0000000000..d76f1b9a57
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxh263dec.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxh263dec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_h263_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_h263_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_h263_dec_is_format_change (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state);
+static gboolean gst_omx_h263_dec_set_format (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state);
+
+enum
+{
+ PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_h263_dec_debug_category, "omxh263dec", 0, \
+ "debug category for gst-omx video decoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXH263Dec, gst_omx_h263_dec,
+ GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT);
+
+static void
+gst_omx_h263_dec_class_init (GstOMXH263DecClass * klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstOMXVideoDecClass *videodec_class = GST_OMX_VIDEO_DEC_CLASS (klass);
+
+ videodec_class->is_format_change =
+ GST_DEBUG_FUNCPTR (gst_omx_h263_dec_is_format_change);
+ videodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_h263_dec_set_format);
+
+ videodec_class->cdata.default_sink_template_caps = "video/x-h263, "
+ "variant=(string) itu, "
+ "parsed=(boolean) true, " "width=(int) [1,MAX], " "height=(int) [1,MAX]";
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX H.263 Video Decoder",
+ "Codec/Decoder/Video/Hardware",
+ "Decode H.263 video streams",
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+ gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.h263");
+}
+
+static void
+gst_omx_h263_dec_init (GstOMXH263Dec * self)
+{
+}
+
+static gboolean
+gst_omx_h263_dec_is_format_change (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state)
+{
+ return FALSE;
+}
+
+static gboolean
+gst_omx_h263_dec_set_format (GstOMXVideoDec * dec, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ gboolean ret;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+
+ gst_omx_port_get_port_definition (port, &port_def);
+ port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingH263;
+ ret = gst_omx_port_update_port_definition (port, &port_def) == OMX_ErrorNone;
+
+ return ret;
+}
diff --git a/subprojects/gst-omx/omx/gstomxh263dec.h b/subprojects/gst-omx/omx/gstomxh263dec.h
new file mode 100644
index 0000000000..aa24c2f7f8
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxh263dec.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_H263_DEC_H__
+#define __GST_OMX_H263_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_H263_DEC \
+ (gst_omx_h263_dec_get_type())
+#define GST_OMX_H263_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_H263_DEC,GstOMXH263Dec))
+#define GST_OMX_H263_DEC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_H263_DEC,GstOMXH263DecClass))
+#define GST_OMX_H263_DEC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_H263_DEC,GstOMXH263DecClass))
+#define GST_IS_OMX_H263_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_H263_DEC))
+#define GST_IS_OMX_H263_DEC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_H263_DEC))
+
+typedef struct _GstOMXH263Dec GstOMXH263Dec;
+typedef struct _GstOMXH263DecClass GstOMXH263DecClass;
+
+struct _GstOMXH263Dec
+{
+ GstOMXVideoDec parent;
+};
+
+struct _GstOMXH263DecClass
+{
+ GstOMXVideoDecClass parent_class;
+};
+
+GType gst_omx_h263_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_H263_DEC_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxh263enc.c b/subprojects/gst-omx/omx/gstomxh263enc.c
new file mode 100644
index 0000000000..9e80bfbb19
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxh263enc.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxh263enc.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_h263_enc_debug_category);
+#define GST_CAT_DEFAULT gst_omx_h263_enc_debug_category
+
+/* prototypes */
+static gboolean gst_omx_h263_enc_set_format (GstOMXVideoEnc * enc,
+ GstOMXPort * port, GstVideoCodecState * state);
+static GstCaps *gst_omx_h263_enc_get_caps (GstOMXVideoEnc * enc,
+ GstOMXPort * port, GstVideoCodecState * state);
+
+enum
+{
+ PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_h263_enc_debug_category, "omxh263enc", 0, \
+ "debug category for gst-omx video encoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXH263Enc, gst_omx_h263_enc,
+ GST_TYPE_OMX_VIDEO_ENC, DEBUG_INIT);
+
+static void
+gst_omx_h263_enc_class_init (GstOMXH263EncClass * klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstOMXVideoEncClass *videoenc_class = GST_OMX_VIDEO_ENC_CLASS (klass);
+
+ videoenc_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_h263_enc_set_format);
+ videoenc_class->get_caps = GST_DEBUG_FUNCPTR (gst_omx_h263_enc_get_caps);
+
+ videoenc_class->cdata.default_src_template_caps = "video/x-h263, "
+ "width=(int) [ 16, 4096 ], " "height=(int) [ 16, 4096 ]";
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX H.263 Video Encoder",
+ "Codec/Encoder/Video/Hardware",
+ "Encode H.263 video streams",
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+ gst_omx_set_default_role (&videoenc_class->cdata, "video_encoder.h263");
+}
+
+static void
+gst_omx_h263_enc_init (GstOMXH263Enc * self)
+{
+}
+
+static gboolean
+gst_omx_h263_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ GstOMXH263Enc *self = GST_OMX_H263_ENC (enc);
+ GstCaps *peercaps;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+ OMX_ERRORTYPE err;
+ guint profile_id, level_id;
+
+ gst_omx_port_get_port_definition (GST_OMX_VIDEO_ENC (self)->enc_out_port,
+ &port_def);
+ port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingH263;
+ err =
+ gst_omx_port_update_port_definition (GST_OMX_VIDEO_ENC
+ (self)->enc_out_port, &port_def);
+ if (err != OMX_ErrorNone)
+ return FALSE;
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+ err =
+ gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamVideoProfileLevelCurrent, &param);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self,
+ "Getting profile/level not supported by component");
+ return TRUE;
+ }
+
+ peercaps = gst_pad_peer_query_caps (GST_VIDEO_ENCODER_SRC_PAD (enc),
+ gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD (enc)));
+ if (peercaps) {
+ GstStructure *s;
+
+ if (gst_caps_is_empty (peercaps)) {
+ gst_caps_unref (peercaps);
+ GST_ERROR_OBJECT (self, "Empty caps");
+ return FALSE;
+ }
+
+ s = gst_caps_get_structure (peercaps, 0);
+ if (gst_structure_get_uint (s, "profile", &profile_id)) {
+ switch (profile_id) {
+ case 0:
+ param.eProfile = OMX_VIDEO_H263ProfileBaseline;
+ break;
+ case 1:
+ param.eProfile = OMX_VIDEO_H263ProfileH320Coding;
+ break;
+ case 2:
+ param.eProfile = OMX_VIDEO_H263ProfileBackwardCompatible;
+ break;
+ case 3:
+ param.eProfile = OMX_VIDEO_H263ProfileISWV2;
+ break;
+ case 4:
+ param.eProfile = OMX_VIDEO_H263ProfileISWV3;
+ break;
+ case 5:
+ param.eProfile = OMX_VIDEO_H263ProfileHighCompression;
+ break;
+ case 6:
+ param.eProfile = OMX_VIDEO_H263ProfileInternet;
+ break;
+ case 7:
+ param.eProfile = OMX_VIDEO_H263ProfileInterlace;
+ break;
+ case 8:
+ param.eProfile = OMX_VIDEO_H263ProfileHighLatency;
+ break;
+ default:
+ goto unsupported_profile;
+ }
+ }
+ if (gst_structure_get_uint (s, "level", &level_id)) {
+ switch (level_id) {
+ case 10:
+ param.eLevel = OMX_VIDEO_H263Level10;
+ break;
+ case 20:
+ param.eLevel = OMX_VIDEO_H263Level20;
+ break;
+ case 30:
+ param.eLevel = OMX_VIDEO_H263Level30;
+ break;
+ case 40:
+ param.eLevel = OMX_VIDEO_H263Level40;
+ break;
+ case 50:
+ param.eLevel = OMX_VIDEO_H263Level50;
+ break;
+ case 60:
+ param.eLevel = OMX_VIDEO_H263Level60;
+ break;
+ case 70:
+ param.eLevel = OMX_VIDEO_H263Level70;
+ break;
+ default:
+ goto unsupported_level;
+ }
+ }
+ gst_caps_unref (peercaps);
+ }
+
+ err =
+ gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamVideoProfileLevelCurrent, &param);
+ if (err == OMX_ErrorUnsupportedIndex) {
+ GST_WARNING_OBJECT (self,
+ "Setting profile/level not supported by component");
+ } else if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Error setting profile %u and level %u: %s (0x%08x)",
+ (guint) param.eProfile, (guint) param.eLevel,
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+
+unsupported_profile:
+ GST_ERROR_OBJECT (self, "Unsupported profile %u", profile_id);
+ gst_caps_unref (peercaps);
+ return FALSE;
+
+unsupported_level:
+ GST_ERROR_OBJECT (self, "Unsupported level %u", level_id);
+ gst_caps_unref (peercaps);
+ return FALSE;
+}
+
+static GstCaps *
+gst_omx_h263_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ GstOMXH263Enc *self = GST_OMX_H263_ENC (enc);
+ GstCaps *caps;
+ OMX_ERRORTYPE err;
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+ guint profile, level;
+
+ caps = gst_caps_new_empty_simple ("video/x-h263");
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+
+ err =
+ gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamVideoProfileLevelCurrent, &param);
+ if (err != OMX_ErrorNone && err != OMX_ErrorUnsupportedIndex) {
+ gst_caps_unref (caps);
+ return NULL;
+ }
+
+ if (err == OMX_ErrorNone) {
+ switch (param.eProfile) {
+ case OMX_VIDEO_H263ProfileBaseline:
+ profile = 0;
+ break;
+ case OMX_VIDEO_H263ProfileH320Coding:
+ profile = 1;
+ break;
+ case OMX_VIDEO_H263ProfileBackwardCompatible:
+ profile = 2;
+ break;
+ case OMX_VIDEO_H263ProfileISWV2:
+ profile = 3;
+ break;
+ case OMX_VIDEO_H263ProfileISWV3:
+ profile = 4;
+ break;
+ case OMX_VIDEO_H263ProfileHighCompression:
+ profile = 5;
+ break;
+ case OMX_VIDEO_H263ProfileInternet:
+ profile = 6;
+ break;
+ case OMX_VIDEO_H263ProfileInterlace:
+ profile = 7;
+ break;
+ case OMX_VIDEO_H263ProfileHighLatency:
+ profile = 8;
+ break;
+ default:
+ g_assert_not_reached ();
+ gst_caps_unref (caps);
+ return NULL;
+ }
+
+ switch (param.eLevel) {
+ case OMX_VIDEO_H263Level10:
+ level = 10;
+ break;
+ case OMX_VIDEO_H263Level20:
+ level = 20;
+ break;
+ case OMX_VIDEO_H263Level30:
+ level = 30;
+ break;
+ case OMX_VIDEO_H263Level40:
+ level = 40;
+ break;
+ case OMX_VIDEO_H263Level50:
+ level = 50;
+ break;
+ case OMX_VIDEO_H263Level60:
+ level = 60;
+ break;
+ case OMX_VIDEO_H263Level70:
+ level = 70;
+ break;
+ default:
+ g_assert_not_reached ();
+ gst_caps_unref (caps);
+ return NULL;
+ }
+
+ gst_caps_set_simple (caps,
+ "profile", G_TYPE_UINT, profile, "level", G_TYPE_UINT, level, NULL);
+ }
+
+ return caps;
+}
diff --git a/subprojects/gst-omx/omx/gstomxh263enc.h b/subprojects/gst-omx/omx/gstomxh263enc.h
new file mode 100644
index 0000000000..0dbd0deb23
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxh263enc.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_H263_ENC_H__
+#define __GST_OMX_H263_ENC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideoenc.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_H263_ENC \
+ (gst_omx_h263_enc_get_type())
+#define GST_OMX_H263_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_H263_ENC,GstOMXH263Enc))
+#define GST_OMX_H263_ENC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_H263_ENC,GstOMXH263EncClass))
+#define GST_OMX_H263_ENC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_H263_ENC,GstOMXH263EncClass))
+#define GST_IS_OMX_H263_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_H263_ENC))
+#define GST_IS_OMX_H263_ENC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_H263_ENC))
+
+typedef struct _GstOMXH263Enc GstOMXH263Enc;
+typedef struct _GstOMXH263EncClass GstOMXH263EncClass;
+
+struct _GstOMXH263Enc
+{
+ GstOMXVideoEnc parent;
+};
+
+struct _GstOMXH263EncClass
+{
+ GstOMXVideoEncClass parent_class;
+};
+
+GType gst_omx_h263_enc_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_H263_ENC_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxh264dec.c b/subprojects/gst-omx/omx/gstomxh264dec.c
new file mode 100644
index 0000000000..32b575742c
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxh264dec.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxh264dec.h"
+#include "gstomxh264utils.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_h264_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_h264_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_h264_dec_is_format_change (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state);
+static gboolean gst_omx_h264_dec_set_format (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state);
+
+enum
+{
+ PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_h264_dec_debug_category, "omxh264dec", 0, \
+ "debug category for gst-omx video decoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXH264Dec, gst_omx_h264_dec,
+ GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT);
+
+#define MAKE_CAPS(alignment) \
+ "video/x-h264, " \
+ "alignment=(string) " alignment ", " \
+ "stream-format=(string) byte-stream, " \
+ "width=(int) [1,MAX], height=(int) [1,MAX]"
+
+/* The Zynq supports decoding subframes, though we want "au" to be the
+ * default, so we keep it prepended. This is the only way that it works with
+ * rtph264depay. */
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+#define SINK_CAPS MAKE_CAPS ("au") ";" MAKE_CAPS ("nal")
+#else
+#define SINK_CAPS MAKE_CAPS ("au")
+#endif
+
+static void
+gst_omx_h264_dec_class_init (GstOMXH264DecClass * klass)
+{
+ GstOMXVideoDecClass *videodec_class = GST_OMX_VIDEO_DEC_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ videodec_class->is_format_change =
+ GST_DEBUG_FUNCPTR (gst_omx_h264_dec_is_format_change);
+ videodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_h264_dec_set_format);
+
+ videodec_class->cdata.default_sink_template_caps = SINK_CAPS;
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX H.264 Video Decoder",
+ "Codec/Decoder/Video/Hardware",
+ "Decode H.264 video streams",
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+ gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.avc");
+}
+
+static void
+gst_omx_h264_dec_init (GstOMXH264Dec * self)
+{
+}
+
+static gboolean
+gst_omx_h264_dec_is_format_change (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state)
+{
+ GstCaps *old_caps = NULL;
+ GstCaps *new_caps = state->caps;
+ GstStructure *old_structure, *new_structure;
+ const gchar *old_profile, *old_level, *old_alignment, *new_profile,
+ *new_level, *new_alignment;
+
+ if (dec->input_state) {
+ old_caps = dec->input_state->caps;
+ }
+
+ if (!old_caps) {
+ return FALSE;
+ }
+
+ old_structure = gst_caps_get_structure (old_caps, 0);
+ new_structure = gst_caps_get_structure (new_caps, 0);
+ old_profile = gst_structure_get_string (old_structure, "profile");
+ old_level = gst_structure_get_string (old_structure, "level");
+ old_alignment = gst_structure_get_string (old_structure, "alignment");
+ new_profile = gst_structure_get_string (new_structure, "profile");
+ new_level = gst_structure_get_string (new_structure, "level");
+ new_alignment = gst_structure_get_string (new_structure, "alignment");
+
+ if (g_strcmp0 (old_profile, new_profile) != 0
+ || g_strcmp0 (old_level, new_level) != 0
+ || g_strcmp0 (old_alignment, new_alignment) != 0) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+set_profile_and_level (GstOMXH264Dec * self, GstVideoCodecState * state)
+{
+ OMX_ERRORTYPE err;
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+ const gchar *profile_string, *level_string;
+ GstStructure *s;
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = GST_OMX_VIDEO_DEC (self)->dec_in_port->index;
+
+ /* Pass profile and level to the decoder if we have both info from the
+ * caps. */
+ s = gst_caps_get_structure (state->caps, 0);
+ profile_string = gst_structure_get_string (s, "profile");
+ if (!profile_string)
+ return TRUE;
+
+ param.eProfile = gst_omx_h264_utils_get_profile_from_str (profile_string);
+ if (param.eProfile == OMX_VIDEO_AVCProfileMax)
+ goto unsupported_profile;
+
+ level_string = gst_structure_get_string (s, "level");
+ if (!level_string)
+ return TRUE;
+
+ param.eLevel = gst_omx_h264_utils_get_level_from_str (level_string);
+ if (param.eLevel == OMX_VIDEO_AVCLevelMax)
+ goto unsupported_level;
+
+ GST_DEBUG_OBJECT (self, "Set profile (%s) and level (%s) on decoder",
+ profile_string, level_string);
+
+ err =
+ gst_omx_component_set_parameter (GST_OMX_VIDEO_DEC (self)->dec,
+ OMX_IndexParamVideoProfileLevelCurrent, &param);
+ if (err == OMX_ErrorUnsupportedIndex) {
+ GST_WARNING_OBJECT (self,
+ "Setting profile/level not supported by component");
+ } else if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Error setting profile %u and level %u: %s (0x%08x)",
+ (guint) param.eProfile, (guint) param.eLevel,
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+
+unsupported_profile:
+ GST_ERROR_OBJECT (self, "Unsupported profile %s", profile_string);
+ return FALSE;
+
+unsupported_level:
+ GST_ERROR_OBJECT (self, "Unsupported level %s", level_string);
+ return FALSE;
+}
+
+static gboolean
+gst_omx_h264_dec_set_format (GstOMXVideoDec * dec, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ GstOMXVideoDecClass *klass = GST_OMX_VIDEO_DEC_GET_CLASS (dec);
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ OMX_ERRORTYPE err;
+ const GstStructure *s;
+
+ gst_omx_port_get_port_definition (port, &port_def);
+ port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
+ err = gst_omx_port_update_port_definition (port, &port_def);
+ if (err != OMX_ErrorNone)
+ return FALSE;
+
+ if (klass->cdata.hacks & GST_OMX_HACK_PASS_PROFILE_TO_DECODER) {
+ if (!set_profile_and_level (GST_OMX_H264_DEC (dec), state))
+ return FALSE;
+ }
+
+ /* Enable subframe mode if NAL aligned */
+ s = gst_caps_get_structure (state->caps, 0);
+ if (!g_strcmp0 (gst_structure_get_string (s, "alignment"), "nal")
+ && gst_omx_port_set_subframe (dec->dec_in_port, TRUE)) {
+ gst_video_decoder_set_subframe_mode (GST_VIDEO_DECODER (dec), TRUE);
+ }
+
+ return TRUE;
+}
diff --git a/subprojects/gst-omx/omx/gstomxh264dec.h b/subprojects/gst-omx/omx/gstomxh264dec.h
new file mode 100644
index 0000000000..4c0ea1f37b
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxh264dec.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_H264_DEC_H__
+#define __GST_OMX_H264_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_H264_DEC \
+ (gst_omx_h264_dec_get_type())
+#define GST_OMX_H264_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_H264_DEC,GstOMXH264Dec))
+#define GST_OMX_H264_DEC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_H264_DEC,GstOMXH264DecClass))
+#define GST_OMX_H264_DEC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_H264_DEC,GstOMXH264DecClass))
+#define GST_IS_OMX_H264_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_H264_DEC))
+#define GST_IS_OMX_H264_DEC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_H264_DEC))
+
+typedef struct _GstOMXH264Dec GstOMXH264Dec;
+typedef struct _GstOMXH264DecClass GstOMXH264DecClass;
+
+struct _GstOMXH264Dec
+{
+ GstOMXVideoDec parent;
+};
+
+struct _GstOMXH264DecClass
+{
+ GstOMXVideoDecClass parent_class;
+};
+
+GType gst_omx_h264_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_H264_DEC_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxh264enc.c b/subprojects/gst-omx/omx/gstomxh264enc.c
new file mode 100644
index 0000000000..51d84a805a
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxh264enc.c
@@ -0,0 +1,894 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxh264enc.h"
+#include "gstomxh264utils.h"
+
+#ifdef USE_OMX_TARGET_RPI
+#include <OMX_Broadcom.h>
+#include <OMX_Index.h>
+#endif
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_h264_enc_debug_category);
+#define GST_CAT_DEFAULT gst_omx_h264_enc_debug_category
+
+/* prototypes */
+static gboolean gst_omx_h264_enc_set_format (GstOMXVideoEnc * enc,
+ GstOMXPort * port, GstVideoCodecState * state);
+static GstCaps *gst_omx_h264_enc_get_caps (GstOMXVideoEnc * enc,
+ GstOMXPort * port, GstVideoCodecState * state);
+static GstFlowReturn gst_omx_h264_enc_handle_output_frame (GstOMXVideoEnc *
+ self, GstOMXPort * port, GstOMXBuffer * buf, GstVideoCodecFrame * frame);
+static gboolean gst_omx_h264_enc_flush (GstVideoEncoder * enc);
+static gboolean gst_omx_h264_enc_stop (GstVideoEncoder * enc);
+static void gst_omx_h264_enc_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_omx_h264_enc_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+enum
+{
+ PROP_0,
+#ifdef USE_OMX_TARGET_RPI
+ PROP_INLINESPSPPSHEADERS,
+#endif
+ PROP_PERIODICITYOFIDRFRAMES,
+ PROP_PERIODICITYOFIDRFRAMES_COMPAT,
+ PROP_INTERVALOFCODINGINTRAFRAMES,
+ PROP_B_FRAMES,
+ PROP_ENTROPY_MODE,
+ PROP_CONSTRAINED_INTRA_PREDICTION,
+ PROP_LOOP_FILTER_MODE,
+ PROP_REF_FRAMES
+};
+
+#ifdef USE_OMX_TARGET_RPI
+#define GST_OMX_H264_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT TRUE
+#endif
+#define GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT (0xffffffff)
+#define GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT (0xffffffff)
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+#define GST_OMX_H264_VIDEO_ENC_B_FRAMES_DEFAULT (0)
+#define ALIGNMENT "{ au, nal }"
+#else
+#define GST_OMX_H264_VIDEO_ENC_B_FRAMES_DEFAULT (0xffffffff)
+#define ALIGNMENT "au"
+#endif
+#define GST_OMX_H264_VIDEO_ENC_ENTROPY_MODE_DEFAULT (0xffffffff)
+#define GST_OMX_H264_VIDEO_ENC_CONSTRAINED_INTRA_PREDICTION_DEFAULT (FALSE)
+#define GST_OMX_H264_VIDEO_ENC_LOOP_FILTER_MODE_DEFAULT (0xffffffff)
+#define GST_OMX_H264_VIDEO_ENC_REF_FRAMES_DEFAULT 0
+#define GST_OMX_H264_VIDEO_ENC_REF_FRAMES_MIN 0
+#define GST_OMX_H264_VIDEO_ENC_REF_FRAMES_MAX 16
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_h264_enc_debug_category, "omxh264enc", 0, \
+ "debug category for gst-omx video encoder base class");
+
+#define parent_class gst_omx_h264_enc_parent_class
+G_DEFINE_TYPE_WITH_CODE (GstOMXH264Enc, gst_omx_h264_enc,
+ GST_TYPE_OMX_VIDEO_ENC, DEBUG_INIT);
+
+#define GST_TYPE_OMX_H264_ENC_ENTROPY_MODE (gst_omx_h264_enc_entropy_mode_get_type ())
+static GType
+gst_omx_h264_enc_entropy_mode_get_type (void)
+{
+ static GType qtype = 0;
+
+ if (qtype == 0) {
+ static const GEnumValue values[] = {
+ {FALSE, "CAVLC entropy mode", "CAVLC"},
+ {TRUE, "CABAC entropy mode", "CABAC"},
+ {0xffffffff, "Component Default", "default"},
+ {0, NULL, NULL}
+ };
+
+ qtype = g_enum_register_static ("GstOMXH264EncEntropyMode", values);
+ }
+ return qtype;
+}
+
+#define GST_TYPE_OMX_H264_ENC_LOOP_FILTER_MODE (gst_omx_h264_enc_loop_filter_mode_get_type ())
+static GType
+gst_omx_h264_enc_loop_filter_mode_get_type (void)
+{
+ static GType qtype = 0;
+
+ if (qtype == 0) {
+ static const GEnumValue values[] = {
+ {OMX_VIDEO_AVCLoopFilterEnable, "Enable deblocking filter", "enable"},
+ {OMX_VIDEO_AVCLoopFilterDisable, "Disable deblocking filter", "disable"},
+ {OMX_VIDEO_AVCLoopFilterDisableSliceBoundary,
+ "Disables deblocking filter on slice boundary",
+ "disable-slice-boundary"},
+ {0xffffffff, "Component Default", "default"},
+ {0, NULL, NULL}
+ };
+
+ qtype = g_enum_register_static ("GstOMXH264EncLoopFilter", values);
+ }
+ return qtype;
+}
+
+static void
+gst_omx_h264_enc_class_init (GstOMXH264EncClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstVideoEncoderClass *basevideoenc_class = GST_VIDEO_ENCODER_CLASS (klass);
+ GstOMXVideoEncClass *videoenc_class = GST_OMX_VIDEO_ENC_CLASS (klass);
+
+ videoenc_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_h264_enc_set_format);
+ videoenc_class->get_caps = GST_DEBUG_FUNCPTR (gst_omx_h264_enc_get_caps);
+
+ gobject_class->set_property = gst_omx_h264_enc_set_property;
+ gobject_class->get_property = gst_omx_h264_enc_get_property;
+
+#ifdef USE_OMX_TARGET_RPI
+ g_object_class_install_property (gobject_class, PROP_INLINESPSPPSHEADERS,
+ g_param_spec_boolean ("inline-header",
+ "Inline SPS/PPS headers before IDR",
+ "Inline SPS/PPS header before IDR",
+ GST_OMX_H264_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+#endif
+
+ g_object_class_install_property (gobject_class, PROP_PERIODICITYOFIDRFRAMES,
+ g_param_spec_uint ("periodicity-idr", "IDR periodicity",
+ "Periodicity of IDR frames (0xffffffff=component default)",
+ 0, G_MAXUINT,
+ GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class,
+ PROP_PERIODICITYOFIDRFRAMES_COMPAT, g_param_spec_uint ("periodicty-idr",
+ "IDR periodicity",
+ "Periodicity of IDR frames (0xffffffff=component default) DEPRECATED - only for backwards compat",
+ 0, G_MAXUINT,
+ GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class,
+ PROP_INTERVALOFCODINGINTRAFRAMES,
+ g_param_spec_uint ("interval-intraframes",
+ "Interval of coding Intra frames",
+ "Interval of coding Intra frames (0xffffffff=component default)", 0,
+ G_MAXUINT,
+ GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_B_FRAMES,
+ g_param_spec_uint ("b-frames", "Number of B-frames",
+ "Number of B-frames between two consecutive I-frames (0xffffffff=component default)",
+ 0, G_MAXUINT, GST_OMX_H264_VIDEO_ENC_B_FRAMES_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_ENTROPY_MODE,
+ g_param_spec_enum ("entropy-mode", "Entropy Mode",
+ "Entropy mode for encoding process",
+ GST_TYPE_OMX_H264_ENC_ENTROPY_MODE,
+ GST_OMX_H264_VIDEO_ENC_ENTROPY_MODE_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class,
+ PROP_CONSTRAINED_INTRA_PREDICTION,
+ g_param_spec_boolean ("constrained-intra-prediction",
+ "Constrained Intra Prediction",
+ "If enabled, prediction only uses residual data and decoded samples "
+ "from neighbouring coding blocks coded using intra prediction modes",
+ GST_OMX_H264_VIDEO_ENC_CONSTRAINED_INTRA_PREDICTION_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_LOOP_FILTER_MODE,
+ g_param_spec_enum ("loop-filter-mode", "Loop Filter mode",
+ "Enable or disable the deblocking filter (0xffffffff=component default)",
+ GST_TYPE_OMX_H264_ENC_LOOP_FILTER_MODE,
+ GST_OMX_H264_VIDEO_ENC_LOOP_FILTER_MODE_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_REF_FRAMES,
+ g_param_spec_uchar ("ref-frames", "Reference frames",
+ "Number of reference frames used for inter-motion search (0=component default)",
+ GST_OMX_H264_VIDEO_ENC_REF_FRAMES_MIN,
+ GST_OMX_H264_VIDEO_ENC_REF_FRAMES_MAX,
+ GST_OMX_H264_VIDEO_ENC_REF_FRAMES_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ basevideoenc_class->flush = gst_omx_h264_enc_flush;
+ basevideoenc_class->stop = gst_omx_h264_enc_stop;
+
+ videoenc_class->cdata.default_src_template_caps = "video/x-h264, "
+ "width = (int) [ 16, 4096 ], height = (int) [ 16, 4096 ], "
+ "framerate = (fraction) [0, MAX], stream-format=(string) byte-stream, "
+ "alignment = (string) " ALIGNMENT;
+ videoenc_class->handle_output_frame =
+ GST_DEBUG_FUNCPTR (gst_omx_h264_enc_handle_output_frame);
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX H.264 Video Encoder",
+ "Codec/Encoder/Video/Hardware",
+ "Encode H.264 video streams",
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+ gst_omx_set_default_role (&videoenc_class->cdata, "video_encoder.avc");
+}
+
+static void
+gst_omx_h264_enc_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstOMXH264Enc *self = GST_OMX_H264_ENC (object);
+
+ switch (prop_id) {
+#ifdef USE_OMX_TARGET_RPI
+ case PROP_INLINESPSPPSHEADERS:
+ self->inline_sps_pps_headers = g_value_get_boolean (value);
+ break;
+#endif
+ case PROP_PERIODICITYOFIDRFRAMES:
+ case PROP_PERIODICITYOFIDRFRAMES_COMPAT:
+ self->periodicty_idr = g_value_get_uint (value);
+ break;
+ case PROP_INTERVALOFCODINGINTRAFRAMES:
+ self->interval_intraframes = g_value_get_uint (value);
+ break;
+ case PROP_B_FRAMES:
+ self->b_frames = g_value_get_uint (value);
+ break;
+ case PROP_ENTROPY_MODE:
+ self->entropy_mode = g_value_get_enum (value);
+ break;
+ case PROP_CONSTRAINED_INTRA_PREDICTION:
+ self->constrained_intra_prediction = g_value_get_boolean (value);
+ break;
+ case PROP_LOOP_FILTER_MODE:
+ self->loop_filter_mode = g_value_get_enum (value);
+ break;
+ case PROP_REF_FRAMES:
+ self->ref_frames = g_value_get_uchar (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_omx_h264_enc_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec)
+{
+ GstOMXH264Enc *self = GST_OMX_H264_ENC (object);
+
+ switch (prop_id) {
+#ifdef USE_OMX_TARGET_RPI
+ case PROP_INLINESPSPPSHEADERS:
+ g_value_set_boolean (value, self->inline_sps_pps_headers);
+ break;
+#endif
+ case PROP_PERIODICITYOFIDRFRAMES:
+ case PROP_PERIODICITYOFIDRFRAMES_COMPAT:
+ g_value_set_uint (value, self->periodicty_idr);
+ break;
+ case PROP_INTERVALOFCODINGINTRAFRAMES:
+ g_value_set_uint (value, self->interval_intraframes);
+ break;
+ case PROP_B_FRAMES:
+ g_value_set_uint (value, self->b_frames);
+ break;
+ case PROP_ENTROPY_MODE:
+ g_value_set_enum (value, self->entropy_mode);
+ break;
+ case PROP_CONSTRAINED_INTRA_PREDICTION:
+ g_value_set_boolean (value, self->constrained_intra_prediction);
+ break;
+ case PROP_LOOP_FILTER_MODE:
+ g_value_set_enum (value, self->loop_filter_mode);
+ break;
+ case PROP_REF_FRAMES:
+ g_value_set_uchar (value, self->ref_frames);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_omx_h264_enc_init (GstOMXH264Enc * self)
+{
+#ifdef USE_OMX_TARGET_RPI
+ self->inline_sps_pps_headers =
+ GST_OMX_H264_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT;
+#endif
+ self->periodicty_idr =
+ GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT;
+ self->interval_intraframes =
+ GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT;
+ self->b_frames = GST_OMX_H264_VIDEO_ENC_B_FRAMES_DEFAULT;
+ self->entropy_mode = GST_OMX_H264_VIDEO_ENC_ENTROPY_MODE_DEFAULT;
+ self->constrained_intra_prediction =
+ GST_OMX_H264_VIDEO_ENC_CONSTRAINED_INTRA_PREDICTION_DEFAULT;
+ self->loop_filter_mode = GST_OMX_H264_VIDEO_ENC_LOOP_FILTER_MODE_DEFAULT;
+ self->ref_frames = GST_OMX_H264_VIDEO_ENC_REF_FRAMES_DEFAULT;
+}
+
+static gboolean
+gst_omx_h264_enc_flush (GstVideoEncoder * enc)
+{
+ GstOMXH264Enc *self = GST_OMX_H264_ENC (enc);
+
+ g_list_free_full (self->headers, (GDestroyNotify) gst_buffer_unref);
+ self->headers = NULL;
+
+ return GST_VIDEO_ENCODER_CLASS (parent_class)->flush (enc);
+}
+
+static gboolean
+gst_omx_h264_enc_stop (GstVideoEncoder * enc)
+{
+ GstOMXH264Enc *self = GST_OMX_H264_ENC (enc);
+
+ g_list_free_full (self->headers, (GDestroyNotify) gst_buffer_unref);
+ self->headers = NULL;
+
+ return GST_VIDEO_ENCODER_CLASS (parent_class)->stop (enc);
+}
+
+/* Update OMX_VIDEO_PARAM_PROFILELEVELTYPE.{eProfile,eLevel}
+ *
+ * Returns TRUE if succeeded or if not supported, FALSE if failed */
+static gboolean
+update_param_profile_level (GstOMXH264Enc * self,
+ OMX_VIDEO_AVCPROFILETYPE profile, OMX_VIDEO_AVCLEVELTYPE level)
+{
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+
+ err =
+ gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamVideoProfileLevelCurrent, &param);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self,
+ "Getting OMX_IndexParamVideoProfileLevelCurrent not supported by component");
+ return TRUE;
+ }
+
+ if (profile != OMX_VIDEO_AVCProfileMax)
+ param.eProfile = profile;
+ if (level != OMX_VIDEO_AVCLevelMax)
+ param.eLevel = level;
+
+ err =
+ gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamVideoProfileLevelCurrent, &param);
+ if (err == OMX_ErrorUnsupportedIndex) {
+ GST_WARNING_OBJECT (self,
+ "Setting OMX_IndexParamVideoProfileLevelCurrent not supported by component");
+ return TRUE;
+ } else if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Error setting profile %u and level %u: %s (0x%08x)",
+ (guint) param.eProfile, (guint) param.eLevel,
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Update OMX_VIDEO_PARAM_AVCTYPE
+ *
+ * Returns TRUE if succeeded or if not supported, FALSE if failed */
+static gboolean
+update_param_avc (GstOMXH264Enc * self,
+ OMX_VIDEO_AVCPROFILETYPE profile, OMX_VIDEO_AVCLEVELTYPE level)
+{
+ OMX_VIDEO_PARAM_AVCTYPE param;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+
+ /* On Android the param struct is initialized manually with default
+ * settings rather than using GetParameter() to retrieve them.
+ * We should probably do the same when we'll add Android as target.
+ * See bgo#783862 for details. */
+
+ err =
+ gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamVideoAvc, &param);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self,
+ "Getting OMX_IndexParamVideoAvc not supported by component");
+ return TRUE;
+ }
+
+ if (profile != OMX_VIDEO_AVCProfileMax)
+ param.eProfile = profile;
+ if (level != OMX_VIDEO_AVCLevelMax)
+ param.eLevel = level;
+
+ /* GOP pattern */
+ if (self->interval_intraframes !=
+ GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT) {
+ param.nPFrames = self->interval_intraframes;
+
+ /* If user specified a specific number of B-frames, reduce the number of
+ * P-frames by this amount. If not ensure there is no B-frame to have the
+ * requested GOP length. */
+ if (self->b_frames != GST_OMX_H264_VIDEO_ENC_B_FRAMES_DEFAULT) {
+ if (self->b_frames > self->interval_intraframes) {
+ GST_ERROR_OBJECT (self,
+ "The interval_intraframes perdiod (%u) needs to be higher than the number of B-frames (%u)",
+ self->interval_intraframes, self->b_frames);
+ return FALSE;
+ }
+ param.nPFrames -= self->b_frames;
+ } else {
+ param.nBFrames = 0;
+ }
+ }
+
+ if (self->b_frames != GST_OMX_H264_VIDEO_ENC_B_FRAMES_DEFAULT) {
+ if (profile == OMX_VIDEO_AVCProfileBaseline && self->b_frames > 0) {
+ GST_ERROR_OBJECT (self,
+ "Baseline profile doesn't support B-frames (%u requested)",
+ self->b_frames);
+ return FALSE;
+ }
+ param.nBFrames = self->b_frames;
+ }
+
+ if (self->ref_frames != GST_OMX_H264_VIDEO_ENC_REF_FRAMES_DEFAULT)
+ param.nRefFrames = self->ref_frames;
+
+ if (self->entropy_mode != GST_OMX_H264_VIDEO_ENC_ENTROPY_MODE_DEFAULT) {
+ param.bEntropyCodingCABAC = self->entropy_mode;
+ }
+
+ param.bconstIpred = self->constrained_intra_prediction;
+
+ if (self->loop_filter_mode != GST_OMX_H264_VIDEO_ENC_LOOP_FILTER_MODE_DEFAULT) {
+ param.eLoopFilterMode = self->loop_filter_mode;
+ }
+
+ err =
+ gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamVideoAvc, &param);
+ if (err == OMX_ErrorUnsupportedIndex) {
+ GST_WARNING_OBJECT (self,
+ "Setting OMX_IndexParamVideoAvc not supported by component");
+ return TRUE;
+ } else if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Error setting AVC settings (profile %u and level %u): %s (0x%08x)",
+ (guint) param.eProfile, (guint) param.eLevel,
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+set_avc_intra_period (GstOMXH264Enc * self)
+{
+ OMX_VIDEO_CONFIG_AVCINTRAPERIOD config_avcintraperiod;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&config_avcintraperiod);
+ config_avcintraperiod.nPortIndex =
+ GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+ err =
+ gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexConfigVideoAVCIntraPeriod, &config_avcintraperiod);
+ if (err == OMX_ErrorUnsupportedIndex) {
+ GST_WARNING_OBJECT (self,
+ "OMX_IndexConfigVideoAVCIntraPeriod not supported by component");
+ return TRUE;
+ } else if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "can't get OMX_IndexConfigVideoAVCIntraPeriod %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ GST_DEBUG_OBJECT (self, "default nPFrames:%u, nIDRPeriod:%u",
+ (guint) config_avcintraperiod.nPFrames,
+ (guint) config_avcintraperiod.nIDRPeriod);
+
+ if (self->periodicty_idr !=
+ GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT) {
+ config_avcintraperiod.nIDRPeriod = self->periodicty_idr;
+ }
+
+ if (self->interval_intraframes !=
+ GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT) {
+ /* This OMX API doesn't allow us to specify the number of B-frames.
+ * So if user requested one we have to rely on update_param_avc()
+ * to configure the intraframes interval so it can take the
+ * B-frames into account. */
+ if (self->b_frames == GST_OMX_H264_VIDEO_ENC_B_FRAMES_DEFAULT)
+ config_avcintraperiod.nPFrames = self->interval_intraframes;
+ }
+
+ err =
+ gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexConfigVideoAVCIntraPeriod, &config_avcintraperiod);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "can't set OMX_IndexConfigVideoAVCIntraPeriod %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#ifdef USE_OMX_TARGET_RPI
+static gboolean
+set_brcm_video_intra_period (GstOMXH264Enc * self)
+{
+ OMX_PARAM_U32TYPE intra_period;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&intra_period);
+
+ intra_period.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+ err =
+ gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexConfigBrcmVideoIntraPeriod, &intra_period);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "can't get OMX_IndexConfigBrcmVideoIntraPeriod %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ GST_DEBUG_OBJECT (self, "default OMX_IndexConfigBrcmVideoIntraPeriod: %u",
+ (guint) intra_period.nU32);
+
+ if (self->interval_intraframes ==
+ GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT)
+ return TRUE;
+
+ intra_period.nU32 = self->interval_intraframes;
+
+ err =
+ gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexConfigBrcmVideoIntraPeriod, &intra_period);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "can't set OMX_IndexConfigBrcmVideoIntraPeriod %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ GST_DEBUG_OBJECT (self, "OMX_IndexConfigBrcmVideoIntraPeriod set to %u",
+ (guint) intra_period.nU32);
+
+ return TRUE;
+}
+#endif
+
+static gboolean
+gst_omx_h264_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ GstOMXH264Enc *self = GST_OMX_H264_ENC (enc);
+ GstCaps *peercaps;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+#ifdef USE_OMX_TARGET_RPI
+ OMX_CONFIG_PORTBOOLEANTYPE config_inline_header;
+#endif
+ OMX_ERRORTYPE err;
+ const gchar *profile_string, *level_string;
+ OMX_VIDEO_AVCPROFILETYPE profile = OMX_VIDEO_AVCProfileMax;
+ OMX_VIDEO_AVCLEVELTYPE level = OMX_VIDEO_AVCLevelMax;
+ gboolean enable_subframe = FALSE;
+
+#ifdef USE_OMX_TARGET_RPI
+ GST_OMX_INIT_STRUCT (&config_inline_header);
+ config_inline_header.nPortIndex =
+ GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+ err =
+ gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamBrcmVideoAVCInlineHeaderEnable, &config_inline_header);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "can't get OMX_IndexParamBrcmVideoAVCInlineHeaderEnable %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ if (self->inline_sps_pps_headers) {
+ config_inline_header.bEnabled = OMX_TRUE;
+ } else {
+ config_inline_header.bEnabled = OMX_FALSE;
+ }
+
+ err =
+ gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamBrcmVideoAVCInlineHeaderEnable, &config_inline_header);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "can't set OMX_IndexParamBrcmVideoAVCInlineHeaderEnable %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+#endif
+
+ /* Configure GOP pattern */
+ if (self->periodicty_idr !=
+ GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT
+ || self->interval_intraframes !=
+ GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT) {
+ set_avc_intra_period (self);
+ }
+#ifdef USE_OMX_TARGET_RPI
+ /* The Pi uses a specific OMX setting to configure the intra period */
+
+ if (self->interval_intraframes)
+ set_brcm_video_intra_period (self);
+#endif
+
+ gst_omx_port_get_port_definition (GST_OMX_VIDEO_ENC (self)->enc_out_port,
+ &port_def);
+ port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
+ err =
+ gst_omx_port_update_port_definition (GST_OMX_VIDEO_ENC
+ (self)->enc_out_port, &port_def);
+ if (err != OMX_ErrorNone)
+ return FALSE;
+
+ /* Set profile and level */
+ peercaps = gst_pad_peer_query_caps (GST_VIDEO_ENCODER_SRC_PAD (enc),
+ gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD (enc)));
+ if (peercaps) {
+ GstStructure *s;
+ const gchar *alignment_string;
+
+ if (gst_caps_is_empty (peercaps)) {
+ gst_caps_unref (peercaps);
+ GST_ERROR_OBJECT (self, "Empty caps");
+ return FALSE;
+ }
+
+ s = gst_caps_get_structure (peercaps, 0);
+ profile_string = gst_structure_get_string (s, "profile");
+ if (profile_string) {
+ profile = gst_omx_h264_utils_get_profile_from_str (profile_string);
+ if (profile == OMX_VIDEO_AVCProfileMax)
+ goto unsupported_profile;
+ }
+ level_string = gst_structure_get_string (s, "level");
+ if (level_string) {
+ level = gst_omx_h264_utils_get_level_from_str (level_string);
+ if (level == OMX_VIDEO_AVCLevelMax)
+ goto unsupported_level;
+ }
+
+ alignment_string = gst_structure_get_string (s, "alignment");
+ if (alignment_string && g_str_equal (alignment_string, "nal"))
+ enable_subframe = TRUE;
+
+ gst_caps_unref (peercaps);
+ }
+
+ if (profile != OMX_VIDEO_AVCProfileMax || level != OMX_VIDEO_AVCLevelMax) {
+ /* OMX provides 2 API to set the profile and level. We try using the
+ * generic one here and the H264 specific when calling
+ * update_param_avc() */
+ if (!update_param_profile_level (self, profile, level))
+ return FALSE;
+ }
+
+ gst_omx_port_set_subframe (GST_OMX_VIDEO_ENC (self)->enc_out_port,
+ enable_subframe);
+
+ if (!update_param_avc (self, profile, level))
+ return FALSE;
+
+ return TRUE;
+
+unsupported_profile:
+ GST_ERROR_OBJECT (self, "Unsupported profile %s", profile_string);
+ gst_caps_unref (peercaps);
+ return FALSE;
+
+unsupported_level:
+ GST_ERROR_OBJECT (self, "Unsupported level %s", level_string);
+ gst_caps_unref (peercaps);
+ return FALSE;
+}
+
+static GstCaps *
+gst_omx_h264_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ GstOMXH264Enc *self = GST_OMX_H264_ENC (enc);
+ GstCaps *caps;
+ OMX_ERRORTYPE err;
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+ const gchar *profile, *level, *alignment;
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+
+ err =
+ gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamVideoProfileLevelCurrent, &param);
+ if (err != OMX_ErrorNone && err != OMX_ErrorUnsupportedIndex)
+ return NULL;
+
+ if (gst_omx_port_get_subframe (GST_OMX_VIDEO_ENC (self)->enc_out_port))
+ alignment = "nal";
+ else
+ alignment = "au";
+
+ caps = gst_caps_new_simple ("video/x-h264",
+ "stream-format", G_TYPE_STRING, "byte-stream",
+ "alignment", G_TYPE_STRING, alignment, NULL);
+
+ if (err == OMX_ErrorNone) {
+ profile = gst_omx_h264_utils_get_profile_from_enum (param.eProfile);
+ if (!profile) {
+ g_assert_not_reached ();
+ gst_caps_unref (caps);
+ return NULL;
+ }
+
+ switch (param.eLevel) {
+ case OMX_VIDEO_AVCLevel1:
+ level = "1";
+ break;
+ case OMX_VIDEO_AVCLevel1b:
+ level = "1b";
+ break;
+ case OMX_VIDEO_AVCLevel11:
+ level = "1.1";
+ break;
+ case OMX_VIDEO_AVCLevel12:
+ level = "1.2";
+ break;
+ case OMX_VIDEO_AVCLevel13:
+ level = "1.3";
+ break;
+ case OMX_VIDEO_AVCLevel2:
+ level = "2";
+ break;
+ case OMX_VIDEO_AVCLevel21:
+ level = "2.1";
+ break;
+ case OMX_VIDEO_AVCLevel22:
+ level = "2.2";
+ break;
+ case OMX_VIDEO_AVCLevel3:
+ level = "3";
+ break;
+ case OMX_VIDEO_AVCLevel31:
+ level = "3.1";
+ break;
+ case OMX_VIDEO_AVCLevel32:
+ level = "3.2";
+ break;
+ case OMX_VIDEO_AVCLevel4:
+ level = "4";
+ break;
+ case OMX_VIDEO_AVCLevel41:
+ level = "4.1";
+ break;
+ case OMX_VIDEO_AVCLevel42:
+ level = "4.2";
+ break;
+ case OMX_VIDEO_AVCLevel5:
+ level = "5";
+ break;
+ case OMX_VIDEO_AVCLevel51:
+ level = "5.1";
+ break;
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ case OMX_ALG_VIDEO_AVCLevel52:
+ level = "5.2";
+ break;
+ case OMX_ALG_VIDEO_AVCLevel60:
+ level = "6.0";
+ break;
+ case OMX_ALG_VIDEO_AVCLevel61:
+ level = "6.1";
+ break;
+ case OMX_ALG_VIDEO_AVCLevel62:
+ level = "6.2";
+ break;
+#endif
+ default:
+ g_assert_not_reached ();
+ gst_caps_unref (caps);
+ return NULL;
+ }
+ gst_caps_set_simple (caps,
+ "profile", G_TYPE_STRING, profile, "level", G_TYPE_STRING, level, NULL);
+ }
+
+ return caps;
+}
+
+static GstFlowReturn
+gst_omx_h264_enc_handle_output_frame (GstOMXVideoEnc * enc, GstOMXPort * port,
+ GstOMXBuffer * buf, GstVideoCodecFrame * frame)
+{
+ GstOMXH264Enc *self = GST_OMX_H264_ENC (enc);
+
+ if (buf->omx_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
+ /* The codec data is SPS/PPS but our output is stream-format=byte-stream.
+ * For bytestream stream format the SPS/PPS is only in-stream and not
+ * in the caps!
+ */
+ GstBuffer *hdrs;
+ GstMapInfo map = GST_MAP_INFO_INIT;
+ GstFlowReturn flow_ret;
+
+ GST_DEBUG_OBJECT (self, "got codecconfig in byte-stream format");
+
+ hdrs = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
+ GST_BUFFER_FLAG_SET (hdrs, GST_BUFFER_FLAG_HEADER);
+
+ gst_buffer_map (hdrs, &map, GST_MAP_WRITE);
+ memcpy (map.data,
+ buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+ buf->omx_buf->nFilledLen);
+ gst_buffer_unmap (hdrs, &map);
+ self->headers = g_list_append (self->headers, gst_buffer_ref (hdrs));
+ frame->output_buffer = hdrs;
+ flow_ret =
+ gst_video_encoder_finish_subframe (GST_VIDEO_ENCODER (self), frame);
+ gst_video_codec_frame_unref (frame);
+
+ return flow_ret;
+ } else if (self->headers) {
+ gst_video_encoder_set_headers (GST_VIDEO_ENCODER (self), self->headers);
+ self->headers = NULL;
+ }
+
+ return
+ GST_OMX_VIDEO_ENC_CLASS
+ (gst_omx_h264_enc_parent_class)->handle_output_frame (enc, port, buf,
+ frame);
+}
diff --git a/subprojects/gst-omx/omx/gstomxh264enc.h b/subprojects/gst-omx/omx/gstomxh264enc.h
new file mode 100644
index 0000000000..4d67c86b02
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxh264enc.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_H264_ENC_H__
+#define __GST_OMX_H264_ENC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideoenc.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_H264_ENC \
+ (gst_omx_h264_enc_get_type())
+#define GST_OMX_H264_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_H264_ENC,GstOMXH264Enc))
+#define GST_OMX_H264_ENC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_H264_ENC,GstOMXH264EncClass))
+#define GST_OMX_H264_ENC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_H264_ENC,GstOMXH264EncClass))
+#define GST_IS_OMX_H264_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_H264_ENC))
+#define GST_IS_OMX_H264_ENC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_H264_ENC))
+
+typedef struct _GstOMXH264Enc GstOMXH264Enc;
+typedef struct _GstOMXH264EncClass GstOMXH264EncClass;
+
+struct _GstOMXH264Enc
+{
+ GstOMXVideoEnc parent;
+
+#ifdef USE_OMX_TARGET_RPI
+ gboolean inline_sps_pps_headers;
+#endif
+ guint32 periodicty_idr;
+ guint32 interval_intraframes;
+ guint32 b_frames;
+ guint32 entropy_mode;
+ gboolean constrained_intra_prediction;
+ guint32 loop_filter_mode;
+ guint8 ref_frames;
+
+ GList *headers;
+};
+
+struct _GstOMXH264EncClass
+{
+ GstOMXVideoEncClass parent_class;
+};
+
+GType gst_omx_h264_enc_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_H264_ENC_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxh264utils.c b/subprojects/gst-omx/omx/gstomxh264utils.c
new file mode 100644
index 0000000000..ba292115af
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxh264utils.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstomxh264utils.h"
+
+typedef struct
+{
+ const gchar *profile;
+ OMX_VIDEO_AVCPROFILETYPE e;
+} H264ProfileMapping;
+
+static const H264ProfileMapping h264_profiles[] = {
+ {"baseline", OMX_VIDEO_AVCProfileBaseline},
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ {"constrained-baseline",
+ (OMX_VIDEO_AVCPROFILETYPE) OMX_ALG_VIDEO_AVCProfileConstrainedBaseline},
+#else
+ {"constrained-baseline", OMX_VIDEO_AVCProfileBaseline},
+#endif
+ {"main", OMX_VIDEO_AVCProfileMain},
+ {"high", OMX_VIDEO_AVCProfileHigh},
+ {"high-10", OMX_VIDEO_AVCProfileHigh10},
+ {"high-4:2:2", OMX_VIDEO_AVCProfileHigh422},
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ {"progressive-high",
+ (OMX_VIDEO_AVCPROFILETYPE) OMX_ALG_VIDEO_AVCProfileProgressiveHigh},
+ {"constrained-high",
+ (OMX_VIDEO_AVCPROFILETYPE) OMX_ALG_VIDEO_AVCProfileConstrainedHigh},
+ {"high-10-intra",
+ (OMX_VIDEO_AVCPROFILETYPE) OMX_ALG_VIDEO_AVCProfileHigh10_Intra},
+ {"high-4:2:2-intra",
+ (OMX_VIDEO_AVCPROFILETYPE) OMX_ALG_VIDEO_AVCProfileHigh422_Intra},
+#endif
+};
+
+OMX_VIDEO_AVCPROFILETYPE
+gst_omx_h264_utils_get_profile_from_str (const gchar * profile)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (h264_profiles); i++) {
+ if (g_str_equal (profile, h264_profiles[i].profile))
+ return h264_profiles[i].e;
+ }
+
+ return OMX_VIDEO_AVCProfileMax;
+}
+
+const gchar *
+gst_omx_h264_utils_get_profile_from_enum (OMX_VIDEO_AVCPROFILETYPE e)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (h264_profiles); i++) {
+ if (e == h264_profiles[i].e)
+ return h264_profiles[i].profile;
+ }
+
+ return NULL;
+}
+
+OMX_VIDEO_AVCLEVELTYPE
+gst_omx_h264_utils_get_level_from_str (const gchar * level)
+{
+ if (g_str_equal (level, "1")) {
+ return OMX_VIDEO_AVCLevel1;
+ } else if (g_str_equal (level, "1b")) {
+ return OMX_VIDEO_AVCLevel1b;
+ } else if (g_str_equal (level, "1.1")) {
+ return OMX_VIDEO_AVCLevel11;
+ } else if (g_str_equal (level, "1.2")) {
+ return OMX_VIDEO_AVCLevel12;
+ } else if (g_str_equal (level, "1.3")) {
+ return OMX_VIDEO_AVCLevel13;
+ } else if (g_str_equal (level, "2")) {
+ return OMX_VIDEO_AVCLevel2;
+ } else if (g_str_equal (level, "2.1")) {
+ return OMX_VIDEO_AVCLevel21;
+ } else if (g_str_equal (level, "2.2")) {
+ return OMX_VIDEO_AVCLevel22;
+ } else if (g_str_equal (level, "3")) {
+ return OMX_VIDEO_AVCLevel3;
+ } else if (g_str_equal (level, "3.1")) {
+ return OMX_VIDEO_AVCLevel31;
+ } else if (g_str_equal (level, "3.2")) {
+ return OMX_VIDEO_AVCLevel32;
+ } else if (g_str_equal (level, "4")) {
+ return OMX_VIDEO_AVCLevel4;
+ } else if (g_str_equal (level, "4.1")) {
+ return OMX_VIDEO_AVCLevel41;
+ } else if (g_str_equal (level, "4.2")) {
+ return OMX_VIDEO_AVCLevel42;
+ } else if (g_str_equal (level, "5")) {
+ return OMX_VIDEO_AVCLevel5;
+ } else if (g_str_equal (level, "5.1")) {
+ return OMX_VIDEO_AVCLevel51;
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ } else if (g_str_equal (level, "5.2")) {
+ return (OMX_VIDEO_AVCLEVELTYPE) OMX_ALG_VIDEO_AVCLevel52;
+ } else if (g_str_equal (level, "6.0")) {
+ return (OMX_VIDEO_AVCLEVELTYPE) OMX_ALG_VIDEO_AVCLevel60;
+ } else if (g_str_equal (level, "6.1")) {
+ return (OMX_VIDEO_AVCLEVELTYPE) OMX_ALG_VIDEO_AVCLevel61;
+ } else if (g_str_equal (level, "6.2")) {
+ return (OMX_VIDEO_AVCLEVELTYPE) OMX_ALG_VIDEO_AVCLevel62;
+#endif
+ }
+
+ return OMX_VIDEO_AVCLevelMax;
+}
diff --git a/subprojects/gst-omx/omx/gstomxh264utils.h b/subprojects/gst-omx/omx/gstomxh264utils.h
new file mode 100644
index 0000000000..e5c35e4f24
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxh264utils.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_H264_UTILS_H__
+#define __GST_OMX_H264_UTILS_H__
+
+#include "gstomx.h"
+
+G_BEGIN_DECLS
+
+OMX_VIDEO_AVCPROFILETYPE gst_omx_h264_utils_get_profile_from_str (const
+ gchar * profile);
+OMX_VIDEO_AVCLEVELTYPE gst_omx_h264_utils_get_level_from_str (const gchar *
+ level);
+
+const gchar * gst_omx_h264_utils_get_profile_from_enum (OMX_VIDEO_AVCPROFILETYPE e);
+
+G_END_DECLS
+#endif /* __GST_OMX_H264_UTILS_H__ */
diff --git a/subprojects/gst-omx/omx/gstomxh265dec.c b/subprojects/gst-omx/omx/gstomxh265dec.c
new file mode 100644
index 0000000000..f8abf419f7
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxh265dec.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2017 Xilinx, Inc.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxh265dec.h"
+#include "gstomxh265utils.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_h265_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_h265_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_h265_dec_is_format_change (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state);
+static gboolean gst_omx_h265_dec_set_format (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state);
+
+enum
+{
+ PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_h265_dec_debug_category, "omxh265dec", 0, \
+ "debug category for gst-omx H265 video decoder");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXH265Dec, gst_omx_h265_dec,
+ GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT);
+
+#define MAKE_CAPS(alignment) \
+ "video/x-h265, " \
+ "alignment=(string) " alignment ", " \
+ "stream-format=(string) byte-stream, " \
+ "width=(int) [1,MAX], height=(int) [1,MAX]"
+
+/* The Zynq MPSoC supports decoding subframes though we want "au" to be the
+ * default, so we keep it prepended. This is the only way that it works with
+ * rtph265depay. */
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+#define SINK_CAPS MAKE_CAPS ("au") ";" MAKE_CAPS ("nal");
+#else
+#define SINK_CAPS MAKE_CAPS ("au")
+#endif
+
+static void
+gst_omx_h265_dec_class_init (GstOMXH265DecClass * klass)
+{
+ GstOMXVideoDecClass *videodec_class = GST_OMX_VIDEO_DEC_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ videodec_class->is_format_change =
+ GST_DEBUG_FUNCPTR (gst_omx_h265_dec_is_format_change);
+ videodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_h265_dec_set_format);
+
+ videodec_class->cdata.default_sink_template_caps = SINK_CAPS;
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX H.265 Video Decoder",
+ "Codec/Decoder/Video/Hardware",
+ "Decode H.265 video streams",
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+ gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.hevc");
+}
+
+static void
+gst_omx_h265_dec_init (GstOMXH265Dec * self)
+{
+}
+
+static gboolean
+gst_omx_h265_dec_is_format_change (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state)
+{
+ GstCaps *old_caps = NULL;
+ GstCaps *new_caps = state->caps;
+ GstStructure *old_structure, *new_structure;
+ const gchar *old_profile, *old_level, *old_tier, *old_alignment,
+ *new_profile, *new_level, *new_tier, *new_alignment;
+
+ if (dec->input_state) {
+ old_caps = dec->input_state->caps;
+ }
+
+ if (!old_caps) {
+ return FALSE;
+ }
+
+ old_structure = gst_caps_get_structure (old_caps, 0);
+ new_structure = gst_caps_get_structure (new_caps, 0);
+ old_profile = gst_structure_get_string (old_structure, "profile");
+ old_level = gst_structure_get_string (old_structure, "level");
+ old_tier = gst_structure_get_string (old_structure, "tier");
+ old_alignment = gst_structure_get_string (old_structure, "alignment");
+ new_profile = gst_structure_get_string (new_structure, "profile");
+ new_level = gst_structure_get_string (new_structure, "level");
+ new_tier = gst_structure_get_string (new_structure, "tier");
+ new_alignment = gst_structure_get_string (new_structure, "alignment");
+
+ if (g_strcmp0 (old_profile, new_profile) != 0
+ || g_strcmp0 (old_level, new_level) != 0
+ || g_strcmp0 (old_tier, new_tier) != 0
+ || g_strcmp0 (old_alignment, new_alignment) != 0) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+set_profile_and_level (GstOMXH265Dec * self, GstVideoCodecState * state)
+{
+ OMX_ERRORTYPE err;
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+ const gchar *profile_string, *level_string, *tier_string;
+ GstStructure *s;
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = GST_OMX_VIDEO_DEC (self)->dec_in_port->index;
+
+ /* Pass profile, level and tier to the decoder if we have all info from the
+ * caps. */
+ s = gst_caps_get_structure (state->caps, 0);
+ profile_string = gst_structure_get_string (s, "profile");
+ if (!profile_string)
+ return TRUE;
+
+ param.eProfile = gst_omx_h265_utils_get_profile_from_str (profile_string);
+ if (param.eProfile == OMX_VIDEO_HEVCProfileUnknown)
+ goto unsupported_profile;
+
+ level_string = gst_structure_get_string (s, "level");
+ tier_string = gst_structure_get_string (s, "tier");
+ if (!level_string || !tier_string)
+ return TRUE;
+
+ param.eLevel =
+ gst_omx_h265_utils_get_level_from_str (level_string, tier_string);
+ if (param.eLevel == OMX_VIDEO_HEVCLevelUnknown)
+ goto unsupported_level;
+
+ GST_DEBUG_OBJECT (self,
+ "Set profile (%s) level (%s) and tier (%s) on decoder", profile_string,
+ level_string, tier_string);
+
+ err =
+ gst_omx_component_set_parameter (GST_OMX_VIDEO_DEC (self)->dec,
+ OMX_IndexParamVideoProfileLevelCurrent, &param);
+ if (err == OMX_ErrorUnsupportedIndex) {
+ GST_WARNING_OBJECT (self,
+ "Setting profile/level not supported by component");
+ } else if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Error setting profile %u and level %u: %s (0x%08x)",
+ (guint) param.eProfile, (guint) param.eLevel,
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+
+unsupported_profile:
+ GST_ERROR_OBJECT (self, "Unsupported profile %s", profile_string);
+ return FALSE;
+
+unsupported_level:
+ GST_ERROR_OBJECT (self, "Unsupported level %s", level_string);
+ return FALSE;
+}
+
+static gboolean
+gst_omx_h265_dec_set_format (GstOMXVideoDec * dec, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ GstOMXVideoDecClass *klass = GST_OMX_VIDEO_DEC_GET_CLASS (dec);
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ OMX_ERRORTYPE err;
+ const GstStructure *s;
+
+ gst_omx_port_get_port_definition (port, &port_def);
+ port_def.format.video.eCompressionFormat =
+ (OMX_VIDEO_CODINGTYPE) OMX_VIDEO_CodingHEVC;
+ err = gst_omx_port_update_port_definition (port, &port_def);
+ if (err != OMX_ErrorNone)
+ return FALSE;
+
+ if (klass->cdata.hacks & GST_OMX_HACK_PASS_PROFILE_TO_DECODER) {
+ if (!set_profile_and_level (GST_OMX_H265_DEC (dec), state))
+ return FALSE;
+ }
+
+ /* Enable subframe mode if NAL aligned */
+ s = gst_caps_get_structure (state->caps, 0);
+ if (!g_strcmp0 (gst_structure_get_string (s, "alignment"), "nal")
+ && gst_omx_port_set_subframe (dec->dec_in_port, TRUE)) {
+ gst_video_decoder_set_subframe_mode (GST_VIDEO_DECODER (dec), TRUE);
+ }
+
+ return TRUE;
+}
diff --git a/subprojects/gst-omx/omx/gstomxh265dec.h b/subprojects/gst-omx/omx/gstomxh265dec.h
new file mode 100644
index 0000000000..f0f1016ae1
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxh265dec.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2017 Xilinx, Inc.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_H265_DEC_H__
+#define __GST_OMX_H265_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_H265_DEC \
+ (gst_omx_h265_dec_get_type())
+#define GST_OMX_H265_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_H265_DEC,GstOMXH265Dec))
+#define GST_OMX_H265_DEC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_H265_DEC,GstOMXH265DecClass))
+#define GST_OMX_H265_DEC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_H265_DEC,GstOMXH265DecClass))
+#define GST_IS_OMX_H265_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_H265_DEC))
+#define GST_IS_OMX_H265_DEC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_H265_DEC))
+
+typedef struct _GstOMXH265Dec GstOMXH265Dec;
+typedef struct _GstOMXH265DecClass GstOMXH265DecClass;
+
+struct _GstOMXH265Dec
+{
+ GstOMXVideoDec parent;
+};
+
+struct _GstOMXH265DecClass
+{
+ GstOMXVideoDecClass parent_class;
+};
+
+GType gst_omx_h265_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_H265_DEC_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxh265enc.c b/subprojects/gst-omx/omx/gstomxh265enc.c
new file mode 100644
index 0000000000..8b31c42414
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxh265enc.c
@@ -0,0 +1,748 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2017 Xilinx, Inc.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxh265enc.h"
+#include "gstomxh265utils.h"
+#include "gstomxvideo.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_h265_enc_debug_category);
+#define GST_CAT_DEFAULT gst_omx_h265_enc_debug_category
+
+/* prototypes */
+static gboolean gst_omx_h265_enc_set_format (GstOMXVideoEnc * enc,
+ GstOMXPort * port, GstVideoCodecState * state);
+static GstCaps *gst_omx_h265_enc_get_caps (GstOMXVideoEnc * enc,
+ GstOMXPort * port, GstVideoCodecState * state);
+static void gst_omx_h265_enc_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_omx_h265_enc_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+static GstFlowReturn gst_omx_h265_enc_handle_output_frame (GstOMXVideoEnc *
+ self, GstOMXPort * port, GstOMXBuffer * buf, GstVideoCodecFrame * frame);
+
+enum
+{
+ PROP_0,
+ PROP_PERIODICITYOFIDRFRAMES,
+ PROP_INTERVALOFCODINGINTRAFRAMES,
+ PROP_B_FRAMES,
+ PROP_CONSTRAINED_INTRA_PREDICTION,
+ PROP_LOOP_FILTER_MODE,
+};
+
+#define GST_OMX_H265_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT (0xffffffff)
+#define GST_OMX_H265_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT (0xffffffff)
+#define GST_OMX_H265_VIDEO_ENC_B_FRAMES_DEFAULT (0xffffffff)
+#define GST_OMX_H265_VIDEO_ENC_CONSTRAINED_INTRA_PREDICTION_DEFAULT (FALSE)
+#define GST_OMX_H265_VIDEO_ENC_LOOP_FILTER_MODE_DEFAULT (0xffffffff)
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+/* zynqultrascaleplus's OMX uses a param struct different of Android's one */
+#define INDEX_PARAM_VIDEO_HEVC OMX_ALG_IndexParamVideoHevc
+#define ALIGNMENT "{ au, nal }"
+#else
+#define INDEX_PARAM_VIDEO_HEVC OMX_IndexParamVideoHevc
+#define ALIGNMENT "au"
+#endif
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_h265_enc_debug_category, "omxh265enc", 0, \
+ "debug category for gst-omx H265 video encoder");
+
+#define parent_class gst_omx_h265_enc_parent_class
+G_DEFINE_TYPE_WITH_CODE (GstOMXH265Enc, gst_omx_h265_enc,
+ GST_TYPE_OMX_VIDEO_ENC, DEBUG_INIT);
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+#define GST_TYPE_OMX_H265_ENC_LOOP_FILTER_MODE (gst_omx_h265_enc_loop_filter_mode_get_type ())
+static GType
+gst_omx_h265_enc_loop_filter_mode_get_type (void)
+{
+ static GType qtype = 0;
+
+ if (qtype == 0) {
+ static const GEnumValue values[] = {
+ {OMX_ALG_VIDEO_HEVCLoopFilterEnable, "Enable deblocking filter",
+ "enable"},
+ {OMX_ALG_VIDEO_HEVCLoopFilterDisable, "Disable deblocking filter",
+ "disable"},
+ {OMX_ALG_VIDEO_HEVCLoopFilterDisableCrossSlice,
+ "Disable deblocking filter on slice boundary", "disable-cross-slice"},
+ {OMX_ALG_VIDEO_HEVCLoopFilterDisableCrossTile,
+ "Disable deblocking filter on tile boundary", "disable-cross-tile"},
+ {OMX_ALG_VIDEO_HEVCLoopFilterDisableCrossSliceAndTile,
+ "Disable deblocking filter on slice and tile boundary",
+ "disable-slice-and-tile"},
+ {0xffffffff, "Component Default", "default"},
+ {0, NULL, NULL}
+ };
+
+ qtype = g_enum_register_static ("GstOMXH265EncLoopFilter", values);
+ }
+ return qtype;
+}
+#endif
+
+static gboolean
+gst_omx_h265_enc_flush (GstVideoEncoder * enc)
+{
+ GstOMXH265Enc *self = GST_OMX_H265_ENC (enc);
+
+ g_list_free_full (self->headers, (GDestroyNotify) gst_buffer_unref);
+ self->headers = NULL;
+
+ return GST_VIDEO_ENCODER_CLASS (parent_class)->flush (enc);
+}
+
+static gboolean
+gst_omx_h265_enc_stop (GstVideoEncoder * enc)
+{
+ GstOMXH265Enc *self = GST_OMX_H265_ENC (enc);
+
+ g_list_free_full (self->headers, (GDestroyNotify) gst_buffer_unref);
+ self->headers = NULL;
+
+ return GST_VIDEO_ENCODER_CLASS (parent_class)->stop (enc);
+}
+
+static void
+gst_omx_h265_enc_class_init (GstOMXH265EncClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstVideoEncoderClass *basevideoenc_class = GST_VIDEO_ENCODER_CLASS (klass);
+ GstOMXVideoEncClass *videoenc_class = GST_OMX_VIDEO_ENC_CLASS (klass);
+
+ videoenc_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_h265_enc_set_format);
+ videoenc_class->get_caps = GST_DEBUG_FUNCPTR (gst_omx_h265_enc_get_caps);
+ videoenc_class->handle_output_frame =
+ GST_DEBUG_FUNCPTR (gst_omx_h265_enc_handle_output_frame);
+
+ basevideoenc_class->flush = gst_omx_h265_enc_flush;
+ basevideoenc_class->stop = gst_omx_h265_enc_stop;
+
+ gobject_class->set_property = gst_omx_h265_enc_set_property;
+ gobject_class->get_property = gst_omx_h265_enc_get_property;
+
+ g_object_class_install_property (gobject_class,
+ PROP_INTERVALOFCODINGINTRAFRAMES,
+ g_param_spec_uint ("interval-intraframes",
+ "Interval of coding Intra frames",
+ "Interval of coding Intra frames (0xffffffff=component default)", 0,
+ G_MAXUINT,
+ GST_OMX_H265_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ g_object_class_install_property (gobject_class, PROP_PERIODICITYOFIDRFRAMES,
+ g_param_spec_uint ("periodicity-idr", "IDR periodicity",
+ "Periodicity of IDR frames (0xffffffff=component default)",
+ 0, G_MAXUINT,
+ GST_OMX_H265_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_B_FRAMES,
+ g_param_spec_uint ("b-frames", "Number of B-frames",
+ "Number of B-frames between two consecutive I-frames (0xffffffff=component default)",
+ 0, G_MAXUINT, GST_OMX_H265_VIDEO_ENC_B_FRAMES_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class,
+ PROP_CONSTRAINED_INTRA_PREDICTION,
+ g_param_spec_boolean ("constrained-intra-prediction",
+ "Constrained Intra Prediction",
+ "If enabled, prediction only uses residual data and decoded samples "
+ "from neighbouring coding blocks coded using intra prediction modes",
+ GST_OMX_H265_VIDEO_ENC_CONSTRAINED_INTRA_PREDICTION_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_LOOP_FILTER_MODE,
+ g_param_spec_enum ("loop-filter-mode", "Loop Filter mode",
+ "Enable or disable the deblocking filter (0xffffffff=component default)",
+ GST_TYPE_OMX_H265_ENC_LOOP_FILTER_MODE,
+ GST_OMX_H265_VIDEO_ENC_LOOP_FILTER_MODE_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+#endif
+
+ videoenc_class->cdata.default_sink_template_caps =
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_FORMAT_INTERLACED,
+ GST_OMX_VIDEO_ENC_SUPPORTED_FORMATS)
+ ", interlace-mode = (string) alternate ; "
+#endif
+ GST_VIDEO_CAPS_MAKE (GST_OMX_VIDEO_ENC_SUPPORTED_FORMATS);
+
+ videoenc_class->cdata.default_src_template_caps = "video/x-h265, "
+ "width=(int) [ 1, MAX ], " "height=(int) [ 1, MAX ], "
+ "framerate = (fraction) [0, MAX], stream-format=(string) byte-stream, "
+ "aligmment = (string) " ALIGNMENT;
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX H.265 Video Encoder",
+ "Codec/Encoder/Video/Hardware",
+ "Encode H.265 video streams",
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+ gst_omx_set_default_role (&videoenc_class->cdata, "video_encoder.hevc");
+}
+
+static void
+gst_omx_h265_enc_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstOMXH265Enc *self = GST_OMX_H265_ENC (object);
+
+ switch (prop_id) {
+ case PROP_INTERVALOFCODINGINTRAFRAMES:
+ self->interval_intraframes = g_value_get_uint (value);
+ break;
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ case PROP_PERIODICITYOFIDRFRAMES:
+ self->periodicity_idr = g_value_get_uint (value);
+ break;
+ case PROP_B_FRAMES:
+ self->b_frames = g_value_get_uint (value);
+ break;
+ case PROP_CONSTRAINED_INTRA_PREDICTION:
+ self->constrained_intra_prediction = g_value_get_boolean (value);
+ break;
+ case PROP_LOOP_FILTER_MODE:
+ self->loop_filter_mode = g_value_get_enum (value);
+ break;
+#endif
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_omx_h265_enc_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec)
+{
+ GstOMXH265Enc *self = GST_OMX_H265_ENC (object);
+
+ switch (prop_id) {
+ case PROP_INTERVALOFCODINGINTRAFRAMES:
+ g_value_set_uint (value, self->interval_intraframes);
+ break;
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ case PROP_PERIODICITYOFIDRFRAMES:
+ g_value_set_uint (value, self->periodicity_idr);
+ break;
+ case PROP_B_FRAMES:
+ g_value_set_uint (value, self->b_frames);
+ break;
+ case PROP_CONSTRAINED_INTRA_PREDICTION:
+ g_value_set_boolean (value, self->constrained_intra_prediction);
+ break;
+ case PROP_LOOP_FILTER_MODE:
+ g_value_set_enum (value, self->loop_filter_mode);
+ break;
+#endif
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_omx_h265_enc_init (GstOMXH265Enc * self)
+{
+ self->interval_intraframes =
+ GST_OMX_H265_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT;
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ self->periodicity_idr =
+ GST_OMX_H265_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT;
+ self->b_frames = GST_OMX_H265_VIDEO_ENC_B_FRAMES_DEFAULT;
+ self->constrained_intra_prediction =
+ GST_OMX_H265_VIDEO_ENC_CONSTRAINED_INTRA_PREDICTION_DEFAULT;
+ self->loop_filter_mode = GST_OMX_H265_VIDEO_ENC_LOOP_FILTER_MODE_DEFAULT;
+#endif
+}
+
+/* Update OMX_VIDEO_PARAM_PROFILELEVELTYPE.{eProfile,eLevel}
+ *
+ * Returns TRUE if succeeded or if not supported, FALSE if failed */
+static gboolean
+update_param_profile_level (GstOMXH265Enc * self,
+ OMX_VIDEO_HEVCPROFILETYPE profile, OMX_VIDEO_HEVCLEVELTYPE level)
+{
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+
+ err =
+ gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamVideoProfileLevelCurrent, &param);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self,
+ "Getting OMX_IndexParamVideoProfileLevelCurrent not supported by component");
+ return TRUE;
+ }
+
+ if (profile != OMX_VIDEO_HEVCProfileUnknown)
+ param.eProfile = profile;
+ if (level != OMX_VIDEO_HEVCLevelUnknown)
+ param.eLevel = level;
+
+ err =
+ gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamVideoProfileLevelCurrent, &param);
+ if (err == OMX_ErrorUnsupportedIndex) {
+ GST_WARNING_OBJECT (self,
+ "Setting OMX_IndexParamVideoProfileLevelCurrent not supported by component");
+ return TRUE;
+ } else if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Error setting profile %u and level %u: %s (0x%08x)",
+ (guint) param.eProfile, (guint) param.eLevel,
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Update OMX_ALG_VIDEO_PARAM_HEVCTYPE
+ *
+ * Returns TRUE if succeeded or if not supported, FALSE if failed */
+static gboolean
+update_param_hevc (GstOMXH265Enc * self,
+ OMX_VIDEO_HEVCPROFILETYPE profile, OMX_VIDEO_HEVCLEVELTYPE level)
+{
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ OMX_ALG_VIDEO_PARAM_HEVCTYPE param;
+#else
+ OMX_VIDEO_PARAM_HEVCTYPE param;
+#endif
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+
+ /* On Android the param struct is initialized manually with default
+ * settings rather than using GetParameter() to retrieve them.
+ * We should probably do the same when we'll add Android as target.
+ * See bgo#783862 for details. */
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ param.bConstIpred = self->constrained_intra_prediction;
+
+ if (self->loop_filter_mode != GST_OMX_H265_VIDEO_ENC_LOOP_FILTER_MODE_DEFAULT)
+ param.eLoopFilterMode = self->loop_filter_mode;
+
+ err =
+ gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoHevc, &param);
+#else
+ err =
+ gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ (OMX_INDEXTYPE) OMX_IndexParamVideoHevc, &param);
+#endif
+
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self,
+ "Getting OMX_ALG_IndexParamVideoHevc not supported by component");
+ return TRUE;
+ }
+
+ if (profile != OMX_VIDEO_HEVCProfileUnknown)
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ param.eProfile = (OMX_ALG_VIDEO_HEVCPROFILETYPE) profile;
+#else
+ param.eProfile = profile;
+#endif
+
+ if (level != OMX_VIDEO_HEVCLevelUnknown)
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ param.eLevel = (OMX_ALG_VIDEO_HEVCLEVELTYPE) level;
+#else
+ param.eLevel = level;
+#endif
+
+ /* GOP pattern */
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ /* The zynqultrascaleplus uses another PARAM_HEVCTYPE API allowing users to
+ * define the number of P and B frames while Android's API only expose the
+ * former. */
+ if (self->interval_intraframes !=
+ GST_OMX_H265_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT) {
+ param.nPFrames = self->interval_intraframes;
+
+ /* If user specified a specific number of B-frames, reduce the number of
+ * P-frames by this amount. If not ensure there is no B-frame to have the
+ * requested GOP length. */
+ if (self->b_frames != GST_OMX_H265_VIDEO_ENC_B_FRAMES_DEFAULT) {
+ if (self->b_frames > self->interval_intraframes) {
+ GST_ERROR_OBJECT (self,
+ "The interval_intraframes perdiod (%u) needs to be higher than the number of B-frames (%u)",
+ self->interval_intraframes, self->b_frames);
+ return FALSE;
+ }
+ param.nPFrames -= self->b_frames;
+ } else {
+ param.nBFrames = 0;
+ }
+ }
+
+ if (self->b_frames != GST_OMX_H265_VIDEO_ENC_B_FRAMES_DEFAULT)
+ param.nBFrames = self->b_frames;
+#else
+ if (self->interval_intraframes !=
+ GST_OMX_H265_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT)
+ param.nKeyFrameInterval = self->interval_intraframes;
+#endif
+
+ err =
+ gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ (OMX_INDEXTYPE) INDEX_PARAM_VIDEO_HEVC, &param);
+
+ if (err == OMX_ErrorUnsupportedIndex) {
+ GST_WARNING_OBJECT (self,
+ "Setting IndexParamVideoHevc not supported by component");
+ return TRUE;
+ } else if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Error setting HEVC settings (profile %u and level %u): %s (0x%08x)",
+ (guint) param.eProfile, (guint) param.eLevel,
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+static gboolean
+set_intra_period (GstOMXH265Enc * self)
+{
+ OMX_ALG_VIDEO_PARAM_INSTANTANEOUS_DECODING_REFRESH config_idr;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&config_idr);
+ config_idr.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+
+ GST_DEBUG_OBJECT (self, "nIDRPeriod:%u",
+ (guint) config_idr.nInstantaneousDecodingRefreshFrequency);
+
+ config_idr.nInstantaneousDecodingRefreshFrequency = self->periodicity_idr;
+
+ err =
+ gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoInstantaneousDecodingRefresh,
+ &config_idr);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "can't set OMX_IndexConfigVideoAVCIntraPeriod %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+#endif
+
+static gboolean
+gst_omx_h265_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ GstOMXH265Enc *self = GST_OMX_H265_ENC (enc);
+ GstCaps *peercaps;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ OMX_ERRORTYPE err;
+ const gchar *profile_string, *level_string, *tier_string;
+ OMX_VIDEO_HEVCPROFILETYPE profile = OMX_VIDEO_HEVCProfileUnknown;
+ OMX_VIDEO_HEVCLEVELTYPE level = OMX_VIDEO_HEVCLevelUnknown;
+ gboolean enable_subframe = FALSE;
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ if (self->periodicity_idr !=
+ GST_OMX_H265_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT)
+ set_intra_period (self);
+#endif
+
+ gst_omx_port_get_port_definition (GST_OMX_VIDEO_ENC (self)->enc_out_port,
+ &port_def);
+ port_def.format.video.eCompressionFormat =
+ (OMX_VIDEO_CODINGTYPE) OMX_VIDEO_CodingHEVC;
+ err =
+ gst_omx_port_update_port_definition (GST_OMX_VIDEO_ENC
+ (self)->enc_out_port, &port_def);
+ if (err != OMX_ErrorNone)
+ return FALSE;
+
+ /* Set profile and level */
+ peercaps = gst_pad_peer_query_caps (GST_VIDEO_ENCODER_SRC_PAD (enc),
+ gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD (enc)));
+ if (peercaps) {
+ GstStructure *s;
+ const gchar *alignment_string;
+
+ if (gst_caps_is_empty (peercaps)) {
+ gst_caps_unref (peercaps);
+ GST_ERROR_OBJECT (self, "Empty caps");
+ return FALSE;
+ }
+
+ s = gst_caps_get_structure (peercaps, 0);
+ profile_string = gst_structure_get_string (s, "profile");
+ if (profile_string) {
+ profile = gst_omx_h265_utils_get_profile_from_str (profile_string);
+ if (profile == OMX_VIDEO_HEVCProfileUnknown)
+ goto unsupported_profile;
+ }
+
+ level_string = gst_structure_get_string (s, "level");
+ tier_string = gst_structure_get_string (s, "tier");
+ if (level_string && tier_string) {
+ level = gst_omx_h265_utils_get_level_from_str (level_string, tier_string);
+ if (level == OMX_VIDEO_HEVCLevelUnknown)
+ goto unsupported_level;
+ }
+
+ alignment_string = gst_structure_get_string (s, "alignment");
+ if (alignment_string && g_str_equal (alignment_string, "nal"))
+ enable_subframe = TRUE;
+
+ gst_caps_unref (peercaps);
+ }
+
+ if (profile != OMX_VIDEO_HEVCProfileUnknown
+ || level != OMX_VIDEO_HEVCLevelUnknown) {
+ /* OMX provides 2 API to set the profile and level. We try using the
+ * generic one here and the H265 specific when calling
+ * update_param_hevc() */
+ if (!update_param_profile_level (self, profile, level))
+ return FALSE;
+ }
+
+ if (!update_param_hevc (self, profile, level))
+ return FALSE;
+
+ gst_omx_port_set_subframe (GST_OMX_VIDEO_ENC (self)->enc_out_port,
+ enable_subframe);
+
+ return TRUE;
+
+unsupported_profile:
+ GST_ERROR_OBJECT (self, "Unsupported profile %s", profile_string);
+ gst_caps_unref (peercaps);
+ return FALSE;
+
+unsupported_level:
+ GST_ERROR_OBJECT (self, "Unsupported level %s", level_string);
+ gst_caps_unref (peercaps);
+ return FALSE;
+}
+
+static GstCaps *
+gst_omx_h265_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ GstOMXH265Enc *self = GST_OMX_H265_ENC (enc);
+ GstCaps *caps;
+ OMX_ERRORTYPE err;
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+ const gchar *profile, *level, *tier, *alignment;
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+
+ err =
+ gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamVideoProfileLevelCurrent, &param);
+ if (err != OMX_ErrorNone && err != OMX_ErrorUnsupportedIndex)
+ return NULL;
+
+ if (gst_omx_port_get_subframe (GST_OMX_VIDEO_ENC (self)->enc_out_port))
+ alignment = "nal";
+ else
+ alignment = "au";
+
+ caps = gst_caps_new_simple ("video/x-h265",
+ "stream-format", G_TYPE_STRING, "byte-stream",
+ "alignment", G_TYPE_STRING, alignment, NULL);
+
+ if (err == OMX_ErrorNone) {
+ profile = gst_omx_h265_utils_get_profile_from_enum (param.eProfile);
+ if (!profile) {
+ g_assert_not_reached ();
+ gst_caps_unref (caps);
+ return NULL;
+ }
+
+ switch (param.eLevel) {
+ case OMX_VIDEO_HEVCMainTierLevel1:
+ tier = "main";
+ level = "1";
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel2:
+ tier = "main";
+ level = "2";
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel21:
+ tier = "main";
+ level = "2.1";
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel3:
+ tier = "main";
+ level = "3";
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel31:
+ tier = "main";
+ level = "3.1";
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel4:
+ tier = "main";
+ level = "4";
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel41:
+ tier = "main";
+ level = "4.1";
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel5:
+ tier = "main";
+ level = "5";
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel51:
+ tier = "main";
+ level = "5.1";
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel52:
+ tier = "main";
+ level = "5.2";
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel6:
+ tier = "main";
+ level = "6";
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel61:
+ tier = "main";
+ level = "6.1";
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel62:
+ tier = "main";
+ level = "6.2";
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel4:
+ tier = "high";
+ level = "4";
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel41:
+ tier = "high";
+ level = "4.1";
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel5:
+ tier = "high";
+ level = "5";
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel51:
+ tier = "high";
+ level = "5.1";
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel52:
+ tier = "high";
+ level = "5.2";
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel6:
+ tier = "high";
+ level = "6";
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel61:
+ tier = "high";
+ level = "6.1";
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel62:
+ tier = "high";
+ level = "6.2";
+ break;
+ default:
+ g_assert_not_reached ();
+ gst_caps_unref (caps);
+ return NULL;
+ }
+
+ gst_caps_set_simple (caps,
+ "profile", G_TYPE_STRING, profile, "level", G_TYPE_STRING, level,
+ "tier", G_TYPE_STRING, tier, NULL);
+ }
+
+ return caps;
+}
+
+static GstFlowReturn
+gst_omx_h265_enc_handle_output_frame (GstOMXVideoEnc * enc, GstOMXPort * port,
+ GstOMXBuffer * buf, GstVideoCodecFrame * frame)
+{
+ GstOMXH265Enc *self = GST_OMX_H265_ENC (enc);
+
+ if (buf->omx_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
+ /* The codec data is SPS/PPS but our output is stream-format=byte-stream.
+ * For bytestream stream format the SPS/PPS is only in-stream and not
+ * in the caps!
+ */
+ GstBuffer *hdrs;
+ GstMapInfo map = GST_MAP_INFO_INIT;
+ GstFlowReturn flow_ret;
+
+ GST_DEBUG_OBJECT (self, "got codecconfig in byte-stream format");
+
+ hdrs = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
+ GST_BUFFER_FLAG_SET (hdrs, GST_BUFFER_FLAG_HEADER);
+
+ gst_buffer_map (hdrs, &map, GST_MAP_WRITE);
+ memcpy (map.data,
+ buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+ buf->omx_buf->nFilledLen);
+ gst_buffer_unmap (hdrs, &map);
+ self->headers = g_list_append (self->headers, gst_buffer_ref (hdrs));
+ frame->output_buffer = hdrs;
+ flow_ret =
+ gst_video_encoder_finish_subframe (GST_VIDEO_ENCODER (self), frame);
+ gst_video_codec_frame_unref (frame);
+
+ return flow_ret;
+ } else if (self->headers) {
+ gst_video_encoder_set_headers (GST_VIDEO_ENCODER (self), self->headers);
+ self->headers = NULL;
+ }
+
+ return
+ GST_OMX_VIDEO_ENC_CLASS
+ (gst_omx_h265_enc_parent_class)->handle_output_frame (enc, port, buf,
+ frame);
+}
diff --git a/subprojects/gst-omx/omx/gstomxh265enc.h b/subprojects/gst-omx/omx/gstomxh265enc.h
new file mode 100644
index 0000000000..b67fa1f0fb
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxh265enc.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2017 Xilinx, Inc.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_H265_ENC_H__
+#define __GST_OMX_H265_ENC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideoenc.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_H265_ENC \
+ (gst_omx_h265_enc_get_type())
+#define GST_OMX_H265_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_H265_ENC,GstOMXH265Enc))
+#define GST_OMX_H265_ENC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_H265_ENC,GstOMXH265EncClass))
+#define GST_OMX_H265_ENC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_H265_ENC,GstOMXH265EncClass))
+#define GST_IS_OMX_H265_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_H265_ENC))
+#define GST_IS_OMX_H265_ENC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_H265_ENC))
+
+typedef struct _GstOMXH265Enc GstOMXH265Enc;
+typedef struct _GstOMXH265EncClass GstOMXH265EncClass;
+
+struct _GstOMXH265Enc
+{
+ GstOMXVideoEnc parent;
+
+ /* properties */
+ guint32 interval_intraframes;
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ guint32 periodicity_idr;
+ guint32 b_frames;
+ gboolean constrained_intra_prediction;
+ guint32 loop_filter_mode;
+#endif
+
+ GList *headers;
+};
+
+struct _GstOMXH265EncClass
+{
+ GstOMXVideoEncClass parent_class;
+};
+
+GType gst_omx_h265_enc_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_H265_ENC_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxh265utils.c b/subprojects/gst-omx/omx/gstomxh265utils.c
new file mode 100644
index 0000000000..8bf81da06d
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxh265utils.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2017 Xilinx, Inc.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstomxh265utils.h"
+
+typedef struct
+{
+ const gchar *profile;
+ OMX_VIDEO_HEVCPROFILETYPE e;
+} H265ProfileMapping;
+
+static const H265ProfileMapping h265_profiles[] = {
+ {"main", OMX_VIDEO_HEVCProfileMain},
+ {"main-10", OMX_VIDEO_HEVCProfileMain10},
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ {"main-still-picture",
+ (OMX_VIDEO_HEVCPROFILETYPE) OMX_ALG_VIDEO_HEVCProfileMainStill},
+ /* Format range extensions profiles (A.3.5) */
+ {"monochrome",
+ (OMX_VIDEO_HEVCPROFILETYPE) OMX_ALG_VIDEO_HEVCProfileMonochrome},
+ /* Not standard: 10 bits variation of monochrome-12 */
+ {"monochrome-10",
+ (OMX_VIDEO_HEVCPROFILETYPE) OMX_ALG_VIDEO_HEVCProfileMonochrome10},
+ /* Not standard: 8 bits variation of main-422-10 */
+ {"main-422", (OMX_VIDEO_HEVCPROFILETYPE) OMX_ALG_VIDEO_HEVCProfileMain422},
+ {"main-422-10",
+ (OMX_VIDEO_HEVCPROFILETYPE) OMX_ALG_VIDEO_HEVCProfileMain422_10},
+ {"main-intra",
+ (OMX_VIDEO_HEVCPROFILETYPE) OMX_ALG_VIDEO_HEVCProfileMain_Intra},
+ {"main-10-intra",
+ (OMX_VIDEO_HEVCPROFILETYPE) OMX_ALG_VIDEO_HEVCProfileMain10_Intra},
+ /* Not standard: intra variation of main-422 */
+ {"main-422-intra",
+ (OMX_VIDEO_HEVCPROFILETYPE) OMX_ALG_VIDEO_HEVCProfileMain422_Intra},
+ {"main-422-10-intra",
+ (OMX_VIDEO_HEVCPROFILETYPE) OMX_ALG_VIDEO_HEVCProfileMain422_10_Intra},
+#endif
+};
+
+OMX_VIDEO_HEVCPROFILETYPE
+gst_omx_h265_utils_get_profile_from_str (const gchar * profile)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (h265_profiles); i++) {
+ if (g_str_equal (profile, h265_profiles[i].profile))
+ return h265_profiles[i].e;
+ }
+
+ return OMX_VIDEO_HEVCProfileUnknown;
+}
+
+const gchar *
+gst_omx_h265_utils_get_profile_from_enum (OMX_VIDEO_HEVCPROFILETYPE e)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (h265_profiles); i++) {
+ if (e == h265_profiles[i].e)
+ return h265_profiles[i].profile;
+ }
+
+ return NULL;
+}
+
+OMX_VIDEO_HEVCLEVELTYPE
+gst_omx_h265_utils_get_level_from_str (const gchar * level, const gchar * tier)
+{
+ if (g_str_equal (tier, "main")) {
+ if (g_str_equal (level, "1"))
+ return OMX_VIDEO_HEVCMainTierLevel1;
+ else if (g_str_equal (level, "2"))
+ return OMX_VIDEO_HEVCMainTierLevel2;
+ else if (g_str_equal (level, "2.1"))
+ return OMX_VIDEO_HEVCMainTierLevel21;
+ else if (g_str_equal (level, "3"))
+ return OMX_VIDEO_HEVCMainTierLevel3;
+ else if (g_str_equal (level, "3.1"))
+ return OMX_VIDEO_HEVCMainTierLevel31;
+ else if (g_str_equal (level, "4"))
+ return OMX_VIDEO_HEVCMainTierLevel4;
+ else if (g_str_equal (level, "4.1"))
+ return OMX_VIDEO_HEVCMainTierLevel41;
+ else if (g_str_equal (level, "5"))
+ return OMX_VIDEO_HEVCMainTierLevel5;
+ else if (g_str_equal (level, "5.1"))
+ return OMX_VIDEO_HEVCMainTierLevel51;
+ else if (g_str_equal (level, "5.2"))
+ return OMX_VIDEO_HEVCMainTierLevel52;
+ else if (g_str_equal (level, "6"))
+ return OMX_VIDEO_HEVCMainTierLevel6;
+ else if (g_str_equal (level, "6.1"))
+ return OMX_VIDEO_HEVCMainTierLevel61;
+ else if (g_str_equal (level, "6.2"))
+ return OMX_VIDEO_HEVCMainTierLevel62;
+ } else if (g_str_equal (tier, "high")) {
+ if (g_str_equal (level, "4"))
+ return OMX_VIDEO_HEVCHighTierLevel4;
+ else if (g_str_equal (level, "4.1"))
+ return OMX_VIDEO_HEVCHighTierLevel41;
+ else if (g_str_equal (level, "5"))
+ return OMX_VIDEO_HEVCHighTierLevel5;
+ else if (g_str_equal (level, "5.1"))
+ return OMX_VIDEO_HEVCHighTierLevel51;
+ else if (g_str_equal (level, "5.2"))
+ return OMX_VIDEO_HEVCHighTierLevel52;
+ else if (g_str_equal (level, "6"))
+ return OMX_VIDEO_HEVCHighTierLevel6;
+ else if (g_str_equal (level, "6.1"))
+ return OMX_VIDEO_HEVCHighTierLevel61;
+ else if (g_str_equal (level, "6.2"))
+ return OMX_VIDEO_HEVCHighTierLevel62;
+ }
+
+ return OMX_VIDEO_HEVCLevelUnknown;
+}
diff --git a/subprojects/gst-omx/omx/gstomxh265utils.h b/subprojects/gst-omx/omx/gstomxh265utils.h
new file mode 100644
index 0000000000..1987a326aa
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxh265utils.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2017 Xilinx, Inc.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_H265_UTILS_H__
+#define __GST_OMX_H265_UTILS_H__
+
+#include "gstomx.h"
+
+G_BEGIN_DECLS
+
+OMX_VIDEO_HEVCPROFILETYPE gst_omx_h265_utils_get_profile_from_str (const
+ gchar * profile);
+OMX_VIDEO_HEVCLEVELTYPE gst_omx_h265_utils_get_level_from_str (const gchar *
+ level, const gchar * tier);
+
+const gchar * gst_omx_h265_utils_get_profile_from_enum (OMX_VIDEO_HEVCPROFILETYPE e);
+
+G_END_DECLS
+#endif /* __GST_OMX_H265_UTILS_H__ */
diff --git a/subprojects/gst-omx/omx/gstomxhdmiaudiosink.c b/subprojects/gst-omx/omx/gstomxhdmiaudiosink.c
new file mode 100644
index 0000000000..211b719343
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxhdmiaudiosink.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2014, Fluendo, S.A.
+ * Copyright (C) 2014, Metrological Media Innovations B.V.
+ * Author: Josep Torra <josep@fluendo.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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxhdmiaudiosink.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_hdmi_audio_sink_debug_category);
+#define GST_CAT_DEFAULT gst_omx_hdmi_audio_sink_debug_category
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_hdmi_audio_sink_debug_category, \
+ "omxhdmiaudiosink", 0, "debug category for gst-omx hdmi audio sink");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXHdmiAudioSink, gst_omx_hdmi_audio_sink,
+ GST_TYPE_OMX_AUDIO_SINK, DEBUG_INIT);
+
+static void
+gst_omx_hdmi_audio_sink_class_init (GstOMXHdmiAudioSinkClass * klass)
+{
+ GstOMXAudioSinkClass *audiosink_class = GST_OMX_AUDIO_SINK_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ audiosink_class->cdata.default_sink_template_caps = "audio/x-raw, "
+ "format = (string) " GST_AUDIO_FORMATS_ALL ", "
+ "layout = (string) interleaved, "
+ "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
+ PASSTHROUGH_CAPS;
+ audiosink_class->destination = "hdmi";
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX HDMI Audio Sink",
+ "Sink/Audio",
+ "Output audio through HDMI", "Josep Torra <josep@fluendo.com>");
+
+ gst_omx_set_default_role (&audiosink_class->cdata, "audio_render.hdmi");
+}
+
+static void
+gst_omx_hdmi_audio_sink_init (GstOMXHdmiAudioSink * self)
+{
+}
diff --git a/subprojects/gst-omx/omx/gstomxhdmiaudiosink.h b/subprojects/gst-omx/omx/gstomxhdmiaudiosink.h
new file mode 100644
index 0000000000..e45e56b3ce
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxhdmiaudiosink.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2014, Fluendo, S.A.
+ * Copyright (C) 2014, Metrological Media Innovations B.V.
+ * Author: Josep Torra <josep@fluendo.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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_HDMI_AUDIO_SINK_H__
+#define __GST_OMX_HDMI_AUDIO_SINK_H__
+
+#include <gst/gst.h>
+#include "gstomxaudiosink.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_HDMI_AUDIO_SINK \
+ (gst_omx_hdmi_audio_sink_get_type())
+#define GST_OMX_HDMI_AUDIO_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_HDMI_AUDIO_SINK,GstOMXHdmiAudioSink))
+#define GST_OMX_HDMI_AUDIO_SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_HDMI_AUDIO_SINK,GstOMXHdmiAudioSinkClass))
+#define GST_OMX_HDMI_AUDIO_SINK_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_HDMI_AUDIO_SINK,GstOMXHdmiAudioSinkClass))
+#define GST_IS_OMX_HDMI_AUDIO_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_HDMI_AUDIO_SINK))
+#define GST_IS_OMX_HDMI_AUDIO_SINK_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_HDMI_AUDIO_SINK))
+
+typedef struct _GstOMXHdmiAudioSink GstOMXHdmiAudioSink;
+typedef struct _GstOMXHdmiAudioSinkClass GstOMXHdmiAudioSinkClass;
+
+struct _GstOMXHdmiAudioSink
+{
+ GstOMXAudioSink parent;
+};
+
+struct _GstOMXHdmiAudioSinkClass
+{
+ GstOMXAudioSinkClass parent_class;
+};
+
+GType gst_omx_hdmi_audio_sink_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_HDMI_AUDIO_SINK_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxmjpegdec.c b/subprojects/gst-omx/omx/gstomxmjpegdec.c
new file mode 100644
index 0000000000..6ca34f2d56
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxmjpegdec.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2013, Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxmjpegdec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_mjpeg_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_mjpeg_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_mjpeg_dec_is_format_change (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state);
+static gboolean gst_omx_mjpeg_dec_set_format (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state);
+
+enum
+{
+ PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_mjpeg_dec_debug_category, "omxmjpegdec", 0, \
+ "debug category for gst-omx video decoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXMJPEGDec, gst_omx_mjpeg_dec,
+ GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT);
+
+static void
+gst_omx_mjpeg_dec_class_init (GstOMXMJPEGDecClass * klass)
+{
+ GstOMXVideoDecClass *videodec_class = GST_OMX_VIDEO_DEC_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ videodec_class->is_format_change =
+ GST_DEBUG_FUNCPTR (gst_omx_mjpeg_dec_is_format_change);
+ videodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_mjpeg_dec_set_format);
+
+ videodec_class->cdata.default_sink_template_caps = "image/jpeg, "
+ "width=(int) [1,MAX], " "height=(int) [1,MAX]";
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX MJPEG Video Decoder",
+ "Codec/Decoder/Video/Hardware",
+ "Decode MJPEG video streams",
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+ gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.mjpeg");
+}
+
+static void
+gst_omx_mjpeg_dec_init (GstOMXMJPEGDec * self)
+{
+}
+
+static gboolean
+gst_omx_mjpeg_dec_is_format_change (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state)
+{
+ return FALSE;
+}
+
+static gboolean
+gst_omx_mjpeg_dec_set_format (GstOMXVideoDec * dec, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ gboolean ret;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+
+ gst_omx_port_get_port_definition (port, &port_def);
+ port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingMJPEG;
+ ret = gst_omx_port_update_port_definition (port, &port_def) == OMX_ErrorNone;
+
+ return ret;
+}
diff --git a/subprojects/gst-omx/omx/gstomxmjpegdec.h b/subprojects/gst-omx/omx/gstomxmjpegdec.h
new file mode 100644
index 0000000000..8802c8d7ea
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxmjpegdec.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_MJPEG_DEC_H__
+#define __GST_OMX_MJPEG_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_MJPEG_DEC \
+ (gst_omx_mjpeg_dec_get_type())
+#define GST_OMX_MJPEG_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_MJPEG_DEC,GstOMXMJPEGDec))
+#define GST_OMX_MJPEG_DEC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_MJPEG_DEC,GstOMXMJPEGDecClass))
+#define GST_OMX_MJPEG_DEC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_MJPEG_DEC,GstOMXMJPEGDecClass))
+#define GST_IS_OMX_MJPEG_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_MJPEG_DEC))
+#define GST_IS_OMX_MJPEG_DEC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_MJPEG_DEC))
+
+typedef struct _GstOMXMJPEGDec GstOMXMJPEGDec;
+typedef struct _GstOMXMJPEGDecClass GstOMXMJPEGDecClass;
+
+struct _GstOMXMJPEGDec
+{
+ GstOMXVideoDec parent;
+};
+
+struct _GstOMXMJPEGDecClass
+{
+ GstOMXVideoDecClass parent_class;
+};
+
+GType gst_omx_mjpeg_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_MJPEG_DEC_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxmp3dec.c b/subprojects/gst-omx/omx/gstomxmp3dec.c
new file mode 100644
index 0000000000..aa22e80fb0
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxmp3dec.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxmp3dec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_mp3_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_mp3_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_mp3_dec_set_format (GstOMXAudioDec * dec,
+ GstOMXPort * port, GstCaps * caps);
+static gboolean gst_omx_mp3_dec_is_format_change (GstOMXAudioDec * dec,
+ GstOMXPort * port, GstCaps * caps);
+static gint gst_omx_mp3_dec_get_samples_per_frame (GstOMXAudioDec * dec,
+ GstOMXPort * port);
+static gboolean gst_omx_mp3_dec_get_channel_positions (GstOMXAudioDec * dec,
+ GstOMXPort * port, GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS]);
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_mp3_dec_debug_category, "omxmp3dec", 0, \
+ "debug category for gst-omx mp3 audio decoder");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXMP3Dec, gst_omx_mp3_dec,
+ GST_TYPE_OMX_AUDIO_DEC, DEBUG_INIT);
+
+
+static void
+gst_omx_mp3_dec_class_init (GstOMXMP3DecClass * klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstOMXAudioDecClass *audiodec_class = GST_OMX_AUDIO_DEC_CLASS (klass);
+
+ audiodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_mp3_dec_set_format);
+ audiodec_class->is_format_change =
+ GST_DEBUG_FUNCPTR (gst_omx_mp3_dec_is_format_change);
+ audiodec_class->get_samples_per_frame =
+ GST_DEBUG_FUNCPTR (gst_omx_mp3_dec_get_samples_per_frame);
+ audiodec_class->get_channel_positions =
+ GST_DEBUG_FUNCPTR (gst_omx_mp3_dec_get_channel_positions);
+
+ audiodec_class->cdata.default_sink_template_caps = "audio/mpeg, "
+ "mpegversion=(int)1, "
+ "layer=(int)3, "
+ "mpegaudioversion=(int)[1,3], "
+ "rate=(int)[8000,48000], "
+ "channels=(int)[1,2], " "parsed=(boolean) true";
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX MP3 Audio Decoder",
+ "Codec/Decoder/Audio/Hardware",
+ "Decode MP3 audio streams",
+ "Sebastian Dröge <sebastian@centricular.com>");
+
+ gst_omx_set_default_role (&audiodec_class->cdata, "audio_decoder.mp3");
+}
+
+static void
+gst_omx_mp3_dec_init (GstOMXMP3Dec * self)
+{
+ self->spf = -1;
+}
+
+static gboolean
+gst_omx_mp3_dec_set_format (GstOMXAudioDec * dec, GstOMXPort * port,
+ GstCaps * caps)
+{
+ GstOMXMP3Dec *self = GST_OMX_MP3_DEC (dec);
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ OMX_AUDIO_PARAM_MP3TYPE mp3_param;
+ OMX_ERRORTYPE err;
+ GstStructure *s;
+ gint rate, channels, layer, mpegaudioversion;
+
+ gst_omx_port_get_port_definition (port, &port_def);
+ port_def.format.audio.eEncoding = OMX_AUDIO_CodingMP3;
+ err = gst_omx_port_update_port_definition (port, &port_def);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to set MP3 format on component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ GST_OMX_INIT_STRUCT (&mp3_param);
+ mp3_param.nPortIndex = port->index;
+
+ err =
+ gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioMp3,
+ &mp3_param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to get MP3 parameters from component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ s = gst_caps_get_structure (caps, 0);
+
+ if (!gst_structure_get_int (s, "mpegaudioversion", &mpegaudioversion) ||
+ !gst_structure_get_int (s, "layer", &layer) ||
+ !gst_structure_get_int (s, "rate", &rate) ||
+ !gst_structure_get_int (s, "channels", &channels)) {
+ GST_ERROR_OBJECT (self, "Incomplete caps");
+ return FALSE;
+ }
+
+ self->spf = (mpegaudioversion == 1 ? 1152 : 576);
+
+ mp3_param.nChannels = channels;
+ mp3_param.nBitRate = 0; /* unknown */
+ mp3_param.nSampleRate = rate;
+ mp3_param.nAudioBandWidth = 0; /* decoder decision */
+ mp3_param.eChannelMode = 0; /* FIXME */
+ if (mpegaudioversion == 1)
+ mp3_param.eFormat = OMX_AUDIO_MP3StreamFormatMP1Layer3;
+ else if (mpegaudioversion == 2)
+ mp3_param.eFormat = OMX_AUDIO_MP3StreamFormatMP2Layer3;
+ else
+ mp3_param.eFormat = OMX_AUDIO_MP3StreamFormatMP2_5Layer3;
+
+ err =
+ gst_omx_component_set_parameter (dec->dec, OMX_IndexParamAudioMp3,
+ &mp3_param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Error setting MP3 parameters: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_mp3_dec_is_format_change (GstOMXAudioDec * dec, GstOMXPort * port,
+ GstCaps * caps)
+{
+ GstOMXMP3Dec *self = GST_OMX_MP3_DEC (dec);
+ OMX_AUDIO_PARAM_MP3TYPE mp3_param;
+ OMX_ERRORTYPE err;
+ GstStructure *s;
+ gint rate, channels, layer, mpegaudioversion;
+
+ GST_OMX_INIT_STRUCT (&mp3_param);
+ mp3_param.nPortIndex = port->index;
+
+ err =
+ gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioMp3,
+ &mp3_param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to get MP3 parameters from component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ s = gst_caps_get_structure (caps, 0);
+
+ if (!gst_structure_get_int (s, "mpegaudioversion", &mpegaudioversion) ||
+ !gst_structure_get_int (s, "layer", &layer) ||
+ !gst_structure_get_int (s, "rate", &rate) ||
+ !gst_structure_get_int (s, "channels", &channels)) {
+ GST_ERROR_OBJECT (self, "Incomplete caps");
+ return FALSE;
+ }
+
+ if (mp3_param.nChannels != channels)
+ return TRUE;
+
+ if (mp3_param.nSampleRate != rate)
+ return TRUE;
+
+ if (mpegaudioversion == 1
+ && mp3_param.eFormat != OMX_AUDIO_MP3StreamFormatMP1Layer3)
+ return TRUE;
+ if (mpegaudioversion == 2
+ && mp3_param.eFormat != OMX_AUDIO_MP3StreamFormatMP2Layer3)
+ return TRUE;
+ if (mpegaudioversion == 3
+ && mp3_param.eFormat != OMX_AUDIO_MP3StreamFormatMP2_5Layer3)
+ return TRUE;
+
+ return FALSE;
+}
+
+static gint
+gst_omx_mp3_dec_get_samples_per_frame (GstOMXAudioDec * dec, GstOMXPort * port)
+{
+ return GST_OMX_MP3_DEC (dec)->spf;
+}
+
+static gboolean
+gst_omx_mp3_dec_get_channel_positions (GstOMXAudioDec * dec,
+ GstOMXPort * port, GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS])
+{
+ OMX_AUDIO_PARAM_PCMMODETYPE pcm_param;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&pcm_param);
+ pcm_param.nPortIndex = port->index;
+ err =
+ gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioPcm,
+ &pcm_param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (dec, "Failed to get PCM parameters: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ switch (pcm_param.nChannels) {
+ case 1:
+ position[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
+ break;
+ case 2:
+ position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
+ position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/subprojects/gst-omx/omx/gstomxmp3dec.h b/subprojects/gst-omx/omx/gstomxmp3dec.h
new file mode 100644
index 0000000000..4f07659783
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxmp3dec.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_MP3_DEC_H__
+#define __GST_OMX_MP3_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxaudiodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_MP3_DEC \
+ (gst_omx_mp3_dec_get_type())
+#define GST_OMX_MP3_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_MP3_DEC,GstOMXMP3Dec))
+#define GST_OMX_MP3_DEC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_MP3_DEC,GstOMXMP3DecClass))
+#define GST_OMX_MP3_DEC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_MP3_DEC,GstOMXMP3DecClass))
+#define GST_IS_OMX_MP3_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_MP3_DEC))
+#define GST_IS_OMX_MP3_DEC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_MP3_DEC))
+
+typedef struct _GstOMXMP3Dec GstOMXMP3Dec;
+typedef struct _GstOMXMP3DecClass GstOMXMP3DecClass;
+
+struct _GstOMXMP3Dec
+{
+ GstOMXAudioDec parent;
+ gint spf;
+};
+
+struct _GstOMXMP3DecClass
+{
+ GstOMXAudioDecClass parent_class;
+};
+
+GType gst_omx_mp3_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_MP3_DEC_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxmp3enc.c b/subprojects/gst-omx/omx/gstomxmp3enc.c
new file mode 100644
index 0000000000..1296564f31
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxmp3enc.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2017
+ * Author: Julien Isorce <julien.isorce@gmail.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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxmp3enc.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_mp3_enc_debug_category);
+#define GST_CAT_DEFAULT gst_omx_mp3_enc_debug_category
+
+/* prototypes */
+static void gst_omx_mp3_enc_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_omx_mp3_enc_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+static gboolean gst_omx_mp3_enc_set_format (GstOMXAudioEnc * enc,
+ GstOMXPort * port, GstAudioInfo * info);
+static GstCaps *gst_omx_mp3_enc_get_caps (GstOMXAudioEnc * enc,
+ GstOMXPort * port, GstAudioInfo * info);
+static guint gst_omx_mp3_enc_get_num_samples (GstOMXAudioEnc * enc,
+ GstOMXPort * port, GstAudioInfo * info, GstOMXBuffer * buf);
+
+enum
+{
+ PROP_0,
+ PROP_BITRATE
+};
+
+#define DEFAULT_BITRATE (128)
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_mp3_enc_debug_category, "omxmp3enc", 0, \
+ "debug category for gst-omx audio encoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXMP3Enc, gst_omx_mp3_enc,
+ GST_TYPE_OMX_AUDIO_ENC, DEBUG_INIT);
+
+
+static void
+gst_omx_mp3_enc_class_init (GstOMXMP3EncClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstOMXAudioEncClass *audioenc_class = GST_OMX_AUDIO_ENC_CLASS (klass);
+
+ gobject_class->set_property = gst_omx_mp3_enc_set_property;
+ gobject_class->get_property = gst_omx_mp3_enc_get_property;
+
+ g_object_class_install_property (gobject_class, PROP_BITRATE,
+ g_param_spec_uint ("bitrate", "Bitrate (kb/s)",
+ "Bitrate in kbit/sec",
+ 0, G_MAXUINT, DEFAULT_BITRATE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ audioenc_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_mp3_enc_set_format);
+ audioenc_class->get_caps = GST_DEBUG_FUNCPTR (gst_omx_mp3_enc_get_caps);
+ audioenc_class->get_num_samples =
+ GST_DEBUG_FUNCPTR (gst_omx_mp3_enc_get_num_samples);
+
+ audioenc_class->cdata.default_src_template_caps = "audio/mpeg, "
+ "mpegversion=(int)1, "
+ "layer=(int)3, "
+ "mpegaudioversion=(int)[1,3], "
+ "rate=(int)[8000,48000], " "channels=(int)[1,2]";
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX MP3 Audio Encoder",
+ "Codec/Encoder/Audio/Hardware",
+ "Encode AAC audio streams", "Julien Isorce <julien.isorce@gmail.com>");
+
+ gst_omx_set_default_role (&audioenc_class->cdata, "audio_encoder.mp3");
+}
+
+static void
+gst_omx_mp3_enc_init (GstOMXMP3Enc * self)
+{
+ self->mpegaudioversion = 1;
+ self->bitrate = DEFAULT_BITRATE;
+}
+
+static void
+gst_omx_mp3_enc_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstOMXMP3Enc *self = GST_OMX_MP3_ENC (object);
+
+ switch (prop_id) {
+ case PROP_BITRATE:
+ self->bitrate = g_value_get_uint (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_omx_mp3_enc_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec)
+{
+ GstOMXMP3Enc *self = GST_OMX_MP3_ENC (object);
+
+ switch (prop_id) {
+ case PROP_BITRATE:
+ g_value_set_uint (value, self->bitrate);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static gboolean
+gst_omx_mp3_enc_set_format (GstOMXAudioEnc * enc, GstOMXPort * port,
+ GstAudioInfo * info)
+{
+ GstOMXMP3Enc *self = GST_OMX_MP3_ENC (enc);
+ OMX_AUDIO_PARAM_MP3TYPE mp3_param;
+ GstCaps *peercaps;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&mp3_param);
+ mp3_param.nPortIndex = enc->enc_out_port->index;
+
+ err =
+ gst_omx_component_get_parameter (enc->enc, OMX_IndexParamAudioMp3,
+ &mp3_param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to get MP# parameters from component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ peercaps = gst_pad_peer_query_caps (GST_AUDIO_ENCODER_SRC_PAD (self),
+ gst_pad_get_pad_template_caps (GST_AUDIO_ENCODER_SRC_PAD (self)));
+ if (peercaps) {
+ GstStructure *s;
+ gint mpegaudioversion = 0;
+
+ if (gst_caps_is_empty (peercaps)) {
+ gst_caps_unref (peercaps);
+ GST_ERROR_OBJECT (self, "Empty caps");
+ return FALSE;
+ }
+
+ s = gst_caps_get_structure (peercaps, 0);
+
+ if (gst_structure_get_int (s, "mpegaudioversion", &mpegaudioversion)) {
+ switch (mpegaudioversion) {
+ case 1:
+ mp3_param.eFormat = OMX_AUDIO_MP3StreamFormatMP1Layer3;
+ break;
+ case 2:
+ mp3_param.eFormat = OMX_AUDIO_MP3StreamFormatMP2Layer3;
+ break;
+ case 3:
+ mp3_param.eFormat = OMX_AUDIO_MP3StreamFormatMP2_5Layer3;
+ break;
+ default:
+ GST_ERROR_OBJECT (self, "Unsupported mpegaudioversion '%d'",
+ mpegaudioversion);
+ gst_caps_unref (peercaps);
+ return FALSE;
+ }
+ self->mpegaudioversion = mpegaudioversion;
+ }
+
+ gst_caps_unref (peercaps);
+
+ mp3_param.nSampleRate = info->rate;
+ mp3_param.nChannels = info->channels;
+
+ mp3_param.eChannelMode =
+ info->channels ==
+ 1 ? OMX_AUDIO_ChannelModeMono : OMX_AUDIO_ChannelModeStereo;
+ }
+
+ mp3_param.nBitRate = self->bitrate;
+
+ err =
+ gst_omx_component_set_parameter (enc->enc, OMX_IndexParamAudioMp3,
+ &mp3_param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Error setting MP3 parameters: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static GstCaps *
+gst_omx_mp3_enc_get_caps (GstOMXAudioEnc * enc, GstOMXPort * port,
+ GstAudioInfo * info)
+{
+ GstCaps *caps;
+ OMX_ERRORTYPE err;
+ OMX_AUDIO_PARAM_MP3TYPE mp3_param;
+ gint mpegaudioversion = 0;
+
+ GST_OMX_INIT_STRUCT (&mp3_param);
+ mp3_param.nPortIndex = enc->enc_out_port->index;
+
+ err =
+ gst_omx_component_get_parameter (enc->enc, OMX_IndexParamAudioMp3,
+ &mp3_param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (enc,
+ "Failed to get MP3 parameters from component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return NULL;
+ }
+
+ switch (mp3_param.eFormat) {
+ case OMX_AUDIO_MP3StreamFormatMP1Layer3:
+ mpegaudioversion = 1;
+ break;
+ case OMX_AUDIO_MP3StreamFormatMP2Layer3:
+ mpegaudioversion = 2;
+ break;
+ case OMX_AUDIO_MP3StreamFormatMP2_5Layer3:
+ mpegaudioversion = 3;
+ break;
+ default:
+ GST_ERROR_OBJECT (enc, "Unsupported mpegaudioversion %d",
+ mp3_param.eFormat);
+ break;
+ }
+
+ caps =
+ gst_caps_new_simple ("audio/mpeg", "mpegversion", G_TYPE_INT, 1, "layer",
+ G_TYPE_INT, 3, NULL);
+
+ if (mpegaudioversion != 0)
+ gst_caps_set_simple (caps, "mpegaudioversion", G_TYPE_INT, mpegaudioversion,
+ NULL);
+ if (mp3_param.nChannels != 0)
+ gst_caps_set_simple (caps, "channels", G_TYPE_INT, mp3_param.nChannels,
+ NULL);
+ if (mp3_param.nSampleRate != 0)
+ gst_caps_set_simple (caps, "rate", G_TYPE_INT, mp3_param.nSampleRate, NULL);
+
+ return caps;
+
+}
+
+static guint
+gst_omx_mp3_enc_get_num_samples (GstOMXAudioEnc * enc, GstOMXPort * port,
+ GstAudioInfo * info, GstOMXBuffer * buf)
+{
+ GstOMXMP3Enc *self = GST_OMX_MP3_ENC (enc);
+ return (self->mpegaudioversion == 1) ? 1152 : 576;
+}
diff --git a/subprojects/gst-omx/omx/gstomxmp3enc.h b/subprojects/gst-omx/omx/gstomxmp3enc.h
new file mode 100644
index 0000000000..74e115e6c6
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxmp3enc.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2017
+ * Author: Julien Isorce <julien.isorce@gmail.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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_MP3_ENC_H__
+#define __GST_OMX_MP3_ENC_H__
+
+#include <gst/gst.h>
+#include "gstomxaudioenc.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_MP3_ENC \
+ (gst_omx_mp3_enc_get_type())
+#define GST_OMX_MP3_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_MP3_ENC,GstOMXMP3Enc))
+#define GST_OMX_MP3_ENC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_MP3_ENC,GstOMXMP3EncClass))
+#define GST_OMX_MP3_ENC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_MP3_ENC,GstOMXMP3EncClass))
+#define GST_IS_OMX_MP3_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_MP3_ENC))
+#define GST_IS_OMX_MP3_ENC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_MP3_ENC))
+
+typedef struct _GstOMXMP3Enc GstOMXMP3Enc;
+typedef struct _GstOMXMP3EncClass GstOMXMP3EncClass;
+
+struct _GstOMXMP3Enc
+{
+ GstOMXAudioEnc parent;
+
+ guint mpegaudioversion;
+
+ /* properties */
+ guint bitrate;
+};
+
+struct _GstOMXMP3EncClass
+{
+ GstOMXAudioEncClass parent_class;
+};
+
+GType gst_omx_mp3_enc_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_MP3_ENC_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxmpeg2videodec.c b/subprojects/gst-omx/omx/gstomxmpeg2videodec.c
new file mode 100644
index 0000000000..144845060d
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxmpeg2videodec.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxmpeg2videodec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_mpeg2_video_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_mpeg2_video_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_mpeg2_video_dec_is_format_change (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state);
+static gboolean gst_omx_mpeg2_video_dec_set_format (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state);
+
+enum
+{
+ PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_mpeg2_video_dec_debug_category, "omxmpeg2dec", 0, \
+ "debug category for gst-omx video decoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXMPEG2VideoDec, gst_omx_mpeg2_video_dec,
+ GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT);
+
+static void
+gst_omx_mpeg2_video_dec_class_init (GstOMXMPEG2VideoDecClass * klass)
+{
+ GstOMXVideoDecClass *videodec_class = GST_OMX_VIDEO_DEC_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ videodec_class->is_format_change =
+ GST_DEBUG_FUNCPTR (gst_omx_mpeg2_video_dec_is_format_change);
+ videodec_class->set_format =
+ GST_DEBUG_FUNCPTR (gst_omx_mpeg2_video_dec_set_format);
+
+ videodec_class->cdata.default_sink_template_caps = "video/mpeg, "
+ "mpegversion=(int) [1, 2], "
+ "systemstream=(boolean) false, "
+ "parsed=(boolean) true, " "width=(int) [1,MAX], " "height=(int) [1,MAX]";
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX MPEG2 Video Decoder",
+ "Codec/Decoder/Video/Hardware",
+ "Decode MPEG2 video streams",
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+ gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.mpeg2");
+}
+
+static void
+gst_omx_mpeg2_video_dec_init (GstOMXMPEG2VideoDec * self)
+{
+}
+
+static gboolean
+gst_omx_mpeg2_video_dec_is_format_change (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state)
+{
+ return FALSE;
+}
+
+static gboolean
+gst_omx_mpeg2_video_dec_set_format (GstOMXVideoDec * dec, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ gboolean ret;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+
+ gst_omx_port_get_port_definition (port, &port_def);
+ port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG2;
+ ret = gst_omx_port_update_port_definition (port, &port_def) == OMX_ErrorNone;
+
+ return ret;
+}
diff --git a/subprojects/gst-omx/omx/gstomxmpeg2videodec.h b/subprojects/gst-omx/omx/gstomxmpeg2videodec.h
new file mode 100644
index 0000000000..ff86bcdee5
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxmpeg2videodec.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_MPEG2_VIDEO_DEC_H__
+#define __GST_OMX_MPEG2_VIDEO_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_MPEG2_VIDEO_DEC \
+ (gst_omx_mpeg2_video_get_type())
+#define GST_OMX_MPEG2_VIDEO_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_MPEG2_VIDEO_DEC,GstOMXMPEG2VideoDec))
+#define GST_OMX_MPEG2_VIDEO_DEC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_MPEG2_VIDEO_DEC,GstOMXMPEG2VideoDecClass))
+#define GST_OMX_MPEG2_VIDEO_DEC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_MPEG2_VIDEO_DEC,GstOMXMPEG2VideoDecClass))
+#define GST_IS_OMX_MPEG2_VIDEO_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_MPEG2_VIDEO_DEC))
+#define GST_IS_OMX_MPEG2_VIDEO_DEC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_MPEG2_VIDEO_DEC))
+
+typedef struct _GstOMXMPEG2VideoDec GstOMXMPEG2VideoDec;
+typedef struct _GstOMXMPEG2VideoDecClass GstOMXMPEG2VideoDecClass;
+
+struct _GstOMXMPEG2VideoDec
+{
+ GstOMXVideoDec parent;
+};
+
+struct _GstOMXMPEG2VideoDecClass
+{
+ GstOMXVideoDecClass parent_class;
+};
+
+GType gst_omx_mpeg2_video_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_MPEG2_VIDEO_DEC_H__ */
diff --git a/subprojects/gst-omx/omx/gstomxmpeg4videodec.c b/subprojects/gst-omx/omx/gstomxmpeg4videodec.c
new file mode 100644
index 0000000000..8cebef82d6
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxmpeg4videodec.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxmpeg4videodec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_mpeg4_video_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_mpeg4_video_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_mpeg4_video_dec_is_format_change (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state);
+static gboolean gst_omx_mpeg4_video_dec_set_format (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state);
+
+enum
+{
+ PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_mpeg4_video_dec_debug_category, "omxmpeg4videodec", 0, \
+ "debug category for gst-omx video decoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXMPEG4VideoDec, gst_omx_mpeg4_video_dec,
+ GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT);
+
+
+static void
+gst_omx_mpeg4_video_dec_class_init (GstOMXMPEG4VideoDecClass * klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstOMXVideoDecClass *videodec_class = GST_OMX_VIDEO_DEC_CLASS (klass);
+
+ videodec_class->is_format_change =
+ GST_DEBUG_FUNCPTR (gst_omx_mpeg4_video_dec_is_format_change);
+ videodec_class->set_format =
+ GST_DEBUG_FUNCPTR (gst_omx_mpeg4_video_dec_set_format);
+
+ videodec_class->cdata.default_sink_template_caps = "video/mpeg, "
+ "mpegversion=(int) 4, "
+ "systemstream=(boolean) false, "
+ "parsed=(boolean) true, " "width=(int) [1,MAX], " "height=(int) [1,MAX]";
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX MPEG4 Video Decoder",
+ "Codec/Decoder/Video/Hardware",
+ "Decode MPEG4 video streams",
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+ gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.mpeg4");
+}
+
+static void
+gst_omx_mpeg4_video_dec_init (GstOMXMPEG4VideoDec * self)
+{
+}
+
+static gboolean
+gst_omx_mpeg4_video_dec_is_format_change (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state)
+{
+ return FALSE;
+}
+
+static gboolean
+gst_omx_mpeg4_video_dec_set_format (GstOMXVideoDec * dec, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ gboolean ret;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+
+ gst_omx_port_get_port_definition (port, &port_def);
+ port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
+ ret = gst_omx_port_update_port_definition (port, &port_def) == OMX_ErrorNone;
+
+ return ret;
+}
diff --git a/subprojects/gst-omx/omx/gstomxmpeg4videodec.h b/subprojects/gst-omx/omx/gstomxmpeg4videodec.h
new file mode 100644
index 0000000000..73a68d5d70
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxmpeg4videodec.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_MPEG4_VIDEO_DEC_H__
+#define __GST_OMX_MPEG4_VIDEO_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_MPEG4_VIDEO_DEC \
+ (gst_omx_mpeg4_video_dec_get_type())
+#define GST_OMX_MPEG4_VIDEO_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_MPEG4_VIDEO_DEC,GstOMXMPEG4VideoDec))
+#define GST_OMX_MPEG4_VIDEO_DEC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_MPEG4_VIDEO_DEC,GstOMXMPEG4VideoDecClass))
+#define GST_OMX_MPEG4_VIDEO_DEC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_MPEG4_VIDEO_DEC,GstOMXMPEG4VideoDecClass))
+#define GST_IS_OMX_MPEG4_VIDEO_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_MPEG4_VIDEO_DEC))
+#define GST_IS_OMX_MPEG4_VIDEO_DEC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_MPEG4_VIDEO_DEC))
+
+typedef struct _GstOMXMPEG4VideoDec GstOMXMPEG4VideoDec;
+typedef struct _GstOMXMPEG4VideoDecClass GstOMXMPEG4VideoDecClass;
+
+struct _GstOMXMPEG4VideoDec
+{
+ GstOMXVideoDec parent;
+};
+
+struct _GstOMXMPEG4VideoDecClass
+{
+ GstOMXVideoDecClass parent_class;
+};
+
+GType gst_omx_mpeg4_video_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_MPEG4_VIDEO_DEC_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxmpeg4videoenc.c b/subprojects/gst-omx/omx/gstomxmpeg4videoenc.c
new file mode 100644
index 0000000000..c928171c33
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxmpeg4videoenc.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxmpeg4videoenc.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_mpeg4_video_enc_debug_category);
+#define GST_CAT_DEFAULT gst_omx_mpeg4_video_enc_debug_category
+
+/* prototypes */
+static gboolean gst_omx_mpeg4_video_enc_set_format (GstOMXVideoEnc * enc,
+ GstOMXPort * port, GstVideoCodecState * state);
+static GstCaps *gst_omx_mpeg4_video_enc_get_caps (GstOMXVideoEnc * enc,
+ GstOMXPort * port, GstVideoCodecState * state);
+
+enum
+{
+ PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_mpeg4_video_enc_debug_category, "omxmpeg4videoenc", 0, \
+ "debug category for gst-omx video encoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXMPEG4VideoEnc, gst_omx_mpeg4_video_enc,
+ GST_TYPE_OMX_VIDEO_ENC, DEBUG_INIT);
+
+static void
+gst_omx_mpeg4_video_enc_class_init (GstOMXMPEG4VideoEncClass * klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstOMXVideoEncClass *videoenc_class = GST_OMX_VIDEO_ENC_CLASS (klass);
+
+ videoenc_class->set_format =
+ GST_DEBUG_FUNCPTR (gst_omx_mpeg4_video_enc_set_format);
+ videoenc_class->get_caps =
+ GST_DEBUG_FUNCPTR (gst_omx_mpeg4_video_enc_get_caps);
+
+ videoenc_class->cdata.default_src_template_caps = "video/mpeg, "
+ "mpegversion=(int) 4, "
+ "systemstream=(boolean) false, "
+ "width=(int) [ 16, 4096 ], " "height=(int) [ 16, 4096 ]";
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX MPEG4 Video Encoder",
+ "Codec/Encoder/Video/Hardware",
+ "Encode MPEG4 video streams",
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+ gst_omx_set_default_role (&videoenc_class->cdata, "video_encoder.mpeg4");
+}
+
+static void
+gst_omx_mpeg4_video_enc_init (GstOMXMPEG4VideoEnc * self)
+{
+}
+
+static gboolean
+gst_omx_mpeg4_video_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ GstOMXMPEG4VideoEnc *self = GST_OMX_MPEG4_VIDEO_ENC (enc);
+ GstCaps *peercaps, *intersection;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+ OMX_ERRORTYPE err;
+ const gchar *profile_string, *level_string;
+
+ gst_omx_port_get_port_definition (GST_OMX_VIDEO_ENC (self)->enc_out_port,
+ &port_def);
+ port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
+ err =
+ gst_omx_port_update_port_definition (GST_OMX_VIDEO_ENC
+ (self)->enc_out_port, &port_def);
+ if (err != OMX_ErrorNone)
+ return FALSE;
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+
+ err =
+ gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamVideoProfileLevelCurrent, &param);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self,
+ "Getting profile/level not supported by component");
+ return FALSE;
+ }
+
+ peercaps = gst_pad_peer_query_caps (GST_VIDEO_ENCODER_SRC_PAD (enc), NULL);
+ if (peercaps) {
+ GstStructure *s;
+
+ intersection =
+ gst_caps_intersect (peercaps,
+ gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD (enc)));
+
+ gst_caps_unref (peercaps);
+ if (gst_caps_is_empty (intersection)) {
+ gst_caps_unref (intersection);
+ GST_ERROR_OBJECT (self, "Empty caps");
+ return FALSE;
+ }
+
+ s = gst_caps_get_structure (intersection, 0);
+ profile_string = gst_structure_get_string (s, "profile");
+ if (profile_string) {
+ if (g_str_equal (profile_string, "simple")) {
+ param.eProfile = OMX_VIDEO_MPEG4ProfileSimple;
+ } else if (g_str_equal (profile_string, "simple-scalable")) {
+ param.eProfile = OMX_VIDEO_MPEG4ProfileSimpleScalable;
+ } else if (g_str_equal (profile_string, "core")) {
+ param.eProfile = OMX_VIDEO_MPEG4ProfileCore;
+ } else if (g_str_equal (profile_string, "main")) {
+ param.eProfile = OMX_VIDEO_MPEG4ProfileMain;
+ } else if (g_str_equal (profile_string, "n-bit")) {
+ param.eProfile = OMX_VIDEO_MPEG4ProfileNbit;
+ } else if (g_str_equal (profile_string, "scalable")) {
+ param.eProfile = OMX_VIDEO_MPEG4ProfileScalableTexture;
+ } else if (g_str_equal (profile_string, "simple-face")) {
+ param.eProfile = OMX_VIDEO_MPEG4ProfileSimpleFace;
+ } else if (g_str_equal (profile_string, "simple-fba")) {
+ param.eProfile = OMX_VIDEO_MPEG4ProfileSimpleFBA;
+ } else if (g_str_equal (profile_string, "basic-animated-texture")) {
+ param.eProfile = OMX_VIDEO_MPEG4ProfileBasicAnimated;
+ } else if (g_str_equal (profile_string, "hybrid")) {
+ param.eProfile = OMX_VIDEO_MPEG4ProfileHybrid;
+ } else if (g_str_equal (profile_string, "advanced-real-time-simple")) {
+ param.eProfile = OMX_VIDEO_MPEG4ProfileAdvancedRealTime;
+ } else if (g_str_equal (profile_string, "core-scalable")) {
+ param.eProfile = OMX_VIDEO_MPEG4ProfileCoreScalable;
+ } else if (g_str_equal (profile_string, "advanced-coding-efficiency")) {
+ param.eProfile = OMX_VIDEO_MPEG4ProfileAdvancedCoding;
+ } else if (g_str_equal (profile_string, "advanced-core")) {
+ param.eProfile = OMX_VIDEO_MPEG4ProfileAdvancedCore;
+ } else if (g_str_equal (profile_string, "advanced-scalable-texture")) {
+ param.eProfile = OMX_VIDEO_MPEG4ProfileAdvancedScalable;
+ } else if (g_str_equal (profile_string, "advanced-simple")) {
+ param.eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
+ } else {
+ goto unsupported_profile;
+ }
+ }
+ level_string = gst_structure_get_string (s, "level");
+ if (level_string) {
+ if (g_str_equal (level_string, "0")) {
+ param.eLevel = OMX_VIDEO_MPEG4Level0;
+ } else if (g_str_equal (level_string, "0b")) {
+ param.eLevel = OMX_VIDEO_MPEG4Level0b;
+ } else if (g_str_equal (level_string, "1")) {
+ param.eLevel = OMX_VIDEO_MPEG4Level1;
+ } else if (g_str_equal (level_string, "2")) {
+ param.eLevel = OMX_VIDEO_MPEG4Level2;
+ } else if (g_str_equal (level_string, "3")) {
+ param.eLevel = OMX_VIDEO_MPEG4Level3;
+ } else if (g_str_equal (level_string, "4")) {
+ param.eLevel = OMX_VIDEO_MPEG4Level4;
+ } else if (g_str_equal (level_string, "4a")) {
+ param.eLevel = OMX_VIDEO_MPEG4Level4a;
+ } else if (g_str_equal (level_string, "5")) {
+ param.eLevel = OMX_VIDEO_MPEG4Level5;
+ } else {
+ goto unsupported_level;
+ }
+ }
+
+ gst_caps_unref (intersection);
+ }
+
+ err =
+ gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamVideoProfileLevelCurrent, &param);
+ if (err == OMX_ErrorUnsupportedIndex) {
+ GST_WARNING_OBJECT (self,
+ "Setting profile/level not supported by component");
+ } else if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Error setting profile %u and level %u: %s (0x%08x)",
+ (guint) param.eProfile, (guint) param.eLevel,
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ return TRUE;
+
+unsupported_profile:
+ GST_ERROR_OBJECT (self, "Unsupported profile %s", profile_string);
+ gst_caps_unref (intersection);
+ return FALSE;
+
+unsupported_level:
+ GST_ERROR_OBJECT (self, "Unsupported level %s", level_string);
+ gst_caps_unref (intersection);
+ return FALSE;
+}
+
+static GstCaps *
+gst_omx_mpeg4_video_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ GstOMXMPEG4VideoEnc *self = GST_OMX_MPEG4_VIDEO_ENC (enc);
+ GstCaps *caps;
+ OMX_ERRORTYPE err;
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+ const gchar *profile, *level;
+
+ caps =
+ gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
+ "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+
+ err =
+ gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+ OMX_IndexParamVideoProfileLevelCurrent, &param);
+ if (err != OMX_ErrorNone && err != OMX_ErrorUnsupportedIndex) {
+ gst_caps_unref (caps);
+ return NULL;
+ }
+
+ if (err == OMX_ErrorNone) {
+ switch (param.eProfile) {
+ case OMX_VIDEO_MPEG4ProfileSimple:
+ profile = "simple";
+ break;
+ case OMX_VIDEO_MPEG4ProfileSimpleScalable:
+ profile = "simple-scalable";
+ break;
+ case OMX_VIDEO_MPEG4ProfileCore:
+ profile = "core";
+ break;
+ case OMX_VIDEO_MPEG4ProfileMain:
+ profile = "main";
+ break;
+ case OMX_VIDEO_MPEG4ProfileNbit:
+ profile = "n-bit";
+ break;
+ case OMX_VIDEO_MPEG4ProfileScalableTexture:
+ profile = "scalable";
+ break;
+ case OMX_VIDEO_MPEG4ProfileSimpleFace:
+ profile = "simple-face";
+ break;
+ case OMX_VIDEO_MPEG4ProfileSimpleFBA:
+ profile = "simple-fba";
+ break;
+ case OMX_VIDEO_MPEG4ProfileBasicAnimated:
+ profile = "basic-animated-texture";
+ break;
+ case OMX_VIDEO_MPEG4ProfileHybrid:
+ profile = "hybrid";
+ break;
+ case OMX_VIDEO_MPEG4ProfileAdvancedRealTime:
+ profile = "advanced-real-time-simple";
+ break;
+ case OMX_VIDEO_MPEG4ProfileCoreScalable:
+ profile = "core-scalable";
+ break;
+ case OMX_VIDEO_MPEG4ProfileAdvancedCoding:
+ profile = "advanced-coding-efficiency";
+ break;
+ case OMX_VIDEO_MPEG4ProfileAdvancedCore:
+ profile = "advanced-core";
+ break;
+ case OMX_VIDEO_MPEG4ProfileAdvancedScalable:
+ profile = "advanced-scalable-texture";
+ break;
+ case OMX_VIDEO_MPEG4ProfileAdvancedSimple:
+ profile = "advanced-simple";
+ break;
+ default:
+ g_assert_not_reached ();
+ return NULL;
+ }
+
+ switch (param.eLevel) {
+ case OMX_VIDEO_MPEG4Level0:
+ level = "0";
+ break;
+ case OMX_VIDEO_MPEG4Level0b:
+ level = "0b";
+ break;
+ case OMX_VIDEO_MPEG4Level1:
+ level = "1";
+ break;
+ case OMX_VIDEO_MPEG4Level2:
+ level = "2";
+ break;
+ case OMX_VIDEO_MPEG4Level3:
+ level = "3";
+ break;
+ case OMX_VIDEO_MPEG4Level4:
+ level = "4";
+ break;
+ case OMX_VIDEO_MPEG4Level4a:
+ level = "4a";
+ break;
+ case OMX_VIDEO_MPEG4Level5:
+ level = "5";
+ break;
+ default:
+ g_assert_not_reached ();
+ return NULL;
+ }
+
+ gst_caps_set_simple (caps,
+ "profile", G_TYPE_STRING, profile, "level", G_TYPE_STRING, level, NULL);
+ }
+
+ return caps;
+}
diff --git a/subprojects/gst-omx/omx/gstomxmpeg4videoenc.h b/subprojects/gst-omx/omx/gstomxmpeg4videoenc.h
new file mode 100644
index 0000000000..01d6698c87
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxmpeg4videoenc.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_MPEG4_VIDEO_ENC_H__
+#define __GST_OMX_MPEG4_VIDEO_ENC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideoenc.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_MPEG4_VIDEO_ENC \
+ (gst_omx_mpeg4_video_enc_get_type())
+#define GST_OMX_MPEG4_VIDEO_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_MPEG4_VIDEO_ENC,GstOMXMPEG4VideoEnc))
+#define GST_OMX_MPEG4_VIDEO_ENC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_MPEG4_VIDEO_ENC,GstOMXMPEG4VideoEncClass))
+#define GST_OMX_MPEG4_VIDEO_ENC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_MPEG4_VIDEO_ENC,GstOMXMPEG4VideoEncClass))
+#define GST_IS_OMX_MPEG4_VIDEO_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_MPEG4_VIDEO_ENC))
+#define GST_IS_OMX_MPEG4_VIDEO_ENC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_MPEG4_VIDEO_ENC))
+
+typedef struct _GstOMXMPEG4VideoEnc GstOMXMPEG4VideoEnc;
+typedef struct _GstOMXMPEG4VideoEncClass GstOMXMPEG4VideoEncClass;
+
+struct _GstOMXMPEG4VideoEnc
+{
+ GstOMXVideoEnc parent;
+};
+
+struct _GstOMXMPEG4VideoEncClass
+{
+ GstOMXVideoEncClass parent_class;
+};
+
+GType gst_omx_mpeg4_video_enc_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_MPEG4_VIDEO_ENC_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxtheoradec.c b/subprojects/gst-omx/omx/gstomxtheoradec.c
new file mode 100644
index 0000000000..b17419e41f
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxtheoradec.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2013, Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxtheoradec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_theora_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_theora_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_theora_dec_is_format_change (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state);
+static gboolean gst_omx_theora_dec_set_format (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state);
+static GstFlowReturn gst_omx_theora_dec_handle_frame (GstVideoDecoder * decoder,
+ GstVideoCodecFrame * frame);
+static gboolean gst_omx_theora_dec_stop (GstVideoDecoder * decoder);
+
+enum
+{
+ PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_theora_dec_debug_category, "omxtheoradec", 0, \
+ "debug category for gst-omx video decoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXTheoraDec, gst_omx_theora_dec,
+ GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT);
+
+static void
+gst_omx_theora_dec_class_init (GstOMXTheoraDecClass * klass)
+{
+ GstVideoDecoderClass *gstvideodec_class = GST_VIDEO_DECODER_CLASS (klass);
+ GstOMXVideoDecClass *videodec_class = GST_OMX_VIDEO_DEC_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ videodec_class->is_format_change =
+ GST_DEBUG_FUNCPTR (gst_omx_theora_dec_is_format_change);
+ videodec_class->set_format =
+ GST_DEBUG_FUNCPTR (gst_omx_theora_dec_set_format);
+
+ videodec_class->cdata.default_sink_template_caps = "video/x-theora, "
+ "width=(int) [1,MAX], " "height=(int) [1,MAX]";
+
+ gstvideodec_class->handle_frame = gst_omx_theora_dec_handle_frame;
+ gstvideodec_class->stop = gst_omx_theora_dec_stop;
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX Theora Video Decoder",
+ "Codec/Decoder/Video/Hardware",
+ "Decode Theora video streams",
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+ gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.theora");
+}
+
+static void
+gst_omx_theora_dec_init (GstOMXTheoraDec * self)
+{
+}
+
+static gboolean
+gst_omx_theora_dec_is_format_change (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state)
+{
+ return FALSE;
+}
+
+static gboolean
+gst_omx_theora_dec_set_format (GstOMXVideoDec * dec, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ gboolean ret;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+
+ gst_omx_port_get_port_definition (port, &port_def);
+ port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingTheora;
+ ret = gst_omx_port_update_port_definition (port, &port_def) == OMX_ErrorNone;
+
+ return ret;
+}
+
+static GstFlowReturn
+gst_omx_theora_dec_handle_frame (GstVideoDecoder * decoder,
+ GstVideoCodecFrame * frame)
+{
+ GstOMXTheoraDec *self = GST_OMX_THEORA_DEC (decoder);
+
+ if (GST_BUFFER_FLAG_IS_SET (frame->input_buffer, GST_BUFFER_FLAG_HEADER)) {
+ guint16 size;
+ GstBuffer *sbuf;
+
+ if (!self->header) {
+ self->header = gst_buffer_new ();
+ gst_buffer_copy_into (self->header, frame->input_buffer,
+ GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
+ }
+
+ size = gst_buffer_get_size (frame->input_buffer);
+ size = GUINT16_TO_BE (size);
+ sbuf = gst_buffer_new_and_alloc (2);
+ gst_buffer_fill (sbuf, 0, &size, 2);
+ self->header = gst_buffer_append (self->header, sbuf);
+
+ self->header =
+ gst_buffer_append (self->header, gst_buffer_ref (frame->input_buffer));
+
+ gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
+
+ return GST_FLOW_OK;
+ }
+
+ if (self->header) {
+ gst_buffer_replace (&GST_OMX_VIDEO_DEC (self)->codec_data, self->header);
+ gst_buffer_unref (self->header);
+ self->header = NULL;
+ }
+
+ return
+ GST_VIDEO_DECODER_CLASS (gst_omx_theora_dec_parent_class)->handle_frame
+ (GST_VIDEO_DECODER (self), frame);
+}
+
+static gboolean
+gst_omx_theora_dec_stop (GstVideoDecoder * decoder)
+{
+ GstOMXTheoraDec *self = GST_OMX_THEORA_DEC (decoder);
+
+ gst_buffer_replace (&self->header, NULL);
+
+ return TRUE;
+}
diff --git a/subprojects/gst-omx/omx/gstomxtheoradec.h b/subprojects/gst-omx/omx/gstomxtheoradec.h
new file mode 100644
index 0000000000..4b5a2fa2fa
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxtheoradec.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2013, Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * 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_OMX_THEORA_DEC_H__
+#define __GST_OMX_THEORA_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_THEORA_DEC \
+ (gst_omx_theora_dec_get_type())
+#define GST_OMX_THEORA_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_THEORA_DEC,GstOMXTheoraDec))
+#define GST_OMX_THEORA_DEC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_THEORA_DEC,GstOMXTheoraDecClass))
+#define GST_OMX_THEORA_DEC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_THEORA_DEC,GstOMXTheoraDecClass))
+#define GST_IS_OMX_THEORA_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_THEORA_DEC))
+#define GST_IS_OMX_THEORA_DEC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_THEORA_DEC))
+
+typedef struct _GstOMXTheoraDec GstOMXTheoraDec;
+typedef struct _GstOMXTheoraDecClass GstOMXTheoraDecClass;
+
+struct _GstOMXTheoraDec
+{
+ GstOMXVideoDec parent;
+ GstBuffer *header;
+};
+
+struct _GstOMXTheoraDecClass
+{
+ GstOMXVideoDecClass parent_class;
+};
+
+GType gst_omx_theora_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_THEORA_DEC_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxvideo.c b/subprojects/gst-omx/omx/gstomxvideo.c
new file mode 100644
index 0000000000..e08ff4ceaa
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxvideo.c
@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ * Copyright (C) 2013, Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk> *
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ * Author: Christian König <christian.koenig@amd.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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstomxvideo.h"
+
+#include <math.h>
+
+GST_DEBUG_CATEGORY (gst_omx_video_debug_category);
+#define GST_CAT_DEFAULT gst_omx_video_debug_category
+
+/* Keep synced with GST_OMX_VIDEO_DEC_SUPPORTED_FORMATS */
+GstVideoFormat
+gst_omx_video_get_format_from_omx (OMX_COLOR_FORMATTYPE omx_colorformat)
+{
+ GstVideoFormat format;
+
+ switch (omx_colorformat) {
+ case OMX_COLOR_FormatL8:
+ format = GST_VIDEO_FORMAT_GRAY8;
+ break;
+ case OMX_COLOR_FormatYUV420Planar:
+ case OMX_COLOR_FormatYUV420PackedPlanar:
+ format = GST_VIDEO_FORMAT_I420;
+ break;
+ case OMX_COLOR_FormatYUV420SemiPlanar:
+ case OMX_COLOR_FormatYUV420PackedSemiPlanar:
+ format = GST_VIDEO_FORMAT_NV12;
+ break;
+ case OMX_COLOR_FormatYUV422SemiPlanar:
+ format = GST_VIDEO_FORMAT_NV16;
+ break;
+ case OMX_COLOR_FormatYCbYCr:
+ format = GST_VIDEO_FORMAT_YUY2;
+ break;
+ case OMX_COLOR_FormatYCrYCb:
+ format = GST_VIDEO_FORMAT_YVYU;
+ break;
+ case OMX_COLOR_FormatCbYCrY:
+ format = GST_VIDEO_FORMAT_UYVY;
+ break;
+ case OMX_COLOR_Format32bitARGB8888:
+ /* There is a mismatch in omxil specification 4.2.1 between
+ * OMX_COLOR_Format32bitARGB8888 and its description
+ * Follow the description */
+ format = GST_VIDEO_FORMAT_ABGR;
+ break;
+ case OMX_COLOR_Format32bitBGRA8888:
+ /* Same issue as OMX_COLOR_Format32bitARGB8888 */
+ format = GST_VIDEO_FORMAT_ARGB;
+ break;
+ case OMX_COLOR_Format16bitRGB565:
+ format = GST_VIDEO_FORMAT_RGB16;
+ break;
+ case OMX_COLOR_Format16bitBGR565:
+ format = GST_VIDEO_FORMAT_BGR16;
+ break;
+ case OMX_COLOR_Format24bitBGR888:
+ format = GST_VIDEO_FORMAT_BGR;
+ break;
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ /* Formats defined in extensions have their own enum so disable to -Wswitch warning */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wswitch"
+ case OMX_ALG_COLOR_FormatYUV420SemiPlanar10bitPacked:
+ format = GST_VIDEO_FORMAT_NV12_10LE32;
+ break;
+ case OMX_ALG_COLOR_FormatYUV422SemiPlanar10bitPacked:
+ format = GST_VIDEO_FORMAT_NV16_10LE32;
+ break;
+#pragma GCC diagnostic pop
+#endif
+ default:
+ format = GST_VIDEO_FORMAT_UNKNOWN;
+ break;
+ }
+
+ return format;
+}
+
+GList *
+gst_omx_video_get_supported_colorformats (GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ GstOMXComponent *comp = port->comp;
+ OMX_VIDEO_PARAM_PORTFORMATTYPE param;
+ OMX_ERRORTYPE err;
+ GList *negotiation_map = NULL;
+ gint old_index;
+ GstOMXVideoNegotiationMap *m;
+ GstVideoFormat f;
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = port->index;
+ param.nIndex = 0;
+ param.xFramerate =
+ state ? gst_omx_video_calculate_framerate_q16 (&state->info) : 0;
+
+ old_index = -1;
+ do {
+ err =
+ gst_omx_component_get_parameter (comp,
+ OMX_IndexParamVideoPortFormat, &param);
+
+ /* FIXME: Workaround for Bellagio that simply always
+ * returns the same value regardless of nIndex and
+ * never returns OMX_ErrorNoMore
+ */
+ if (old_index == param.nIndex)
+ break;
+
+ if (err == OMX_ErrorNone || err == OMX_ErrorNoMore) {
+ f = gst_omx_video_get_format_from_omx (param.eColorFormat);
+
+ if (f != GST_VIDEO_FORMAT_UNKNOWN) {
+ m = g_slice_new (GstOMXVideoNegotiationMap);
+ m->format = f;
+ m->type = param.eColorFormat;
+ negotiation_map = g_list_append (negotiation_map, m);
+ GST_DEBUG_OBJECT (comp->parent,
+ "Component port %d supports %s (%d) at index %u", port->index,
+ gst_video_format_to_string (f), param.eColorFormat,
+ (guint) param.nIndex);
+ } else {
+ GST_DEBUG_OBJECT (comp->parent,
+ "Component port %d supports unsupported color format %d at index %u",
+ port->index, param.eColorFormat, (guint) param.nIndex);
+ }
+ }
+ old_index = param.nIndex++;
+ } while (err == OMX_ErrorNone);
+
+ return negotiation_map;
+}
+
+GstCaps *
+gst_omx_video_get_caps_for_map (GList * map)
+{
+ GstCaps *caps = gst_caps_new_empty ();
+ GList *l;
+
+ for (l = map; l; l = l->next) {
+ GstOMXVideoNegotiationMap *entry = l->data;
+
+ gst_caps_append_structure (caps,
+ gst_structure_new ("video/x-raw",
+ "format", G_TYPE_STRING,
+ gst_video_format_to_string (entry->format), NULL));
+ }
+ return caps;
+}
+
+void
+gst_omx_video_negotiation_map_free (GstOMXVideoNegotiationMap * m)
+{
+ g_slice_free (GstOMXVideoNegotiationMap, m);
+}
+
+GstVideoCodecFrame *
+gst_omx_video_find_nearest_frame (GstElement * element, GstOMXBuffer * buf,
+ GList * frames)
+{
+ GstVideoCodecFrame *best = NULL;
+ GstClockTimeDiff best_diff = G_MAXINT64;
+ GstClockTime timestamp;
+ GList *l;
+
+ timestamp =
+ gst_util_uint64_scale (GST_OMX_GET_TICKS (buf->omx_buf->nTimeStamp),
+ GST_SECOND, OMX_TICKS_PER_SECOND);
+
+ GST_LOG_OBJECT (element, "look for ts %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (timestamp));
+
+ for (l = frames; l; l = l->next) {
+ GstVideoCodecFrame *tmp = l->data;
+ GstClockTimeDiff diff = ABS (GST_CLOCK_DIFF (timestamp, tmp->pts));
+
+ GST_LOG_OBJECT (element,
+ " frame %u diff %" G_GINT64_FORMAT " ts %" GST_TIME_FORMAT,
+ tmp->system_frame_number, diff, GST_TIME_ARGS (tmp->pts));
+
+ if (diff < best_diff) {
+ best = tmp;
+ best_diff = diff;
+
+ if (diff == 0)
+ break;
+ }
+ }
+
+ if (best) {
+ gst_video_codec_frame_ref (best);
+
+ /* OMX timestamps are in microseconds while gst ones are in nanoseconds.
+ * So if the difference between them is higher than 1 microsecond we likely
+ * picked the wrong frame. */
+ if (best_diff >= GST_USECOND)
+ GST_WARNING_OBJECT (element,
+ "Difference between ts (%" GST_TIME_FORMAT ") and frame %u (%"
+ GST_TIME_FORMAT ") seems too high (%" GST_TIME_FORMAT ")",
+ GST_TIME_ARGS (timestamp), best->system_frame_number,
+ GST_TIME_ARGS (best->pts), GST_TIME_ARGS (best_diff));
+ } else
+ GST_WARNING_OBJECT (element, "No best frame has been found");
+
+ g_list_foreach (frames, (GFunc) gst_video_codec_frame_unref, NULL);
+ g_list_free (frames);
+
+ return best;
+}
+
+OMX_U32
+gst_omx_video_calculate_framerate_q16 (GstVideoInfo * info)
+{
+ g_assert (info);
+
+ if (!info->fps_d)
+ return 0;
+
+ /* OMX API expects frame rate to actually be the field rate, so twice
+ * the frame rate in interlace mode. */
+ return gst_util_uint64_scale_int (1 << 16, GST_VIDEO_INFO_FIELD_RATE_N (info),
+ info->fps_d);
+}
+
+gboolean
+gst_omx_video_is_equal_framerate_q16 (OMX_U32 q16_a, OMX_U32 q16_b)
+{
+ /* If one of them is 0 use the classic comparison. The value 0 has a special
+ meaning and is used to indicate the frame rate is unknown, variable, or
+ is not needed. */
+ if (!q16_a || !q16_b)
+ return q16_a == q16_b;
+
+ /* If the 'percentage change' is less than 1% then consider it equal to avoid
+ * an unnecessary re-negotiation. */
+ return fabs (((gdouble) q16_a) - ((gdouble) q16_b)) / (gdouble) q16_b < 0.01;
+}
+
+gboolean
+gst_omx_video_get_port_padding (GstOMXPort * port, GstVideoInfo * info_orig,
+ GstVideoAlignment * align)
+{
+ guint nstride;
+ guint nslice_height;
+ GstVideoInfo info;
+ gsize plane_size[GST_VIDEO_MAX_PLANES];
+
+ gst_video_alignment_reset (align);
+
+ /* Create a copy of @info_orig without any offset/stride as we need a
+ * 'standard' version to compute the paddings. */
+ gst_video_info_init (&info);
+ gst_video_info_set_interlaced_format (&info,
+ GST_VIDEO_INFO_FORMAT (info_orig),
+ GST_VIDEO_INFO_INTERLACE_MODE (info_orig),
+ GST_VIDEO_INFO_WIDTH (info_orig), GST_VIDEO_INFO_HEIGHT (info_orig));
+
+ /* Retrieve the plane sizes */
+ if (!gst_video_info_align_full (&info, align, plane_size)) {
+ GST_WARNING_OBJECT (port->comp->parent, "Failed to retrieve plane sizes");
+ return FALSE;
+ }
+
+ nstride = port->port_def.format.video.nStride;
+ nslice_height = port->port_def.format.video.nSliceHeight;
+
+ if (nstride > GST_VIDEO_INFO_PLANE_STRIDE (&info, 0)) {
+ align->padding_right = nstride - GST_VIDEO_INFO_PLANE_STRIDE (&info, 0);
+
+ if (GST_VIDEO_FORMAT_INFO_IS_COMPLEX (info.finfo)) {
+ /* Stride is in bytes while padding is in pixels so we need to do manual
+ * conversions for complex formats. */
+ switch (GST_VIDEO_INFO_FORMAT (&info)) {
+ case GST_VIDEO_FORMAT_NV12_10LE32:
+ case GST_VIDEO_FORMAT_NV16_10LE32:
+ /* Need ((width + 2) / 3) 32-bits words to store one row,
+ * see unpack_NV12_10LE32 in -base.
+ *
+ * So let's say:
+ * - W = the width, in pixels
+ * - S = the stride, in bytes
+ * - P = the padding, in bytes
+ * - Δ = the padding, in pixels
+ *
+ * we then have:
+ * S = ((W+2)/3) * 4
+ * S+P = ((W+2+Δ)/3) * 4
+ *
+ * By solving this system we get:
+ * Δ = (3/4) * P
+ */
+ align->padding_right *= 0.75;
+ break;
+ default:
+ GST_FIXME_OBJECT (port->comp->parent,
+ "Stride conversion is not supported for format %s",
+ GST_VIDEO_INFO_NAME (&info));
+ return FALSE;
+ }
+ }
+
+ GST_LOG_OBJECT (port->comp->parent,
+ "OMX stride (%d) is higher than standard (%d) for port %u; right padding: %d",
+ nstride, GST_VIDEO_INFO_PLANE_STRIDE (&info, 0), port->index,
+ align->padding_right);
+ }
+
+ if (nslice_height > GST_VIDEO_INFO_PLANE_HEIGHT (&info, 0, plane_size)) {
+ align->padding_bottom =
+ nslice_height - GST_VIDEO_INFO_PLANE_HEIGHT (&info, 0, plane_size);
+
+ if (GST_VIDEO_INFO_INTERLACE_MODE (&info) ==
+ GST_VIDEO_INTERLACE_MODE_ALTERNATE) {
+ /* GstVideoAlignment defines the alignment for the full frame while
+ * OMX gives us the slice height for a single field, so we have to
+ * double the vertical padding. */
+ GST_DEBUG_OBJECT (port->comp->parent,
+ "Double bottom padding because of alternate stream");
+ align->padding_bottom *= 2;
+ }
+
+ GST_LOG_OBJECT (port->comp->parent,
+ "OMX slice height (%d) is higher than standard (%" G_GSIZE_FORMAT
+ ") for port %u; vertical padding: %d", nslice_height,
+ GST_VIDEO_INFO_PLANE_HEIGHT (&info, 0, plane_size), port->index,
+ align->padding_bottom);
+ }
+
+ return TRUE;
+}
diff --git a/subprojects/gst-omx/omx/gstomxvideo.h b/subprojects/gst-omx/omx/gstomxvideo.h
new file mode 100644
index 0000000000..8664345f21
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxvideo.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ * Author: Christian König <christian.koenig@amd.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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_VIDEO_H__
+#define __GST_OMX_VIDEO_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/video/gstvideodecoder.h>
+#include <gst/video/gstvideoencoder.h>
+
+#include "gstomx.h"
+
+G_BEGIN_DECLS
+
+/* Keep synced with gst_omx_video_get_format_from_omx(). Sort by decreasing quality */
+#define GST_OMX_VIDEO_DEC_SUPPORTED_FORMATS "{ NV16_10LE32, NV12_10LE32, " \
+ "NV16, YUY2, YVYU, UYVY, NV12, I420, RGB16, BGR16, ABGR, ARGB, GRAY8 }"
+
+#define GST_OMX_VIDEO_ENC_SUPPORTED_FORMATS "{ NV16_10LE32, NV12_10LE32, " \
+ "NV16, NV12, I420, GRAY8 }"
+
+typedef struct
+{
+ GstVideoFormat format;
+ OMX_COLOR_FORMATTYPE type;
+} GstOMXVideoNegotiationMap;
+
+GstVideoFormat
+gst_omx_video_get_format_from_omx (OMX_COLOR_FORMATTYPE omx_colorformat);
+
+GList *
+gst_omx_video_get_supported_colorformats (GstOMXPort * port,
+ GstVideoCodecState * state);
+
+GstCaps * gst_omx_video_get_caps_for_map(GList * map);
+
+void
+gst_omx_video_negotiation_map_free (GstOMXVideoNegotiationMap * m);
+
+GstVideoCodecFrame *
+gst_omx_video_find_nearest_frame (GstElement * element, GstOMXBuffer * buf, GList * frames);
+
+OMX_U32 gst_omx_video_calculate_framerate_q16 (GstVideoInfo * info);
+
+gboolean gst_omx_video_is_equal_framerate_q16 (OMX_U32 q16_a, OMX_U32 q16_b);
+
+gboolean gst_omx_video_get_port_padding (GstOMXPort * port, GstVideoInfo * info_orig,
+ GstVideoAlignment * align);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_VIDEO_H__ */
diff --git a/subprojects/gst-omx/omx/gstomxvideodec.c b/subprojects/gst-omx/omx/gstomxvideodec.c
new file mode 100644
index 0000000000..917ce8a315
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxvideodec.c
@@ -0,0 +1,3524 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ * Copyright (C) 2013, Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/allocators/gstdmabuf.h>
+
+#if defined (USE_OMX_TARGET_RPI) && defined(__GNUC__)
+#ifndef __VCCOREVER__
+#define __VCCOREVER__ 0x04000000
+#endif
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+#pragma GCC optimize ("gnu89-inline")
+#endif
+
+#if defined (HAVE_GST_GL)
+#include <gst/gl/egl/gstglmemoryegl.h>
+#endif
+
+#if defined (USE_OMX_TARGET_RPI) && defined(__GNUC__)
+#pragma GCC reset_options
+#pragma GCC diagnostic pop
+#endif
+
+#include <string.h>
+
+#include "gstomxbufferpool.h"
+#include "gstomxvideo.h"
+#include "gstomxvideodec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_video_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_video_dec_debug_category
+
+/* prototypes */
+static void gst_omx_video_dec_finalize (GObject * object);
+
+static GstStateChangeReturn
+gst_omx_video_dec_change_state (GstElement * element,
+ GstStateChange transition);
+
+static gboolean gst_omx_video_dec_open (GstVideoDecoder * decoder);
+static gboolean gst_omx_video_dec_close (GstVideoDecoder * decoder);
+static gboolean gst_omx_video_dec_start (GstVideoDecoder * decoder);
+static gboolean gst_omx_video_dec_stop (GstVideoDecoder * decoder);
+static gboolean gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
+ GstVideoCodecState * state);
+static gboolean gst_omx_video_dec_flush (GstVideoDecoder * decoder);
+static GstFlowReturn gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
+ GstVideoCodecFrame * frame);
+static GstFlowReturn gst_omx_video_dec_finish (GstVideoDecoder * decoder);
+static gboolean gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec,
+ GstQuery * query);
+static gboolean gst_omx_video_dec_propose_allocation (GstVideoDecoder * bdec,
+ GstQuery * query);
+
+static GstFlowReturn gst_omx_video_dec_drain (GstVideoDecoder * decoder);
+
+static OMX_ERRORTYPE gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec *
+ self);
+static gboolean gst_omx_video_dec_deallocate_output_buffers (GstOMXVideoDec
+ * self);
+
+enum
+{
+ PROP_0,
+ PROP_INTERNAL_ENTROPY_BUFFERS,
+};
+
+#define GST_OMX_VIDEO_DEC_INTERNAL_ENTROPY_BUFFERS_DEFAULT (5)
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_video_dec_debug_category, "omxvideodec", 0, \
+ "debug category for gst-omx video decoder base class");
+
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstOMXVideoDec, gst_omx_video_dec,
+ GST_TYPE_VIDEO_DECODER, DEBUG_INIT);
+
+static void
+gst_omx_video_dec_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (object);
+#endif
+
+ switch (prop_id) {
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ case PROP_INTERNAL_ENTROPY_BUFFERS:
+ self->internal_entropy_buffers = g_value_get_uint (value);
+ break;
+#endif
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_omx_video_dec_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (object);
+#endif
+
+ switch (prop_id) {
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ case PROP_INTERNAL_ENTROPY_BUFFERS:
+ g_value_set_uint (value, self->internal_entropy_buffers);
+ break;
+#endif
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_omx_video_dec_class_init (GstOMXVideoDecClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstVideoDecoderClass *video_decoder_class = GST_VIDEO_DECODER_CLASS (klass);
+
+ gobject_class->finalize = gst_omx_video_dec_finalize;
+ gobject_class->set_property = gst_omx_video_dec_set_property;
+ gobject_class->get_property = gst_omx_video_dec_get_property;
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ g_object_class_install_property (gobject_class, PROP_INTERNAL_ENTROPY_BUFFERS,
+ g_param_spec_uint ("internal-entropy-buffers", "Internal entropy buffers",
+ "Number of internal buffers used by the decoder to smooth out entropy decoding performance. "
+ "Increasing it may improve the frame rate when decoding high bitrate streams. "
+ "Decreasing it reduces the memory footprint",
+ 2, 16, GST_OMX_VIDEO_DEC_INTERNAL_ENTROPY_BUFFERS_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+#endif
+
+ element_class->change_state =
+ GST_DEBUG_FUNCPTR (gst_omx_video_dec_change_state);
+
+ video_decoder_class->open = GST_DEBUG_FUNCPTR (gst_omx_video_dec_open);
+ video_decoder_class->close = GST_DEBUG_FUNCPTR (gst_omx_video_dec_close);
+ video_decoder_class->start = GST_DEBUG_FUNCPTR (gst_omx_video_dec_start);
+ video_decoder_class->stop = GST_DEBUG_FUNCPTR (gst_omx_video_dec_stop);
+ video_decoder_class->flush = GST_DEBUG_FUNCPTR (gst_omx_video_dec_flush);
+ video_decoder_class->set_format =
+ GST_DEBUG_FUNCPTR (gst_omx_video_dec_set_format);
+ video_decoder_class->handle_frame =
+ GST_DEBUG_FUNCPTR (gst_omx_video_dec_handle_frame);
+ video_decoder_class->finish = GST_DEBUG_FUNCPTR (gst_omx_video_dec_finish);
+ video_decoder_class->drain = GST_DEBUG_FUNCPTR (gst_omx_video_dec_drain);
+ video_decoder_class->decide_allocation =
+ GST_DEBUG_FUNCPTR (gst_omx_video_dec_decide_allocation);
+ video_decoder_class->propose_allocation =
+ GST_DEBUG_FUNCPTR (gst_omx_video_dec_propose_allocation);
+
+ klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
+ klass->cdata.default_src_template_caps =
+#if defined (HAVE_GST_GL)
+ GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_GL_MEMORY,
+ "RGBA") "; "
+#endif
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_FORMAT_INTERLACED,
+ GST_OMX_VIDEO_DEC_SUPPORTED_FORMATS)
+ ", interlace-mode = (string) alternate ; "
+#endif
+ GST_VIDEO_CAPS_MAKE (GST_OMX_VIDEO_DEC_SUPPORTED_FORMATS);
+}
+
+static void
+gst_omx_video_dec_init (GstOMXVideoDec * self)
+{
+ self->dmabuf = FALSE;
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ self->internal_entropy_buffers =
+ GST_OMX_VIDEO_DEC_INTERNAL_ENTROPY_BUFFERS_DEFAULT;
+#endif
+
+ gst_video_decoder_set_packetized (GST_VIDEO_DECODER (self), TRUE);
+ gst_video_decoder_set_use_default_pad_acceptcaps (GST_VIDEO_DECODER_CAST
+ (self), TRUE);
+ GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_DECODER_SINK_PAD (self));
+
+ g_mutex_init (&self->drain_lock);
+ g_cond_init (&self->drain_cond);
+}
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+
+#define CHECK_ERR(setting) \
+ if (err == OMX_ErrorUnsupportedIndex || err == OMX_ErrorUnsupportedSetting) { \
+ GST_WARNING_OBJECT (self, \
+ "Setting " setting " parameters not supported by the component"); \
+ } else if (err != OMX_ErrorNone) { \
+ GST_ERROR_OBJECT (self, \
+ "Failed to set " setting " parameters: %s (0x%08x)", \
+ gst_omx_error_to_string (err), err); \
+ return FALSE; \
+ }
+
+static gboolean
+set_zynqultrascaleplus_props (GstOMXVideoDec * self)
+{
+ OMX_ERRORTYPE err;
+
+ {
+ OMX_ALG_VIDEO_PARAM_INTERNAL_ENTROPY_BUFFERS entropy_buffers;
+
+ GST_OMX_INIT_STRUCT (&entropy_buffers);
+ entropy_buffers.nPortIndex = self->dec_in_port->index;
+ entropy_buffers.nNumInternalEntropyBuffers = self->internal_entropy_buffers;
+
+ GST_DEBUG_OBJECT (self, "setting number of internal entropy buffers to %d",
+ self->internal_entropy_buffers);
+
+ err =
+ gst_omx_component_set_parameter (self->dec,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoInternalEntropyBuffers,
+ &entropy_buffers);
+ CHECK_ERR ("internal entropy buffers");
+ }
+
+ return TRUE;
+}
+#endif
+
+static gboolean
+gst_omx_video_dec_open (GstVideoDecoder * decoder)
+{
+ GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (decoder);
+ GstOMXVideoDecClass *klass = GST_OMX_VIDEO_DEC_GET_CLASS (self);
+ gint in_port_index, out_port_index;
+
+ GST_DEBUG_OBJECT (self, "Opening decoder");
+
+ self->dec =
+ gst_omx_component_new (GST_OBJECT_CAST (self), klass->cdata.core_name,
+ klass->cdata.component_name, klass->cdata.component_role,
+ klass->cdata.hacks);
+ self->started = FALSE;
+
+ if (!self->dec)
+ return FALSE;
+
+ if (gst_omx_component_get_state (self->dec,
+ GST_CLOCK_TIME_NONE) != OMX_StateLoaded)
+ return FALSE;
+
+ in_port_index = klass->cdata.in_port_index;
+ out_port_index = klass->cdata.out_port_index;
+
+ if (in_port_index == -1 || out_port_index == -1) {
+ OMX_PORT_PARAM_TYPE param;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&param);
+
+ err =
+ gst_omx_component_get_parameter (self->dec, OMX_IndexParamVideoInit,
+ &param);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self, "Couldn't get port information: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ /* Fallback */
+ in_port_index = 0;
+ out_port_index = 1;
+ } else {
+ GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u",
+ (guint) param.nPorts, (guint) param.nStartPortNumber);
+ in_port_index = param.nStartPortNumber + 0;
+ out_port_index = param.nStartPortNumber + 1;
+ }
+ }
+ self->dec_in_port = gst_omx_component_add_port (self->dec, in_port_index);
+ self->dec_out_port = gst_omx_component_add_port (self->dec, out_port_index);
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ GST_DEBUG_OBJECT (self, "Configure decoder output to export dmabuf");
+ self->dmabuf = gst_omx_port_set_dmabuf (self->dec_out_port, TRUE);
+#endif
+
+ if (!self->dec_in_port || !self->dec_out_port)
+ return FALSE;
+
+ GST_DEBUG_OBJECT (self, "Opened decoder");
+
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+ GST_DEBUG_OBJECT (self, "Opening EGL renderer");
+ self->egl_render =
+ gst_omx_component_new (GST_OBJECT_CAST (self), klass->cdata.core_name,
+ "OMX.broadcom.egl_render", NULL, klass->cdata.hacks);
+
+ if (!self->egl_render)
+ return FALSE;
+
+ if (gst_omx_component_get_state (self->egl_render,
+ GST_CLOCK_TIME_NONE) != OMX_StateLoaded)
+ return FALSE;
+
+ {
+ OMX_PORT_PARAM_TYPE param;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&param);
+
+ err =
+ gst_omx_component_get_parameter (self->egl_render,
+ OMX_IndexParamVideoInit, &param);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self, "Couldn't get port information: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ /* Fallback */
+ in_port_index = 0;
+ out_port_index = 1;
+ } else {
+ GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u", param.nPorts,
+ param.nStartPortNumber);
+ in_port_index = param.nStartPortNumber + 0;
+ out_port_index = param.nStartPortNumber + 1;
+ }
+ }
+
+ self->egl_in_port =
+ gst_omx_component_add_port (self->egl_render, in_port_index);
+ self->egl_out_port =
+ gst_omx_component_add_port (self->egl_render, out_port_index);
+
+ if (!self->egl_in_port || !self->egl_out_port)
+ return FALSE;
+
+ GST_DEBUG_OBJECT (self, "Opened EGL renderer");
+#endif
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ if (!set_zynqultrascaleplus_props (self))
+ return FALSE;
+#endif
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_dec_shutdown (GstOMXVideoDec * self)
+{
+ OMX_STATETYPE state;
+
+ GST_DEBUG_OBJECT (self, "Shutting down decoder");
+
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+ state = gst_omx_component_get_state (self->egl_render, 0);
+ if (state > OMX_StateLoaded || state == OMX_StateInvalid) {
+ if (state > OMX_StateIdle) {
+ gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
+ gst_omx_component_set_state (self->dec, OMX_StateIdle);
+ gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
+ gst_omx_component_get_state (self->dec, 1 * GST_SECOND);
+ }
+ gst_omx_component_set_state (self->egl_render, OMX_StateLoaded);
+ gst_omx_component_set_state (self->dec, OMX_StateLoaded);
+
+ gst_omx_port_deallocate_buffers (self->dec_in_port);
+ gst_omx_video_dec_deallocate_output_buffers (self);
+ gst_omx_close_tunnel (self->dec_out_port, self->egl_in_port);
+ if (state > OMX_StateLoaded) {
+ gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
+ gst_omx_component_get_state (self->dec, 1 * GST_SECOND);
+ }
+ }
+
+ /* Otherwise we didn't use EGL and just fall back to
+ * shutting down the decoder */
+#endif
+
+ state = gst_omx_component_get_state (self->dec, 0);
+ if (state > OMX_StateLoaded || state == OMX_StateInvalid) {
+ if (state > OMX_StateIdle) {
+ gst_omx_component_set_state (self->dec, OMX_StateIdle);
+ gst_omx_component_get_state (self->dec, 5 * GST_SECOND);
+ }
+ gst_omx_component_set_state (self->dec, OMX_StateLoaded);
+ gst_omx_port_deallocate_buffers (self->dec_in_port);
+ gst_omx_video_dec_deallocate_output_buffers (self);
+ if (state > OMX_StateLoaded) {
+ if (self->dec_out_port->buffers)
+ /* Don't wait for the state transition if the pool still has outstanding
+ * buffers as it will timeout anyway */
+ GST_WARNING_OBJECT (self,
+ "Output buffers haven't been freed; still owned downstream?");
+ else
+ gst_omx_component_get_state (self->dec, 5 * GST_SECOND);
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_dec_close (GstVideoDecoder * decoder)
+{
+ GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (decoder);
+
+ GST_DEBUG_OBJECT (self, "Closing decoder");
+
+ if (!gst_omx_video_dec_shutdown (self))
+ return FALSE;
+
+ self->dec_in_port = NULL;
+ self->dec_out_port = NULL;
+ if (self->dec)
+ gst_omx_component_unref (self->dec);
+ self->dec = NULL;
+
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+ self->egl_in_port = NULL;
+ self->egl_out_port = NULL;
+ if (self->egl_render)
+ gst_omx_component_unref (self->egl_render);
+ self->egl_render = NULL;
+#endif
+
+ self->started = FALSE;
+
+ GST_DEBUG_OBJECT (self, "Closed decoder");
+
+ return TRUE;
+}
+
+static void
+gst_omx_video_dec_finalize (GObject * object)
+{
+ GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (object);
+
+ g_mutex_clear (&self->drain_lock);
+ g_cond_clear (&self->drain_cond);
+
+ G_OBJECT_CLASS (gst_omx_video_dec_parent_class)->finalize (object);
+}
+
+static GstStateChangeReturn
+gst_omx_video_dec_change_state (GstElement * element, GstStateChange transition)
+{
+ GstOMXVideoDec *self;
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+
+ g_return_val_if_fail (GST_IS_OMX_VIDEO_DEC (element),
+ GST_STATE_CHANGE_FAILURE);
+ self = GST_OMX_VIDEO_DEC (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ break;
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ self->downstream_flow_ret = GST_FLOW_OK;
+ self->draining = FALSE;
+ self->started = FALSE;
+ self->use_buffers = FALSE;
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ if (self->dec_in_port)
+ gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
+ if (self->dec_out_port)
+ gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+ if (self->egl_in_port)
+ gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, TRUE);
+ if (self->egl_out_port)
+ gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, TRUE);
+#endif
+
+ g_mutex_lock (&self->drain_lock);
+ self->draining = FALSE;
+ g_cond_broadcast (&self->drain_cond);
+ g_mutex_unlock (&self->drain_lock);
+ break;
+ default:
+ break;
+ }
+
+ ret =
+ GST_ELEMENT_CLASS (gst_omx_video_dec_parent_class)->change_state
+ (element, transition);
+
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ return ret;
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ self->downstream_flow_ret = GST_FLOW_FLUSHING;
+ self->started = FALSE;
+ break;
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static gboolean
+gst_omx_video_dec_fill_buffer (GstOMXVideoDec * self,
+ GstOMXBuffer * inbuf, GstBuffer * outbuf)
+{
+ GstVideoCodecState *state =
+ gst_video_decoder_get_output_state (GST_VIDEO_DECODER (self));
+ GstVideoInfo *vinfo = &state->info;
+ OMX_PARAM_PORTDEFINITIONTYPE *port_def = &self->dec_out_port->port_def;
+ gboolean ret = FALSE;
+ GstVideoFrame frame;
+
+ if (vinfo->width != port_def->format.video.nFrameWidth ||
+ GST_VIDEO_INFO_FIELD_HEIGHT (vinfo) !=
+ port_def->format.video.nFrameHeight) {
+ GST_ERROR_OBJECT (self, "Resolution do not match: port=%ux%u vinfo=%dx%d",
+ (guint) port_def->format.video.nFrameWidth,
+ (guint) port_def->format.video.nFrameHeight,
+ vinfo->width, GST_VIDEO_INFO_FIELD_HEIGHT (vinfo));
+ goto done;
+ }
+
+ /* Same strides and everything */
+ if (gst_buffer_get_size (outbuf) == inbuf->omx_buf->nFilledLen) {
+ GstMapInfo map = GST_MAP_INFO_INIT;
+
+ if (!gst_buffer_map (outbuf, &map, GST_MAP_WRITE)) {
+ GST_ERROR_OBJECT (self, "Failed to map output buffer");
+ goto done;
+ }
+
+ memcpy (map.data,
+ inbuf->omx_buf->pBuffer + inbuf->omx_buf->nOffset,
+ inbuf->omx_buf->nFilledLen);
+ gst_buffer_unmap (outbuf, &map);
+ ret = TRUE;
+ goto done;
+ }
+
+ /* Different strides */
+ if (gst_video_frame_map (&frame, vinfo, outbuf, GST_MAP_WRITE)) {
+ const guint nstride = port_def->format.video.nStride;
+ const guint nslice = port_def->format.video.nSliceHeight;
+ guint src_stride[GST_VIDEO_MAX_PLANES] = { nstride, 0, };
+ guint src_size[GST_VIDEO_MAX_PLANES] = { nstride * nslice, 0, };
+ gint dst_width[GST_VIDEO_MAX_PLANES] = { 0, };
+ gint dst_height[GST_VIDEO_MAX_PLANES] =
+ { GST_VIDEO_INFO_FIELD_HEIGHT (vinfo), 0, };
+ const guint8 *src;
+ guint p;
+
+ switch (GST_VIDEO_INFO_FORMAT (vinfo)) {
+ case GST_VIDEO_FORMAT_ABGR:
+ case GST_VIDEO_FORMAT_ARGB:
+ dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo) * 4;
+ break;
+ case GST_VIDEO_FORMAT_RGB16:
+ case GST_VIDEO_FORMAT_BGR16:
+ case GST_VIDEO_FORMAT_YUY2:
+ case GST_VIDEO_FORMAT_UYVY:
+ case GST_VIDEO_FORMAT_YVYU:
+ dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo) * 2;
+ break;
+ case GST_VIDEO_FORMAT_GRAY8:
+ dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
+ break;
+ case GST_VIDEO_FORMAT_I420:
+ dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
+ src_stride[1] = nstride / 2;
+ src_size[1] = (src_stride[1] * nslice) / 2;
+ dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo) / 2;
+ dst_height[1] = GST_VIDEO_INFO_FIELD_HEIGHT (vinfo) / 2;
+ src_stride[2] = nstride / 2;
+ src_size[2] = (src_stride[1] * nslice) / 2;
+ dst_width[2] = GST_VIDEO_INFO_WIDTH (vinfo) / 2;
+ dst_height[2] = GST_VIDEO_INFO_FIELD_HEIGHT (vinfo) / 2;
+ break;
+ case GST_VIDEO_FORMAT_NV12:
+ dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
+ src_stride[1] = nstride;
+ src_size[1] = src_stride[1] * nslice / 2;
+ dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo);
+ dst_height[1] = GST_VIDEO_INFO_FIELD_HEIGHT (vinfo) / 2;
+ break;
+ case GST_VIDEO_FORMAT_NV16:
+ dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
+ src_stride[1] = nstride;
+ src_size[1] = src_stride[1] * nslice;
+ dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo);
+ dst_height[1] = GST_VIDEO_INFO_FIELD_HEIGHT (vinfo);
+ break;
+ case GST_VIDEO_FORMAT_NV12_10LE32:
+ /* Need ((width + 2) / 3) 32-bits words */
+ dst_width[0] = (GST_VIDEO_INFO_WIDTH (vinfo) + 2) / 3 * 4;
+ dst_width[1] = dst_width[0];
+ src_stride[1] = nstride;
+ src_size[1] = src_stride[1] * nslice / 2;
+ dst_height[1] = GST_VIDEO_INFO_FIELD_HEIGHT (vinfo) / 2;
+ break;
+ case GST_VIDEO_FORMAT_NV16_10LE32:
+ /* Need ((width + 2) / 3) 32-bits words */
+ dst_width[0] = (GST_VIDEO_INFO_WIDTH (vinfo) + 2) / 3 * 4;
+ dst_width[1] = dst_width[0];
+ src_stride[1] = nstride;
+ src_size[1] = src_stride[1] * nslice;
+ dst_height[1] = GST_VIDEO_INFO_FIELD_HEIGHT (vinfo);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ src = inbuf->omx_buf->pBuffer + inbuf->omx_buf->nOffset;
+ for (p = 0; p < GST_VIDEO_INFO_N_PLANES (vinfo); p++) {
+ const guint8 *data;
+ guint8 *dst;
+ guint h;
+
+ dst = GST_VIDEO_FRAME_PLANE_DATA (&frame, p);
+ data = src;
+ for (h = 0; h < dst_height[p]; h++) {
+ memcpy (dst, data, dst_width[p]);
+ dst += GST_VIDEO_FRAME_PLANE_STRIDE (&frame, p);
+ data += src_stride[p];
+ }
+ src += src_size[p];
+ }
+
+ gst_video_frame_unmap (&frame);
+ ret = TRUE;
+ } else {
+ GST_ERROR_OBJECT (self, "Can't map output buffer to frame");
+ goto done;
+ }
+
+done:
+ if (ret) {
+ GST_BUFFER_PTS (outbuf) =
+ gst_util_uint64_scale (GST_OMX_GET_TICKS (inbuf->omx_buf->nTimeStamp),
+ GST_SECOND, OMX_TICKS_PER_SECOND);
+ if (inbuf->omx_buf->nTickCount != 0)
+ GST_BUFFER_DURATION (outbuf) =
+ gst_util_uint64_scale (inbuf->omx_buf->nTickCount, GST_SECOND,
+ OMX_TICKS_PER_SECOND);
+ }
+
+ gst_video_codec_state_unref (state);
+
+ return ret;
+}
+
+static GstBuffer *
+gst_omx_try_importing_buffer (GstOMXVideoDec * self, GstBufferPool * pool,
+ GstOMXPort * port, GstVideoInfo * v_info, guint i, GstVideoFrame ** frame)
+{
+ GstBufferPoolAcquireParams params = { 0, };
+ GstBuffer *buffer = NULL;
+ GstMemory *mem;
+ GstMapFlags flags = GST_MAP_WRITE | GST_VIDEO_FRAME_MAP_FLAG_NO_REF;
+ gboolean is_mapped = FALSE;
+
+ *frame = NULL;
+
+ if (gst_buffer_pool_acquire_buffer (pool, &buffer, &params) != GST_FLOW_OK) {
+ GST_INFO_OBJECT (self, "Failed to acquire %d-th buffer", i);
+ return NULL;
+ }
+
+ if (gst_buffer_n_memory (buffer) != 1) {
+ GST_INFO_OBJECT (self, "%d-th buffer has more than one memory (%d)", i,
+ gst_buffer_n_memory (buffer));
+ goto out;
+ }
+
+ mem = gst_buffer_peek_memory (buffer, 0);
+ if (!mem) {
+ GST_INFO_OBJECT (self, "Failed to acquire memory of %d-th buffer", i);
+ goto out;
+ }
+
+ if (self->dmabuf && !gst_is_dmabuf_memory (mem)) {
+ GST_INFO_OBJECT (self,
+ "%d-th buffer doesn't contain dmabuf while the decoder is in dmabuf mode",
+ i);
+ goto out;
+ }
+
+ *frame = g_slice_new0 (GstVideoFrame);
+
+ is_mapped = gst_video_frame_map (*frame, v_info, buffer, flags);
+ if (!is_mapped) {
+ GST_INFO_OBJECT (self, "Failed to map %d-th buffer", i);
+ goto out;
+ }
+
+ if (GST_VIDEO_FRAME_SIZE (*frame) < port->port_def.nBufferSize) {
+ GST_INFO_OBJECT (self,
+ "Frame size of %d-th buffer (%" G_GSIZE_FORMAT
+ ") is too small for port buffer size (%d)", i,
+ GST_VIDEO_FRAME_SIZE (*frame), (guint32) port->port_def.nBufferSize);
+ goto out;
+ }
+
+ return buffer;
+
+out:
+ if (*frame) {
+ if (is_mapped)
+ gst_video_frame_unmap (*frame);
+ g_slice_free (GstVideoFrame, *frame);
+ *frame = NULL;
+ }
+ gst_buffer_unref (buffer);
+ return NULL;
+}
+
+static OMX_ERRORTYPE
+gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self)
+{
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+ GstOMXPort *port;
+ GstBufferPool *pool;
+ GstStructure *config;
+ gboolean eglimage = FALSE, add_videometa = FALSE;
+ GstCaps *caps = NULL;
+ guint min = 0, max = 0;
+ GstVideoCodecState *state =
+ gst_video_decoder_get_output_state (GST_VIDEO_DECODER (self));
+
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+ port = self->eglimage ? self->egl_out_port : self->dec_out_port;
+#else
+ port = self->dec_out_port;
+#endif
+
+ pool = gst_video_decoder_get_buffer_pool (GST_VIDEO_DECODER (self));
+ if (pool) {
+ GstAllocator *allocator;
+
+ config = gst_buffer_pool_get_config (pool);
+ if (!gst_buffer_pool_config_get_params (config, &caps, NULL, &min, &max)) {
+ GST_ERROR_OBJECT (self, "Can't get buffer pool params");
+ gst_structure_free (config);
+ err = OMX_ErrorUndefined;
+ goto done;
+ }
+ if (!gst_buffer_pool_config_get_allocator (config, &allocator, NULL)) {
+ GST_ERROR_OBJECT (self, "Can't get buffer pool allocator");
+ gst_structure_free (config);
+ err = OMX_ErrorUndefined;
+ goto done;
+ }
+
+ /* Need at least 4 buffers for anything meaningful */
+ min = MAX (min + port->port_def.nBufferCountMin, 4);
+ if (max == 0) {
+ max = min;
+ } else if (max < min) {
+ /* Can't use pool because can't have enough buffers */
+ GST_DEBUG_OBJECT (self,
+ "pool can only provide %d buffers but %d are required", max, min);
+ caps = NULL;
+ } else {
+ min = max;
+ }
+
+ add_videometa = gst_buffer_pool_config_has_option (config,
+ GST_BUFFER_POOL_OPTION_VIDEO_META);
+ gst_structure_free (config);
+
+#if defined (HAVE_GST_GL)
+ eglimage = self->eglimage
+ && (allocator && GST_IS_GL_MEMORY_EGL_ALLOCATOR (allocator));
+#else
+ eglimage = FALSE;
+#endif
+ caps = caps ? gst_caps_ref (caps) : NULL;
+
+ GST_DEBUG_OBJECT (self, "Trying to use pool %p with caps %" GST_PTR_FORMAT
+ " and memory type %s", pool, caps,
+ (allocator ? allocator->mem_type : "(null)"));
+ } else {
+ gst_caps_replace (&caps, NULL);
+ min = max = port->port_def.nBufferCountMin;
+ GST_DEBUG_OBJECT (self, "No pool available, not negotiated yet");
+ }
+
+#if defined (HAVE_GST_GL)
+ /* Will retry without EGLImage */
+ if (self->eglimage && !eglimage) {
+ GST_DEBUG_OBJECT (self,
+ "Wanted to use EGLImage but downstream doesn't support it");
+ err = OMX_ErrorUndefined;
+ goto done;
+ }
+#endif
+
+ if (caps)
+ self->out_port_pool =
+ gst_omx_buffer_pool_new (GST_ELEMENT_CAST (self), self->dec, port,
+ self->dmabuf ? GST_OMX_BUFFER_MODE_DMABUF :
+ GST_OMX_BUFFER_MODE_SYSTEM_MEMORY);
+
+#if defined (HAVE_GST_GL)
+ if (eglimage) {
+ GList *buffers = NULL;
+ GList *images = NULL;
+ gint i;
+ GstBufferPoolAcquireParams params = { 0, };
+ gpointer egl_display = 0;
+
+ GST_DEBUG_OBJECT (self, "Trying to allocate %d EGLImages", min);
+
+ for (i = 0; i < min; i++) {
+ GstBuffer *buffer = NULL;
+ GstMemory *mem;
+ GstGLMemoryEGL *gl_mem;
+
+ if (gst_buffer_pool_acquire_buffer (pool, &buffer, &params) != GST_FLOW_OK
+ || gst_buffer_n_memory (buffer) != 1
+ || !(mem = gst_buffer_peek_memory (buffer, 0))
+ || !GST_IS_GL_MEMORY_EGL_ALLOCATOR (mem->allocator)) {
+ GST_INFO_OBJECT (self, "Failed to allocated %d-th EGLImage", i);
+ gst_buffer_replace (&buffer, NULL);
+ g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+ g_list_free (images);
+ buffers = NULL;
+ images = NULL;
+ err = OMX_ErrorUndefined;
+ goto done;
+ }
+ gl_mem = (GstGLMemoryEGL *) mem;
+ buffers = g_list_append (buffers, buffer);
+ images = g_list_append (images, gst_gl_memory_egl_get_image (gl_mem));
+ if (!egl_display)
+ egl_display = gst_gl_memory_egl_get_display (gl_mem);
+ }
+
+ GST_DEBUG_OBJECT (self, "Allocated %d EGLImages successfully", min);
+
+ /* Everything went fine? */
+ if (eglimage) {
+ GST_DEBUG_OBJECT (self, "Setting EGLDisplay");
+ port->port_def.format.video.pNativeWindow = egl_display;
+ err = gst_omx_port_update_port_definition (port, &port->port_def);
+ if (err != OMX_ErrorNone) {
+ GST_INFO_OBJECT (self,
+ "Failed to set EGLDisplay on port: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+ g_list_free (images);
+ goto done;
+ } else {
+ GList *l;
+
+ if (min != port->port_def.nBufferCountActual) {
+ err = gst_omx_port_update_port_definition (port, NULL);
+ if (err == OMX_ErrorNone) {
+ port->port_def.nBufferCountActual = min;
+ err = gst_omx_port_update_port_definition (port, &port->port_def);
+ }
+
+ if (err != OMX_ErrorNone) {
+ GST_INFO_OBJECT (self,
+ "Failed to configure %u output buffers: %s (0x%08x)", min,
+ gst_omx_error_to_string (err), err);
+ g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+ g_list_free (images);
+ goto done;
+ }
+#if OMX_VERSION_MINOR == 2
+ /* In OMX-IL 1.2.0, the nBufferCountActual change is propagated to the
+ * the input port upon call to the SetParameter on out port above. This
+ * propagation triggers a SettingsChanged event. It is up to the client
+ * to decide if this event should lead to reconfigure the port. Here
+ * this is clearly informal so lets just acknowledge the event to avoid
+ * input port reconfiguration. Note that the SettingsChanged event will
+ * be sent in-context of the SetParameter call above. So the event is
+ * garantie to be proceeded in the handle_message call below. */
+ err = gst_omx_port_mark_reconfigured (self->dec_in_port);
+
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to acknowledge port settings changed: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+ g_list_free (images);
+ goto done;
+ }
+#endif
+ }
+
+ if (!gst_omx_port_is_enabled (port)) {
+ err = gst_omx_port_set_enabled (port, TRUE);
+ if (err != OMX_ErrorNone) {
+ GST_INFO_OBJECT (self,
+ "Failed to enable port: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+ g_list_free (images);
+ goto done;
+ }
+ }
+
+ err = gst_omx_port_use_eglimages (port, images);
+ g_list_free (images);
+
+ if (err != OMX_ErrorNone) {
+ GST_INFO_OBJECT (self,
+ "Failed to pass EGLImages to port: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+ goto done;
+ }
+
+ err = gst_omx_port_wait_enabled (port, 2 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ GST_INFO_OBJECT (self,
+ "Failed to wait until port is enabled: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+ goto done;
+ }
+
+ GST_DEBUG_OBJECT (self, "Populating internal buffer pool");
+ GST_OMX_BUFFER_POOL (self->out_port_pool)->other_pool =
+ GST_BUFFER_POOL (gst_object_ref (pool));
+ for (l = buffers; l; l = l->next) {
+ g_ptr_array_add (GST_OMX_BUFFER_POOL (self->out_port_pool)->buffers,
+ l->data);
+ }
+ g_list_free (buffers);
+ /* All good and done, set caps below */
+ }
+ }
+ }
+#endif /* defined (HAVE_GST_GL) */
+
+ /* If not using EGLImage or trying to use EGLImage failed */
+ if (!eglimage) {
+ gboolean was_enabled = TRUE;
+ GList *buffers = NULL;
+ GList *l = NULL;
+
+ if (min != port->port_def.nBufferCountActual) {
+ err = gst_omx_port_update_port_definition (port, NULL);
+ if (err == OMX_ErrorNone) {
+ port->port_def.nBufferCountActual = min;
+ err = gst_omx_port_update_port_definition (port, &port->port_def);
+ }
+
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to configure %u output buffers: %s (0x%08x)", min,
+ gst_omx_error_to_string (err), err);
+ goto done;
+ }
+#if OMX_VERSION_MINOR == 2
+ /* In OMX-IL 1.2.0, the nBufferCountActual change is propagated to the
+ * the input port upon call to the SetParameter on out port above. This
+ * propagation triggers a SettingsChanged event. It is up to the client
+ * to decide if this event should lead to reconfigure the port. Here
+ * this is clearly informal so lets just acknowledge the event to avoid
+ * input port reconfiguration. Note that the SettingsChanged event will
+ * be sent in-context of the SetParameter call above. So the event is
+ * garantie to be proceeded in the handle_message call below. */
+ err = gst_omx_port_mark_reconfigured (self->dec_in_port);
+
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to acknowledge port settings changed: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto done;
+ }
+#endif
+ }
+
+ if (!gst_omx_port_is_enabled (port)) {
+ err = gst_omx_port_set_enabled (port, TRUE);
+ if (err != OMX_ErrorNone) {
+ GST_INFO_OBJECT (self,
+ "Failed to enable port: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto done;
+ }
+ was_enabled = FALSE;
+ }
+
+ if (!caps)
+ self->use_buffers = FALSE;
+
+ if (self->use_buffers) {
+ GList *images = NULL;
+ GList *frames = NULL;
+ GstVideoInfo v_info;
+ gint i;
+
+ if (!gst_video_info_from_caps (&v_info, caps)) {
+ GST_INFO_OBJECT (self,
+ "Failed to get video info from caps %" GST_PTR_FORMAT, caps);
+ err = OMX_ErrorUndefined;
+ self->use_buffers = FALSE;
+ }
+
+ GST_DEBUG_OBJECT (self, "Trying to use %d buffers", min);
+
+ for (i = 0; i < min && self->use_buffers; i++) {
+ GstBuffer *buffer = NULL;
+ GstVideoFrame *frame = NULL;
+
+ buffer =
+ gst_omx_try_importing_buffer (self, pool, port, &v_info, i, &frame);
+ if (!buffer) {
+ /* buffer does not match minimal requirement to try OMX_UseBuffer */
+ GST_DEBUG_OBJECT (self, "Failed to import %d-th buffer", i);
+ g_list_free (images);
+ g_list_free_full (frames, (GDestroyNotify) gst_video_frame_unmap);
+ g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+ buffers = NULL;
+ images = NULL;
+ err = OMX_ErrorUndefined;
+ self->use_buffers = FALSE;
+ break;
+ } else {
+ /* if downstream pool is 1 n_mem then always try to use buffers
+ * and retry without using them if it fails */
+ GstMemory *mem;
+
+ buffers = g_list_append (buffers, buffer);
+ frames = g_list_append (frames, frame);
+
+ mem = gst_buffer_peek_memory (buffer, 0);
+ if (self->dmabuf && gst_is_dmabuf_memory (mem))
+ /* Use the imported fd rather than mapped address in dmabuf mode */
+ images =
+ g_list_append (images,
+ GUINT_TO_POINTER (gst_dmabuf_memory_get_fd (mem)));
+ else
+ images =
+ g_list_append (images, GST_VIDEO_FRAME_PLANE_DATA (frame, 0));
+ }
+ }
+
+ /* buffers match minimal requirements then
+ * now try to actually use them */
+ if (images) {
+ err = gst_omx_port_use_buffers (port, images);
+ g_list_free (images);
+ g_list_free_full (frames, (GDestroyNotify) gst_video_frame_unmap);
+
+ if (err == OMX_ErrorNone) {
+ GST_DEBUG_OBJECT (self, "Using %d buffers", min);
+ } else {
+ GST_INFO_OBJECT (self,
+ "Failed to OMX_UseBuffer on port: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+ self->use_buffers = FALSE;
+ }
+ }
+ }
+
+ if (!self->use_buffers)
+ err = gst_omx_port_allocate_buffers (port);
+
+ if (err != OMX_ErrorNone && min > port->port_def.nBufferCountMin) {
+ GST_ERROR_OBJECT (self,
+ "Failed to allocate required number of buffers %d, trying less and copying",
+ min);
+ min = port->port_def.nBufferCountMin;
+
+ if (!was_enabled) {
+ err = gst_omx_port_set_enabled (port, FALSE);
+ if (err != OMX_ErrorNone) {
+ GST_INFO_OBJECT (self,
+ "Failed to disable port again: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto done;
+ }
+ }
+
+ if (min != port->port_def.nBufferCountActual) {
+ err = gst_omx_port_update_port_definition (port, NULL);
+ if (err == OMX_ErrorNone) {
+ port->port_def.nBufferCountActual = min;
+ err = gst_omx_port_update_port_definition (port, &port->port_def);
+ }
+
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to configure %u output buffers: %s (0x%08x)", min,
+ gst_omx_error_to_string (err), err);
+ goto done;
+ }
+ }
+
+ err = gst_omx_port_allocate_buffers (port);
+
+ /* Can't provide buffers downstream in this case */
+ gst_caps_replace (&caps, NULL);
+ }
+
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to allocate %d buffers: %s (0x%08x)", min,
+ gst_omx_error_to_string (err), err);
+ goto done;
+ }
+
+ if (!was_enabled) {
+ err = gst_omx_port_wait_enabled (port, 2 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to wait until port is enabled: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ goto done;
+ }
+ }
+
+ if (self->use_buffers) {
+ GST_DEBUG_OBJECT (self, "Populating internal buffer pool");
+ GST_OMX_BUFFER_POOL (self->out_port_pool)->other_pool =
+ GST_BUFFER_POOL (gst_object_ref (pool));
+ for (l = buffers; l; l = l->next) {
+ g_ptr_array_add (GST_OMX_BUFFER_POOL (self->out_port_pool)->buffers,
+ l->data);
+ }
+ g_list_free (buffers);
+ }
+
+ }
+
+ err = OMX_ErrorNone;
+
+ if (caps) {
+ config = gst_buffer_pool_get_config (self->out_port_pool);
+
+ if (add_videometa)
+ gst_buffer_pool_config_add_option (config,
+ GST_BUFFER_POOL_OPTION_VIDEO_META);
+
+ gst_buffer_pool_config_set_params (config, caps,
+ self->dec_out_port->port_def.nBufferSize, min, max);
+
+ if (!gst_buffer_pool_set_config (self->out_port_pool, config)) {
+ GST_INFO_OBJECT (self, "Failed to set config on internal pool");
+ gst_object_unref (self->out_port_pool);
+ self->out_port_pool = NULL;
+ goto done;
+ }
+
+ /* This now allocates all the buffers */
+ if (!gst_buffer_pool_set_active (self->out_port_pool, TRUE)) {
+ GST_INFO_OBJECT (self, "Failed to activate internal pool");
+ gst_object_unref (self->out_port_pool);
+ self->out_port_pool = NULL;
+ } else if (!self->use_buffers) {
+ gst_buffer_pool_set_active (pool, FALSE);
+ }
+ } else if (self->out_port_pool) {
+ gst_object_unref (self->out_port_pool);
+ self->out_port_pool = NULL;
+ }
+
+done:
+ if (!self->out_port_pool && err == OMX_ErrorNone)
+ GST_DEBUG_OBJECT (self,
+ "Not using our internal pool and copying buffers for downstream");
+
+ if (caps)
+ gst_caps_unref (caps);
+ if (pool)
+ gst_object_unref (pool);
+ if (state)
+ gst_video_codec_state_unref (state);
+
+ return err;
+}
+
+static gboolean
+gst_omx_video_dec_deallocate_output_buffers (GstOMXVideoDec * self)
+{
+ if (self->out_port_pool) {
+ /* Pool will free buffers when stopping */
+ gst_buffer_pool_set_active (self->out_port_pool, FALSE);
+#if 0
+ gst_buffer_pool_wait_released (self->out_port_pool);
+#endif
+ GST_OMX_BUFFER_POOL (self->out_port_pool)->deactivated = TRUE;
+ gst_object_unref (self->out_port_pool);
+ self->out_port_pool = NULL;
+ } else {
+ OMX_ERRORTYPE err;
+
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+ err =
+ gst_omx_port_deallocate_buffers (self->eglimage ? self->
+ egl_out_port : self->dec_out_port);
+#else
+ err = gst_omx_port_deallocate_buffers (self->dec_out_port);
+#endif
+
+ return err == OMX_ErrorNone;
+ }
+
+ return TRUE;
+}
+
+static GstVideoInterlaceMode
+gst_omx_video_dec_get_output_interlace_info (GstOMXVideoDec * self)
+{
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ OMX_ERRORTYPE err;
+ OMX_ALG_COMMON_PARAM_SEQUENCE_PICTURE_MODE seq_pic_mode;
+
+ GST_OMX_INIT_STRUCT (&seq_pic_mode);
+ seq_pic_mode.nPortIndex = self->dec_out_port->index;
+
+ err = gst_omx_component_get_parameter (self->dec,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamCommonSequencePictureModeCurrent,
+ &seq_pic_mode);
+
+ if (err != OMX_ErrorNone) {
+ if (err == OMX_ErrorUnsupportedIndex) {
+ GST_WARNING_OBJECT (self,
+ "Picture sequence mode not supported by the component");
+ } else {
+ GST_DEBUG_OBJECT (self,
+ "Failed to get picture sequence mode: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ }
+
+ return GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
+ }
+
+ if (seq_pic_mode.eMode == OMX_ALG_SEQUENCE_PICTURE_FIELD) {
+ GST_DEBUG_OBJECT (self, "Decoding interlaced video frames");
+ return GST_VIDEO_INTERLACE_MODE_ALTERNATE;
+ } else if (seq_pic_mode.eMode == OMX_ALG_SEQUENCE_PICTURE_FRAME) {
+ GST_DEBUG_OBJECT (self, "Decoding progressive video frames");
+ return GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
+ } else {
+ GST_ERROR_OBJECT (self, "Unsupported interlace format: (0x%08x)",
+ seq_pic_mode.eMode);
+ return GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
+ }
+
+#endif
+ return GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
+}
+
+#if defined (HAVE_GST_GL)
+static void
+add_caps_gl_memory_feature (GstCaps * caps)
+{
+ GstCapsFeatures *old, *features;
+
+ features = gst_caps_features_new_empty ();
+ old = gst_caps_get_features (caps, 0);
+
+ if (old) {
+ guint i;
+
+ /* Copy the existing features ignoring memory ones as we are changing
+ * it to GL. */
+ for (i = 0; i < gst_caps_features_get_size (old); i++) {
+ const gchar *f = gst_caps_features_get_nth (old, i);
+
+ if (!g_str_has_prefix (f, "memory:"))
+ gst_caps_features_add (features, f);
+ }
+ }
+
+ gst_caps_features_add (features, GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
+ gst_caps_set_features (caps, 0, features);
+}
+#endif
+
+static OMX_ERRORTYPE
+gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self)
+{
+ GstOMXPort *port;
+ OMX_ERRORTYPE err;
+ GstVideoCodecState *state;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ GstVideoFormat format;
+ GstVideoInterlaceMode interlace_mode;
+ guint frame_height;
+
+ /* At this point the decoder output port is disabled */
+ interlace_mode = gst_omx_video_dec_get_output_interlace_info (self);
+
+#if defined (HAVE_GST_GL)
+ {
+#if defined (USE_OMX_TARGET_RPI)
+ OMX_STATETYPE egl_state;
+#endif
+
+ if (self->eglimage) {
+ /* Nothing to do here, we could however fall back to non-EGLImage in theory */
+#if defined (USE_OMX_TARGET_RPI)
+ port = self->egl_out_port;
+#else
+ port = self->dec_out_port;
+#endif
+ err = OMX_ErrorNone;
+ goto enable_port;
+ } else {
+ /* Set up egl_render */
+
+ self->eglimage = TRUE;
+
+ gst_omx_port_get_port_definition (self->dec_out_port, &port_def);
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+
+ frame_height = port_def.format.video.nFrameHeight;
+ /* OMX's frame height is actually the field height in alternate mode
+ * while it's always the full frame height in gst. */
+ if (interlace_mode == GST_VIDEO_INTERLACE_MODE_ALTERNATE ||
+ interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED) {
+ frame_height *= 2;
+ /* Decoder outputs interlaced content using the alternate mode */
+ interlace_mode = GST_VIDEO_INTERLACE_MODE_ALTERNATE;
+ }
+
+ state =
+ gst_video_decoder_set_interlaced_output_state (GST_VIDEO_DECODER
+ (self), GST_VIDEO_FORMAT_RGBA, interlace_mode,
+ port_def.format.video.nFrameWidth, frame_height, self->input_state);
+
+ /* at this point state->caps is NULL */
+ if (state->caps)
+ gst_caps_unref (state->caps);
+ state->caps = gst_video_info_to_caps (&state->info);
+ add_caps_gl_memory_feature (state->caps);
+
+ /* try to negotiate with caps feature */
+ if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
+
+ GST_DEBUG_OBJECT (self,
+ "Failed to negotiate with feature %s",
+ GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
+
+ if (state->caps)
+ gst_caps_replace (&state->caps, NULL);
+
+#if defined (USE_OMX_TARGET_RPI)
+ /* fallback: try to use EGLImage even if it is not in the caps feature */
+ if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
+ gst_video_codec_state_unref (state);
+ GST_DEBUG_OBJECT (self, "Failed to negotiate RGBA for EGLImage");
+ GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+ goto no_egl;
+ }
+#else
+ gst_video_codec_state_unref (state);
+ GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+ goto no_egl;
+#endif
+ }
+
+ gst_video_codec_state_unref (state);
+ GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+
+#if defined (USE_OMX_TARGET_RPI)
+ /* Now link it all together */
+
+ err = gst_omx_port_set_enabled (self->egl_in_port, FALSE);
+ if (err != OMX_ErrorNone)
+ goto no_egl;
+
+ err = gst_omx_port_wait_enabled (self->egl_in_port, 1 * GST_SECOND);
+ if (err != OMX_ErrorNone)
+ goto no_egl;
+
+ err = gst_omx_port_set_enabled (self->egl_out_port, FALSE);
+ if (err != OMX_ErrorNone)
+ goto no_egl;
+
+ err = gst_omx_port_wait_enabled (self->egl_out_port, 1 * GST_SECOND);
+ if (err != OMX_ErrorNone)
+ goto no_egl;
+
+ {
+#define OMX_IndexParamBrcmVideoEGLRenderDiscardMode 0x7f0000db
+ OMX_CONFIG_PORTBOOLEANTYPE discardMode;
+ memset (&discardMode, 0, sizeof (discardMode));
+ discardMode.nSize = sizeof (discardMode);
+ discardMode.nPortIndex = 220;
+ discardMode.nVersion.nVersion = OMX_VERSION;
+ discardMode.bEnabled = OMX_FALSE;
+ if (gst_omx_component_set_parameter (self->egl_render,
+ OMX_IndexParamBrcmVideoEGLRenderDiscardMode,
+ &discardMode) != OMX_ErrorNone)
+ goto no_egl;
+#undef OMX_IndexParamBrcmVideoEGLRenderDiscardMode
+ }
+
+ err = gst_omx_setup_tunnel (self->dec_out_port, self->egl_in_port);
+ if (err != OMX_ErrorNone)
+ goto no_egl;
+
+ err = gst_omx_port_set_enabled (self->egl_in_port, TRUE);
+ if (err != OMX_ErrorNone)
+ goto no_egl;
+
+ err = gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
+ if (err != OMX_ErrorNone)
+ goto no_egl;
+
+ err = gst_omx_port_wait_enabled (self->egl_in_port, 1 * GST_SECOND);
+ if (err != OMX_ErrorNone)
+ goto no_egl;
+
+ if (gst_omx_component_get_state (self->egl_render,
+ GST_CLOCK_TIME_NONE) != OMX_StateIdle)
+ goto no_egl;
+
+ err = gst_omx_video_dec_allocate_output_buffers (self);
+ if (err != OMX_ErrorNone)
+ goto no_egl;
+
+ if (gst_omx_component_set_state (self->egl_render,
+ OMX_StateExecuting) != OMX_ErrorNone)
+ goto no_egl;
+
+ if (gst_omx_component_get_state (self->egl_render,
+ GST_CLOCK_TIME_NONE) != OMX_StateExecuting)
+ goto no_egl;
+
+ err =
+ gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, FALSE);
+ if (err != OMX_ErrorNone)
+ goto no_egl;
+
+ err =
+ gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, FALSE);
+ if (err != OMX_ErrorNone)
+ goto no_egl;
+
+ err =
+ gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, FALSE);
+ if (err != OMX_ErrorNone)
+ goto no_egl;
+
+ err = gst_omx_port_populate (self->egl_out_port);
+ if (err != OMX_ErrorNone)
+ goto no_egl;
+
+ err = gst_omx_port_set_enabled (self->dec_out_port, TRUE);
+ if (err != OMX_ErrorNone)
+ goto no_egl;
+
+ err = gst_omx_port_wait_enabled (self->dec_out_port, 1 * GST_SECOND);
+ if (err != OMX_ErrorNone)
+ goto no_egl;
+
+
+ err = gst_omx_port_mark_reconfigured (self->dec_out_port);
+ if (err != OMX_ErrorNone)
+ goto no_egl;
+
+ err = gst_omx_port_mark_reconfigured (self->egl_out_port);
+ if (err != OMX_ErrorNone)
+ goto no_egl;
+
+ goto done;
+#else
+ port = self->dec_out_port;
+ err = OMX_ErrorNone;
+ goto enable_port;
+#endif /* defined (USE_OMX_TARGET_RPI) */
+ }
+
+ no_egl:
+
+#if defined (USE_OMX_TARGET_RPI)
+ gst_omx_port_set_enabled (self->dec_out_port, FALSE);
+ gst_omx_port_wait_enabled (self->dec_out_port, 1 * GST_SECOND);
+ egl_state = gst_omx_component_get_state (self->egl_render, 0);
+ if (egl_state > OMX_StateLoaded || egl_state == OMX_StateInvalid) {
+ if (egl_state > OMX_StateIdle) {
+ gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
+ gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
+ }
+ gst_omx_component_set_state (self->egl_render, OMX_StateLoaded);
+
+ gst_omx_video_dec_deallocate_output_buffers (self);
+ gst_omx_close_tunnel (self->dec_out_port, self->egl_in_port);
+
+ if (egl_state > OMX_StateLoaded) {
+ gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
+ }
+ }
+#endif
+
+ /* After this egl_render should be deactivated
+ * and the decoder's output port disabled */
+ self->eglimage = FALSE;
+ }
+#endif /* defined (HAVE_GST_GL) */
+
+ port = self->dec_out_port;
+
+ /* Update caps */
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+
+ gst_omx_port_get_port_definition (port, &port_def);
+ g_assert (port_def.format.video.eCompressionFormat == OMX_VIDEO_CodingUnused);
+
+ format =
+ gst_omx_video_get_format_from_omx (port_def.format.video.eColorFormat);
+
+ if (format == GST_VIDEO_FORMAT_UNKNOWN) {
+ GST_ERROR_OBJECT (self, "Unsupported color format: %d",
+ port_def.format.video.eColorFormat);
+ GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+ err = OMX_ErrorUndefined;
+ goto done;
+ }
+
+ frame_height = port_def.format.video.nFrameHeight;
+ /* OMX's frame height is actually the field height in alternate mode
+ * while it's always the full frame height in gst. */
+ if (interlace_mode == GST_VIDEO_INTERLACE_MODE_ALTERNATE ||
+ interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED) {
+ frame_height *= 2;
+ /* Decoder outputs interlaced content using the alternate mode */
+ interlace_mode = GST_VIDEO_INTERLACE_MODE_ALTERNATE;
+ }
+
+ GST_DEBUG_OBJECT (self,
+ "Setting output state: format %s (%d), width %u, height %u",
+ gst_video_format_to_string (format),
+ port_def.format.video.eColorFormat,
+ (guint) port_def.format.video.nFrameWidth, frame_height);
+
+ state =
+ gst_video_decoder_set_interlaced_output_state (GST_VIDEO_DECODER (self),
+ format, interlace_mode, port_def.format.video.nFrameWidth,
+ frame_height, self->input_state);
+
+ if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
+ gst_video_codec_state_unref (state);
+ GST_ERROR_OBJECT (self, "Failed to negotiate");
+ err = OMX_ErrorUndefined;
+ GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+ goto done;
+ }
+
+ gst_video_codec_state_unref (state);
+
+ GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+
+#if defined (HAVE_GST_GL)
+enable_port:
+#endif
+
+ err = gst_omx_video_dec_allocate_output_buffers (self);
+ if (err != OMX_ErrorNone) {
+#if defined (HAVE_GST_GL)
+ /* TODO: works on desktop but need to try on RPI. */
+#if !defined (USE_OMX_TARGET_RPI)
+ if (self->eglimage) {
+ GST_INFO_OBJECT (self, "Fallback to non eglimage");
+ goto no_egl;
+ }
+#endif
+#endif
+ goto done;
+ }
+
+ err = gst_omx_port_populate (port);
+ if (err != OMX_ErrorNone)
+ goto done;
+
+ err = gst_omx_port_mark_reconfigured (port);
+ if (err != OMX_ErrorNone)
+ goto done;
+
+done:
+
+ return err;
+}
+
+static void
+gst_omx_video_dec_clean_older_frames (GstOMXVideoDec * self,
+ GstOMXBuffer * buf, GList * frames)
+{
+ GList *l;
+ GstClockTime timestamp;
+
+ timestamp =
+ gst_util_uint64_scale (GST_OMX_GET_TICKS (buf->omx_buf->nTimeStamp),
+ GST_SECOND, OMX_TICKS_PER_SECOND);
+
+ if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
+ /* We could release all frames stored with pts < timestamp since the
+ * decoder will likely output frames in display order */
+ for (l = frames; l; l = l->next) {
+ GstVideoCodecFrame *tmp = l->data;
+
+ if (tmp->pts < timestamp) {
+ GST_LOG_OBJECT (self,
+ "discarding ghost frame %p (#%d) PTS:%" GST_TIME_FORMAT " DTS:%"
+ GST_TIME_FORMAT, tmp, tmp->system_frame_number,
+ GST_TIME_ARGS (tmp->pts), GST_TIME_ARGS (tmp->dts));
+ gst_video_decoder_release_frame (GST_VIDEO_DECODER (self), tmp);
+ } else {
+ gst_video_codec_frame_unref (tmp);
+ }
+ }
+ } else {
+ /* We will release all frames with invalid timestamp because we don't even
+ * know if they will be output some day. */
+ for (l = frames; l; l = l->next) {
+ GstVideoCodecFrame *tmp = l->data;
+
+ if (!GST_CLOCK_TIME_IS_VALID (tmp->pts)) {
+ GST_LOG_OBJECT (self,
+ "discarding frame %p (#%d) with invalid PTS:%" GST_TIME_FORMAT
+ " DTS:%" GST_TIME_FORMAT, tmp, tmp->system_frame_number,
+ GST_TIME_ARGS (tmp->pts), GST_TIME_ARGS (tmp->dts));
+ gst_video_decoder_release_frame (GST_VIDEO_DECODER (self), tmp);
+ } else {
+ gst_video_codec_frame_unref (tmp);
+ }
+ }
+ }
+
+ g_list_free (frames);
+}
+
+/* copy_frame() will consume @outpuf resulting in the buffer being released to
+ * the pool and so reset fields such as outbuf->omx_buf->nFlags.
+ * Make sure to handle them all before. */
+static GstBuffer *
+copy_frame (const GstVideoInfo * info, GstBuffer * outbuf)
+{
+ GstVideoInfo out_info, tmp_info;
+ GstBuffer *tmpbuf;
+ GstVideoFrame out_frame, tmp_frame;
+
+ out_info = *info;
+ tmp_info = *info;
+
+ tmpbuf = gst_buffer_new_and_alloc (out_info.size);
+
+ gst_video_frame_map (&out_frame, &out_info, outbuf, GST_MAP_READ);
+ gst_video_frame_map (&tmp_frame, &tmp_info, tmpbuf, GST_MAP_WRITE);
+ gst_video_frame_copy (&tmp_frame, &out_frame);
+ gst_video_frame_unmap (&out_frame);
+ gst_video_frame_unmap (&tmp_frame);
+
+ /* Use gst_video_frame_copy() to copy the content of the buffer so it
+ * will handle the stride/offset/etc from the source buffer.
+ * It doesn't copy buffer flags so do it manually. */
+ gst_buffer_copy_into (tmpbuf, outbuf, GST_BUFFER_COPY_FLAGS, 0, -1);
+
+ gst_buffer_unref (outbuf);
+
+ return tmpbuf;
+}
+
+static void
+gst_omx_video_dec_pause_loop (GstOMXVideoDec * self, GstFlowReturn flow_ret)
+{
+ g_mutex_lock (&self->drain_lock);
+ if (self->draining) {
+ self->draining = FALSE;
+ g_cond_broadcast (&self->drain_cond);
+ }
+ gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
+ self->downstream_flow_ret = flow_ret;
+ self->started = FALSE;
+ g_mutex_unlock (&self->drain_lock);
+}
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+static void
+set_outbuffer_interlace_flags (GstOMXBuffer * buf, GstBuffer * outbuf)
+{
+ if (buf->omx_buf->nFlags & OMX_ALG_BUFFERFLAG_TOP_FIELD) {
+ GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_TOP_FIELD);
+ } else if (buf->omx_buf->nFlags & OMX_ALG_BUFFERFLAG_BOT_FIELD) {
+ GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_BOTTOM_FIELD);
+ }
+}
+#endif // USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+
+static void
+gst_omx_video_dec_loop (GstOMXVideoDec * self)
+{
+ GstOMXPort *port;
+ GstOMXBuffer *buf = NULL;
+ GstVideoCodecFrame *frame;
+ GstFlowReturn flow_ret = GST_FLOW_OK;
+ GstOMXAcquireBufferReturn acq_return;
+ OMX_ERRORTYPE err;
+
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+ port = self->eglimage ? self->egl_out_port : self->dec_out_port;
+#else
+ port = self->dec_out_port;
+#endif
+
+ acq_return = gst_omx_port_acquire_buffer (port, &buf, GST_OMX_WAIT);
+ if (acq_return == GST_OMX_ACQUIRE_BUFFER_ERROR) {
+ goto component_error;
+ } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
+ goto flushing;
+ } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_EOS) {
+ goto eos;
+ }
+
+ if (!gst_pad_has_current_caps (GST_VIDEO_DECODER_SRC_PAD (self)) ||
+ acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+ GstVideoCodecState *state;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ GstVideoFormat format;
+
+ GST_DEBUG_OBJECT (self, "Port settings have changed, updating caps");
+
+ /* Reallocate all buffers */
+ if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE
+ && gst_omx_port_is_enabled (port)) {
+ err = gst_omx_port_set_enabled (port, FALSE);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_wait_buffers_released (port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ if (!gst_omx_video_dec_deallocate_output_buffers (self))
+ goto reconfigure_error;
+
+ err = gst_omx_port_wait_enabled (port, 1 * GST_SECOND);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+ }
+
+ if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+ /* We have the possibility to reconfigure everything now */
+ err = gst_omx_video_dec_reconfigure_output_port (self);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+ } else {
+ GstVideoInterlaceMode interlace_mode;
+
+ /* Just update caps */
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+
+ gst_omx_port_get_port_definition (port, &port_def);
+ g_assert (port_def.format.video.eCompressionFormat ==
+ OMX_VIDEO_CodingUnused);
+
+ format =
+ gst_omx_video_get_format_from_omx (port_def.format.video.
+ eColorFormat);
+
+ if (format == GST_VIDEO_FORMAT_UNKNOWN) {
+ GST_ERROR_OBJECT (self, "Unsupported color format: %d",
+ port_def.format.video.eColorFormat);
+ if (buf)
+ gst_omx_port_release_buffer (port, buf);
+ GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+ goto caps_failed;
+ }
+
+ GST_DEBUG_OBJECT (self,
+ "Setting output state: format %s (%d), width %u, height %u",
+ gst_video_format_to_string (format),
+ port_def.format.video.eColorFormat,
+ (guint) port_def.format.video.nFrameWidth,
+ (guint) port_def.format.video.nFrameHeight);
+ interlace_mode = gst_omx_video_dec_get_output_interlace_info (self);
+
+ state =
+ gst_video_decoder_set_interlaced_output_state (GST_VIDEO_DECODER
+ (self), format, interlace_mode, port_def.format.video.nFrameWidth,
+ port_def.format.video.nFrameHeight, self->input_state);
+
+ /* Take framerate and pixel-aspect-ratio from sinkpad caps */
+
+ if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
+ if (buf)
+ gst_omx_port_release_buffer (port, buf);
+ gst_video_codec_state_unref (state);
+ goto caps_failed;
+ }
+
+ gst_video_codec_state_unref (state);
+
+ GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+ }
+
+ /* Now get a buffer */
+ if (acq_return != GST_OMX_ACQUIRE_BUFFER_OK) {
+ return;
+ }
+ }
+
+ g_assert (acq_return == GST_OMX_ACQUIRE_BUFFER_OK);
+
+ /* This prevents a deadlock between the srcpad stream
+ * lock and the videocodec stream lock, if ::reset()
+ * is called at the wrong time
+ */
+ if (gst_omx_port_is_flushing (port)) {
+ GST_DEBUG_OBJECT (self, "Flushing");
+ gst_omx_port_release_buffer (port, buf);
+ goto flushing;
+ }
+
+ GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x (%s) %" G_GUINT64_FORMAT,
+ (guint) buf->omx_buf->nFlags,
+ gst_omx_buffer_flags_to_string (buf->omx_buf->nFlags),
+ (guint64) GST_OMX_GET_TICKS (buf->omx_buf->nTimeStamp));
+
+ frame = gst_omx_video_find_nearest_frame (GST_ELEMENT_CAST (self), buf,
+ gst_video_decoder_get_frames (GST_VIDEO_DECODER (self)));
+
+ /* So we have a timestamped OMX buffer and get, or not, corresponding frame.
+ * Assuming decoder output frames in display order, frames preceding this
+ * frame could be discarded as they seems useless due to e.g interlaced
+ * stream, corrupted input data...
+ * In any cases, not likely to be seen again. so drop it before they pile up
+ * and use all the memory. */
+ gst_omx_video_dec_clean_older_frames (self, buf,
+ gst_video_decoder_get_frames (GST_VIDEO_DECODER (self)));
+
+ if (!frame && (buf->omx_buf->nFilledLen > 0 || buf->eglimage)) {
+ GstBuffer *outbuf = NULL;
+
+ /* This sometimes happens at EOS or if the input is not properly framed,
+ * let's handle it gracefully by allocating a new buffer for the current
+ * caps and filling it
+ */
+
+ GST_ERROR_OBJECT (self, "No corresponding frame found");
+
+ if (self->out_port_pool) {
+ gint i, n;
+ GstBufferPoolAcquireParams params = { 0, };
+
+ n = port->buffers->len;
+ for (i = 0; i < n; i++) {
+ GstOMXBuffer *tmp = g_ptr_array_index (port->buffers, i);
+
+ if (tmp == buf)
+ break;
+ }
+ g_assert (i != n);
+
+ GST_OMX_BUFFER_POOL (self->out_port_pool)->current_buffer_index = i;
+ flow_ret =
+ gst_buffer_pool_acquire_buffer (self->out_port_pool, &outbuf,
+ &params);
+ if (flow_ret != GST_FLOW_OK) {
+ gst_omx_port_release_buffer (port, buf);
+ goto invalid_buffer;
+ }
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ set_outbuffer_interlace_flags (buf, outbuf);
+#endif
+
+ if (GST_OMX_BUFFER_POOL (self->out_port_pool)->need_copy)
+ outbuf =
+ copy_frame (&GST_OMX_BUFFER_POOL (self->out_port_pool)->video_info,
+ outbuf);
+
+ buf = NULL;
+ } else {
+ outbuf =
+ gst_video_decoder_allocate_output_buffer (GST_VIDEO_DECODER (self));
+ if (!gst_omx_video_dec_fill_buffer (self, buf, outbuf)) {
+ gst_buffer_unref (outbuf);
+ gst_omx_port_release_buffer (port, buf);
+ goto invalid_buffer;
+ }
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ set_outbuffer_interlace_flags (buf, outbuf);
+#endif
+ }
+
+ flow_ret = gst_pad_push (GST_VIDEO_DECODER_SRC_PAD (self), outbuf);
+ } else if (buf->omx_buf->nFilledLen > 0 || buf->eglimage) {
+ if (self->out_port_pool) {
+ gint i, n;
+ GstBuffer *outbuf;
+ GstBufferPoolAcquireParams params = { 0, };
+
+ n = port->buffers->len;
+ for (i = 0; i < n; i++) {
+ GstOMXBuffer *tmp = g_ptr_array_index (port->buffers, i);
+
+ if (tmp == buf)
+ break;
+ }
+ g_assert (i != n);
+
+ GST_OMX_BUFFER_POOL (self->out_port_pool)->current_buffer_index = i;
+ flow_ret =
+ gst_buffer_pool_acquire_buffer (self->out_port_pool,
+ &outbuf, &params);
+ if (flow_ret != GST_FLOW_OK) {
+ flow_ret =
+ gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
+ frame = NULL;
+ gst_omx_port_release_buffer (port, buf);
+ goto invalid_buffer;
+ }
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ set_outbuffer_interlace_flags (buf, outbuf);
+#endif
+
+ if (GST_OMX_BUFFER_POOL (self->out_port_pool)->need_copy)
+ outbuf =
+ copy_frame (&GST_OMX_BUFFER_POOL (self->out_port_pool)->video_info,
+ outbuf);
+
+ frame->output_buffer = outbuf;
+
+ flow_ret =
+ gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
+ frame = NULL;
+ buf = NULL;
+ } else {
+ if ((flow_ret =
+ gst_video_decoder_allocate_output_frame (GST_VIDEO_DECODER
+ (self), frame)) == GST_FLOW_OK) {
+ /* FIXME: This currently happens because of a race condition too.
+ * We first need to reconfigure the output port and then the input
+ * port if both need reconfiguration.
+ */
+ if (!gst_omx_video_dec_fill_buffer (self, buf, frame->output_buffer)) {
+ gst_buffer_replace (&frame->output_buffer, NULL);
+ flow_ret =
+ gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
+ frame = NULL;
+ gst_omx_port_release_buffer (port, buf);
+ goto invalid_buffer;
+ }
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ set_outbuffer_interlace_flags (buf, frame->output_buffer);
+#endif
+
+ flow_ret =
+ gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
+ frame = NULL;
+ }
+ }
+ } else if (frame != NULL) {
+ /* Just ignore empty buffers, don't drop a frame for that */
+ flow_ret = GST_FLOW_OK;
+ gst_video_codec_frame_unref (frame);
+ frame = NULL;
+ }
+
+ GST_DEBUG_OBJECT (self, "Finished frame: %s", gst_flow_get_name (flow_ret));
+
+ if (buf) {
+ err = gst_omx_port_release_buffer (port, buf);
+ if (err != OMX_ErrorNone)
+ goto release_error;
+ }
+
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+ self->downstream_flow_ret = flow_ret;
+ GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+
+ if (flow_ret != GST_FLOW_OK)
+ goto flow_error;
+
+ return;
+
+component_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+ ("OpenMAX component in error state %s (0x%08x)",
+ gst_omx_component_get_last_error_string (self->dec),
+ gst_omx_component_get_last_error (self->dec)));
+ gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ());
+ gst_omx_video_dec_pause_loop (self, GST_FLOW_ERROR);
+ return;
+ }
+
+flushing:
+ {
+ GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
+ gst_omx_video_dec_pause_loop (self, GST_FLOW_FLUSHING);
+ return;
+ }
+
+eos:
+ {
+ g_mutex_lock (&self->drain_lock);
+ if (self->draining) {
+ GstQuery *query = gst_query_new_drain ();
+
+ /* Drain the pipeline to reclaim all memories back to the pool */
+ if (!gst_pad_peer_query (GST_VIDEO_DECODER_SRC_PAD (self), query))
+ GST_DEBUG_OBJECT (self, "drain query failed");
+ gst_query_unref (query);
+
+ GST_DEBUG_OBJECT (self, "Drained");
+ self->draining = FALSE;
+ g_cond_broadcast (&self->drain_cond);
+ flow_ret = GST_FLOW_OK;
+ gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
+ } else {
+ GST_DEBUG_OBJECT (self, "Component signalled EOS");
+ flow_ret = GST_FLOW_EOS;
+ }
+ g_mutex_unlock (&self->drain_lock);
+
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+ self->downstream_flow_ret = flow_ret;
+ GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+
+ /* Here we fallback and pause the task for the EOS case */
+ if (flow_ret != GST_FLOW_OK)
+ goto flow_error;
+
+ return;
+ }
+
+flow_error:
+ {
+ if (flow_ret == GST_FLOW_EOS) {
+ GST_DEBUG_OBJECT (self, "EOS");
+
+ gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self),
+ gst_event_new_eos ());
+ } else if (flow_ret < GST_FLOW_EOS) {
+ GST_ELEMENT_ERROR (self, STREAM, FAILED,
+ ("Internal data stream error."), ("stream stopped, reason %s",
+ gst_flow_get_name (flow_ret)));
+
+ gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self),
+ gst_event_new_eos ());
+ } else if (flow_ret == GST_FLOW_FLUSHING) {
+ GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
+ }
+ gst_omx_video_dec_pause_loop (self, flow_ret);
+ return;
+ }
+
+reconfigure_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Unable to reconfigure output port"));
+ gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ());
+ gst_omx_video_dec_pause_loop (self, GST_FLOW_ERROR);
+ return;
+ }
+
+invalid_buffer:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Invalid sized input buffer"));
+ gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ());
+ gst_omx_video_dec_pause_loop (self, GST_FLOW_NOT_NEGOTIATED);
+ return;
+ }
+
+caps_failed:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL), ("Failed to set caps"));
+ gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ());
+ gst_omx_video_dec_pause_loop (self, GST_FLOW_NOT_NEGOTIATED);
+ GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+ return;
+ }
+release_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Failed to relase output buffer to component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err));
+ gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ());
+ gst_omx_video_dec_pause_loop (self, GST_FLOW_ERROR);
+ GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+ return;
+ }
+}
+
+static gboolean
+gst_omx_video_dec_start (GstVideoDecoder * decoder)
+{
+ GstOMXVideoDec *self;
+
+ self = GST_OMX_VIDEO_DEC (decoder);
+
+ self->last_upstream_ts = 0;
+ self->downstream_flow_ret = GST_FLOW_OK;
+ self->use_buffers = FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_dec_stop (GstVideoDecoder * decoder)
+{
+ GstOMXVideoDec *self;
+
+ self = GST_OMX_VIDEO_DEC (decoder);
+
+ GST_DEBUG_OBJECT (self, "Stopping decoder");
+
+ gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
+ gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
+
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+ gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, TRUE);
+ gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, TRUE);
+#endif
+
+ gst_pad_stop_task (GST_VIDEO_DECODER_SRC_PAD (decoder));
+
+ if (gst_omx_component_get_state (self->dec, 0) > OMX_StateIdle)
+ gst_omx_component_set_state (self->dec, OMX_StateIdle);
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+ if (gst_omx_component_get_state (self->egl_render, 0) > OMX_StateIdle)
+ gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
+#endif
+
+ self->downstream_flow_ret = GST_FLOW_FLUSHING;
+ self->started = FALSE;
+
+ g_mutex_lock (&self->drain_lock);
+ self->draining = FALSE;
+ g_cond_broadcast (&self->drain_cond);
+ g_mutex_unlock (&self->drain_lock);
+
+ gst_omx_component_get_state (self->dec, 5 * GST_SECOND);
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+ gst_omx_component_get_state (self->egl_render, 1 * GST_SECOND);
+#endif
+
+ gst_buffer_replace (&self->codec_data, NULL);
+
+ if (self->input_state)
+ gst_video_codec_state_unref (self->input_state);
+ self->input_state = NULL;
+
+ GST_DEBUG_OBJECT (self, "Stopped decoder");
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
+{
+ OMX_VIDEO_PARAM_PORTFORMATTYPE param;
+ OMX_ERRORTYPE err;
+ GstCaps *comp_supported_caps;
+ GList *negotiation_map = NULL, *l;
+ GstCaps *templ_caps, *intersection;
+ GstVideoFormat format;
+ GstStructure *s;
+ const gchar *format_str;
+
+ GST_DEBUG_OBJECT (self, "Trying to negotiate a video format with downstream");
+
+ templ_caps = gst_pad_get_pad_template_caps (GST_VIDEO_DECODER_SRC_PAD (self));
+ intersection =
+ gst_pad_peer_query_caps (GST_VIDEO_DECODER_SRC_PAD (self), templ_caps);
+ gst_caps_unref (templ_caps);
+
+ GST_DEBUG_OBJECT (self, "Allowed downstream caps: %" GST_PTR_FORMAT,
+ intersection);
+
+ negotiation_map =
+ gst_omx_video_get_supported_colorformats (self->dec_out_port,
+ self->input_state);
+
+ comp_supported_caps = gst_omx_video_get_caps_for_map (negotiation_map);
+
+ GST_DEBUG_OBJECT (self, "Decoder supported caps: %" GST_PTR_FORMAT,
+ comp_supported_caps);
+
+ if (!gst_caps_is_empty (comp_supported_caps)) {
+ GstCaps *tmp;
+
+ tmp = gst_caps_intersect (comp_supported_caps, intersection);
+ gst_caps_unref (intersection);
+ intersection = tmp;
+ }
+ gst_caps_unref (comp_supported_caps);
+
+ if (gst_caps_is_empty (intersection)) {
+ gst_caps_unref (intersection);
+ GST_ERROR_OBJECT (self, "Empty caps");
+ g_list_free_full (negotiation_map,
+ (GDestroyNotify) gst_omx_video_negotiation_map_free);
+ return FALSE;
+ }
+
+ intersection = gst_caps_truncate (intersection);
+ intersection = gst_caps_fixate (intersection);
+
+ s = gst_caps_get_structure (intersection, 0);
+ format_str = gst_structure_get_string (s, "format");
+ if (!format_str ||
+ (format =
+ gst_video_format_from_string (format_str)) ==
+ GST_VIDEO_FORMAT_UNKNOWN) {
+ GST_ERROR_OBJECT (self, "Invalid caps: %" GST_PTR_FORMAT, intersection);
+ gst_caps_unref (intersection);
+ g_list_free_full (negotiation_map,
+ (GDestroyNotify) gst_omx_video_negotiation_map_free);
+ return FALSE;
+ }
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = self->dec_out_port->index;
+
+ err = gst_omx_component_get_parameter (self->dec,
+ OMX_IndexParamVideoPortFormat, &param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to get video port format: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ for (l = negotiation_map; l; l = l->next) {
+ GstOMXVideoNegotiationMap *m = l->data;
+
+ if (m->format == format) {
+ param.eColorFormat = m->type;
+ break;
+ }
+ }
+
+ GST_DEBUG_OBJECT (self, "Negotiating color format %s (%d)", format_str,
+ param.eColorFormat);
+
+ /* We must find something here */
+ g_assert (l != NULL);
+ g_list_free_full (negotiation_map,
+ (GDestroyNotify) gst_omx_video_negotiation_map_free);
+
+ err =
+ gst_omx_component_set_parameter (self->dec,
+ OMX_IndexParamVideoPortFormat, &param);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to set video port format: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ }
+
+ gst_caps_unref (intersection);
+ return (err == OMX_ErrorNone);
+}
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+static void
+gst_omx_video_dec_set_latency (GstOMXVideoDec * self)
+{
+ GstClockTime latency;
+ OMX_ALG_PARAM_REPORTED_LATENCY param;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&param);
+ err =
+ gst_omx_component_get_parameter (self->dec,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamReportedLatency, &param);
+
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self, "Couldn't retrieve latency: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return;
+ }
+
+ GST_DEBUG_OBJECT (self, "retrieved latency of %d ms",
+ (guint32) param.nLatency);
+
+ /* Convert to ns */
+ latency = param.nLatency * GST_MSECOND;
+
+ gst_video_decoder_set_latency (GST_VIDEO_DECODER (self), latency, latency);
+}
+#endif
+
+static gboolean
+gst_omx_video_dec_disable (GstOMXVideoDec * self)
+{
+ GstOMXVideoDecClass *klass = GST_OMX_VIDEO_DEC_GET_CLASS (self);
+
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+ GstOMXPort *out_port =
+ self->eglimage ? self->egl_out_port : self->dec_out_port;
+#else
+ GstOMXPort *out_port = self->dec_out_port;
+#endif
+
+ GST_DEBUG_OBJECT (self, "Need to disable and drain decoder");
+
+ gst_omx_video_dec_drain (GST_VIDEO_DECODER (self));
+ gst_omx_port_set_flushing (out_port, 5 * GST_SECOND, TRUE);
+
+ if (klass->cdata.hacks & GST_OMX_HACK_NO_COMPONENT_RECONFIGURE) {
+ GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+ gst_omx_video_dec_stop (GST_VIDEO_DECODER (self));
+ gst_omx_video_dec_close (GST_VIDEO_DECODER (self));
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+
+ if (!gst_omx_video_dec_open (GST_VIDEO_DECODER (self)))
+ return FALSE;
+
+ self->disabled = FALSE;
+ } else {
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+ if (self->eglimage) {
+ gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
+ gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
+ gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, TRUE);
+ gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, TRUE);
+ }
+#endif
+
+ /* Disabling at the same time input port and output port is only
+ * required when a buffer is shared between the ports. This cannot
+ * be the case for a decoder because its input and output buffers
+ * are of different nature. So let's disable ports sequencially.
+ * Starting from IL 1.2.0, this point has been clarified.
+ * OMX_SendCommand will return an error if the IL client attempts to
+ * call it when there is already an on-going command being processed.
+ * The exception is for buffer sharing above and the event
+ * OMX_EventPortNeedsDisable will be sent to request disabling the
+ * other port at the same time. */
+ if (gst_omx_port_set_enabled (self->dec_in_port, FALSE) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_wait_buffers_released (self->dec_in_port,
+ 5 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_deallocate_buffers (self->dec_in_port) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_wait_enabled (self->dec_in_port,
+ 1 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+
+ if (gst_omx_port_set_enabled (out_port, FALSE) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_wait_buffers_released (out_port,
+ 1 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ if (!gst_omx_video_dec_deallocate_output_buffers (self))
+ return FALSE;
+ if (gst_omx_port_wait_enabled (out_port, 1 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+ if (self->eglimage) {
+ OMX_STATETYPE egl_state;
+
+ egl_state = gst_omx_component_get_state (self->egl_render, 0);
+ if (egl_state > OMX_StateLoaded || egl_state == OMX_StateInvalid) {
+
+ if (egl_state > OMX_StateIdle) {
+ gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
+ gst_omx_component_set_state (self->dec, OMX_StateIdle);
+ egl_state = gst_omx_component_get_state (self->egl_render,
+ 5 * GST_SECOND);
+ gst_omx_component_get_state (self->dec, 1 * GST_SECOND);
+ }
+ gst_omx_component_set_state (self->egl_render, OMX_StateLoaded);
+ gst_omx_component_set_state (self->dec, OMX_StateLoaded);
+
+ gst_omx_close_tunnel (self->dec_out_port, self->egl_in_port);
+
+ if (egl_state > OMX_StateLoaded) {
+ gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
+ }
+
+ gst_omx_component_set_state (self->dec, OMX_StateIdle);
+
+ gst_omx_component_set_state (self->dec, OMX_StateExecuting);
+ gst_omx_component_get_state (self->dec, GST_CLOCK_TIME_NONE);
+ }
+ self->eglimage = FALSE;
+ }
+#endif
+
+ self->disabled = TRUE;
+ }
+ if (self->input_state)
+ gst_video_codec_state_unref (self->input_state);
+ self->input_state = NULL;
+
+ GST_DEBUG_OBJECT (self, "Decoder drained and disabled");
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_dec_allocate_in_buffers (GstOMXVideoDec * self)
+{
+ switch (self->input_allocation) {
+ case GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER:
+ if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone)
+ return FALSE;
+ break;
+ case GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC:
+ if (gst_omx_port_use_dynamic_buffers (self->dec_in_port) != OMX_ErrorNone)
+ return FALSE;
+ break;
+ case GST_OMX_BUFFER_ALLOCATION_USE_BUFFER:
+ default:
+ /* Not supported */
+ g_return_val_if_reached (FALSE);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+check_input_alignment (GstOMXVideoDec * self, GstMapInfo * map)
+{
+ OMX_PARAM_PORTDEFINITIONTYPE *port_def = &self->dec_in_port->port_def;
+
+ if (port_def->nBufferAlignment &&
+ (GPOINTER_TO_UINT (map->data) & (port_def->nBufferAlignment - 1)) != 0) {
+ GST_DEBUG_OBJECT (self,
+ "input buffer is not properly aligned (address: %p alignment: %u bytes), can't use dynamic allocation",
+ map->data, (guint32) port_def->nBufferAlignment);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Check if @inbuf's alignment matches the requirements to use the
+ * dynamic buffer mode. */
+static gboolean
+can_use_dynamic_buffer_mode (GstOMXVideoDec * self, GstBuffer * inbuf)
+{
+ gboolean result = TRUE;
+ guint i;
+
+ for (i = 0; i < gst_buffer_n_memory (inbuf) && result; i++) {
+ GstMemory *mem = gst_buffer_peek_memory (inbuf, i);
+ GstMapInfo map;
+
+ if (!gst_memory_map (mem, &map, GST_MAP_READ)) {
+ GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL),
+ ("failed to map input buffer"));
+ return FALSE;
+ }
+
+ result = check_input_alignment (self, &map);
+
+ gst_memory_unmap (mem, &map);
+ }
+
+ return result;
+}
+
+/* Choose the allocation mode for input buffers depending of what's supported by
+ * the component and the size/alignment of the input buffer. */
+static GstOMXBufferAllocation
+gst_omx_video_dec_pick_input_allocation_mode (GstOMXVideoDec * self,
+ GstBuffer * inbuf)
+{
+ if (!gst_omx_is_dynamic_allocation_supported ())
+ return GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER;
+
+ if (can_use_dynamic_buffer_mode (self, inbuf)) {
+ GST_DEBUG_OBJECT (self,
+ "input buffer is properly aligned, use dynamic allocation");
+ return GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC;
+ }
+
+ GST_DEBUG_OBJECT (self, "let input buffer allocate its buffers");
+ return GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER;
+}
+
+static gboolean
+gst_omx_video_dec_ensure_nb_in_buffers (GstOMXVideoDec * self)
+{
+ GstOMXVideoDecClass *klass = GST_OMX_VIDEO_DEC_GET_CLASS (self);
+
+ if ((klass->cdata.hacks & GST_OMX_HACK_ENSURE_BUFFER_COUNT_ACTUAL)) {
+ if (!gst_omx_port_ensure_buffer_count_actual (self->dec_in_port, 0))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_dec_enable (GstOMXVideoDec * self, GstBuffer * input)
+{
+ GstOMXVideoDecClass *klass = GST_OMX_VIDEO_DEC_GET_CLASS (self);
+
+ GST_DEBUG_OBJECT (self, "Enabling component");
+
+ self->input_allocation = gst_omx_video_dec_pick_input_allocation_mode (self,
+ input);
+
+ if (self->disabled) {
+ if (!gst_omx_video_dec_ensure_nb_in_buffers (self))
+ return FALSE;
+ if (gst_omx_port_set_enabled (self->dec_in_port, TRUE) != OMX_ErrorNone)
+ return FALSE;
+ if (!gst_omx_video_dec_allocate_in_buffers (self))
+ return FALSE;
+
+ if ((klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
+ if (gst_omx_port_set_enabled (self->dec_out_port, TRUE) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_allocate_buffers (self->dec_out_port) != OMX_ErrorNone)
+ return FALSE;
+
+ if (gst_omx_port_wait_enabled (self->dec_out_port,
+ 5 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ }
+
+ if (gst_omx_port_wait_enabled (self->dec_in_port,
+ 5 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_mark_reconfigured (self->dec_in_port) != OMX_ErrorNone)
+ return FALSE;
+ } else {
+ if (!gst_omx_video_dec_negotiate (self))
+ GST_LOG_OBJECT (self, "Negotiation failed, will get output format later");
+
+ if (!gst_omx_video_dec_ensure_nb_in_buffers (self))
+ return FALSE;
+
+ if (!(klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
+ /* Disable output port */
+ if (gst_omx_port_set_enabled (self->dec_out_port, FALSE) != OMX_ErrorNone)
+ return FALSE;
+
+ if (gst_omx_port_wait_enabled (self->dec_out_port,
+ 1 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+
+ if (gst_omx_component_set_state (self->dec,
+ OMX_StateIdle) != OMX_ErrorNone)
+ return FALSE;
+
+ /* Need to allocate buffers to reach Idle state */
+ if (!gst_omx_video_dec_allocate_in_buffers (self))
+ return FALSE;
+ } else {
+ if (gst_omx_component_set_state (self->dec,
+ OMX_StateIdle) != OMX_ErrorNone)
+ return FALSE;
+
+ /* Need to allocate buffers to reach Idle state */
+ if (!gst_omx_video_dec_allocate_in_buffers (self))
+ return FALSE;
+ if (gst_omx_port_allocate_buffers (self->dec_out_port) != OMX_ErrorNone)
+ return FALSE;
+ }
+
+ if (gst_omx_component_get_state (self->dec,
+ GST_CLOCK_TIME_NONE) != OMX_StateIdle)
+ return FALSE;
+
+ if (gst_omx_component_set_state (self->dec,
+ OMX_StateExecuting) != OMX_ErrorNone)
+ return FALSE;
+
+ if (gst_omx_component_get_state (self->dec,
+ GST_CLOCK_TIME_NONE) != OMX_StateExecuting)
+ return FALSE;
+ }
+
+ /* Unset flushing to allow ports to accept data again */
+ gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, FALSE);
+ gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, FALSE);
+
+ if (gst_omx_component_get_last_error (self->dec) != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Component in error state: %s (0x%08x)",
+ gst_omx_component_get_last_error_string (self->dec),
+ gst_omx_component_get_last_error (self->dec));
+ return FALSE;
+ }
+
+ self->disabled = FALSE;
+
+ return TRUE;
+}
+
+static OMX_COLOR_FORMATTYPE
+get_color_format_from_chroma (const gchar * chroma_format,
+ guint bit_depth_luma, guint bit_depth_chroma)
+{
+ if (chroma_format == NULL)
+ goto out;
+
+ if (!g_strcmp0 (chroma_format, "4:0:0") && bit_depth_chroma == 0) {
+ switch (bit_depth_luma) {
+ case 1:
+ return OMX_COLOR_FormatMonochrome;
+ case 2:
+ return OMX_COLOR_FormatL2;
+ case 4:
+ return OMX_COLOR_FormatL4;
+ case 8:
+ return OMX_COLOR_FormatL8;
+ case 16:
+ return OMX_COLOR_FormatL16;
+ case 24:
+ return OMX_COLOR_FormatL24;
+ case 32:
+ return OMX_COLOR_FormatL32;
+ }
+ goto out;
+ }
+
+ if (bit_depth_luma == 8 && bit_depth_chroma == 8) {
+ if (!g_strcmp0 (chroma_format, "4:2:0"))
+ return OMX_COLOR_FormatYUV420SemiPlanar;
+ else if (!g_strcmp0 (chroma_format, "4:2:2"))
+ return OMX_COLOR_FormatYUV422SemiPlanar;
+ }
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ if (bit_depth_luma == 10 && bit_depth_chroma == 10) {
+ if (!g_strcmp0 (chroma_format, "4:2:0"))
+ return (OMX_COLOR_FORMATTYPE)
+ OMX_ALG_COLOR_FormatYUV420SemiPlanar10bitPacked;
+ else if (!g_strcmp0 (chroma_format, "4:2:2"))
+ return (OMX_COLOR_FORMATTYPE)
+ OMX_ALG_COLOR_FormatYUV422SemiPlanar10bitPacked;
+ }
+#endif
+
+out:
+ return OMX_COLOR_FormatUnused;
+}
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+static gboolean
+gst_omx_video_dec_set_interlacing_parameters (GstOMXVideoDec * self,
+ GstVideoInfo * info)
+{
+ OMX_ERRORTYPE err;
+ OMX_ALG_COMMON_PARAM_SEQUENCE_PICTURE_MODE seq_pic_mode;
+
+ GST_OMX_INIT_STRUCT (&seq_pic_mode);
+ seq_pic_mode.nPortIndex = self->dec_in_port->index;
+
+ err = gst_omx_component_get_parameter (self->dec,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamCommonSequencePictureModeCurrent,
+ &seq_pic_mode);
+
+ if (err != OMX_ErrorNone) {
+ if (err == OMX_ErrorUnsupportedIndex) {
+ GST_WARNING_OBJECT (self,
+ "Picture sequence mode not supported by the component");
+ } else {
+ GST_DEBUG_OBJECT (self,
+ "Failed to get picture sequence mode: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ }
+
+ return FALSE;
+ }
+
+ if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_ALTERNATE ||
+ info->interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED)
+ seq_pic_mode.eMode = OMX_ALG_SEQUENCE_PICTURE_FIELD;
+ else if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_PROGRESSIVE)
+ seq_pic_mode.eMode = OMX_ALG_SEQUENCE_PICTURE_FRAME;
+ else {
+ /* Caps templates should ensure this doesn't happen but just to be safe.. */
+ GST_ERROR_OBJECT (self, "Video interlacing mode %s not supported",
+ gst_video_interlace_mode_to_string (info->interlace_mode));
+ return FALSE;
+ }
+
+ err = gst_omx_component_set_parameter (self->dec,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamCommonSequencePictureModeCurrent,
+ &seq_pic_mode);
+
+ if (err == OMX_ErrorUnsupportedIndex) {
+ GST_WARNING_OBJECT (self,
+ "Setting picture sequence mode not supported by the component");
+ } else if (err == OMX_ErrorUnsupportedSetting) {
+ GST_WARNING_OBJECT (self,
+ "Interlaced picture sequence mode not supported by the component");
+ } else if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to set picture sequence mode: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ } else {
+ GST_DEBUG_OBJECT (self, "Video interlacing mode %s set on component",
+ gst_video_interlace_mode_to_string (info->interlace_mode));
+ }
+
+ return TRUE;
+}
+#endif // USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+
+static gboolean
+gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
+ GstVideoCodecState * state)
+{
+ GstOMXVideoDec *self;
+ GstOMXVideoDecClass *klass;
+ GstVideoInfo *info = &state->info;
+ gboolean is_format_change = FALSE;
+ gboolean needs_disable = FALSE;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ OMX_U32 framerate_q16 = gst_omx_video_calculate_framerate_q16 (info);
+
+ self = GST_OMX_VIDEO_DEC (decoder);
+ klass = GST_OMX_VIDEO_DEC_GET_CLASS (decoder);
+
+ GST_DEBUG_OBJECT (self, "Setting new caps %" GST_PTR_FORMAT, state->caps);
+
+ if (!self->dmabuf
+ && gst_caps_features_contains (gst_caps_get_features (state->caps, 0),
+ GST_CAPS_FEATURE_MEMORY_DMABUF)) {
+ GST_WARNING_OBJECT (self,
+ "caps has the 'memory:DMABuf' feature but decoder cannot produce dmabuf");
+ return FALSE;
+ }
+
+ gst_omx_port_get_port_definition (self->dec_in_port, &port_def);
+
+ /* Check if the caps change is a real format change or if only irrelevant
+ * parts of the caps have changed or nothing at all.
+ */
+ is_format_change |= port_def.format.video.nFrameWidth != info->width;
+ is_format_change |=
+ port_def.format.video.nFrameHeight != GST_VIDEO_INFO_FIELD_HEIGHT (info);
+ is_format_change |= (port_def.format.video.xFramerate == 0
+ && info->fps_n != 0)
+ || !gst_omx_video_is_equal_framerate_q16 (port_def.format.
+ video.xFramerate, framerate_q16);
+ is_format_change |= (self->codec_data != state->codec_data);
+ if (klass->is_format_change)
+ is_format_change |=
+ klass->is_format_change (self, self->dec_in_port, state);
+
+ needs_disable =
+ gst_omx_component_get_state (self->dec,
+ GST_CLOCK_TIME_NONE) != OMX_StateLoaded;
+ /* If the component is not in Loaded state and a real format change happens
+ * we have to disable the port and re-allocate all buffers. If no real
+ * format change happened we can just exit here.
+ */
+ if (needs_disable && !is_format_change) {
+ GST_DEBUG_OBJECT (self,
+ "Already running and caps did not change the format");
+ if (self->input_state)
+ gst_video_codec_state_unref (self->input_state);
+ self->input_state = gst_video_codec_state_ref (state);
+ return TRUE;
+ }
+
+ if (needs_disable && is_format_change) {
+ if (!gst_omx_video_dec_disable (self))
+ return FALSE;
+
+ if (!self->disabled) {
+ /* The local port_def is now obsolete so get it again. */
+ gst_omx_port_get_port_definition (self->dec_in_port, &port_def);
+ }
+ }
+
+ port_def.format.video.nFrameWidth = info->width;
+ port_def.format.video.nFrameHeight = GST_VIDEO_INFO_HEIGHT (info);
+ /*We cannot use GST_VIDEO_INFO_FIELD_HEIGHT() as encoded content may use either
+ * interlace-mode=interleaved or alternate. In both case we'll output alternate
+ * so the OMX frame height needs to be halfed. */
+ if (GST_VIDEO_INFO_IS_INTERLACED (info))
+ port_def.format.video.nFrameHeight =
+ GST_ROUND_UP_2 (port_def.format.video.nFrameHeight / 2);
+ port_def.format.video.xFramerate = framerate_q16;
+
+ if (klass->cdata.hacks & GST_OMX_HACK_PASS_COLOR_FORMAT_TO_DECODER) {
+ /* Let the decoder know the colar format of the encoded input stream.
+ * It may use it to pre-allocate its internal buffers and so save time when
+ * it will actually start to decode. */
+ GstStructure *s;
+ const gchar *chroma_format;
+ guint bit_depth_luma, bit_depth_chroma;
+
+ s = gst_caps_get_structure (state->caps, 0);
+ chroma_format = gst_structure_get_string (s, "chroma-format");
+ if (s && gst_structure_get_uint (s, "bit-depth-luma", &bit_depth_luma) &&
+ gst_structure_get_uint (s, "bit-depth-chroma", &bit_depth_chroma)) {
+ OMX_COLOR_FORMATTYPE color_format;
+
+ color_format =
+ get_color_format_from_chroma (chroma_format,
+ bit_depth_luma, bit_depth_chroma);
+ if (color_format != OMX_COLOR_FormatUnused) {
+ GST_DEBUG_OBJECT (self, "Setting input eColorFormat to %d",
+ color_format);
+ port_def.format.video.eColorFormat = color_format;
+ } else {
+ GST_WARNING_OBJECT (self,
+ "Unsupported input color format: %s (luma %d bits, chroma %d bits)",
+ chroma_format, bit_depth_luma, bit_depth_chroma);
+ }
+ } else {
+ GST_DEBUG_OBJECT (self,
+ "Input color format info not present in caps, can't pass them to decoder");
+ }
+ }
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ if (!gst_omx_video_dec_set_interlacing_parameters (self, info))
+ return FALSE;
+#endif
+
+ GST_DEBUG_OBJECT (self, "Setting inport port definition");
+
+ if (gst_omx_port_update_port_definition (self->dec_in_port,
+ &port_def) != OMX_ErrorNone)
+ return FALSE;
+
+ if (klass->set_format) {
+ if (!klass->set_format (self, self->dec_in_port, state)) {
+ GST_ERROR_OBJECT (self, "Subclass failed to set the new format");
+ return FALSE;
+ }
+ }
+
+ GST_DEBUG_OBJECT (self, "Updating ports definition");
+ if (gst_omx_port_update_port_definition (self->dec_out_port,
+ NULL) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_update_port_definition (self->dec_in_port,
+ NULL) != OMX_ErrorNone)
+ return FALSE;
+
+ gst_buffer_replace (&self->codec_data, state->codec_data);
+ self->input_state = gst_video_codec_state_ref (state);
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ gst_omx_video_dec_set_latency (self);
+#endif
+
+ self->downstream_flow_ret = GST_FLOW_OK;
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_dec_flush (GstVideoDecoder * decoder)
+{
+ GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (decoder);
+ OMX_ERRORTYPE err = OMX_ErrorNone;
+
+ GST_DEBUG_OBJECT (self, "Flushing decoder");
+
+ if (gst_omx_component_get_state (self->dec, 0) == OMX_StateLoaded)
+ return TRUE;
+
+ /* 0) Pause the components */
+ if (gst_omx_component_get_state (self->dec, 0) == OMX_StateExecuting) {
+ gst_omx_component_set_state (self->dec, OMX_StatePause);
+ gst_omx_component_get_state (self->dec, GST_CLOCK_TIME_NONE);
+ }
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+ if (self->eglimage) {
+ if (gst_omx_component_get_state (self->egl_render, 0) == OMX_StateExecuting) {
+ gst_omx_component_set_state (self->egl_render, OMX_StatePause);
+ gst_omx_component_get_state (self->egl_render, GST_CLOCK_TIME_NONE);
+ }
+ }
+#endif
+
+ /* 1) Flush the ports */
+ GST_DEBUG_OBJECT (self, "flushing ports");
+ gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
+ gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
+
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+ if (self->eglimage) {
+ gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, TRUE);
+ gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, TRUE);
+ }
+#endif
+
+ /* 2) Wait until the srcpad loop is stopped,
+ * unlock GST_VIDEO_DECODER_STREAM_LOCK to prevent deadlocks
+ * caused by using this lock from inside the loop function */
+ GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+ gst_pad_stop_task (GST_VIDEO_DECODER_SRC_PAD (decoder));
+ GST_DEBUG_OBJECT (self, "Flushing -- task stopped");
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+
+ /* 3) Resume components */
+ gst_omx_component_set_state (self->dec, OMX_StateExecuting);
+ gst_omx_component_get_state (self->dec, GST_CLOCK_TIME_NONE);
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+ if (self->eglimage) {
+ gst_omx_component_set_state (self->egl_render, OMX_StateExecuting);
+ gst_omx_component_get_state (self->egl_render, GST_CLOCK_TIME_NONE);
+ }
+#endif
+
+ /* 4) Unset flushing to allow ports to accept data again */
+ gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, FALSE);
+ gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, FALSE);
+
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+ if (self->eglimage) {
+ gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, FALSE);
+ gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, FALSE);
+ err = gst_omx_port_populate (self->egl_out_port);
+ gst_omx_port_mark_reconfigured (self->egl_out_port);
+ } else {
+ err = gst_omx_port_populate (self->dec_out_port);
+ }
+#else
+ err = gst_omx_port_populate (self->dec_out_port);
+#endif
+
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self, "Failed to populate output port: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ }
+
+ /* Reset our state */
+ self->last_upstream_ts = 0;
+ self->downstream_flow_ret = GST_FLOW_OK;
+ self->started = FALSE;
+ GST_DEBUG_OBJECT (self, "Flush finished");
+
+ return TRUE;
+}
+
+static GstFlowReturn
+gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
+ GstVideoCodecFrame * frame)
+{
+ GstOMXAcquireBufferReturn acq_ret = GST_OMX_ACQUIRE_BUFFER_ERROR;
+ GstOMXVideoDec *self;
+ GstOMXPort *port;
+ GstOMXBuffer *buf;
+ GstBuffer *codec_data = NULL;
+ guint offset = 0, size;
+ GstClockTime timestamp, duration;
+ OMX_ERRORTYPE err;
+ gboolean done = FALSE;
+ gboolean first_ouput_buffer = TRUE;
+ guint memory_idx = 0; /* only used in dynamic buffer mode */
+ gboolean last_subframe = GST_BUFFER_FLAG_IS_SET (frame->input_buffer,
+ GST_VIDEO_BUFFER_FLAG_MARKER);
+ gboolean header =
+ GST_BUFFER_FLAG_IS_SET (frame->input_buffer, GST_BUFFER_FLAG_HEADER);
+ gboolean subframe_mode = gst_video_decoder_get_subframe_mode (decoder);
+
+ self = GST_OMX_VIDEO_DEC (decoder);
+
+ GST_DEBUG_OBJECT (self,
+ "Handling frame %p last_subframe=%d header %d subframes %d", frame,
+ last_subframe, header, frame->abidata.ABI.num_subframes);
+
+ if (self->downstream_flow_ret != GST_FLOW_OK) {
+ gst_video_codec_frame_unref (frame);
+ return self->downstream_flow_ret;
+ }
+
+ if (!self->started) {
+ if (!GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame) && !header) {
+ gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
+ return GST_FLOW_OK;
+ }
+
+ if (gst_omx_port_is_flushing (self->dec_out_port)) {
+ if (!gst_omx_video_dec_enable (self, frame->input_buffer))
+ goto enable_error;
+ }
+
+ GST_DEBUG_OBJECT (self, "Starting task");
+ gst_pad_start_task (GST_VIDEO_DECODER_SRC_PAD (self),
+ (GstTaskFunction) gst_omx_video_dec_loop, decoder, NULL);
+ }
+
+ timestamp = frame->pts;
+ duration = frame->duration;
+ port = self->dec_in_port;
+
+ size = gst_buffer_get_size (frame->input_buffer);
+ while (!done) {
+ /* Make sure to release the base class stream lock, otherwise
+ * _loop() can't call _finish_frame() and we might block forever
+ * because no input buffers are released */
+ GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+ acq_ret = gst_omx_port_acquire_buffer (port, &buf, GST_OMX_WAIT);
+
+ if (acq_ret == GST_OMX_ACQUIRE_BUFFER_ERROR) {
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+ goto component_error;
+ } else if (acq_ret == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+ goto flushing;
+ } else if (acq_ret == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+ /* Reallocate all buffers */
+ err = gst_omx_port_set_enabled (port, FALSE);
+ if (err != OMX_ErrorNone) {
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_wait_buffers_released (port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_deallocate_buffers (port);
+ if (err != OMX_ErrorNone) {
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_wait_enabled (port, 1 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ if (!gst_omx_video_dec_ensure_nb_in_buffers (self)) {
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_set_enabled (port, TRUE);
+ if (err != OMX_ErrorNone) {
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ if (!gst_omx_video_dec_allocate_in_buffers (self)) {
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_wait_enabled (port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_mark_reconfigured (port);
+ if (err != OMX_ErrorNone) {
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ /* Now get a new buffer and fill it */
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+ continue;
+ }
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+
+ g_assert (acq_ret == GST_OMX_ACQUIRE_BUFFER_OK && buf != NULL);
+
+ if (buf->omx_buf->nAllocLen - buf->omx_buf->nOffset <= 0) {
+ gst_omx_port_release_buffer (port, buf);
+ goto full_buffer;
+ }
+
+ if (self->downstream_flow_ret != GST_FLOW_OK) {
+ gst_omx_port_release_buffer (port, buf);
+ goto flow_error;
+ }
+
+ if (self->codec_data) {
+ GST_DEBUG_OBJECT (self, "Passing codec data to the component");
+
+ codec_data = self->codec_data;
+
+ if (self->input_allocation ==
+ GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC) {
+ /* Map the full buffer, this may lead to copying if for some reason its
+ * content is split on more than one memory but that seems unlikely and
+ * the codec data aren't supposed to be that big anyway. */
+ if (!gst_omx_buffer_map_buffer (buf, codec_data))
+ goto map_failed;
+ } else {
+ if (buf->omx_buf->nAllocLen - buf->omx_buf->nOffset <
+ gst_buffer_get_size (codec_data)) {
+ gst_omx_port_release_buffer (port, buf);
+ goto too_large_codec_data;
+ }
+
+ buf->omx_buf->nFilledLen = gst_buffer_get_size (codec_data);;
+ gst_buffer_extract (codec_data, 0,
+ buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+ buf->omx_buf->nFilledLen);
+ }
+
+ buf->omx_buf->nFlags |= OMX_BUFFERFLAG_CODECCONFIG;
+
+ if (GST_CLOCK_TIME_IS_VALID (timestamp))
+ GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp,
+ gst_util_uint64_scale (timestamp, OMX_TICKS_PER_SECOND,
+ GST_SECOND));
+ else
+ GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp, G_GUINT64_CONSTANT (0));
+ buf->omx_buf->nTickCount = 0;
+
+ self->started = TRUE;
+ err = gst_omx_port_release_buffer (port, buf);
+ gst_buffer_replace (&self->codec_data, NULL);
+ if (err != OMX_ErrorNone)
+ goto release_error;
+ /* Acquire new buffer for the actual frame */
+ continue;
+ }
+
+ /* Now handle the frame */
+
+ if (self->input_allocation == GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC) {
+ /* Transfer the buffer content per memory rather than mapping the full
+ * buffer to prevent copies. */
+ GstMemory *mem = gst_buffer_peek_memory (frame->input_buffer, memory_idx);
+
+ GST_LOG_OBJECT (self,
+ "Transferring %" G_GSIZE_FORMAT " bytes to the component",
+ gst_memory_get_sizes (mem, NULL, NULL));
+
+ if (!gst_omx_buffer_map_memory (buf, mem))
+ goto map_failed;
+
+ if (!check_input_alignment (self, &buf->map)) {
+ GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL),
+ ("input buffer now has wrong alignment/stride, can't use dynamic allocation any more"));
+ return FALSE;
+ }
+
+ memory_idx++;
+ if (memory_idx == gst_buffer_n_memory (frame->input_buffer))
+ done = TRUE;
+ } else {
+ /* Copy the buffer content in chunks of size as requested
+ * by the port */
+ buf->omx_buf->nFilledLen =
+ MIN (size - offset, buf->omx_buf->nAllocLen - buf->omx_buf->nOffset);
+
+ GST_LOG_OBJECT (self,
+ "Copying %d bytes (frame offset %d) to the component",
+ (guint) buf->omx_buf->nFilledLen, offset);
+
+ gst_buffer_extract (frame->input_buffer, offset,
+ buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+ buf->omx_buf->nFilledLen);
+
+ offset += buf->omx_buf->nFilledLen;
+ if (offset == size)
+ done = TRUE;
+ }
+
+ if (timestamp != GST_CLOCK_TIME_NONE) {
+ GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp,
+ gst_util_uint64_scale (timestamp, OMX_TICKS_PER_SECOND, GST_SECOND));
+ self->last_upstream_ts = timestamp;
+ } else {
+ GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp, G_GUINT64_CONSTANT (0));
+ }
+
+ if (duration != GST_CLOCK_TIME_NONE && first_ouput_buffer) {
+ buf->omx_buf->nTickCount =
+ gst_util_uint64_scale (duration, OMX_TICKS_PER_SECOND, GST_SECOND);
+ self->last_upstream_ts += duration;
+ } else {
+ buf->omx_buf->nTickCount = 0;
+ }
+
+ if (first_ouput_buffer && GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame))
+ buf->omx_buf->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
+
+ if (header)
+ buf->omx_buf->nFlags |= OMX_BUFFERFLAG_CODECCONFIG;
+
+ /* TODO: Set flags
+ * - OMX_BUFFERFLAG_DECODEONLY for buffers that are outside
+ * the segment
+ */
+
+ if (done) {
+ /* If the input buffer is a subframe mark the OMX buffer as such */
+ if (subframe_mode && !last_subframe) {
+#ifdef OMX_BUFFERFLAG_ENDOFSUBFRAME
+ buf->omx_buf->nFlags |= OMX_BUFFERFLAG_ENDOFSUBFRAME;
+#endif
+ } else {
+ buf->omx_buf->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
+ if (subframe_mode && last_subframe)
+ gst_video_decoder_have_last_subframe (decoder, frame);
+ }
+ }
+
+ self->started = TRUE;
+ err = gst_omx_port_release_buffer (port, buf);
+ if (err != OMX_ErrorNone)
+ goto release_error;
+
+ first_ouput_buffer = FALSE;
+ }
+
+ gst_video_codec_frame_unref (frame);
+
+ GST_DEBUG_OBJECT (self, "Passed frame to component");
+
+ return self->downstream_flow_ret;
+
+full_buffer:
+ {
+ gst_video_codec_frame_unref (frame);
+ GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+ ("Got OpenMAX buffer with no free space (%p, %u/%u)", buf,
+ (guint) buf->omx_buf->nOffset, (guint) buf->omx_buf->nAllocLen));
+ return GST_FLOW_ERROR;
+ }
+
+flow_error:
+ {
+ gst_video_codec_frame_unref (frame);
+
+ return self->downstream_flow_ret;
+ }
+
+too_large_codec_data:
+ {
+ gst_video_codec_frame_unref (frame);
+ GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL),
+ ("codec_data larger than supported by OpenMAX port "
+ "(%" G_GSIZE_FORMAT " > %u)", gst_buffer_get_size (codec_data),
+ (guint) self->dec_in_port->port_def.nBufferSize));
+ return GST_FLOW_ERROR;
+ }
+
+map_failed:
+ {
+ gst_video_codec_frame_unref (frame);
+ GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL),
+ ("failed to map input buffer"));
+ return GST_FLOW_ERROR;
+ }
+
+enable_error:
+ {
+ /* Report the OMX error, if any */
+ if (gst_omx_component_get_last_error (self->dec) != OMX_ErrorNone)
+ GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+ ("Failed to enable OMX decoder: %s (0x%08x)",
+ gst_omx_component_get_last_error_string (self->dec),
+ gst_omx_component_get_last_error (self->dec)));
+ else
+ GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+ ("Failed to enable OMX decoder"));
+ gst_video_codec_frame_unref (frame);
+ return GST_FLOW_ERROR;
+ }
+
+component_error:
+ {
+ gst_video_codec_frame_unref (frame);
+ GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+ ("OpenMAX component in error state %s (0x%08x)",
+ gst_omx_component_get_last_error_string (self->dec),
+ gst_omx_component_get_last_error (self->dec)));
+ return GST_FLOW_ERROR;
+ }
+
+flushing:
+ {
+ gst_video_codec_frame_unref (frame);
+ GST_DEBUG_OBJECT (self, "Flushing -- returning FLUSHING");
+ return GST_FLOW_FLUSHING;
+ }
+reconfigure_error:
+ {
+ gst_video_codec_frame_unref (frame);
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Unable to reconfigure input port"));
+ return GST_FLOW_ERROR;
+ }
+release_error:
+ {
+ gst_video_codec_frame_unref (frame);
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Failed to relase input buffer to component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err));
+ return GST_FLOW_ERROR;
+ }
+}
+
+static GstFlowReturn
+gst_omx_video_dec_drain (GstVideoDecoder * decoder)
+{
+ gboolean ret;
+ ret = gst_omx_video_dec_finish (decoder);
+ gst_omx_video_dec_flush (decoder);
+ return ret;
+}
+
+static GstFlowReturn
+gst_omx_video_dec_finish (GstVideoDecoder * decoder)
+{
+ GstOMXVideoDec *self;
+ GstOMXVideoDecClass *klass;
+ GstOMXBuffer *buf;
+ GstOMXAcquireBufferReturn acq_ret;
+ OMX_ERRORTYPE err;
+
+ self = GST_OMX_VIDEO_DEC (decoder);
+
+ GST_DEBUG_OBJECT (self, "Draining component");
+
+ klass = GST_OMX_VIDEO_DEC_GET_CLASS (self);
+
+ if (!self->started) {
+ GST_DEBUG_OBJECT (self, "Component not started yet");
+ return GST_FLOW_OK;
+ }
+ self->started = FALSE;
+
+ if ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
+ GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
+ return GST_FLOW_OK;
+ }
+
+ /* Make sure to release the base class stream lock, otherwise
+ * _loop() can't call _finish_frame() and we might block forever
+ * because no input buffers are released */
+ GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+
+ /* Send an EOS buffer to the component and let the base
+ * class drop the EOS event. We will send it later when
+ * the EOS buffer arrives on the output port. */
+ acq_ret = gst_omx_port_acquire_buffer (self->dec_in_port, &buf, GST_OMX_WAIT);
+ if (acq_ret != GST_OMX_ACQUIRE_BUFFER_OK) {
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+ GST_ERROR_OBJECT (self, "Failed to acquire buffer for draining: %d",
+ acq_ret);
+ return GST_FLOW_ERROR;
+ }
+
+ g_mutex_lock (&self->drain_lock);
+ self->draining = TRUE;
+ buf->omx_buf->nFilledLen = 0;
+ GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp,
+ gst_util_uint64_scale (self->last_upstream_ts, OMX_TICKS_PER_SECOND,
+ GST_SECOND));
+ buf->omx_buf->nTickCount = 0;
+ buf->omx_buf->nFlags |= OMX_BUFFERFLAG_EOS;
+ err = gst_omx_port_release_buffer (self->dec_in_port, buf);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to drain component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ g_mutex_unlock (&self->drain_lock);
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+ return GST_FLOW_ERROR;
+ }
+
+ GST_DEBUG_OBJECT (self, "Waiting until component is drained");
+
+ if (G_UNLIKELY (self->dec->hacks & GST_OMX_HACK_DRAIN_MAY_NOT_RETURN)) {
+ gint64 wait_until = g_get_monotonic_time () + G_TIME_SPAN_SECOND / 2;
+
+ if (!g_cond_wait_until (&self->drain_cond, &self->drain_lock, wait_until))
+ GST_WARNING_OBJECT (self, "Drain timed out");
+ else
+ GST_DEBUG_OBJECT (self, "Drained component");
+
+ } else {
+ g_cond_wait (&self->drain_cond, &self->drain_lock);
+ GST_DEBUG_OBJECT (self, "Drained component");
+ }
+
+ g_mutex_unlock (&self->drain_lock);
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+
+ self->started = FALSE;
+
+ return GST_FLOW_OK;
+}
+
+static gboolean
+gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query)
+{
+ GstBufferPool *pool = NULL;
+ GstStructure *config;
+ GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (bdec);
+ guint i;
+
+#if defined (HAVE_GST_GL)
+ {
+ GstCaps *caps;
+ gint i, n;
+ GstVideoInfo info;
+
+ gst_query_parse_allocation (query, &caps, NULL);
+ if (caps && gst_video_info_from_caps (&info, caps)
+ && info.finfo->format == GST_VIDEO_FORMAT_RGBA) {
+ gboolean found = FALSE;
+ GstCapsFeatures *feature = gst_caps_get_features (caps, 0);
+ /* Prefer an EGLImage allocator if available and we want to use it */
+ n = gst_query_get_n_allocation_params (query);
+ for (i = 0; i < n; i++) {
+ GstAllocator *allocator;
+ GstAllocationParams params;
+
+ gst_query_parse_nth_allocation_param (query, i, &allocator, &params);
+ if (allocator) {
+ if (GST_IS_GL_MEMORY_EGL_ALLOCATOR (allocator)) {
+ found = TRUE;
+ gst_query_set_nth_allocation_param (query, 0, allocator, &params);
+ while (gst_query_get_n_allocation_params (query) > 1)
+ gst_query_remove_nth_allocation_param (query, 1);
+ }
+
+ gst_object_unref (allocator);
+
+ if (found)
+ break;
+ }
+ }
+
+ /* if try to negotiate with caps feature memory:EGLImage
+ * and if allocator is not of type memory EGLImage then fails */
+ if (feature
+ && gst_caps_features_contains (feature,
+ GST_CAPS_FEATURE_MEMORY_GL_MEMORY) && !found) {
+ return FALSE;
+ }
+ }
+ }
+#endif /* defined (HAVE_GST_GL) */
+
+ self->use_buffers = FALSE;
+
+ /* Importing OMX buffers from downstream isn't supported.
+ * That wouldn't bring us much as the dynamic buffer mode already
+ * prevent copies between OMX components. */
+ i = 0;
+ while (i < gst_query_get_n_allocation_pools (query)) {
+ gst_query_parse_nth_allocation_pool (query, i, &pool, NULL, NULL, NULL);
+ if (GST_IS_OMX_BUFFER_POOL (pool)) {
+ GST_DEBUG_OBJECT (self, "Discard OMX pool from downstream");
+ gst_query_remove_nth_allocation_pool (query, i);
+ } else {
+ GST_DEBUG_OBJECT (self,
+ "Try using downstream buffers with OMX_UseBuffer");
+ self->use_buffers = TRUE;
+ i++;
+ }
+
+ if (pool)
+ gst_object_unref (pool);
+ }
+
+ if (!GST_VIDEO_DECODER_CLASS
+ (gst_omx_video_dec_parent_class)->decide_allocation (bdec, query))
+ return FALSE;
+
+ g_assert (gst_query_get_n_allocation_pools (query) > 0);
+ gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL);
+ g_assert (pool != NULL);
+
+ config = gst_buffer_pool_get_config (pool);
+ if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) {
+ gst_buffer_pool_config_add_option (config,
+ GST_BUFFER_POOL_OPTION_VIDEO_META);
+ }
+ gst_buffer_pool_set_config (pool, config);
+ gst_object_unref (pool);
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_dec_propose_allocation (GstVideoDecoder * bdec, GstQuery * query)
+{
+ GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (bdec);
+ guint size, num_buffers;
+
+ size = self->dec_in_port->port_def.nBufferSize;
+ num_buffers = self->dec_in_port->port_def.nBufferCountMin + 1;
+
+ GST_DEBUG_OBJECT (self,
+ "request at least %d buffers of size %d", num_buffers, size);
+ gst_query_add_allocation_pool (query, NULL, size, num_buffers, 0);
+
+ return
+ GST_VIDEO_DECODER_CLASS
+ (gst_omx_video_dec_parent_class)->propose_allocation (bdec, query);
+}
diff --git a/subprojects/gst-omx/omx/gstomxvideodec.h b/subprojects/gst-omx/omx/gstomxvideodec.h
new file mode 100644
index 0000000000..df441d9d08
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxvideodec.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_VIDEO_DEC_H__
+#define __GST_OMX_VIDEO_DEC_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/video/gstvideodecoder.h>
+
+#include "gstomx.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_VIDEO_DEC \
+ (gst_omx_video_dec_get_type())
+#define GST_OMX_VIDEO_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_VIDEO_DEC,GstOMXVideoDec))
+#define GST_OMX_VIDEO_DEC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_VIDEO_DEC,GstOMXVideoDecClass))
+#define GST_OMX_VIDEO_DEC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_VIDEO_DEC,GstOMXVideoDecClass))
+#define GST_IS_OMX_VIDEO_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_VIDEO_DEC))
+#define GST_IS_OMX_VIDEO_DEC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_VIDEO_DEC))
+
+typedef struct _GstOMXVideoDec GstOMXVideoDec;
+typedef struct _GstOMXVideoDecClass GstOMXVideoDecClass;
+
+struct _GstOMXVideoDec
+{
+ GstVideoDecoder parent;
+
+ /* < protected > */
+ GstOMXComponent *dec;
+ GstOMXPort *dec_in_port, *dec_out_port;
+
+ GstBufferPool *in_port_pool, *out_port_pool;
+
+ /* < private > */
+ GstVideoCodecState *input_state;
+ GstBuffer *codec_data;
+ /* TRUE if the component is configured and saw
+ * the first buffer */
+ gboolean started;
+ /* TRUE if the ports where disabled after being activated the first time. */
+ gboolean disabled;
+
+ GstClockTime last_upstream_ts;
+
+ /* Draining state */
+ GMutex drain_lock;
+ GCond drain_cond;
+ /* TRUE if EOS buffers shouldn't be forwarded */
+ gboolean draining; /* protected by drain_lock */
+
+ GstFlowReturn downstream_flow_ret;
+ /* Initially FALSE. Switched to TRUE when all requirements
+ * are met to try setting up the decoder with OMX_UseBuffer.
+ * Switched to FALSE if this trial fails so that the decoder
+ * can fallback to OMX_AllocateBuffer. */
+ gboolean use_buffers;
+
+#if defined (USE_OMX_TARGET_RPI)
+ GstOMXComponent *egl_render;
+ GstOMXPort *egl_in_port, *egl_out_port;
+#endif
+
+#if defined (HAVE_GST_GL)
+ gboolean eglimage;
+#endif
+
+ /* TRUE if decoder is producing dmabuf */
+ gboolean dmabuf;
+ GstOMXBufferAllocation input_allocation;
+
+ /* properties */
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ guint32 internal_entropy_buffers;
+#endif
+};
+
+struct _GstOMXVideoDecClass
+{
+ GstVideoDecoderClass parent_class;
+
+ GstOMXClassData cdata;
+
+ gboolean (*is_format_change) (GstOMXVideoDec * self, GstOMXPort * port, GstVideoCodecState * state);
+ gboolean (*set_format) (GstOMXVideoDec * self, GstOMXPort * port, GstVideoCodecState * state);
+};
+
+GType gst_omx_video_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_VIDEO_DEC_H__ */
diff --git a/subprojects/gst-omx/omx/gstomxvideoenc.c b/subprojects/gst-omx/omx/gstomxvideoenc.c
new file mode 100644
index 0000000000..6dbfb411ca
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxvideoenc.c
@@ -0,0 +1,3732 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/video/gstvideometa.h>
+#include <gst/allocators/gstdmabuf.h>
+
+#include <string.h>
+
+#include "gstomxbufferpool.h"
+#include "gstomxvideo.h"
+#include "gstomxvideoenc.h"
+
+#ifdef USE_OMX_TARGET_RPI
+#include <OMX_Broadcom.h>
+#include <OMX_Index.h>
+#endif
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_video_enc_debug_category);
+#define GST_CAT_DEFAULT gst_omx_video_enc_debug_category
+
+#define GST_TYPE_OMX_VIDEO_ENC_CONTROL_RATE (gst_omx_video_enc_control_rate_get_type ())
+static GType
+gst_omx_video_enc_control_rate_get_type (void)
+{
+ static GType qtype = 0;
+
+ if (qtype == 0) {
+ static const GEnumValue values[] = {
+ {OMX_Video_ControlRateDisable, "Disable", "disable"},
+ {OMX_Video_ControlRateVariable, "Variable", "variable"},
+ {OMX_Video_ControlRateConstant, "Constant", "constant"},
+ {OMX_Video_ControlRateVariableSkipFrames, "Variable Skip Frames",
+ "variable-skip-frames"},
+ {OMX_Video_ControlRateConstantSkipFrames, "Constant Skip Frames",
+ "constant-skip-frames"},
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ {OMX_ALG_Video_ControlRateLowLatency, "Low Latency", "low-latency"},
+#endif
+ {0xffffffff, "Component Default", "default"},
+ {0, NULL, NULL}
+ };
+
+ qtype = g_enum_register_static ("GstOMXVideoEncControlRate", values);
+ }
+ return qtype;
+}
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+#define GST_TYPE_OMX_VIDEO_ENC_QP_MODE (gst_omx_video_enc_qp_mode_get_type ())
+typedef enum
+{
+ UNIFORM_QP,
+ ROI_QP,
+ AUTO_QP,
+ LOAD_QP_ABSOLUTE,
+ LOAD_QP_RELATIVE,
+} GstOMXVideoEncQpMode;
+
+
+static GType
+gst_omx_video_enc_qp_mode_get_type (void)
+{
+ static GType qtype = 0;
+
+ if (qtype == 0) {
+ static const GEnumValue values[] = {
+ {UNIFORM_QP, "Use the same QP for all coding units of the frame",
+ "uniform"},
+ {ROI_QP,
+ "Adjust QP according to the regions of interest defined on each frame. Must be set to handle ROI metadata.",
+ "roi"},
+ {AUTO_QP,
+ "Let the VCU encoder change the QP for each coding unit according to its content",
+ "auto"},
+ {LOAD_QP_ABSOLUTE,
+ "Uses absolute QP values set by user. Must be set to use External QP buffer",
+ "load-qp-absolute"},
+ {LOAD_QP_RELATIVE,
+ "Uses Relative/Delta QP values set by user. Must be set to use External QP buffer",
+ "load-qp-relative"},
+ {0xffffffff, "Component Default", "default"},
+ {0, NULL, NULL}
+ };
+
+ qtype = g_enum_register_static ("GstOMXVideoEncQpMode", values);
+ }
+ return qtype;
+}
+
+#define GST_TYPE_OMX_VIDEO_ENC_GOP_MODE (gst_omx_video_enc_gop_mode_get_type ())
+static GType
+gst_omx_video_enc_gop_mode_get_type (void)
+{
+ static GType qtype = 0;
+
+ if (qtype == 0) {
+ static const GEnumValue values[] = {
+ {OMX_ALG_GOP_MODE_DEFAULT, "Basic GOP settings", "basic"},
+ {OMX_ALG_GOP_MODE_PYRAMIDAL,
+ "Advanced GOP pattern with hierarchical B-frames", "pyramidal"},
+ {OMX_ALG_GOP_MODE_LOW_DELAY_P, "Single I-frame followed by P-frames only",
+ "low-delay-p"},
+ {OMX_ALG_GOP_MODE_LOW_DELAY_B, "Single I-frame followed by B-frames only",
+ "low-delay-b"},
+ {OMX_ALG_GOP_MODE_ADAPTIVE, "Advanced GOP pattern with adaptive B-frames",
+ "adaptive"},
+ {0, NULL, NULL}
+ };
+
+ qtype = g_enum_register_static ("GstOMXVideoEncGopMode", values);
+ }
+ return qtype;
+}
+
+#define GST_TYPE_OMX_VIDEO_ENC_GDR_MODE (gst_omx_video_enc_gdr_mode_get_type ())
+static GType
+gst_omx_video_enc_gdr_mode_get_type (void)
+{
+ static GType qtype = 0;
+
+ if (qtype == 0) {
+ static const GEnumValue values[] = {
+ {OMX_ALG_GDR_OFF, "No GDR", "disabled"},
+ {OMX_ALG_GDR_VERTICAL,
+ "Gradual refresh using a vertical bar moving from left to right",
+ "vertical"},
+ {OMX_ALG_GDR_HORIZONTAL,
+ "Gradual refresh using a horizontal bar moving from top to bottom",
+ "horizontal"},
+ {0, NULL, NULL}
+ };
+
+ qtype = g_enum_register_static ("GstOMXVideoEncGdrMode", values);
+ }
+ return qtype;
+}
+
+#define GST_TYPE_OMX_VIDEO_ENC_SCALING_LIST (gst_omx_video_enc_scaling_list_get_type ())
+static GType
+gst_omx_video_enc_scaling_list_get_type (void)
+{
+ static GType qtype = 0;
+
+ if (qtype == 0) {
+ static const GEnumValue values[] = {
+ {OMX_ALG_SCL_DEFAULT, "Default scaling list mode", "default"},
+ {OMX_ALG_SCL_FLAT, "Flat scaling list mode", "flat"},
+ {0, NULL, NULL}
+ };
+
+ qtype = g_enum_register_static ("GstOMXVideoEncScalingList", values);
+ }
+ return qtype;
+}
+
+#define GST_TYPE_OMX_VIDEO_ENC_ASPECT_RATIO (gst_omx_video_enc_aspect_ratio_get_type ())
+static GType
+gst_omx_video_enc_aspect_ratio_get_type (void)
+{
+ static GType qtype = 0;
+
+ if (qtype == 0) {
+ static const GEnumValue values[] = {
+ {OMX_ALG_ASPECT_RATIO_AUTO,
+ "4:3 for SD video,16:9 for HD video,unspecified for unknown format",
+ "auto"},
+ {OMX_ALG_ASPECT_RATIO_4_3, "4:3 aspect ratio", "4-3"},
+ {OMX_ALG_ASPECT_RATIO_16_9, "16:9 aspect ratio", "16-9"},
+ {OMX_ALG_ASPECT_RATIO_NONE,
+ "Aspect ratio information is not present in the stream", "none"},
+ {0, NULL, NULL}
+ };
+
+ qtype = g_enum_register_static ("GstOMXVideoEncAspectRatio", values);
+ }
+ return qtype;
+}
+
+#define GST_TYPE_OMX_VIDEO_ENC_ROI_QUALITY (gst_omx_video_enc_roi_quality_type ())
+static GType
+gst_omx_video_enc_roi_quality_type (void)
+{
+ static GType qtype = 0;
+
+ if (qtype == 0) {
+ static const GEnumValue values[] = {
+ {OMX_ALG_ROI_QUALITY_HIGH, "Delta QP of -5", "high"},
+ {OMX_ALG_ROI_QUALITY_MEDIUM, "Delta QP of 0", "medium"},
+ {OMX_ALG_ROI_QUALITY_LOW, "Delta QP of +5", "low"},
+ {OMX_ALG_ROI_QUALITY_DONT_CARE, "Maximum delta QP value", "dont-care"},
+ {0, NULL, NULL}
+ };
+
+ qtype = g_enum_register_static ("GstOMXVideoEncRoiQuality", values);
+ }
+ return qtype;
+}
+#endif
+
+/* prototypes */
+static void gst_omx_video_enc_finalize (GObject * object);
+static void gst_omx_video_enc_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_omx_video_enc_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+
+static GstStateChangeReturn
+gst_omx_video_enc_change_state (GstElement * element,
+ GstStateChange transition);
+
+static gboolean gst_omx_video_enc_open (GstVideoEncoder * encoder);
+static gboolean gst_omx_video_enc_close (GstVideoEncoder * encoder);
+static gboolean gst_omx_video_enc_start (GstVideoEncoder * encoder);
+static gboolean gst_omx_video_enc_stop (GstVideoEncoder * encoder);
+static gboolean gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
+ GstVideoCodecState * state);
+static gboolean gst_omx_video_enc_flush (GstVideoEncoder * encoder);
+static GstFlowReturn gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
+ GstVideoCodecFrame * frame);
+static gboolean gst_omx_video_enc_finish (GstVideoEncoder * encoder);
+static gboolean gst_omx_video_enc_propose_allocation (GstVideoEncoder * encoder,
+ GstQuery * query);
+static GstCaps *gst_omx_video_enc_getcaps (GstVideoEncoder * encoder,
+ GstCaps * filter);
+static gboolean gst_omx_video_enc_decide_allocation (GstVideoEncoder * encoder,
+ GstQuery * query);
+
+static GstFlowReturn gst_omx_video_enc_drain (GstOMXVideoEnc * self);
+
+static GstFlowReturn gst_omx_video_enc_handle_output_frame (GstOMXVideoEnc *
+ self, GstOMXPort * port, GstOMXBuffer * buf, GstVideoCodecFrame * frame);
+
+static gboolean gst_omx_video_enc_sink_event (GstVideoEncoder * encoder,
+ GstEvent * event);
+
+enum
+{
+ PROP_0,
+ PROP_CONTROL_RATE,
+ PROP_TARGET_BITRATE,
+ PROP_QUANT_I_FRAMES,
+ PROP_QUANT_P_FRAMES,
+ PROP_QUANT_B_FRAMES,
+ PROP_QP_MODE,
+ PROP_MIN_QP,
+ PROP_MAX_QP,
+ PROP_GOP_MODE,
+ PROP_GDR_MODE,
+ PROP_INITIAL_DELAY,
+ PROP_CPB_SIZE,
+ PROP_SCALING_LIST,
+ PROP_LOW_BANDWIDTH,
+ PROP_MAX_BITRATE,
+ PROP_ASPECT_RATIO,
+ PROP_FILLER_DATA,
+ PROP_NUM_SLICES,
+ PROP_SLICE_SIZE,
+ PROP_DEPENDENT_SLICE,
+ PROP_DEFAULT_ROI_QUALITY,
+ PROP_LONGTERM_REF,
+ PROP_LONGTERM_FREQUENCY,
+ PROP_LOOK_AHEAD,
+};
+
+/* FIXME: Better defaults */
+#define GST_OMX_VIDEO_ENC_CONTROL_RATE_DEFAULT (0xffffffff)
+#define GST_OMX_VIDEO_ENC_TARGET_BITRATE_DEFAULT (0xffffffff)
+#define GST_OMX_VIDEO_ENC_QUANT_I_FRAMES_DEFAULT (0xffffffff)
+#define GST_OMX_VIDEO_ENC_QUANT_P_FRAMES_DEFAULT (0xffffffff)
+#define GST_OMX_VIDEO_ENC_QUANT_B_FRAMES_DEFAULT (0xffffffff)
+#define GST_OMX_VIDEO_ENC_QP_MODE_DEFAULT (0xffffffff)
+#define GST_OMX_VIDEO_ENC_MIN_QP_DEFAULT (10)
+#define GST_OMX_VIDEO_ENC_MAX_QP_DEFAULT (51)
+#define GST_OMX_VIDEO_ENC_GOP_MODE_DEFAULT (OMX_ALG_GOP_MODE_DEFAULT)
+#define GST_OMX_VIDEO_ENC_GDR_MODE_DEFAULT (OMX_ALG_GDR_OFF)
+#define GST_OMX_VIDEO_ENC_INITIAL_DELAY_DEFAULT (1500)
+#define GST_OMX_VIDEO_ENC_CPB_SIZE_DEFAULT (3000)
+#define GST_OMX_VIDEO_ENC_SCALING_LIST_DEFAULT (OMX_ALG_SCL_DEFAULT)
+#define GST_OMX_VIDEO_ENC_LOW_BANDWIDTH_DEFAULT (FALSE)
+#define GST_OMX_VIDEO_ENC_MAX_BITRATE_DEFAULT (0xffffffff)
+#define GST_OMX_VIDEO_ENC_ASPECT_RATIO_DEFAULT (OMX_ALG_ASPECT_RATIO_AUTO)
+#define GST_OMX_VIDEO_ENC_FILLER_DATA_DEFAULT (TRUE)
+#define GST_OMX_VIDEO_ENC_NUM_SLICES_DEFAULT (0xffffffff)
+#define GST_OMX_VIDEO_ENC_SLICE_SIZE_DEFAULT (0)
+#define GST_OMX_VIDEO_ENC_DEPENDENT_SLICE_DEFAULT (FALSE)
+#define GST_OMX_VIDEO_ENC_DEFAULT_ROI_QUALITY OMX_ALG_ROI_QUALITY_HIGH
+#define GST_OMX_VIDEO_ENC_LONGTERM_REF_DEFAULT (FALSE)
+#define GST_OMX_VIDEO_ENC_LONGTERM_FREQUENCY_DEFAULT (0)
+#define GST_OMX_VIDEO_ENC_LOOK_AHEAD_DEFAULT (0)
+
+/* ZYNQ_USCALE_PLUS encoder custom events */
+#define OMX_ALG_GST_EVENT_INSERT_LONGTERM "omx-alg/insert-longterm"
+#define OMX_ALG_GST_EVENT_USE_LONGTERM "omx-alg/use-longterm"
+
+/* class initialization */
+#define do_init \
+{ \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_video_enc_debug_category, "omxvideoenc", 0, \
+ "debug category for gst-omx video encoder base class"); \
+ G_IMPLEMENT_INTERFACE (GST_TYPE_PRESET, NULL); \
+}
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstOMXVideoEnc, gst_omx_video_enc,
+ GST_TYPE_VIDEO_ENCODER, do_init);
+
+static void
+gst_omx_video_enc_class_init (GstOMXVideoEncClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstVideoEncoderClass *video_encoder_class = GST_VIDEO_ENCODER_CLASS (klass);
+
+
+ gobject_class->finalize = gst_omx_video_enc_finalize;
+ gobject_class->set_property = gst_omx_video_enc_set_property;
+ gobject_class->get_property = gst_omx_video_enc_get_property;
+
+ g_object_class_install_property (gobject_class, PROP_CONTROL_RATE,
+ g_param_spec_enum ("control-rate", "Control Rate",
+ "Bitrate control method",
+ GST_TYPE_OMX_VIDEO_ENC_CONTROL_RATE,
+ GST_OMX_VIDEO_ENC_CONTROL_RATE_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_TARGET_BITRATE,
+ g_param_spec_uint ("target-bitrate", "Target Bitrate",
+ "Target bitrate in bits per second (0xffffffff=component default)",
+ 0, G_MAXUINT, GST_OMX_VIDEO_ENC_TARGET_BITRATE_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_PLAYING));
+
+ g_object_class_install_property (gobject_class, PROP_QUANT_I_FRAMES,
+ g_param_spec_uint ("quant-i-frames", "I-Frame Quantization",
+ "Quantization parameter for I-frames (0xffffffff=component default)",
+ 0, G_MAXUINT, GST_OMX_VIDEO_ENC_QUANT_I_FRAMES_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_QUANT_P_FRAMES,
+ g_param_spec_uint ("quant-p-frames", "P-Frame Quantization",
+ "Quantization parameter for P-frames (0xffffffff=component default)",
+ 0, G_MAXUINT, GST_OMX_VIDEO_ENC_QUANT_P_FRAMES_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_QUANT_B_FRAMES,
+ g_param_spec_uint ("quant-b-frames", "B-Frame Quantization",
+ "Quantization parameter for B-frames (0xffffffff=component default)",
+ 0, G_MAXUINT, GST_OMX_VIDEO_ENC_QUANT_B_FRAMES_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ g_object_class_install_property (gobject_class, PROP_QP_MODE,
+ g_param_spec_enum ("qp-mode", "QP mode",
+ "QP control mode used by the VCU encoder",
+ GST_TYPE_OMX_VIDEO_ENC_QP_MODE,
+ GST_OMX_VIDEO_ENC_QP_MODE_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_MIN_QP,
+ g_param_spec_uint ("min-qp", "min Quantization value",
+ "Minimum QP value allowed for the rate control",
+ 0, 51, GST_OMX_VIDEO_ENC_MIN_QP_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_MAX_QP,
+ g_param_spec_uint ("max-qp", "max Quantization value",
+ "Maximum QP value allowed for the rate control",
+ 0, 51, GST_OMX_VIDEO_ENC_MAX_QP_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_GOP_MODE,
+ g_param_spec_enum ("gop-mode", "GOP mode",
+ "Group Of Pictures mode",
+ GST_TYPE_OMX_VIDEO_ENC_GOP_MODE,
+ GST_OMX_VIDEO_ENC_GOP_MODE_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_GDR_MODE,
+ g_param_spec_enum ("gdr-mode", "GDR mode",
+ "Gradual Decoder Refresh scheme mode. Only used if gop-mode=low-delay-p",
+ GST_TYPE_OMX_VIDEO_ENC_GDR_MODE,
+ GST_OMX_VIDEO_ENC_GDR_MODE_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_INITIAL_DELAY,
+ g_param_spec_uint ("initial-delay", "Initial Delay",
+ "The initial removal delay as specified in the HRD model in msec. "
+ "Not used when control-rate=disable",
+ 0, G_MAXUINT, GST_OMX_VIDEO_ENC_INITIAL_DELAY_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_CPB_SIZE,
+ g_param_spec_uint ("cpb-size", "CPB size",
+ "Coded Picture Buffer as specified in the HRD model in msec. "
+ "Not used when control-rate=disable",
+ 0, G_MAXUINT, GST_OMX_VIDEO_ENC_CPB_SIZE_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_SCALING_LIST,
+ g_param_spec_enum ("scaling-list", "Scaling List",
+ "Scaling list mode",
+ GST_TYPE_OMX_VIDEO_ENC_SCALING_LIST,
+ GST_OMX_VIDEO_ENC_SCALING_LIST_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_LOW_BANDWIDTH,
+ g_param_spec_boolean ("low-bandwidth", "Low bandwidth mode",
+ "If enabled, decrease the vertical search range "
+ "used for P-frame motion estimation to reduce the bandwidth",
+ GST_OMX_VIDEO_ENC_LOW_BANDWIDTH_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_MAX_BITRATE,
+ g_param_spec_uint ("max-bitrate", "Max Bitrate",
+ "Max bitrate in bits per second, only used if control-rate=variable (0xffffffff=component default)",
+ 0, G_MAXUINT, GST_OMX_VIDEO_ENC_MAX_BITRATE_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_ASPECT_RATIO,
+ g_param_spec_enum ("aspect-ratio", "Aspect ratio",
+ "Display aspect ratio of the video sequence to be written in SPS/VUI",
+ GST_TYPE_OMX_VIDEO_ENC_ASPECT_RATIO,
+ GST_OMX_VIDEO_ENC_ASPECT_RATIO_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_FILLER_DATA,
+ g_param_spec_boolean ("filler-data", "Filler Data",
+ "Enable/Disable Filler Data NAL units for CBR rate control",
+ GST_OMX_VIDEO_ENC_FILLER_DATA_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_NUM_SLICES,
+ g_param_spec_uint ("num-slices", "Number of slices",
+ "Number of slices produced for each frame. Each slice contains one or more complete macroblock/CTU row(s). "
+ "Slices are distributed over the frame as regularly as possible. If slice-size is defined as well more slices "
+ "may be produced to fit the slice-size requirement (0xffffffff=component default)",
+ 1, G_MAXUINT, GST_OMX_VIDEO_ENC_NUM_SLICES_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_SLICE_SIZE,
+ g_param_spec_uint ("slice-size", "Target slice size",
+ "Target slice size (in bytes) that the encoder uses to "
+ "automatically split the bitstream into approximately equally-sized slices",
+ 0, 65535, GST_OMX_VIDEO_ENC_SLICE_SIZE_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_DEPENDENT_SLICE,
+ g_param_spec_boolean ("dependent-slice", "Dependent slice",
+ "If encoding with multiple slices, specify whether the additional slices are "
+ "dependent slice segments or regular slices",
+ GST_OMX_VIDEO_ENC_DEPENDENT_SLICE_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_DEFAULT_ROI_QUALITY,
+ g_param_spec_enum ("default-roi-quality", "Default ROI Qualtiy",
+ "The default quality level to apply to each Region of Interest",
+ GST_TYPE_OMX_VIDEO_ENC_ROI_QUALITY,
+ GST_OMX_VIDEO_ENC_DEFAULT_ROI_QUALITY,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_LONGTERM_REF,
+ g_param_spec_boolean ("long-term-ref", "LongTerm Reference Pictures",
+ "If enabled, encoder accepts dynamically inserting and using long-term reference "
+ "picture events from upstream elements",
+ GST_OMX_VIDEO_ENC_LONGTERM_REF_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_LONGTERM_FREQUENCY,
+ g_param_spec_uint ("long-term-freq", "LongTerm reference frequency",
+ "Periodicity of LongTerm reference picture marking in encoding process "
+ "Units in frames, distance between two consequtive long-term reference pictures",
+ 0, G_MAXUINT, GST_OMX_VIDEO_ENC_LONGTERM_REF_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+
+ g_object_class_install_property (gobject_class, PROP_LOOK_AHEAD,
+ g_param_spec_uint ("look-ahead", "look ahead size",
+ "The number of frames processed ahead of second pass encoding. If smaller than 2, dual pass encoding is disabled",
+ 0, G_MAXUINT, GST_OMX_VIDEO_ENC_LOOK_AHEAD_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ GST_PARAM_MUTABLE_READY));
+#endif
+
+ element_class->change_state =
+ GST_DEBUG_FUNCPTR (gst_omx_video_enc_change_state);
+
+ video_encoder_class->open = GST_DEBUG_FUNCPTR (gst_omx_video_enc_open);
+ video_encoder_class->close = GST_DEBUG_FUNCPTR (gst_omx_video_enc_close);
+ video_encoder_class->start = GST_DEBUG_FUNCPTR (gst_omx_video_enc_start);
+ video_encoder_class->stop = GST_DEBUG_FUNCPTR (gst_omx_video_enc_stop);
+ video_encoder_class->flush = GST_DEBUG_FUNCPTR (gst_omx_video_enc_flush);
+ video_encoder_class->set_format =
+ GST_DEBUG_FUNCPTR (gst_omx_video_enc_set_format);
+ video_encoder_class->handle_frame =
+ GST_DEBUG_FUNCPTR (gst_omx_video_enc_handle_frame);
+ video_encoder_class->finish = GST_DEBUG_FUNCPTR (gst_omx_video_enc_finish);
+ video_encoder_class->propose_allocation =
+ GST_DEBUG_FUNCPTR (gst_omx_video_enc_propose_allocation);
+ video_encoder_class->getcaps = GST_DEBUG_FUNCPTR (gst_omx_video_enc_getcaps);
+ video_encoder_class->sink_event =
+ GST_DEBUG_FUNCPTR (gst_omx_video_enc_sink_event);
+ video_encoder_class->decide_allocation =
+ GST_DEBUG_FUNCPTR (gst_omx_video_enc_decide_allocation);
+
+ klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
+ klass->cdata.default_sink_template_caps =
+ GST_VIDEO_CAPS_MAKE (GST_OMX_VIDEO_ENC_SUPPORTED_FORMATS);
+
+ klass->handle_output_frame =
+ GST_DEBUG_FUNCPTR (gst_omx_video_enc_handle_output_frame);
+}
+
+static void
+gst_omx_video_enc_init (GstOMXVideoEnc * self)
+{
+ self->control_rate = GST_OMX_VIDEO_ENC_CONTROL_RATE_DEFAULT;
+ self->target_bitrate = GST_OMX_VIDEO_ENC_TARGET_BITRATE_DEFAULT;
+ self->quant_i_frames = GST_OMX_VIDEO_ENC_QUANT_I_FRAMES_DEFAULT;
+ self->quant_p_frames = GST_OMX_VIDEO_ENC_QUANT_P_FRAMES_DEFAULT;
+ self->quant_b_frames = GST_OMX_VIDEO_ENC_QUANT_B_FRAMES_DEFAULT;
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ self->qp_mode = GST_OMX_VIDEO_ENC_QP_MODE_DEFAULT;
+ self->min_qp = GST_OMX_VIDEO_ENC_MIN_QP_DEFAULT;
+ self->max_qp = GST_OMX_VIDEO_ENC_MAX_QP_DEFAULT;
+ self->gop_mode = GST_OMX_VIDEO_ENC_GOP_MODE_DEFAULT;
+ self->gdr_mode = GST_OMX_VIDEO_ENC_GDR_MODE_DEFAULT;
+ self->initial_delay = GST_OMX_VIDEO_ENC_INITIAL_DELAY_DEFAULT;
+ self->cpb_size = GST_OMX_VIDEO_ENC_CPB_SIZE_DEFAULT;
+ self->scaling_list = GST_OMX_VIDEO_ENC_SCALING_LIST_DEFAULT;
+ self->low_bandwidth = GST_OMX_VIDEO_ENC_LOW_BANDWIDTH_DEFAULT;
+ self->max_bitrate = GST_OMX_VIDEO_ENC_MAX_BITRATE_DEFAULT;
+ self->aspect_ratio = GST_OMX_VIDEO_ENC_ASPECT_RATIO_DEFAULT;
+ self->filler_data = GST_OMX_VIDEO_ENC_FILLER_DATA_DEFAULT;
+ self->num_slices = GST_OMX_VIDEO_ENC_NUM_SLICES_DEFAULT;
+ self->slice_size = GST_OMX_VIDEO_ENC_SLICE_SIZE_DEFAULT;
+ self->dependent_slice = GST_OMX_VIDEO_ENC_DEPENDENT_SLICE_DEFAULT;
+ self->default_roi_quality = GST_OMX_VIDEO_ENC_DEFAULT_ROI_QUALITY;
+ self->long_term_ref = GST_OMX_VIDEO_ENC_LONGTERM_REF_DEFAULT;
+ self->long_term_freq = GST_OMX_VIDEO_ENC_LONGTERM_FREQUENCY_DEFAULT;
+ self->look_ahead = GST_OMX_VIDEO_ENC_LOOK_AHEAD_DEFAULT;
+#endif
+
+ self->default_target_bitrate = GST_OMX_PROP_OMX_DEFAULT;
+
+ g_mutex_init (&self->drain_lock);
+ g_cond_init (&self->drain_cond);
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ self->alg_roi_quality_enum_class =
+ g_type_class_ref (GST_TYPE_OMX_VIDEO_ENC_ROI_QUALITY);
+#endif
+}
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+
+#define CHECK_ERR(setting) \
+ if (err == OMX_ErrorUnsupportedIndex || err == OMX_ErrorUnsupportedSetting) { \
+ GST_WARNING_OBJECT (self, \
+ "Setting " setting " parameters not supported by the component"); \
+ } else if (err != OMX_ErrorNone) { \
+ GST_ERROR_OBJECT (self, \
+ "Failed to set " setting " parameters: %s (0x%08x)", \
+ gst_omx_error_to_string (err), err); \
+ return FALSE; \
+ }
+
+static gboolean
+set_zynqultrascaleplus_props (GstOMXVideoEnc * self)
+{
+ OMX_ERRORTYPE err;
+ OMX_ALG_VIDEO_PARAM_QUANTIZATION_CONTROL quant;
+ OMX_ALG_VIDEO_PARAM_QUANTIZATION_TABLE quant_table;
+
+ if (self->qp_mode != GST_OMX_VIDEO_ENC_QP_MODE_DEFAULT) {
+ guint32 qp_mode = OMX_ALG_QP_CTRL_NONE;
+ guint32 qp_table = OMX_ALG_QP_TABLE_NONE;
+
+ /* qp_mode should be mapped to combination QUANTIZATION_CONTROL & QUANTIZATION_TABLE Params */
+ switch (self->qp_mode) {
+ case UNIFORM_QP:
+ qp_mode = OMX_ALG_QP_CTRL_NONE;
+ qp_table = OMX_ALG_QP_TABLE_NONE;
+ break;
+ case AUTO_QP:
+ qp_mode = OMX_ALG_QP_CTRL_AUTO;
+ qp_table = OMX_ALG_QP_TABLE_NONE;
+ break;
+ case ROI_QP:
+ qp_mode = OMX_ALG_QP_CTRL_NONE;
+ qp_table = OMX_ALG_QP_TABLE_RELATIVE;
+ break;
+ case LOAD_QP_ABSOLUTE:
+ qp_mode = OMX_ALG_QP_CTRL_NONE;
+ qp_table = OMX_ALG_QP_TABLE_ABSOLUTE;
+ break;
+ case LOAD_QP_RELATIVE:
+ qp_mode = OMX_ALG_QP_CTRL_NONE;
+ qp_table = OMX_ALG_QP_TABLE_RELATIVE;
+ break;
+ default:
+ GST_WARNING_OBJECT (self,
+ "Invalid option. Falling back to Uniform mode");
+ break;
+ }
+
+ GST_OMX_INIT_STRUCT (&quant);
+ quant.nPortIndex = self->enc_out_port->index;
+ quant.eQpControlMode = qp_mode;
+
+ GST_DEBUG_OBJECT (self, "setting QP mode to %d", qp_mode);
+
+ err =
+ gst_omx_component_set_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoQuantizationControl, &quant);
+ CHECK_ERR ("quantization");
+
+ GST_OMX_INIT_STRUCT (&quant_table);
+ quant_table.nPortIndex = self->enc_out_port->index;
+ quant_table.eQpTableMode = qp_table;
+
+ GST_DEBUG_OBJECT (self, "setting QP Table Mode to %d", qp_table);
+
+ err =
+ gst_omx_component_set_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoQuantizationTable, &quant_table);
+ CHECK_ERR ("quantization table");
+ }
+
+ {
+ OMX_ALG_VIDEO_PARAM_QUANTIZATION_EXTENSION qp_values;
+
+ GST_OMX_INIT_STRUCT (&qp_values);
+ qp_values.nPortIndex = self->enc_out_port->index;
+ qp_values.nQpMin = self->min_qp;
+ qp_values.nQpMax = self->max_qp;
+
+ GST_DEBUG_OBJECT (self, "setting min QP as %d and max QP as %d",
+ self->min_qp, self->max_qp);
+
+ err =
+ gst_omx_component_set_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoQuantizationExtension,
+ &qp_values);
+ CHECK_ERR ("min-qp and max-qp");
+ }
+
+ {
+ OMX_ALG_VIDEO_PARAM_GOP_CONTROL gop_mode;
+
+ if (self->gdr_mode != OMX_ALG_GDR_OFF &&
+ self->gop_mode != OMX_ALG_GOP_MODE_LOW_DELAY_P) {
+ GST_ERROR_OBJECT (self,
+ "gdr-mode mode only can be set if gop-mode=low-delay-p");
+ return FALSE;
+ }
+
+ GST_OMX_INIT_STRUCT (&gop_mode);
+ gop_mode.nPortIndex = self->enc_out_port->index;
+ gop_mode.eGopControlMode = self->gop_mode;
+ gop_mode.eGdrMode = self->gdr_mode;
+
+ GST_DEBUG_OBJECT (self, "setting GOP mode to %d and GDR mode to %d",
+ self->gop_mode, self->gdr_mode);
+
+ err =
+ gst_omx_component_set_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoGopControl, &gop_mode);
+ CHECK_ERR ("GOP & GDR");
+ }
+
+ if (self->control_rate != OMX_Video_ControlRateDisable) {
+ if (self->cpb_size < self->initial_delay) {
+ GST_ERROR_OBJECT (self,
+ "cpb-size (%d) cannot be smaller than initial-delay (%d)",
+ self->cpb_size, self->initial_delay);
+ g_critical ("cpb-size (%d) cannot be smaller than initial-delay (%d)",
+ self->cpb_size, self->initial_delay);
+ } else {
+ OMX_ALG_VIDEO_PARAM_CODED_PICTURE_BUFFER cpb;
+
+ GST_OMX_INIT_STRUCT (&cpb);
+ cpb.nPortIndex = self->enc_out_port->index;
+ cpb.nCodedPictureBufferSize = self->cpb_size;
+ cpb.nInitialRemovalDelay = self->initial_delay;
+
+ GST_DEBUG_OBJECT (self, "setting cpb size to %d and initial delay to %d",
+ self->cpb_size, self->initial_delay);
+
+ err =
+ gst_omx_component_set_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoCodedPictureBuffer, &cpb);
+ CHECK_ERR ("cpb size & initial delay");
+ }
+ }
+
+ {
+ OMX_ALG_VIDEO_PARAM_SCALING_LIST scaling_list;
+
+ GST_OMX_INIT_STRUCT (&scaling_list);
+ scaling_list.nPortIndex = self->enc_out_port->index;
+ scaling_list.eScalingListMode = self->scaling_list;
+
+ GST_DEBUG_OBJECT (self, "setting scaling list mode as %d",
+ self->scaling_list);
+
+ err =
+ gst_omx_component_set_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoScalingList, &scaling_list);
+ CHECK_ERR ("scaling-list");
+ }
+
+ {
+ OMX_ALG_VIDEO_PARAM_LOW_BANDWIDTH low_bw;
+
+ GST_OMX_INIT_STRUCT (&low_bw);
+ low_bw.nPortIndex = self->enc_out_port->index;
+ low_bw.bEnableLowBandwidth = self->low_bandwidth;
+
+ GST_DEBUG_OBJECT (self, "%s low bandwith moded",
+ self->low_bandwidth ? "Enable" : "Disable");
+
+ err =
+ gst_omx_component_set_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoLowBandwidth, &low_bw);
+ CHECK_ERR ("low-bandwidth");
+ }
+
+ if (self->max_bitrate != GST_OMX_VIDEO_ENC_MAX_BITRATE_DEFAULT) {
+ OMX_ALG_VIDEO_PARAM_MAX_BITRATE max_bitrate;
+
+ GST_OMX_INIT_STRUCT (&max_bitrate);
+ max_bitrate.nPortIndex = self->enc_out_port->index;
+ /* nMaxBitrate is in kbps while max-bitrate is in bps */
+ max_bitrate.nMaxBitrate = self->max_bitrate / 1000;
+
+ GST_DEBUG_OBJECT (self, "setting max bitrate to %d", self->max_bitrate);
+
+ err =
+ gst_omx_component_set_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoMaxBitrate, &max_bitrate);
+ CHECK_ERR ("max-bitrate");
+ }
+
+ {
+ OMX_ALG_VIDEO_PARAM_ASPECT_RATIO aspect_ratio;
+
+ GST_OMX_INIT_STRUCT (&aspect_ratio);
+ aspect_ratio.nPortIndex = self->enc_out_port->index;
+ aspect_ratio.eAspectRatio = self->aspect_ratio;
+
+ GST_DEBUG_OBJECT (self, "setting aspect ratio to %d", self->aspect_ratio);
+
+ err =
+ gst_omx_component_set_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoAspectRatio, &aspect_ratio);
+ CHECK_ERR ("aspect-ratio");
+ }
+
+ {
+ OMX_ALG_VIDEO_PARAM_FILLER_DATA filler_data;
+
+ GST_OMX_INIT_STRUCT (&filler_data);
+ filler_data.nPortIndex = self->enc_out_port->index;
+ filler_data.bDisableFillerData = !(self->filler_data);
+
+ GST_DEBUG_OBJECT (self, "%s filler data",
+ self->filler_data ? "Enable" : "Disable");
+
+ err =
+ gst_omx_component_set_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoFillerData, &filler_data);
+ CHECK_ERR ("filler-data");
+ }
+
+ if (self->num_slices != GST_OMX_VIDEO_ENC_NUM_SLICES_DEFAULT ||
+ self->slice_size != GST_OMX_VIDEO_ENC_SLICE_SIZE_DEFAULT) {
+ OMX_ALG_VIDEO_PARAM_SLICES slices;
+
+ GST_OMX_INIT_STRUCT (&slices);
+ slices.nPortIndex = self->enc_out_port->index;
+
+ err = gst_omx_component_get_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoSlices, &slices);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self, "Error getting slice parameters: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ if (self->num_slices != GST_OMX_VIDEO_ENC_NUM_SLICES_DEFAULT) {
+ slices.nNumSlices = self->num_slices;
+ GST_DEBUG_OBJECT (self,
+ "setting number of slices to %d (dependent slices: %d)",
+ self->num_slices, self->dependent_slice);
+ }
+
+ if (self->slice_size != GST_OMX_VIDEO_ENC_SLICE_SIZE_DEFAULT) {
+ slices.nSlicesSize = self->slice_size;
+ GST_DEBUG_OBJECT (self, "setting slice size to %d (dependent slices: %d)",
+ self->slice_size, self->dependent_slice);
+ }
+
+ slices.bDependentSlices = self->dependent_slice;
+
+ err =
+ gst_omx_component_set_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoSlices, &slices);
+ CHECK_ERR ("slices");
+ }
+
+ {
+ OMX_ALG_VIDEO_PARAM_LONG_TERM longterm;
+ GST_OMX_INIT_STRUCT (&longterm);
+ longterm.nPortIndex = self->enc_out_port->index;
+ longterm.bEnableLongTerm = self->long_term_ref;
+ longterm.nLongTermFrequency = self->long_term_freq;
+
+ GST_DEBUG_OBJECT (self, "setting long-term ref to %d, long-term-freq to %d",
+ self->long_term_ref, self->long_term_freq);
+
+ err =
+ gst_omx_component_set_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoLongTerm, &longterm);
+ CHECK_ERR ("longterm");
+ }
+
+ {
+ OMX_ALG_VIDEO_PARAM_LOOKAHEAD look_ahead;
+
+ GST_OMX_INIT_STRUCT (&look_ahead);
+ look_ahead.nPortIndex = self->enc_in_port->index;
+ look_ahead.nLookAhead = self->look_ahead;
+
+ GST_DEBUG_OBJECT (self, "setting look_ahead to %d", self->look_ahead);
+
+ err =
+ gst_omx_component_set_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoLookAhead, &look_ahead);
+ CHECK_ERR ("look-ahead");
+ }
+
+ return TRUE;
+}
+#endif
+
+static gboolean
+gst_omx_video_enc_set_bitrate (GstOMXVideoEnc * self)
+{
+ OMX_ERRORTYPE err;
+ OMX_VIDEO_PARAM_BITRATETYPE bitrate_param;
+ gboolean result = TRUE;
+
+ GST_OBJECT_LOCK (self);
+
+ GST_OMX_INIT_STRUCT (&bitrate_param);
+ bitrate_param.nPortIndex = self->enc_out_port->index;
+
+ err = gst_omx_component_get_parameter (self->enc,
+ OMX_IndexParamVideoBitrate, &bitrate_param);
+
+ if (err == OMX_ErrorNone) {
+#ifdef USE_OMX_TARGET_RPI
+ /* FIXME: Workaround for RPi returning garbage for this parameter */
+ if (bitrate_param.nVersion.nVersion == 0) {
+ GST_OMX_INIT_STRUCT (&bitrate_param);
+ bitrate_param.nPortIndex = self->enc_out_port->index;
+ }
+#endif
+ if (self->default_target_bitrate == GST_OMX_PROP_OMX_DEFAULT)
+ /* Save the actual OMX default so we can restore it if needed */
+ self->default_target_bitrate = bitrate_param.nTargetBitrate;
+
+ if (self->control_rate != 0xffffffff)
+ bitrate_param.eControlRate = self->control_rate;
+ if (self->target_bitrate != 0xffffffff)
+ bitrate_param.nTargetBitrate = self->target_bitrate;
+ else
+ bitrate_param.nTargetBitrate = self->default_target_bitrate;
+
+ err =
+ gst_omx_component_set_parameter (self->enc,
+ OMX_IndexParamVideoBitrate, &bitrate_param);
+ if (err == OMX_ErrorUnsupportedIndex) {
+ GST_WARNING_OBJECT (self,
+ "Setting a bitrate not supported by the component");
+ } else if (err == OMX_ErrorUnsupportedSetting) {
+ GST_WARNING_OBJECT (self,
+ "Setting bitrate settings %u %u not supported by the component",
+ self->control_rate, self->target_bitrate);
+ } else if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to set bitrate parameters: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ result = FALSE;
+ }
+ } else {
+ GST_ERROR_OBJECT (self, "Failed to get bitrate parameters: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ }
+
+ GST_OBJECT_UNLOCK (self);
+ return result;
+}
+
+static gboolean
+gst_omx_video_enc_open (GstVideoEncoder * encoder)
+{
+ GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (encoder);
+ GstOMXVideoEncClass *klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
+ gint in_port_index, out_port_index;
+
+ self->enc =
+ gst_omx_component_new (GST_OBJECT_CAST (self), klass->cdata.core_name,
+ klass->cdata.component_name, klass->cdata.component_role,
+ klass->cdata.hacks);
+ self->started = FALSE;
+
+ if (!self->enc)
+ return FALSE;
+
+ if (gst_omx_component_get_state (self->enc,
+ GST_CLOCK_TIME_NONE) != OMX_StateLoaded)
+ return FALSE;
+
+ in_port_index = klass->cdata.in_port_index;
+ out_port_index = klass->cdata.out_port_index;
+
+ if (in_port_index == -1 || out_port_index == -1) {
+ OMX_PORT_PARAM_TYPE param;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&param);
+
+ err =
+ gst_omx_component_get_parameter (self->enc, OMX_IndexParamVideoInit,
+ &param);
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self, "Couldn't get port information: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ /* Fallback */
+ in_port_index = 0;
+ out_port_index = 1;
+ } else {
+ GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u",
+ (guint) param.nPorts, (guint) param.nStartPortNumber);
+ in_port_index = param.nStartPortNumber + 0;
+ out_port_index = param.nStartPortNumber + 1;
+ }
+ }
+
+ self->enc_in_port = gst_omx_component_add_port (self->enc, in_port_index);
+ self->enc_out_port = gst_omx_component_add_port (self->enc, out_port_index);
+
+ if (!self->enc_in_port || !self->enc_out_port)
+ return FALSE;
+
+ /* Set properties */
+ {
+ OMX_ERRORTYPE err;
+
+ if (!gst_omx_video_enc_set_bitrate (self))
+ return FALSE;
+
+ if (self->quant_i_frames != 0xffffffff ||
+ self->quant_p_frames != 0xffffffff ||
+ self->quant_b_frames != 0xffffffff) {
+ OMX_VIDEO_PARAM_QUANTIZATIONTYPE quant_param;
+
+ GST_OMX_INIT_STRUCT (&quant_param);
+ quant_param.nPortIndex = self->enc_out_port->index;
+
+ err = gst_omx_component_get_parameter (self->enc,
+ OMX_IndexParamVideoQuantization, &quant_param);
+
+ if (err == OMX_ErrorNone) {
+
+ if (self->quant_i_frames != 0xffffffff)
+ quant_param.nQpI = self->quant_i_frames;
+ if (self->quant_p_frames != 0xffffffff)
+ quant_param.nQpP = self->quant_p_frames;
+ if (self->quant_b_frames != 0xffffffff)
+ quant_param.nQpB = self->quant_b_frames;
+
+ err =
+ gst_omx_component_set_parameter (self->enc,
+ OMX_IndexParamVideoQuantization, &quant_param);
+ if (err == OMX_ErrorUnsupportedIndex) {
+ GST_WARNING_OBJECT (self,
+ "Setting quantization parameters not supported by the component");
+ } else if (err == OMX_ErrorUnsupportedSetting) {
+ GST_WARNING_OBJECT (self,
+ "Setting quantization parameters %u %u %u not supported by the component",
+ self->quant_i_frames, self->quant_p_frames, self->quant_b_frames);
+ } else if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to set quantization parameters: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+ } else {
+ GST_ERROR_OBJECT (self,
+ "Failed to get quantization parameters: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+
+ }
+ }
+ }
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ if (!set_zynqultrascaleplus_props (self))
+ return FALSE;
+#endif
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_enc_deallocate_in_buffers (GstOMXVideoEnc * self)
+{
+ /* Pool will take care of deallocating buffers when deactivated upstream */
+ if (!self->in_pool_used
+ && gst_omx_port_deallocate_buffers (self->enc_in_port) != OMX_ErrorNone)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_enc_shutdown (GstOMXVideoEnc * self)
+{
+ OMX_STATETYPE state;
+
+ GST_DEBUG_OBJECT (self, "Shutting down encoder");
+
+ state = gst_omx_component_get_state (self->enc, 0);
+ if (state > OMX_StateLoaded || state == OMX_StateInvalid) {
+ if (state > OMX_StateIdle) {
+ gst_omx_component_set_state (self->enc, OMX_StateIdle);
+ gst_omx_component_get_state (self->enc, 5 * GST_SECOND);
+ }
+ gst_omx_component_set_state (self->enc, OMX_StateLoaded);
+ gst_omx_video_enc_deallocate_in_buffers (self);
+ gst_omx_port_deallocate_buffers (self->enc_out_port);
+ if (state > OMX_StateLoaded)
+ gst_omx_component_get_state (self->enc, 5 * GST_SECOND);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_enc_close (GstVideoEncoder * encoder)
+{
+ GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (encoder);
+
+ GST_DEBUG_OBJECT (self, "Closing encoder");
+
+ if (!gst_omx_video_enc_shutdown (self))
+ return FALSE;
+
+ self->enc_in_port = NULL;
+ self->enc_out_port = NULL;
+ if (self->enc)
+ gst_omx_component_unref (self->enc);
+ self->enc = NULL;
+
+ self->started = FALSE;
+
+ return TRUE;
+}
+
+static void
+gst_omx_video_enc_finalize (GObject * object)
+{
+ GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (object);
+
+ g_mutex_clear (&self->drain_lock);
+ g_cond_clear (&self->drain_cond);
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ g_clear_pointer (&self->alg_roi_quality_enum_class, g_type_class_unref);
+#endif
+
+ G_OBJECT_CLASS (gst_omx_video_enc_parent_class)->finalize (object);
+}
+
+static void
+gst_omx_video_enc_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (object);
+
+ switch (prop_id) {
+ case PROP_CONTROL_RATE:
+ self->control_rate = g_value_get_enum (value);
+ break;
+ case PROP_TARGET_BITRATE:
+ GST_OBJECT_LOCK (self);
+ self->target_bitrate = g_value_get_uint (value);
+ if (self->enc) {
+ OMX_VIDEO_CONFIG_BITRATETYPE config;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&config);
+ config.nPortIndex = self->enc_out_port->index;
+ config.nEncodeBitrate = self->target_bitrate;
+ err =
+ gst_omx_component_set_config (self->enc,
+ OMX_IndexConfigVideoBitrate, &config);
+ if (err != OMX_ErrorNone)
+ GST_ERROR_OBJECT (self,
+ "Failed to set bitrate parameter: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ }
+ GST_OBJECT_UNLOCK (self);
+ break;
+ case PROP_QUANT_I_FRAMES:
+ self->quant_i_frames = g_value_get_uint (value);
+ break;
+ case PROP_QUANT_P_FRAMES:
+ self->quant_p_frames = g_value_get_uint (value);
+ break;
+ case PROP_QUANT_B_FRAMES:
+ self->quant_b_frames = g_value_get_uint (value);
+ break;
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ case PROP_QP_MODE:
+ self->qp_mode = g_value_get_enum (value);
+ break;
+ case PROP_MIN_QP:
+ self->min_qp = g_value_get_uint (value);
+ break;
+ case PROP_MAX_QP:
+ self->max_qp = g_value_get_uint (value);
+ break;
+ case PROP_GOP_MODE:
+ self->gop_mode = g_value_get_enum (value);
+ break;
+ case PROP_GDR_MODE:
+ self->gdr_mode = g_value_get_enum (value);
+ break;
+ case PROP_INITIAL_DELAY:
+ self->initial_delay = g_value_get_uint (value);
+ break;
+ case PROP_CPB_SIZE:
+ self->cpb_size = g_value_get_uint (value);
+ break;
+ case PROP_SCALING_LIST:
+ self->scaling_list = g_value_get_enum (value);
+ break;
+ case PROP_LOW_BANDWIDTH:
+ self->low_bandwidth = g_value_get_boolean (value);
+ break;
+ case PROP_MAX_BITRATE:
+ self->max_bitrate = g_value_get_uint (value);
+ break;
+ case PROP_ASPECT_RATIO:
+ self->aspect_ratio = g_value_get_enum (value);
+ break;
+ case PROP_FILLER_DATA:
+ self->filler_data = g_value_get_boolean (value);
+ break;
+ case PROP_NUM_SLICES:
+ self->num_slices = g_value_get_uint (value);
+ break;
+ case PROP_SLICE_SIZE:
+ self->slice_size = g_value_get_uint (value);
+ break;
+ case PROP_DEPENDENT_SLICE:
+ self->dependent_slice = g_value_get_boolean (value);
+ break;
+ case PROP_DEFAULT_ROI_QUALITY:
+ self->default_roi_quality = g_value_get_enum (value);
+ break;
+ case PROP_LONGTERM_REF:
+ self->long_term_ref = g_value_get_boolean (value);
+ break;
+ case PROP_LONGTERM_FREQUENCY:
+ self->long_term_freq = g_value_get_uint (value);
+ break;
+ case PROP_LOOK_AHEAD:
+ self->look_ahead = g_value_get_uint (value);
+ break;
+#endif
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_omx_video_enc_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec)
+{
+ GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (object);
+
+ switch (prop_id) {
+ case PROP_CONTROL_RATE:
+ g_value_set_enum (value, self->control_rate);
+ break;
+ case PROP_TARGET_BITRATE:
+ GST_OBJECT_LOCK (self);
+ g_value_set_uint (value, self->target_bitrate);
+ GST_OBJECT_UNLOCK (self);
+ break;
+ case PROP_QUANT_I_FRAMES:
+ g_value_set_uint (value, self->quant_i_frames);
+ break;
+ case PROP_QUANT_P_FRAMES:
+ g_value_set_uint (value, self->quant_p_frames);
+ break;
+ case PROP_QUANT_B_FRAMES:
+ g_value_set_uint (value, self->quant_b_frames);
+ break;
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ case PROP_QP_MODE:
+ g_value_set_enum (value, self->qp_mode);
+ break;
+ case PROP_MIN_QP:
+ g_value_set_uint (value, self->min_qp);
+ break;
+ case PROP_MAX_QP:
+ g_value_set_uint (value, self->max_qp);
+ break;
+ case PROP_GOP_MODE:
+ g_value_set_enum (value, self->gop_mode);
+ break;
+ case PROP_GDR_MODE:
+ g_value_set_enum (value, self->gdr_mode);
+ break;
+ case PROP_INITIAL_DELAY:
+ g_value_set_uint (value, self->initial_delay);
+ break;
+ case PROP_CPB_SIZE:
+ g_value_set_uint (value, self->cpb_size);
+ break;
+ case PROP_SCALING_LIST:
+ g_value_set_enum (value, self->scaling_list);
+ break;
+ case PROP_LOW_BANDWIDTH:
+ g_value_set_boolean (value, self->low_bandwidth);
+ break;
+ case PROP_MAX_BITRATE:
+ g_value_set_uint (value, self->max_bitrate);
+ break;
+ case PROP_ASPECT_RATIO:
+ g_value_set_enum (value, self->aspect_ratio);
+ break;
+ case PROP_FILLER_DATA:
+ g_value_set_boolean (value, self->filler_data);
+ break;
+ case PROP_NUM_SLICES:
+ g_value_set_uint (value, self->num_slices);
+ break;
+ case PROP_SLICE_SIZE:
+ g_value_set_uint (value, self->slice_size);
+ break;
+ case PROP_DEPENDENT_SLICE:
+ g_value_set_boolean (value, self->dependent_slice);
+ break;
+ case PROP_DEFAULT_ROI_QUALITY:
+ g_value_set_enum (value, self->default_roi_quality);
+ break;
+ case PROP_LONGTERM_REF:
+ g_value_set_boolean (value, self->long_term_ref);
+ break;
+ case PROP_LONGTERM_FREQUENCY:
+ g_value_set_uint (value, self->long_term_freq);
+ break;
+ case PROP_LOOK_AHEAD:
+ g_value_set_uint (value, self->look_ahead);
+ break;
+#endif
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GstStateChangeReturn
+gst_omx_video_enc_change_state (GstElement * element, GstStateChange transition)
+{
+ GstOMXVideoEnc *self;
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+
+ g_return_val_if_fail (GST_IS_OMX_VIDEO_ENC (element),
+ GST_STATE_CHANGE_FAILURE);
+ self = GST_OMX_VIDEO_ENC (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ break;
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ self->downstream_flow_ret = GST_FLOW_OK;
+
+ self->draining = FALSE;
+ self->started = FALSE;
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ if (self->enc_in_port)
+ gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, TRUE);
+ if (self->enc_out_port)
+ gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE);
+
+ g_mutex_lock (&self->drain_lock);
+ self->draining = FALSE;
+ g_cond_broadcast (&self->drain_cond);
+ g_mutex_unlock (&self->drain_lock);
+ break;
+ default:
+ break;
+ }
+
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ return ret;
+
+ ret =
+ GST_ELEMENT_CLASS (gst_omx_video_enc_parent_class)->change_state (element,
+ transition);
+
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ return ret;
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ self->downstream_flow_ret = GST_FLOW_FLUSHING;
+ self->started = FALSE;
+ break;
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static gboolean
+get_chroma_info_from_input (GstOMXVideoEnc * self, const gchar ** chroma_format,
+ guint * bit_depth_luma, guint * bit_depth_chroma)
+{
+ switch (self->input_state->info.finfo->format) {
+ case GST_VIDEO_FORMAT_GRAY8:
+ *chroma_format = "4:0:0";
+ *bit_depth_luma = 8;
+ *bit_depth_chroma = 0;
+ break;
+ case GST_VIDEO_FORMAT_I420:
+ case GST_VIDEO_FORMAT_NV12:
+ *chroma_format = "4:2:0";
+ *bit_depth_luma = *bit_depth_chroma = 8;
+ break;
+ case GST_VIDEO_FORMAT_NV16:
+ case GST_VIDEO_FORMAT_YUY2:
+ case GST_VIDEO_FORMAT_YVYU:
+ case GST_VIDEO_FORMAT_UYVY:
+ *chroma_format = "4:2:2";
+ *bit_depth_luma = *bit_depth_chroma = 8;
+ break;
+ case GST_VIDEO_FORMAT_GRAY10_LE32:
+ *chroma_format = "4:0:0";
+ *bit_depth_luma = 10;
+ *bit_depth_chroma = 0;
+ break;
+ case GST_VIDEO_FORMAT_NV12_10LE32:
+ *chroma_format = "4:2:0";
+ *bit_depth_luma = *bit_depth_chroma = 10;
+ break;
+ case GST_VIDEO_FORMAT_NV16_10LE32:
+ *chroma_format = "4:2:2";
+ *bit_depth_luma = *bit_depth_chroma = 10;
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static GstCaps *
+get_output_caps (GstOMXVideoEnc * self)
+{
+ GstOMXVideoEncClass *klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
+ GstCaps *caps;
+ const gchar *chroma_format;
+ guint bit_depth_luma, bit_depth_chroma;
+
+ caps = klass->get_caps (self, self->enc_out_port, self->input_state);
+
+ /* Add chroma info about the encoded stream inferred from the format of the input */
+ if (get_chroma_info_from_input (self, &chroma_format, &bit_depth_luma,
+ &bit_depth_chroma)) {
+ GST_DEBUG_OBJECT (self,
+ "adding chroma info to output caps: %s (luma %d bits) (chroma %d bits)",
+ chroma_format, bit_depth_luma, bit_depth_chroma);
+
+ gst_caps_set_simple (caps, "chroma-format", G_TYPE_STRING, chroma_format,
+ "bit-depth-luma", G_TYPE_UINT, bit_depth_luma,
+ "bit-depth-chroma", G_TYPE_UINT, bit_depth_chroma, NULL);
+ }
+
+ return caps;
+}
+
+static GstFlowReturn
+gst_omx_video_enc_handle_output_frame (GstOMXVideoEnc * self, GstOMXPort * port,
+ GstOMXBuffer * buf, GstVideoCodecFrame * frame)
+{
+ GstOMXVideoEncClass *klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
+ GstFlowReturn flow_ret = GST_FLOW_OK;
+
+ if ((buf->omx_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG)
+ && buf->omx_buf->nFilledLen > 0) {
+ GstVideoCodecState *state;
+ GstBuffer *codec_data;
+ GstMapInfo map = GST_MAP_INFO_INIT;
+ GstCaps *caps;
+
+ GST_DEBUG_OBJECT (self, "Handling codec data");
+
+ caps = get_output_caps (self);
+ codec_data = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
+
+ gst_buffer_map (codec_data, &map, GST_MAP_WRITE);
+ memcpy (map.data,
+ buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+ buf->omx_buf->nFilledLen);
+ gst_buffer_unmap (codec_data, &map);
+ state =
+ gst_video_encoder_set_output_state (GST_VIDEO_ENCODER (self), caps,
+ self->input_state);
+ state->codec_data = codec_data;
+ gst_video_codec_state_unref (state);
+ if (!gst_video_encoder_negotiate (GST_VIDEO_ENCODER (self))) {
+ gst_video_codec_frame_unref (frame);
+ GST_ERROR_OBJECT (self,
+ "Downstream element refused to negotiate codec_data in the caps");
+ return GST_FLOW_NOT_NEGOTIATED;
+ }
+ gst_video_codec_frame_unref (frame);
+ flow_ret = GST_FLOW_OK;
+ } else if (buf->omx_buf->nFilledLen > 0) {
+ GstBuffer *outbuf;
+ GstMapInfo map = GST_MAP_INFO_INIT;
+
+ GST_DEBUG_OBJECT (self, "Handling output data");
+
+ outbuf = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
+
+ gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
+ memcpy (map.data,
+ buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+ buf->omx_buf->nFilledLen);
+ gst_buffer_unmap (outbuf, &map);
+
+ GST_BUFFER_TIMESTAMP (outbuf) =
+ gst_util_uint64_scale (GST_OMX_GET_TICKS (buf->omx_buf->nTimeStamp),
+ GST_SECOND, OMX_TICKS_PER_SECOND);
+ if (buf->omx_buf->nTickCount != 0)
+ GST_BUFFER_DURATION (outbuf) =
+ gst_util_uint64_scale (buf->omx_buf->nTickCount, GST_SECOND,
+ OMX_TICKS_PER_SECOND);
+
+ if ((klass->cdata.hacks & GST_OMX_HACK_SYNCFRAME_FLAG_NOT_USED)
+ || (buf->omx_buf->nFlags & OMX_BUFFERFLAG_SYNCFRAME)) {
+ if (frame)
+ GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
+ else
+ GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
+ } else {
+ if (frame)
+ GST_VIDEO_CODEC_FRAME_UNSET_SYNC_POINT (frame);
+ else
+ GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
+ }
+
+ if (frame) {
+ frame->output_buffer = outbuf;
+ if ((buf->omx_buf->nFlags & OMX_BUFFERFLAG_ENDOFFRAME)
+ || !gst_omx_port_get_subframe (self->enc_out_port)) {
+ flow_ret =
+ gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (self), frame);
+ if (!(buf->omx_buf->nFlags & OMX_BUFFERFLAG_ENDOFFRAME))
+ GST_WARNING_OBJECT (self,
+ "OMX_BUFFERFLAG_ENDOFFRAME is missing in flags 0x%x",
+ (guint) buf->omx_buf->nFlags);
+ } else {
+ flow_ret =
+ gst_video_encoder_finish_subframe (GST_VIDEO_ENCODER (self), frame);
+ gst_video_codec_frame_unref (frame);
+ }
+ } else {
+ GST_ERROR_OBJECT (self, "No corresponding frame found");
+ flow_ret = gst_pad_push (GST_VIDEO_ENCODER_SRC_PAD (self), outbuf);
+ }
+ } else if (frame != NULL) {
+ /* Just ignore empty buffers, don't drop a frame for that */
+ flow_ret = GST_FLOW_OK;
+ gst_video_codec_frame_unref (frame);
+ }
+
+ return flow_ret;
+}
+
+static gboolean
+gst_omx_video_enc_ensure_nb_out_buffers (GstOMXVideoEnc * self)
+{
+ GstOMXVideoEncClass *klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
+ guint extra = 0;
+
+ if (!(klass->cdata.hacks & GST_OMX_HACK_ENSURE_BUFFER_COUNT_ACTUAL))
+ return TRUE;
+
+ /* If dowstream tell us how many buffers it needs allocate as many extra buffers so we won't starve
+ * if it keeps them downstream (like when using dynamic mode). */
+ if (self->nb_downstream_buffers)
+ extra = self->nb_downstream_buffers;
+
+ if (!gst_omx_port_ensure_buffer_count_actual (self->enc_out_port, extra))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_enc_allocate_out_buffers (GstOMXVideoEnc * self)
+{
+ if (gst_omx_port_allocate_buffers (self->enc_out_port) != OMX_ErrorNone)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+gst_omx_video_enc_pause_loop (GstOMXVideoEnc * self, GstFlowReturn flow_ret)
+{
+ g_mutex_lock (&self->drain_lock);
+ if (self->draining) {
+ self->draining = FALSE;
+ g_cond_broadcast (&self->drain_cond);
+ }
+ gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
+ self->downstream_flow_ret = flow_ret;
+ self->started = FALSE;
+ g_mutex_unlock (&self->drain_lock);
+}
+
+static void
+gst_omx_video_enc_loop (GstOMXVideoEnc * self)
+{
+ GstOMXVideoEncClass *klass;
+ GstOMXPort *port = self->enc_out_port;
+ GstOMXBuffer *buf = NULL;
+ GstVideoCodecFrame *frame;
+ GstFlowReturn flow_ret = GST_FLOW_OK;
+ GstOMXAcquireBufferReturn acq_return;
+ OMX_ERRORTYPE err;
+
+ klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
+
+ acq_return = gst_omx_port_acquire_buffer (port, &buf, GST_OMX_WAIT);
+ if (acq_return == GST_OMX_ACQUIRE_BUFFER_ERROR) {
+ goto component_error;
+ } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
+ goto flushing;
+ } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_EOS) {
+ goto eos;
+ }
+
+ if (!gst_pad_has_current_caps (GST_VIDEO_ENCODER_SRC_PAD (self))
+ || acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+ GstCaps *caps;
+ GstVideoCodecState *state;
+
+ GST_DEBUG_OBJECT (self, "Port settings have changed, updating caps");
+
+ if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE
+ && gst_omx_port_is_enabled (port)) {
+ /* Reallocate all buffers */
+ err = gst_omx_port_set_enabled (port, FALSE);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_wait_buffers_released (port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_deallocate_buffers (port);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_wait_enabled (port, 1 * GST_SECOND);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+ }
+
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+
+ caps = get_output_caps (self);
+ if (!caps) {
+ if (buf)
+ gst_omx_port_release_buffer (self->enc_out_port, buf);
+ GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
+ goto caps_failed;
+ }
+
+ GST_DEBUG_OBJECT (self, "Setting output state: %" GST_PTR_FORMAT, caps);
+
+ state =
+ gst_video_encoder_set_output_state (GST_VIDEO_ENCODER (self), caps,
+ self->input_state);
+ gst_video_codec_state_unref (state);
+
+ if (!gst_video_encoder_negotiate (GST_VIDEO_ENCODER (self))) {
+ if (buf)
+ gst_omx_port_release_buffer (self->enc_out_port, buf);
+ GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
+ goto caps_failed;
+ }
+
+ GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
+
+ if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+ if (!gst_omx_video_enc_ensure_nb_out_buffers (self))
+ goto reconfigure_error;
+
+ err = gst_omx_port_set_enabled (port, TRUE);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ if (!gst_omx_video_enc_allocate_out_buffers (self))
+ goto reconfigure_error;
+
+ err = gst_omx_port_wait_enabled (port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_populate (port);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+
+ err = gst_omx_port_mark_reconfigured (port);
+ if (err != OMX_ErrorNone)
+ goto reconfigure_error;
+ }
+
+ /* Now get a buffer */
+ if (acq_return != GST_OMX_ACQUIRE_BUFFER_OK) {
+ return;
+ }
+ }
+
+ g_assert (acq_return == GST_OMX_ACQUIRE_BUFFER_OK);
+
+ /* This prevents a deadlock between the srcpad stream
+ * lock and the videocodec stream lock, if ::flush()
+ * is called at the wrong time
+ */
+ if (gst_omx_port_is_flushing (self->enc_out_port)) {
+ GST_DEBUG_OBJECT (self, "Flushing");
+ gst_omx_port_release_buffer (self->enc_out_port, buf);
+ goto flushing;
+ }
+
+ GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x (%s) %" G_GUINT64_FORMAT,
+ (guint) buf->omx_buf->nFlags,
+ gst_omx_buffer_flags_to_string (buf->omx_buf->nFlags),
+ (guint64) GST_OMX_GET_TICKS (buf->omx_buf->nTimeStamp));
+
+ frame = gst_omx_video_find_nearest_frame (GST_ELEMENT_CAST (self), buf,
+ gst_video_encoder_get_frames (GST_VIDEO_ENCODER (self)));
+
+ g_assert (klass->handle_output_frame);
+
+ if (frame)
+ flow_ret =
+ klass->handle_output_frame (self, self->enc_out_port, buf, frame);
+ else {
+ gst_omx_port_release_buffer (self->enc_out_port, buf);
+ goto flow_error;
+ }
+
+
+ GST_DEBUG_OBJECT (self, "Finished frame: %s", gst_flow_get_name (flow_ret));
+
+ err = gst_omx_port_release_buffer (port, buf);
+ if (err != OMX_ErrorNone)
+ goto release_error;
+
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+ self->downstream_flow_ret = flow_ret;
+ GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
+
+ GST_DEBUG_OBJECT (self, "Read frame from component");
+
+ if (flow_ret != GST_FLOW_OK)
+ goto flow_error;
+
+ return;
+
+component_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+ ("OpenMAX component in error state %s (0x%08x)",
+ gst_omx_component_get_last_error_string (self->enc),
+ gst_omx_component_get_last_error (self->enc)));
+ gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
+ gst_omx_video_enc_pause_loop (self, GST_FLOW_ERROR);
+ return;
+ }
+flushing:
+ {
+ GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
+ gst_omx_video_enc_pause_loop (self, GST_FLOW_FLUSHING);
+ return;
+ }
+
+eos:
+ {
+ g_mutex_lock (&self->drain_lock);
+ if (self->draining) {
+ GST_DEBUG_OBJECT (self, "Drained");
+ self->draining = FALSE;
+ g_cond_broadcast (&self->drain_cond);
+ flow_ret = GST_FLOW_OK;
+ gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
+ } else {
+ GST_DEBUG_OBJECT (self, "Component signalled EOS");
+ flow_ret = GST_FLOW_EOS;
+ }
+ g_mutex_unlock (&self->drain_lock);
+
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+ self->downstream_flow_ret = flow_ret;
+ GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
+
+ /* Here we fallback and pause the task for the EOS case */
+ if (flow_ret != GST_FLOW_OK)
+ goto flow_error;
+
+ return;
+ }
+flow_error:
+ {
+ if (flow_ret == GST_FLOW_EOS) {
+ GST_DEBUG_OBJECT (self, "EOS");
+
+ gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self),
+ gst_event_new_eos ());
+ } else if (flow_ret < GST_FLOW_EOS) {
+ GST_ELEMENT_ERROR (self, STREAM, FAILED, ("Internal data stream error."),
+ ("stream stopped, reason %s", gst_flow_get_name (flow_ret)));
+
+ gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self),
+ gst_event_new_eos ());
+ } else if (flow_ret == GST_FLOW_FLUSHING) {
+ GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
+ }
+ gst_omx_video_enc_pause_loop (self, flow_ret);
+ return;
+ }
+reconfigure_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Unable to reconfigure output port"));
+ gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
+ gst_omx_video_enc_pause_loop (self, GST_FLOW_NOT_NEGOTIATED);
+ return;
+ }
+caps_failed:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL), ("Failed to set caps"));
+ gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
+ gst_omx_video_enc_pause_loop (self, GST_FLOW_NOT_NEGOTIATED);
+ return;
+ }
+release_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Failed to relase output buffer to component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err));
+ gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
+ gst_omx_video_enc_pause_loop (self, GST_FLOW_ERROR);
+ return;
+ }
+}
+
+static gboolean
+gst_omx_video_enc_start (GstVideoEncoder * encoder)
+{
+ GstOMXVideoEnc *self;
+
+ self = GST_OMX_VIDEO_ENC (encoder);
+
+ self->last_upstream_ts = 0;
+ self->downstream_flow_ret = GST_FLOW_OK;
+ self->nb_downstream_buffers = 0;
+ self->in_pool_used = FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_enc_stop (GstVideoEncoder * encoder)
+{
+ GstOMXVideoEnc *self;
+
+ self = GST_OMX_VIDEO_ENC (encoder);
+
+ GST_DEBUG_OBJECT (self, "Stopping encoder");
+
+ gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, TRUE);
+ gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE);
+
+ gst_pad_stop_task (GST_VIDEO_ENCODER_SRC_PAD (encoder));
+
+ if (gst_omx_component_get_state (self->enc, 0) > OMX_StateIdle)
+ gst_omx_component_set_state (self->enc, OMX_StateIdle);
+
+ self->downstream_flow_ret = GST_FLOW_FLUSHING;
+ self->started = FALSE;
+
+ if (self->input_state)
+ gst_video_codec_state_unref (self->input_state);
+ self->input_state = NULL;
+
+ g_mutex_lock (&self->drain_lock);
+ self->draining = FALSE;
+ g_cond_broadcast (&self->drain_cond);
+ g_mutex_unlock (&self->drain_lock);
+
+ self->default_target_bitrate = GST_OMX_PROP_OMX_DEFAULT;
+
+ gst_omx_component_get_state (self->enc, 5 * GST_SECOND);
+
+ return TRUE;
+}
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+static void
+gst_omx_video_enc_set_latency (GstOMXVideoEnc * self)
+{
+ GstClockTime latency;
+ OMX_ALG_PARAM_REPORTED_LATENCY param;
+ OMX_ERRORTYPE err;
+
+ GST_OMX_INIT_STRUCT (&param);
+ err =
+ gst_omx_component_get_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamReportedLatency, &param);
+
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self, "Couldn't retrieve latency: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return;
+ }
+
+ GST_DEBUG_OBJECT (self, "retrieved latency of %d ms",
+ (guint32) param.nLatency);
+
+ /* Convert to ns */
+ latency = param.nLatency * GST_MSECOND;
+
+ gst_video_encoder_set_latency (GST_VIDEO_ENCODER (self), latency, latency);
+}
+#endif
+
+static gboolean
+gst_omx_video_enc_disable (GstOMXVideoEnc * self)
+{
+ GstOMXVideoEncClass *klass;
+
+ klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
+
+ GST_DEBUG_OBJECT (self, "Need to disable and drain encoder");
+ gst_omx_video_enc_drain (self);
+ gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE);
+
+ /* Wait until the srcpad loop is finished,
+ * unlock GST_VIDEO_ENCODER_STREAM_LOCK to prevent deadlocks
+ * caused by using this lock from inside the loop function */
+ GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
+ gst_pad_stop_task (GST_VIDEO_ENCODER_SRC_PAD (self));
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+
+ if (klass->cdata.hacks & GST_OMX_HACK_NO_COMPONENT_RECONFIGURE) {
+ GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
+ gst_omx_video_enc_stop (GST_VIDEO_ENCODER (self));
+ gst_omx_video_enc_close (GST_VIDEO_ENCODER (self));
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+
+ if (!gst_omx_video_enc_open (GST_VIDEO_ENCODER (self)))
+ return FALSE;
+
+ /* The decoder is returned to initial state */
+ self->disabled = FALSE;
+ } else {
+ /* Disabling at the same time input port and output port is only
+ * required when a buffer is shared between the ports. This cannot
+ * be the case for a encoder because its input and output buffers
+ * are of different nature. So let's disable ports sequencially.
+ * Starting from IL 1.2.0, this point has been clarified.
+ * OMX_SendCommand will return an error if the IL client attempts to
+ * call it when there is already an on-going command being processed.
+ * The exception is for buffer sharing above and the event
+ * OMX_EventPortNeedsDisable will be sent to request disabling the
+ * other port at the same time. */
+ if (gst_omx_port_set_enabled (self->enc_in_port, FALSE) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_wait_buffers_released (self->enc_in_port,
+ 5 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ if (!gst_omx_video_enc_deallocate_in_buffers (self))
+ return FALSE;
+ if (gst_omx_port_wait_enabled (self->enc_in_port,
+ 1 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+
+ if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_wait_buffers_released (self->enc_out_port,
+ 1 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_deallocate_buffers (self->enc_out_port) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_wait_enabled (self->enc_out_port,
+ 1 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+
+ self->disabled = TRUE;
+ }
+
+ GST_DEBUG_OBJECT (self, "Encoder drained and disabled");
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_enc_configure_input_buffer (GstOMXVideoEnc * self,
+ GstBuffer * input)
+{
+ GstOMXVideoEncClass *klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
+ GstVideoInfo *info = &self->input_state->info;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ GstVideoMeta *meta;
+ guint stride, slice_height;
+
+ gst_omx_port_get_port_definition (self->enc_in_port, &port_def);
+
+ meta = gst_buffer_get_video_meta (input);
+ if (meta) {
+ guint plane_height[GST_VIDEO_MAX_PLANES];
+
+ /* Use the stride and slice height of the first plane */
+ if (!gst_video_meta_get_plane_height (meta, plane_height)) {
+ GST_WARNING_OBJECT (self, "Failed to retrieve plane height from meta");
+ slice_height = GST_VIDEO_INFO_FIELD_HEIGHT (info);
+ } else {
+ slice_height = plane_height[0];
+ }
+
+ stride = meta->stride[0];
+ g_assert (stride != 0);
+
+ GST_DEBUG_OBJECT (self,
+ "adjusting stride (%d) and slice-height (%d) using input buffer meta",
+ stride, slice_height);
+ } else {
+ GST_WARNING_OBJECT (self,
+ "input buffer doesn't provide video meta, can't adjust stride and slice height");
+
+ stride = info->stride[0];
+ slice_height = GST_VIDEO_INFO_FIELD_HEIGHT (info);
+ }
+
+ if (port_def.nBufferAlignment)
+ port_def.format.video.nStride =
+ GST_ROUND_UP_N (stride, port_def.nBufferAlignment);
+ else
+ port_def.format.video.nStride = GST_ROUND_UP_4 (stride); /* safe (?) default */
+
+ if (klass->cdata.hacks & GST_OMX_HACK_HEIGHT_MULTIPLE_16)
+ port_def.format.video.nSliceHeight = GST_ROUND_UP_16 (slice_height);
+ else
+ port_def.format.video.nSliceHeight = slice_height;
+
+ switch (port_def.format.video.eColorFormat) {
+ case OMX_COLOR_FormatYUV420Planar:
+ case OMX_COLOR_FormatYUV420PackedPlanar:
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ /* Formats defined in extensions have their own enum so disable to -Wswitch warning */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wswitch"
+ case OMX_ALG_COLOR_FormatYUV420SemiPlanar10bitPacked:
+#pragma GCC diagnostic pop
+#endif
+ port_def.nBufferSize =
+ (port_def.format.video.nStride * port_def.format.video.nFrameHeight) +
+ 2 * ((port_def.format.video.nStride / 2) *
+ ((port_def.format.video.nFrameHeight + 1) / 2));
+ break;
+
+ case OMX_COLOR_FormatYUV420PackedSemiPlanar:
+ case OMX_COLOR_FormatYUV420SemiPlanar:
+ port_def.nBufferSize =
+ (port_def.format.video.nStride * port_def.format.video.nFrameHeight) +
+ (port_def.format.video.nStride *
+ ((port_def.format.video.nFrameHeight + 1) / 2));
+ break;
+
+ case OMX_COLOR_FormatL8:
+ port_def.nBufferSize =
+ port_def.format.video.nStride * port_def.format.video.nFrameHeight;
+ break;
+
+ case OMX_COLOR_FormatYUV422SemiPlanar:
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ /* Formats defined in extensions have their own enum so disable to -Wswitch warning */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wswitch"
+ case OMX_ALG_COLOR_FormatYUV422SemiPlanar10bitPacked:
+#pragma GCC diagnostic pop
+#endif
+ port_def.nBufferSize =
+ (port_def.format.video.nStride * port_def.format.video.nFrameHeight) +
+ 2 * (port_def.format.video.nStride *
+ ((port_def.format.video.nFrameHeight + 1) / 2));
+ break;
+
+ default:
+ GST_ERROR_OBJECT (self, "Unsupported port format %x",
+ port_def.format.video.eColorFormat);
+ g_assert_not_reached ();
+ }
+
+ GST_DEBUG_OBJECT (self,
+ "setting input nStride=%d nSliceHeight=%d nBufferSize=%d (nBufferAlignment=%d)",
+ (guint) port_def.format.video.nStride,
+ (guint) port_def.format.video.nSliceHeight,
+ (guint) port_def.nBufferSize, (guint) port_def.nBufferAlignment);
+
+ if (gst_omx_port_update_port_definition (self->enc_in_port,
+ &port_def) != OMX_ErrorNone)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_enc_ensure_nb_in_buffers (GstOMXVideoEnc * self)
+{
+ GstOMXVideoEncClass *klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
+
+ if ((klass->cdata.hacks & GST_OMX_HACK_ENSURE_BUFFER_COUNT_ACTUAL)) {
+ if (!gst_omx_port_ensure_buffer_count_actual (self->enc_in_port, 0))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_enc_allocate_in_buffers (GstOMXVideoEnc * self)
+{
+ switch (self->input_allocation) {
+ case GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER:
+ if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
+ return FALSE;
+ break;
+ case GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC:
+ if (gst_omx_port_use_dynamic_buffers (self->enc_in_port) != OMX_ErrorNone)
+ return FALSE;
+ break;
+ case GST_OMX_BUFFER_ALLOCATION_USE_BUFFER:
+ default:
+ /* Not supported */
+ g_return_val_if_reached (FALSE);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+check_input_alignment (GstOMXVideoEnc * self, GstMapInfo * map)
+{
+ OMX_PARAM_PORTDEFINITIONTYPE *port_def = &self->enc_in_port->port_def;
+
+ if (map->size != port_def->nBufferSize) {
+ GST_DEBUG_OBJECT (self,
+ "input buffer has wrong size/stride (%" G_GSIZE_FORMAT
+ " expected: %u), can't use dynamic allocation",
+ map->size, (guint32) port_def->nBufferSize);
+ return FALSE;
+ }
+
+ if (port_def->nBufferAlignment &&
+ (GPOINTER_TO_UINT (map->data) & (port_def->nBufferAlignment - 1)) != 0) {
+ GST_DEBUG_OBJECT (self,
+ "input buffer is not properly aligned (address: %p alignment: %u bytes), can't use dynamic allocation",
+ map->data, (guint32) port_def->nBufferAlignment);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Check if @inbuf's alignment and stride matches the requirements to use the
+ * dynamic buffer mode. */
+static gboolean
+can_use_dynamic_buffer_mode (GstOMXVideoEnc * self, GstBuffer * inbuf)
+{
+ GstMapInfo map;
+ gboolean result = FALSE;
+
+ if (gst_buffer_n_memory (inbuf) > 1) {
+ GST_DEBUG_OBJECT (self,
+ "input buffer contains more than one memory, can't use dynamic allocation");
+ return FALSE;
+ }
+
+ if (!gst_buffer_map (inbuf, &map, GST_MAP_READ)) {
+ GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL),
+ ("failed to map input buffer"));
+ return FALSE;
+ }
+
+ result = check_input_alignment (self, &map);
+
+ gst_buffer_unmap (inbuf, &map);
+ return result;
+}
+
+/* Choose the allocation mode for input buffers depending of what's supported by
+ * the component and the size/alignment of the input buffer. */
+static GstOMXBufferAllocation
+gst_omx_video_enc_pick_input_allocation_mode (GstOMXVideoEnc * self,
+ GstBuffer * inbuf)
+{
+ if (!gst_omx_is_dynamic_allocation_supported ())
+ return GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER;
+
+ if (can_use_dynamic_buffer_mode (self, inbuf)) {
+ GST_DEBUG_OBJECT (self,
+ "input buffer is properly aligned, use dynamic allocation");
+ return GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC;
+ }
+
+ GST_DEBUG_OBJECT (self, "let input buffer allocate its buffers");
+ return GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER;
+}
+
+static gboolean
+gst_omx_video_enc_set_to_idle (GstOMXVideoEnc * self)
+{
+ GstOMXVideoEncClass *klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
+ gboolean no_disable_outport;
+
+ no_disable_outport = klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT;
+
+ if (!no_disable_outport) {
+ /* Disable output port */
+ if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone)
+ return FALSE;
+
+ if (gst_omx_port_wait_enabled (self->enc_out_port,
+ 1 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ }
+
+ if (gst_omx_component_set_state (self->enc, OMX_StateIdle) != OMX_ErrorNone)
+ return FALSE;
+
+ /* Need to allocate buffers to reach Idle state */
+ if (!gst_omx_video_enc_allocate_in_buffers (self))
+ return FALSE;
+
+ if (no_disable_outport) {
+ if (!gst_omx_video_enc_allocate_out_buffers (self))
+ return FALSE;
+ }
+
+ if (gst_omx_component_get_state (self->enc,
+ GST_CLOCK_TIME_NONE) != OMX_StateIdle)
+ return FALSE;
+
+ return TRUE;
+}
+
+static GstOMXBuffer *
+get_omx_buf (GstBuffer * buffer)
+{
+ GstMemory *mem;
+
+ mem = gst_buffer_peek_memory (buffer, 0);
+ return gst_omx_memory_get_omx_buf (mem);
+}
+
+static gboolean
+buffer_is_from_input_pool (GstOMXVideoEnc * self, GstBuffer * buffer)
+{
+ /* Buffer from our input pool will already have a GstOMXBuffer associated
+ * with our input port. */
+ GstOMXBuffer *buf;
+
+ buf = get_omx_buf (buffer);
+ if (!buf)
+ return FALSE;
+
+ return buf->port == self->enc_in_port;
+}
+
+static gboolean
+gst_omx_video_enc_enable (GstOMXVideoEnc * self, GstBuffer * input)
+{
+ GstOMXVideoEncClass *klass;
+
+ klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
+
+ /* Is downstream using our buffer pool? */
+ if (buffer_is_from_input_pool (self, input)) {
+ self->in_pool_used = TRUE;
+ }
+
+ if (!self->in_pool_used) {
+ if (!gst_omx_video_enc_configure_input_buffer (self, input))
+ return FALSE;
+
+ self->input_allocation = gst_omx_video_enc_pick_input_allocation_mode (self,
+ input);
+ self->input_dmabuf = FALSE;
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ if (gst_is_dmabuf_memory (gst_buffer_peek_memory (input, 0))) {
+ if (self->input_allocation ==
+ GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC) {
+ GST_DEBUG_OBJECT (self, "Configure encoder input to import dmabuf");
+ gst_omx_port_set_dmabuf (self->enc_in_port, TRUE);
+ } else {
+ GST_DEBUG_OBJECT (self,
+ "Wrong input allocation mode (%d); dynamic buffers are required to use dmabuf import",
+ self->input_allocation);
+ }
+
+ self->input_dmabuf = TRUE;
+ }
+#endif
+ }
+
+ GST_DEBUG_OBJECT (self, "Enabling component");
+
+ if (!self->in_pool_used) {
+ if (!gst_omx_video_enc_ensure_nb_in_buffers (self))
+ return FALSE;
+ if (!gst_omx_video_enc_ensure_nb_out_buffers (self))
+ return FALSE;
+ }
+
+ if (self->disabled) {
+ if (gst_omx_port_set_enabled (self->enc_in_port, TRUE) != OMX_ErrorNone)
+ return FALSE;
+ if (!gst_omx_video_enc_allocate_in_buffers (self))
+ return FALSE;
+
+ if ((klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
+ if (gst_omx_port_set_enabled (self->enc_out_port, TRUE) != OMX_ErrorNone)
+ return FALSE;
+ if (!gst_omx_video_enc_allocate_out_buffers (self))
+ return FALSE;
+
+ if (gst_omx_port_wait_enabled (self->enc_out_port,
+ 5 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ }
+
+ if (gst_omx_port_wait_enabled (self->enc_in_port,
+ 5 * GST_SECOND) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_mark_reconfigured (self->enc_in_port) != OMX_ErrorNone)
+ return FALSE;
+ } else {
+ /* If the input pool is active we already allocated buffers and set the component to Idle. */
+ if (!self->in_pool_used) {
+ if (!gst_omx_video_enc_set_to_idle (self))
+ return FALSE;
+ }
+
+ if (gst_omx_component_set_state (self->enc,
+ OMX_StateExecuting) != OMX_ErrorNone)
+ return FALSE;
+
+ if (gst_omx_component_get_state (self->enc,
+ GST_CLOCK_TIME_NONE) != OMX_StateExecuting)
+ return FALSE;
+ }
+
+ /* Unset flushing to allow ports to accept data again */
+ gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, FALSE);
+ gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, FALSE);
+
+ if (gst_omx_component_get_last_error (self->enc) != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Component in error state: %s (0x%08x)",
+ gst_omx_component_get_last_error_string (self->enc),
+ gst_omx_component_get_last_error (self->enc));
+ return FALSE;
+ }
+
+ self->disabled = FALSE;
+
+ return TRUE;
+}
+
+/* returns TRUE if only the framerate changed and that framerate could be
+ * updated using OMX_IndexConfigVideoFramerate */
+static gboolean
+gst_omx_video_enc_framerate_changed (GstOMXVideoEnc * self,
+ GstVideoCodecState * state)
+{
+ GstVideoInfo prev_info = self->input_state->info;
+ GstVideoInfo *info = &state->info;
+ GstOMXVideoEncClass *klass;
+
+ klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
+
+ prev_info.fps_n = info->fps_n;
+ prev_info.fps_d = info->fps_d;
+
+ /* if only the framerate changed, try and set the framerate parameter */
+ if (gst_video_info_is_equal (info, &prev_info)) {
+ OMX_CONFIG_FRAMERATETYPE config;
+ OMX_ERRORTYPE err;
+
+ GST_DEBUG_OBJECT (self, "Framerate change detected: %d/%d -> %d/%d",
+ self->input_state->info.fps_n, self->input_state->info.fps_d,
+ info->fps_n, info->fps_d);
+
+ GST_OMX_INIT_STRUCT (&config);
+ config.nPortIndex = self->enc_in_port->index;
+ if (klass->cdata.hacks & GST_OMX_HACK_VIDEO_FRAMERATE_INTEGER) {
+ config.xEncodeFramerate =
+ info->fps_d ? GST_VIDEO_INFO_FIELD_RATE_N (info) / (info->fps_d) : 0;
+ } else {
+ config.xEncodeFramerate = gst_omx_video_calculate_framerate_q16 (info);
+ }
+
+ err = gst_omx_component_set_config (self->enc,
+ OMX_IndexConfigVideoFramerate, &config);
+ if (err == OMX_ErrorNone) {
+ gst_video_codec_state_unref (self->input_state);
+ self->input_state = gst_video_codec_state_ref (state);
+ return TRUE;
+ } else {
+ GST_WARNING_OBJECT (self,
+ "Failed to set framerate configuration: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ /* if changing the rate dynamically didn't work, keep going with a full
+ * encoder reset */
+ }
+ }
+
+ return FALSE;
+}
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+static gboolean
+gst_omx_video_enc_set_interlacing_parameters (GstOMXVideoEnc * self,
+ GstVideoInfo * info)
+{
+ OMX_ERRORTYPE err;
+ OMX_INTERLACEFORMATTYPE interlace_format_param;
+
+ GST_OMX_INIT_STRUCT (&interlace_format_param);
+ interlace_format_param.nPortIndex = self->enc_in_port->index;
+
+ err = gst_omx_component_get_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoInterlaceFormatCurrent,
+ &interlace_format_param);
+
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to get interlace format: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+
+ if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_PROGRESSIVE)
+ interlace_format_param.nFormat = OMX_InterlaceFrameProgressive;
+ else if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_ALTERNATE) {
+ if (GST_VIDEO_INFO_FIELD_ORDER (info) ==
+ GST_VIDEO_FIELD_ORDER_BOTTOM_FIELD_FIRST)
+ interlace_format_param.nFormat =
+ OMX_ALG_InterlaceAlternateBottomFieldFirst;
+ else if (GST_VIDEO_INFO_FIELD_ORDER (info) ==
+ GST_VIDEO_FIELD_ORDER_BOTTOM_FIELD_FIRST)
+ interlace_format_param.nFormat = OMX_ALG_InterlaceAlternateTopFieldFirst;
+ else {
+ GST_INFO_OBJECT (self,
+ "input field-order unspecified, assume top-field-first");
+ interlace_format_param.nFormat = OMX_ALG_InterlaceAlternateTopFieldFirst;
+ }
+ } else {
+ /* Caps templates should ensure this doesn't happen but just to be safe.. */
+ GST_ERROR_OBJECT (self, "Video interlacing mode %s not supported",
+ gst_video_interlace_mode_to_string (info->interlace_mode));
+ return FALSE;
+ }
+
+ err = gst_omx_component_set_parameter (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoInterlaceFormatCurrent,
+ &interlace_format_param);
+
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to set interlacing mode %s (%s) format: %s (0x%08x)",
+ gst_video_interlace_mode_to_string (info->interlace_mode),
+ interlace_format_param.nFormat ==
+ OMX_ALG_InterlaceAlternateTopFieldFirst ? "top-field-first" :
+ "bottom-field-first", gst_omx_error_to_string (err), err);
+ return FALSE;
+ } else {
+ GST_DEBUG_OBJECT (self,
+ "Video interlacing mode %s (%s) set on component",
+ gst_video_interlace_mode_to_string (info->interlace_mode),
+ interlace_format_param.nFormat ==
+ OMX_ALG_InterlaceAlternateTopFieldFirst ? "top-field-first" :
+ "bottom-field-first");
+ }
+
+ return TRUE;
+}
+#endif // USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+
+static gboolean
+gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
+ GstVideoCodecState * state)
+{
+ GstOMXVideoEnc *self;
+ GstOMXVideoEncClass *klass;
+ gboolean needs_disable = FALSE;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+ GstVideoInfo *info = &state->info;
+ GList *negotiation_map = NULL, *l;
+ GstCaps *caps;
+
+ self = GST_OMX_VIDEO_ENC (encoder);
+ klass = GST_OMX_VIDEO_ENC_GET_CLASS (encoder);
+
+ caps = gst_video_info_to_caps (info);
+ GST_DEBUG_OBJECT (self, "Setting new input format: %" GST_PTR_FORMAT, caps);
+ gst_caps_unref (caps);
+
+ gst_omx_port_get_port_definition (self->enc_in_port, &port_def);
+
+ needs_disable =
+ gst_omx_component_get_state (self->enc,
+ GST_CLOCK_TIME_NONE) != OMX_StateLoaded;
+ /* If the component is not in Loaded state and a real format change happens
+ * we have to disable the port and re-allocate all buffers. If no real
+ * format change happened we can just exit here.
+ */
+ if (needs_disable) {
+ if (gst_omx_video_enc_framerate_changed (self, state))
+ return TRUE;
+
+ if (!gst_omx_video_enc_disable (self))
+ return FALSE;
+
+ if (!self->disabled) {
+ /* The local port_def is now obsolete so get it again. */
+ gst_omx_port_get_port_definition (self->enc_in_port, &port_def);
+ }
+ }
+
+ negotiation_map =
+ gst_omx_video_get_supported_colorformats (self->enc_in_port,
+ self->input_state);
+ if (!negotiation_map) {
+ /* Fallback */
+ switch (info->finfo->format) {
+ case GST_VIDEO_FORMAT_I420:
+ port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
+ break;
+ case GST_VIDEO_FORMAT_NV12:
+ port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ break;
+ case GST_VIDEO_FORMAT_NV16:
+ port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV422SemiPlanar;
+ break;
+ case GST_VIDEO_FORMAT_ABGR:
+ port_def.format.video.eColorFormat = OMX_COLOR_Format32bitARGB8888;
+ break;
+ case GST_VIDEO_FORMAT_ARGB:
+ port_def.format.video.eColorFormat = OMX_COLOR_Format32bitBGRA8888;
+ break;
+ default:
+ GST_ERROR_OBJECT (self, "Unsupported format %s",
+ gst_video_format_to_string (info->finfo->format));
+ return FALSE;
+ break;
+ }
+ } else {
+ for (l = negotiation_map; l; l = l->next) {
+ GstOMXVideoNegotiationMap *m = l->data;
+
+ if (m->format == info->finfo->format) {
+ port_def.format.video.eColorFormat = m->type;
+ break;
+ }
+ }
+ g_list_free_full (negotiation_map,
+ (GDestroyNotify) gst_omx_video_negotiation_map_free);
+ }
+
+ port_def.format.video.nFrameWidth = info->width;
+ port_def.format.video.nFrameHeight = GST_VIDEO_INFO_FIELD_HEIGHT (info);
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ if (!gst_omx_video_enc_set_interlacing_parameters (self, info))
+ return FALSE;
+#endif
+
+ if (G_UNLIKELY (klass->cdata.hacks & GST_OMX_HACK_VIDEO_FRAMERATE_INTEGER)) {
+ port_def.format.video.xFramerate =
+ info->fps_d ? GST_VIDEO_INFO_FIELD_RATE_N (info) / (info->fps_d) : 0;
+ } else {
+ port_def.format.video.xFramerate =
+ gst_omx_video_calculate_framerate_q16 (info);
+ }
+
+ GST_DEBUG_OBJECT (self, "Setting inport port definition");
+ if (gst_omx_port_update_port_definition (self->enc_in_port,
+ &port_def) != OMX_ErrorNone)
+ return FALSE;
+
+#ifdef USE_OMX_TARGET_RPI
+ /* aspect ratio */
+ {
+ OMX_ERRORTYPE err;
+ OMX_CONFIG_POINTTYPE aspect_ratio_param;
+
+ GST_OMX_INIT_STRUCT (&aspect_ratio_param);
+ aspect_ratio_param.nPortIndex = self->enc_out_port->index;
+
+ err = gst_omx_component_get_parameter (self->enc,
+ OMX_IndexParamBrcmPixelAspectRatio, &aspect_ratio_param);
+
+ if (err == OMX_ErrorNone) {
+
+ aspect_ratio_param.nX = info->par_n;
+ aspect_ratio_param.nY = info->par_d;
+
+ err =
+ gst_omx_component_set_parameter (self->enc,
+ OMX_IndexParamBrcmPixelAspectRatio, &aspect_ratio_param);
+
+ if (err == OMX_ErrorUnsupportedIndex) {
+ GST_WARNING_OBJECT (self,
+ "Setting aspect ratio parameters not supported by the component");
+ } else if (err == OMX_ErrorUnsupportedSetting) {
+ GST_WARNING_OBJECT (self,
+ "Setting aspect ratio %u %u not supported by the component",
+ aspect_ratio_param.nX, aspect_ratio_param.nY);
+ } else if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self,
+ "Failed to set aspect ratio: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return FALSE;
+ }
+ }
+ }
+#endif // USE_OMX_TARGET_RPI
+
+ if (klass->set_format) {
+ if (!klass->set_format (self, self->enc_in_port, state)) {
+ GST_ERROR_OBJECT (self, "Subclass failed to set the new format");
+ return FALSE;
+ }
+ }
+
+ GST_DEBUG_OBJECT (self, "Updating ports definition");
+ if (gst_omx_port_update_port_definition (self->enc_out_port,
+ NULL) != OMX_ErrorNone)
+ return FALSE;
+ if (gst_omx_port_update_port_definition (self->enc_in_port,
+ NULL) != OMX_ErrorNone)
+ return FALSE;
+
+ /* Some OMX implementations reset the bitrate after setting the compression
+ * format, see bgo#698049, so re-set it */
+ gst_omx_video_enc_set_bitrate (self);
+
+ if (self->input_state)
+ gst_video_codec_state_unref (self->input_state);
+ self->input_state = gst_video_codec_state_ref (state);
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ gst_omx_video_enc_set_latency (self);
+#endif
+
+ self->downstream_flow_ret = GST_FLOW_OK;
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_enc_flush (GstVideoEncoder * encoder)
+{
+ GstOMXVideoEnc *self;
+
+ self = GST_OMX_VIDEO_ENC (encoder);
+
+ GST_DEBUG_OBJECT (self, "Flushing encoder");
+
+ if (gst_omx_component_get_state (self->enc, 0) == OMX_StateLoaded)
+ return TRUE;
+
+ /* 0) Pause the components */
+ if (gst_omx_component_get_state (self->enc, 0) == OMX_StateExecuting) {
+ gst_omx_component_set_state (self->enc, OMX_StatePause);
+ gst_omx_component_get_state (self->enc, GST_CLOCK_TIME_NONE);
+ }
+
+ /* 1) Flush the ports */
+ GST_DEBUG_OBJECT (self, "flushing ports");
+ gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, TRUE);
+ gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE);
+
+ /* Wait until the srcpad loop is finished,
+ * unlock GST_VIDEO_ENCODER_STREAM_LOCK to prevent deadlocks
+ * caused by using this lock from inside the loop function */
+ GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
+ GST_PAD_STREAM_LOCK (GST_VIDEO_ENCODER_SRC_PAD (self));
+ GST_PAD_STREAM_UNLOCK (GST_VIDEO_ENCODER_SRC_PAD (self));
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+
+ /* 3) Resume components */
+ gst_omx_component_set_state (self->enc, OMX_StateExecuting);
+ gst_omx_component_get_state (self->enc, GST_CLOCK_TIME_NONE);
+
+ /* 4) Unset flushing to allow ports to accept data again */
+ gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, FALSE);
+ gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, FALSE);
+ gst_omx_port_populate (self->enc_out_port);
+
+ /* Start the srcpad loop again */
+ self->last_upstream_ts = 0;
+ self->downstream_flow_ret = GST_FLOW_OK;
+ self->started = FALSE;
+ GST_DEBUG_OBJECT (self, "Flush finished");
+
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_enc_copy_plane (GstOMXVideoEnc * self, guint i,
+ GstVideoFrame * frame, GstOMXBuffer * outbuf,
+ const GstVideoFormatInfo * finfo)
+{
+ OMX_PARAM_PORTDEFINITIONTYPE *port_def = &self->enc_in_port->port_def;
+ guint8 *src, *dest;
+ gint src_stride, dest_stride;
+ gint j, height, width;
+
+ src_stride = GST_VIDEO_FRAME_COMP_STRIDE (frame, i);
+ dest_stride = port_def->format.video.nStride;
+ /* XXX: Try this if no stride was set */
+ if (dest_stride == 0)
+ dest_stride = src_stride;
+
+ dest = outbuf->omx_buf->pBuffer + outbuf->omx_buf->nOffset;
+ if (i == 1)
+ dest +=
+ port_def->format.video.nSliceHeight * port_def->format.video.nStride;
+
+ src = GST_VIDEO_FRAME_COMP_DATA (frame, i);
+ height = GST_VIDEO_FRAME_COMP_HEIGHT (frame, i);
+ width = GST_VIDEO_FRAME_COMP_WIDTH (frame, i) * (i == 0 ? 1 : 2);
+
+ if (GST_VIDEO_FORMAT_INFO_BITS (finfo) == 10)
+ /* Need ((width + 2) / 3) 32-bits words */
+ width = (width + 2) / 3 * 4;
+
+ if (dest + dest_stride * height >
+ outbuf->omx_buf->pBuffer + outbuf->omx_buf->nAllocLen) {
+ GST_ERROR_OBJECT (self, "Invalid output buffer size");
+ return FALSE;
+ }
+
+ for (j = 0; j < height; j++) {
+ memcpy (dest, src, width);
+ src += src_stride;
+ dest += dest_stride;
+ }
+
+ /* nFilledLen should include the vertical padding in each slice (spec 3.1.3.7.1) */
+ outbuf->omx_buf->nFilledLen +=
+ GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (finfo, i,
+ port_def->format.video.nSliceHeight) * port_def->format.video.nStride;
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_enc_semi_planar_manual_copy (GstOMXVideoEnc * self,
+ GstBuffer * inbuf, GstOMXBuffer * outbuf, const GstVideoFormatInfo * finfo)
+{
+ GstVideoInfo *info = &self->input_state->info;
+ GstVideoFrame frame;
+ gint i;
+
+ outbuf->omx_buf->nFilledLen = 0;
+
+ if (!gst_video_frame_map (&frame, info, inbuf, GST_MAP_READ)) {
+ GST_ERROR_OBJECT (self, "Invalid input buffer size");
+ return FALSE;
+ }
+
+ for (i = 0; i < 2; i++) {
+ if (!gst_omx_video_enc_copy_plane (self, i, &frame, outbuf, finfo)) {
+ gst_video_frame_unmap (&frame);
+ return FALSE;
+ }
+ }
+
+ gst_video_frame_unmap (&frame);
+ return TRUE;
+}
+
+static gboolean
+gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf,
+ GstOMXBuffer * outbuf)
+{
+ GstVideoCodecState *state = gst_video_codec_state_ref (self->input_state);
+ GstVideoInfo *info = &state->info;
+ OMX_PARAM_PORTDEFINITIONTYPE *port_def = &self->enc_in_port->port_def;
+ gboolean ret = FALSE;
+ GstVideoFrame frame;
+ GstVideoMeta *meta = gst_buffer_get_video_meta (inbuf);
+ gint stride = meta ? meta->stride[0] : info->stride[0];
+
+ if (info->width != port_def->format.video.nFrameWidth ||
+ GST_VIDEO_INFO_FIELD_HEIGHT (info) !=
+ port_def->format.video.nFrameHeight) {
+ GST_ERROR_OBJECT (self, "Width or height do not match");
+ goto done;
+ }
+
+ if (self->enc_in_port->allocation ==
+ GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC) {
+ if (gst_buffer_n_memory (inbuf) > 1) {
+ GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL),
+ ("input buffer now has more than one memory, can't use dynamic allocation any more"));
+ return FALSE;
+ }
+
+ if (!self->input_dmabuf) {
+ /* Map and keep a ref on the buffer while it's being processed
+ * by the OMX component. */
+ if (!gst_omx_buffer_map_frame (outbuf, inbuf, info)) {
+ GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL),
+ ("failed to map input buffer"));
+ return FALSE;
+ }
+
+ if (!check_input_alignment (self, &outbuf->input_frame.map[0])) {
+ GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL),
+ ("input buffer now has wrong alignment/stride, can't use dynamic allocation any more"));
+ return FALSE;
+ }
+
+ GST_LOG_OBJECT (self, "Transfer buffer of %" G_GSIZE_FORMAT " bytes",
+ gst_buffer_get_size (inbuf));
+ } else {
+ /* dmabuf input */
+ if (!gst_omx_buffer_import_fd (outbuf, inbuf)) {
+ GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL),
+ ("failed to import dmabuf"));
+ return FALSE;
+ }
+
+ GST_LOG_OBJECT (self, "Import dmabuf of %" G_GSIZE_FORMAT " bytes",
+ gst_buffer_get_size (inbuf));
+ }
+
+ ret = TRUE;
+ goto done;
+ }
+
+ /* Same strides and everything */
+ if ((gst_buffer_get_size (inbuf) ==
+ outbuf->omx_buf->nAllocLen - outbuf->omx_buf->nOffset) &&
+ (stride == port_def->format.video.nStride)) {
+ outbuf->omx_buf->nFilledLen = gst_buffer_get_size (inbuf);
+
+ GST_LOG_OBJECT (self, "Matched strides - direct copy %u bytes",
+ (guint) outbuf->omx_buf->nFilledLen);
+
+ gst_buffer_extract (inbuf, 0,
+ outbuf->omx_buf->pBuffer + outbuf->omx_buf->nOffset,
+ outbuf->omx_buf->nFilledLen);
+ ret = TRUE;
+ goto done;
+ }
+
+ /* Different strides */
+ GST_LOG_OBJECT (self, "Mismatched strides - copying line-by-line");
+
+ switch (info->finfo->format) {
+ case GST_VIDEO_FORMAT_I420:{
+ gint i, j, height, width;
+ guint8 *src, *dest;
+ gint src_stride, dest_stride;
+
+ outbuf->omx_buf->nFilledLen = 0;
+
+ if (!gst_video_frame_map (&frame, info, inbuf, GST_MAP_READ)) {
+ GST_ERROR_OBJECT (self, "Invalid input buffer size");
+ ret = FALSE;
+ goto done;
+ }
+
+ for (i = 0; i < 3; i++) {
+ if (i == 0) {
+ dest_stride = port_def->format.video.nStride;
+ } else {
+ dest_stride = port_def->format.video.nStride / 2;
+ }
+
+ src_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, i);
+ /* XXX: Try this if no stride was set */
+ if (dest_stride == 0)
+ dest_stride = src_stride;
+
+ dest = outbuf->omx_buf->pBuffer + outbuf->omx_buf->nOffset;
+ if (i > 0)
+ dest +=
+ port_def->format.video.nSliceHeight *
+ port_def->format.video.nStride;
+ if (i == 2)
+ dest +=
+ (port_def->format.video.nSliceHeight / 2) *
+ (port_def->format.video.nStride / 2);
+
+ src = GST_VIDEO_FRAME_COMP_DATA (&frame, i);
+ height = GST_VIDEO_FRAME_COMP_HEIGHT (&frame, i);
+ width = GST_VIDEO_FRAME_COMP_WIDTH (&frame, i);
+
+ if (dest + dest_stride * height >
+ outbuf->omx_buf->pBuffer + outbuf->omx_buf->nAllocLen) {
+ gst_video_frame_unmap (&frame);
+ GST_ERROR_OBJECT (self, "Invalid output buffer size");
+ ret = FALSE;
+ goto done;
+ }
+
+ for (j = 0; j < height; j++) {
+ memcpy (dest, src, width);
+ src += src_stride;
+ dest += dest_stride;
+ }
+
+ /* nFilledLen should include the vertical padding in each slice (spec 3.1.3.7.1) */
+ if (i == 0)
+ outbuf->omx_buf->nFilledLen +=
+ port_def->format.video.nSliceHeight *
+ port_def->format.video.nStride;
+ else
+ outbuf->omx_buf->nFilledLen +=
+ (port_def->format.video.nSliceHeight / 2) *
+ (port_def->format.video.nStride / 2);
+ }
+ gst_video_frame_unmap (&frame);
+ ret = TRUE;
+ break;
+ }
+ case GST_VIDEO_FORMAT_NV12:
+ case GST_VIDEO_FORMAT_NV16:
+ case GST_VIDEO_FORMAT_NV12_10LE32:
+ case GST_VIDEO_FORMAT_NV16_10LE32:
+ ret =
+ gst_omx_video_enc_semi_planar_manual_copy (self, inbuf, outbuf,
+ info->finfo);
+ break;
+ case GST_VIDEO_FORMAT_GRAY8:
+ {
+ if (!gst_video_frame_map (&frame, info, inbuf, GST_MAP_READ)) {
+ GST_ERROR_OBJECT (self, "Failed to map input buffer");
+ ret = FALSE;
+ goto done;
+ }
+
+ ret = gst_omx_video_enc_copy_plane (self, 0, &frame, outbuf, info->finfo);
+ gst_video_frame_unmap (&frame);
+ }
+ break;
+ default:
+ GST_ERROR_OBJECT (self, "Unsupported format");
+ goto done;
+ break;
+ }
+
+done:
+
+ gst_video_codec_state_unref (state);
+
+ return ret;
+}
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+static void
+handle_roi_metadata (GstOMXVideoEnc * self, GstBuffer * input)
+{
+ GstMeta *meta;
+ gpointer state = NULL;
+
+ while ((meta =
+ gst_buffer_iterate_meta_filtered (input, &state,
+ GST_VIDEO_REGION_OF_INTEREST_META_API_TYPE))) {
+ GstVideoRegionOfInterestMeta *roi = (GstVideoRegionOfInterestMeta *) meta;
+ OMX_ALG_VIDEO_CONFIG_REGION_OF_INTEREST roi_param;
+ GstStructure *s;
+
+ GST_LOG_OBJECT (self, "Input buffer ROI: type=%s id=%d (%d, %d) %dx%d",
+ g_quark_to_string (roi->roi_type), roi->id, roi->x, roi->y, roi->w,
+ roi->h);
+
+ if (self->qp_mode != ROI_QP) {
+ GST_WARNING_OBJECT (self,
+ "Need qp-mode=roi to handle ROI metadata (current: %d); ignoring",
+ self->qp_mode);
+ continue;
+ }
+
+ GST_OMX_INIT_STRUCT (&roi_param);
+ roi_param.nPortIndex = self->enc_in_port->index;
+ roi_param.nLeft = roi->x;
+ roi_param.nTop = roi->y;
+ roi_param.nWidth = roi->w;
+ roi_param.nHeight = roi->h;
+
+ s = gst_video_region_of_interest_meta_get_param (roi, "roi/omx-alg");
+ if (s) {
+ const gchar *quality;
+ GEnumValue *evalue;
+
+ quality = gst_structure_get_string (s, "quality");
+
+ evalue =
+ g_enum_get_value_by_nick (self->alg_roi_quality_enum_class, quality);
+ if (!evalue) {
+ roi_param.eQuality = self->default_roi_quality;
+
+ GST_WARNING_OBJECT (self,
+ "Unknown ROI encoding quality '%s', use default (%d)",
+ quality, self->default_roi_quality);
+ } else {
+ roi_param.eQuality = evalue->value;
+
+ GST_LOG_OBJECT (self, "Use encoding quality '%s' from upstream",
+ quality);
+ }
+ } else {
+ roi_param.eQuality = self->default_roi_quality;
+
+ GST_LOG_OBJECT (self, "No quality specified upstream, use default (%d)",
+ self->default_roi_quality);
+ }
+
+ gst_omx_component_set_config (self->enc,
+ (OMX_INDEXTYPE) OMX_ALG_IndexConfigVideoRegionOfInterest, &roi_param);
+ }
+}
+#endif
+
+static GstFlowReturn
+gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
+ GstVideoCodecFrame * frame)
+{
+ GstOMXAcquireBufferReturn acq_ret = GST_OMX_ACQUIRE_BUFFER_ERROR;
+ GstOMXVideoEnc *self;
+ GstOMXPort *port;
+ GstOMXBuffer *buf;
+ OMX_ERRORTYPE err;
+ GstClockTimeDiff deadline;
+
+ self = GST_OMX_VIDEO_ENC (encoder);
+
+ GST_DEBUG_OBJECT (self, "Handling frame");
+
+ if (self->downstream_flow_ret != GST_FLOW_OK) {
+ gst_video_codec_frame_unref (frame);
+ return self->downstream_flow_ret;
+ }
+
+ deadline = gst_video_encoder_get_max_encode_time (encoder, frame);
+ if (deadline < 0) {
+ GST_WARNING_OBJECT (self,
+ "Input frame is too late, dropping (deadline %" GST_TIME_FORMAT ")",
+ GST_TIME_ARGS (-deadline));
+
+ /* Calling finish_frame with frame->output_buffer == NULL will drop it */
+ return gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (self), frame);
+ }
+
+ if (!self->started) {
+ if (gst_omx_port_is_flushing (self->enc_out_port)) {
+ if (!gst_omx_video_enc_enable (self, frame->input_buffer))
+ goto enable_error;
+ }
+
+ GST_DEBUG_OBJECT (self, "Starting task");
+ gst_pad_start_task (GST_VIDEO_ENCODER_SRC_PAD (self),
+ (GstTaskFunction) gst_omx_video_enc_loop, self, NULL);
+ }
+
+ port = self->enc_in_port;
+
+ while (acq_ret != GST_OMX_ACQUIRE_BUFFER_OK) {
+ GstClockTime timestamp, duration;
+ gboolean fill_buffer = TRUE;
+
+ /* Make sure to release the base class stream lock, otherwise
+ * _loop() can't call _finish_frame() and we might block forever
+ * because no input buffers are released */
+ GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
+
+ if (buffer_is_from_input_pool (self, frame->input_buffer)) {
+ /* Receiving a buffer from our input pool */
+ buf = get_omx_buf (frame->input_buffer);
+
+ GST_LOG_OBJECT (self,
+ "Input buffer %p already has a OMX buffer associated: %p",
+ frame->input_buffer, buf);
+
+ g_assert (!buf->input_buffer);
+ /* Prevent the buffer to be released to the pool while it's being
+ * processed by OMX. The reference will be dropped in EmptyBufferDone() */
+ buf->input_buffer = gst_buffer_ref (frame->input_buffer);
+
+ acq_ret = GST_OMX_ACQUIRE_BUFFER_OK;
+ fill_buffer = FALSE;
+ buf->omx_buf->nFilledLen = gst_buffer_get_size (frame->input_buffer);
+ } else {
+ acq_ret = gst_omx_port_acquire_buffer (port, &buf, GST_OMX_WAIT);
+ }
+
+ if (acq_ret == GST_OMX_ACQUIRE_BUFFER_ERROR) {
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+ goto component_error;
+ } else if (acq_ret == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+ goto flushing;
+ } else if (acq_ret == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+ /* Reallocate all buffers */
+ err = gst_omx_port_set_enabled (port, FALSE);
+ if (err != OMX_ErrorNone) {
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_wait_buffers_released (port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_deallocate_buffers (port);
+ if (err != OMX_ErrorNone) {
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_wait_enabled (port, 1 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ if (!gst_omx_video_enc_ensure_nb_in_buffers (self)) {
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_set_enabled (port, TRUE);
+ if (err != OMX_ErrorNone) {
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ if (!gst_omx_video_enc_allocate_in_buffers (self)) {
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_wait_enabled (port, 5 * GST_SECOND);
+ if (err != OMX_ErrorNone) {
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ err = gst_omx_port_mark_reconfigured (port);
+ if (err != OMX_ErrorNone) {
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
+ /* Now get a new buffer and fill it */
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+ continue;
+ }
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+
+ g_assert (acq_ret == GST_OMX_ACQUIRE_BUFFER_OK && buf != NULL);
+
+ if (buf->omx_buf->nAllocLen - buf->omx_buf->nOffset <= 0) {
+ gst_omx_port_release_buffer (port, buf);
+ goto full_buffer;
+ }
+
+ if (self->downstream_flow_ret != GST_FLOW_OK) {
+ gst_omx_port_release_buffer (port, buf);
+ goto flow_error;
+ }
+
+ /* Now handle the frame */
+
+ if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame)) {
+#ifdef USE_OMX_TARGET_RPI
+ OMX_CONFIG_BOOLEANTYPE config;
+
+ GST_OMX_INIT_STRUCT (&config);
+ config.bEnabled = OMX_TRUE;
+
+ GST_DEBUG_OBJECT (self, "Forcing a keyframe (iframe on the RPi)");
+
+ err =
+ gst_omx_component_set_config (self->enc,
+ OMX_IndexConfigBrcmVideoRequestIFrame, &config);
+#elif defined(USE_OMX_TARGET_ZYNQ_USCALE_PLUS)
+ OMX_ALG_VIDEO_CONFIG_INSERT config;
+
+ GST_OMX_INIT_STRUCT (&config);
+ config.nPortIndex = self->enc_out_port->index;
+
+ GST_DEBUG_OBJECT (self, "Forcing a keyframe");
+ err = gst_omx_component_set_config (self->enc, (OMX_INDEXTYPE)
+ OMX_ALG_IndexConfigVideoInsertInstantaneousDecodingRefresh, &config);
+#else
+ OMX_CONFIG_INTRAREFRESHVOPTYPE config;
+
+ GST_OMX_INIT_STRUCT (&config);
+ config.nPortIndex = port->index;
+ config.IntraRefreshVOP = OMX_TRUE;
+
+ GST_DEBUG_OBJECT (self, "Forcing a keyframe");
+ err =
+ gst_omx_component_set_config (self->enc,
+ OMX_IndexConfigVideoIntraVOPRefresh, &config);
+#endif
+ if (err != OMX_ErrorNone)
+ GST_ERROR_OBJECT (self, "Failed to force a keyframe: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ }
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ handle_roi_metadata (self, frame->input_buffer);
+#endif
+
+ /* Copy the buffer content in chunks of size as requested
+ * by the port */
+ if (fill_buffer
+ && !gst_omx_video_enc_fill_buffer (self, frame->input_buffer, buf)) {
+ gst_omx_port_release_buffer (port, buf);
+ goto buffer_fill_error;
+ }
+
+ timestamp = frame->pts;
+ if (timestamp != GST_CLOCK_TIME_NONE) {
+ GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp,
+ gst_util_uint64_scale (timestamp, OMX_TICKS_PER_SECOND, GST_SECOND));
+ self->last_upstream_ts = timestamp;
+ }
+
+ duration = frame->duration;
+ if (duration != GST_CLOCK_TIME_NONE) {
+ buf->omx_buf->nTickCount =
+ gst_util_uint64_scale (duration, OMX_TICKS_PER_SECOND, GST_SECOND);
+ self->last_upstream_ts += duration;
+ } else {
+ buf->omx_buf->nTickCount = 0;
+ }
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ if (GST_VIDEO_BUFFER_IS_TOP_FIELD (frame->input_buffer))
+ buf->omx_buf->nFlags |= OMX_ALG_BUFFERFLAG_TOP_FIELD;
+ else if (GST_VIDEO_BUFFER_IS_BOTTOM_FIELD (frame->input_buffer))
+ buf->omx_buf->nFlags |= OMX_ALG_BUFFERFLAG_BOT_FIELD;
+#endif
+
+ self->started = TRUE;
+ err = gst_omx_port_release_buffer (port, buf);
+ if (err != OMX_ErrorNone)
+ goto release_error;
+
+ GST_DEBUG_OBJECT (self, "Passed frame to component");
+ }
+
+ gst_video_codec_frame_unref (frame);
+
+ return self->downstream_flow_ret;
+
+full_buffer:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+ ("Got OpenMAX buffer with no free space (%p, %u/%u)", buf,
+ (guint) buf->omx_buf->nOffset, (guint) buf->omx_buf->nAllocLen));
+ gst_video_codec_frame_unref (frame);
+ return GST_FLOW_ERROR;
+ }
+
+flow_error:
+ {
+ gst_video_codec_frame_unref (frame);
+ return self->downstream_flow_ret;
+ }
+
+enable_error:
+ {
+ /* Report the OMX error, if any */
+ if (gst_omx_component_get_last_error (self->enc) != OMX_ErrorNone)
+ GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+ ("Failed to enable OMX encoder: %s (0x%08x)",
+ gst_omx_component_get_last_error_string (self->enc),
+ gst_omx_component_get_last_error (self->enc)));
+ else
+ GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+ ("Failed to enable OMX encoder"));
+ gst_video_codec_frame_unref (frame);
+ return GST_FLOW_ERROR;
+ }
+
+component_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+ ("OpenMAX component in error state %s (0x%08x)",
+ gst_omx_component_get_last_error_string (self->enc),
+ gst_omx_component_get_last_error (self->enc)));
+ gst_video_codec_frame_unref (frame);
+ return GST_FLOW_ERROR;
+ }
+
+flushing:
+ {
+ GST_DEBUG_OBJECT (self, "Flushing -- returning FLUSHING");
+ gst_video_codec_frame_unref (frame);
+ return GST_FLOW_FLUSHING;
+ }
+reconfigure_error:
+ {
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Unable to reconfigure input port"));
+ gst_video_codec_frame_unref (frame);
+ return GST_FLOW_ERROR;
+ }
+buffer_fill_error:
+ {
+ GST_ELEMENT_ERROR (self, RESOURCE, WRITE, (NULL),
+ ("Failed to write input into the OpenMAX buffer"));
+ gst_video_codec_frame_unref (frame);
+ return GST_FLOW_ERROR;
+ }
+release_error:
+ {
+ gst_video_codec_frame_unref (frame);
+ GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+ ("Failed to relase input buffer to component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err));
+ return GST_FLOW_ERROR;
+ }
+}
+
+static GstFlowReturn
+gst_omx_video_enc_finish (GstVideoEncoder * encoder)
+{
+ GstOMXVideoEnc *self;
+
+ self = GST_OMX_VIDEO_ENC (encoder);
+
+ return gst_omx_video_enc_drain (self);
+}
+
+static GstFlowReturn
+gst_omx_video_enc_drain (GstOMXVideoEnc * self)
+{
+ GstOMXVideoEncClass *klass;
+ GstOMXBuffer *buf;
+ GstOMXAcquireBufferReturn acq_ret;
+ OMX_ERRORTYPE err;
+
+ GST_DEBUG_OBJECT (self, "Draining component");
+
+ klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
+
+ if (!self->started) {
+ GST_DEBUG_OBJECT (self, "Component not started yet");
+ return GST_FLOW_OK;
+ }
+ self->started = FALSE;
+
+ if ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
+ GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
+ return GST_FLOW_OK;
+ }
+
+ /* Make sure to release the base class stream lock, otherwise
+ * _loop() can't call _finish_frame() and we might block forever
+ * because no input buffers are released */
+ GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
+
+ /* Send an EOS buffer to the component and let the base
+ * class drop the EOS event. We will send it later when
+ * the EOS buffer arrives on the output port. */
+ acq_ret = gst_omx_port_acquire_buffer (self->enc_in_port, &buf, GST_OMX_WAIT);
+ if (acq_ret != GST_OMX_ACQUIRE_BUFFER_OK) {
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+ GST_ERROR_OBJECT (self, "Failed to acquire buffer for draining: %d",
+ acq_ret);
+ return GST_FLOW_ERROR;
+ }
+
+ g_mutex_lock (&self->drain_lock);
+ self->draining = TRUE;
+ buf->omx_buf->nFilledLen = 0;
+ GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp,
+ gst_util_uint64_scale (self->last_upstream_ts, OMX_TICKS_PER_SECOND,
+ GST_SECOND));
+ buf->omx_buf->nTickCount = 0;
+ buf->omx_buf->nFlags |= OMX_BUFFERFLAG_EOS;
+ err = gst_omx_port_release_buffer (self->enc_in_port, buf);
+ if (err != OMX_ErrorNone) {
+ GST_ERROR_OBJECT (self, "Failed to drain component: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ g_mutex_unlock (&self->drain_lock);
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+ return GST_FLOW_ERROR;
+ }
+ GST_DEBUG_OBJECT (self, "Waiting until component is drained");
+ g_cond_wait (&self->drain_cond, &self->drain_lock);
+ GST_DEBUG_OBJECT (self, "Drained component");
+ g_mutex_unlock (&self->drain_lock);
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+
+ self->started = FALSE;
+
+ return GST_FLOW_OK;
+}
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+static gboolean
+pool_request_allocate_cb (GstBufferPool * pool, GstOMXVideoEnc * self)
+{
+ GstStructure *config;
+ guint min;
+
+ gst_omx_port_set_dmabuf (self->enc_in_port, TRUE);
+
+ config = gst_buffer_pool_get_config (pool);
+
+ if (!gst_buffer_pool_config_get_params (config, NULL, NULL, &min, NULL)) {
+ gst_structure_free (config);
+ return FALSE;
+ }
+ gst_structure_free (config);
+
+ GST_DEBUG_OBJECT (self,
+ "input pool configured for %d buffers, adjust nBufferCountActual", min);
+
+ if (!gst_omx_port_update_buffer_count_actual (self->enc_in_port, min))
+ return FALSE;
+
+ if (!gst_omx_video_enc_set_to_idle (self))
+ return FALSE;
+
+ self->input_allocation = GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER;
+ self->input_dmabuf = TRUE;
+
+ /* gst_omx_port_acquire_buffer() will fail if the input port is stil flushing
+ * which will prevent upstream from acquiring buffers. */
+ gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, FALSE);
+
+ return TRUE;
+}
+
+static GstBufferPool *
+create_input_pool (GstOMXVideoEnc * self, GstCaps * caps, guint num_buffers)
+{
+ GstBufferPool *pool;
+ GstStructure *config;
+
+ pool =
+ gst_omx_buffer_pool_new (GST_ELEMENT_CAST (self), self->enc,
+ self->enc_in_port, GST_OMX_BUFFER_MODE_DMABUF);
+
+ g_signal_connect_object (pool, "allocate",
+ G_CALLBACK (pool_request_allocate_cb), self, 0);
+
+ config = gst_buffer_pool_get_config (pool);
+
+ gst_buffer_pool_config_set_params (config, caps,
+ self->enc_in_port->port_def.nBufferSize, num_buffers, 0);
+
+ if (!gst_buffer_pool_set_config (pool, config)) {
+ GST_INFO_OBJECT (self, "Failed to set config on input pool");
+ gst_object_unref (pool);
+ return NULL;
+ }
+
+ return pool;
+}
+#endif
+
+static GstStructure *
+get_allocation_video_meta (GstOMXVideoEnc * self, GstVideoInfo * info)
+{
+ GstStructure *result;
+ GstVideoAlignment align;
+
+ gst_omx_video_get_port_padding (self->enc_in_port, info, &align);
+
+ result = gst_structure_new_empty ("video-meta");
+
+ gst_structure_set (result, "padding-top", G_TYPE_UINT, align.padding_top,
+ "padding-bottom", G_TYPE_UINT, align.padding_bottom,
+ "padding-left", G_TYPE_UINT, align.padding_left,
+ "padding-right", G_TYPE_UINT, align.padding_right, NULL);
+
+ GST_LOG_OBJECT (self, "Request buffer layout to producer: %" GST_PTR_FORMAT,
+ result);
+
+ return result;
+}
+
+static gboolean
+gst_omx_video_enc_propose_allocation (GstVideoEncoder * encoder,
+ GstQuery * query)
+{
+ GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (encoder);
+ guint num_buffers;
+ GstCaps *caps;
+ GstVideoInfo info;
+ GstBufferPool *pool = NULL;
+ GstStructure *params;
+
+ gst_query_parse_allocation (query, &caps, NULL);
+
+ if (!caps) {
+ GST_WARNING_OBJECT (self, "allocation query does not contain caps");
+ return FALSE;
+ }
+
+ if (!gst_video_info_from_caps (&info, caps)) {
+ GST_WARNING_OBJECT (self, "Failed to parse caps %" GST_PTR_FORMAT, caps);
+ return FALSE;
+ }
+
+ params = get_allocation_video_meta (self, &info);
+ gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, params);
+ gst_structure_free (params);
+
+ num_buffers = self->enc_in_port->port_def.nBufferCountMin + 1;
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ /* dmabuf export is currently only supported on Zynqultrascaleplus */
+ pool = create_input_pool (self, caps, num_buffers);
+ if (!pool) {
+ GST_WARNING_OBJECT (self, "Failed to create and configure pool");
+ return FALSE;
+ }
+#endif
+
+ GST_DEBUG_OBJECT (self,
+ "request at least %d buffers of size %d", num_buffers,
+ (guint) self->enc_in_port->port_def.nBufferSize);
+ gst_query_add_allocation_pool (query, pool,
+ self->enc_in_port->port_def.nBufferSize, num_buffers, 0);
+
+ self->in_pool_used = FALSE;
+
+ g_clear_object (&pool);
+
+ return
+ GST_VIDEO_ENCODER_CLASS
+ (gst_omx_video_enc_parent_class)->propose_allocation (encoder, query);
+}
+
+static GList *
+filter_supported_formats (GList * negotiation_map)
+{
+ GList *cur;
+
+ for (cur = negotiation_map; cur != NULL;) {
+ GstOMXVideoNegotiationMap *nmap = (GstOMXVideoNegotiationMap *) (cur->data);
+ GList *next;
+
+ switch (nmap->format) {
+ case GST_VIDEO_FORMAT_I420:
+ case GST_VIDEO_FORMAT_NV12:
+ case GST_VIDEO_FORMAT_NV12_10LE32:
+ case GST_VIDEO_FORMAT_NV16:
+ case GST_VIDEO_FORMAT_NV16_10LE32:
+ case GST_VIDEO_FORMAT_GRAY8:
+ cur = g_list_next (cur);
+ continue;
+ default:
+ gst_omx_video_negotiation_map_free (nmap);
+ next = g_list_next (cur);
+ negotiation_map = g_list_delete_link (negotiation_map, cur);
+ cur = next;
+ }
+ }
+
+ return negotiation_map;
+}
+
+static GstCaps *
+add_interlace_to_caps (GstOMXVideoEnc * self, GstCaps * caps)
+{
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ OMX_ERRORTYPE err;
+ OMX_INTERLACEFORMATTYPE interlace_format_param;
+ GstCaps *caps_alternate;
+
+ if (gst_caps_is_empty (caps))
+ /* No caps to add to */
+ return caps;
+
+ GST_OMX_INIT_STRUCT (&interlace_format_param);
+ interlace_format_param.nPortIndex = self->enc_in_port->index;
+
+ err = gst_omx_component_get_parameter (self->enc,
+ OMX_ALG_IndexParamVideoInterlaceFormatSupported, &interlace_format_param);
+
+ if (err != OMX_ErrorNone) {
+ GST_WARNING_OBJECT (self,
+ "Failed to get OMX_ALG_IndexParamVideoInterlaceFormatSupported %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ return caps;
+ }
+
+ if (!(interlace_format_param.nFormat &
+ OMX_ALG_InterlaceAlternateTopFieldFirst)
+ && !(interlace_format_param.nFormat &
+ OMX_ALG_InterlaceAlternateBottomFieldFirst))
+ return caps;
+
+ /* Alternate mode is supported, create an 'alternate' variant of the caps
+ * with the caps feature. */
+ caps_alternate = gst_caps_copy (caps);
+
+ gst_caps_set_features_simple (caps_alternate,
+ gst_caps_features_new (GST_CAPS_FEATURE_FORMAT_INTERLACED, NULL));
+
+ caps = gst_caps_merge (caps, caps_alternate);
+#endif // USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+
+ return caps;
+}
+
+static GstCaps *
+gst_omx_video_enc_getcaps (GstVideoEncoder * encoder, GstCaps * filter)
+{
+ GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (encoder);
+ GList *negotiation_map = NULL;
+ GstCaps *comp_supported_caps;
+ GstCaps *ret;
+
+ if (!self->enc)
+ return gst_video_encoder_proxy_getcaps (encoder, NULL, filter);
+
+ negotiation_map =
+ gst_omx_video_get_supported_colorformats (self->enc_in_port,
+ self->input_state);
+ negotiation_map = filter_supported_formats (negotiation_map);
+
+ comp_supported_caps = gst_omx_video_get_caps_for_map (negotiation_map);
+ g_list_free_full (negotiation_map,
+ (GDestroyNotify) gst_omx_video_negotiation_map_free);
+
+ comp_supported_caps = add_interlace_to_caps (self, comp_supported_caps);
+
+ if (!gst_caps_is_empty (comp_supported_caps)) {
+ ret =
+ gst_video_encoder_proxy_getcaps (encoder, comp_supported_caps, filter);
+ gst_caps_unref (comp_supported_caps);
+ } else {
+ gst_caps_unref (comp_supported_caps);
+ ret = gst_video_encoder_proxy_getcaps (encoder, NULL, filter);
+ }
+
+ GST_LOG_OBJECT (encoder, "Supported caps %" GST_PTR_FORMAT, ret);
+
+ return ret;
+}
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+static gboolean
+handle_longterm_event (GstOMXVideoEnc * self, GstEvent * event)
+{
+ OMX_ALG_VIDEO_CONFIG_INSERT longterm;
+ OMX_ERRORTYPE err;
+ OMX_INDEXTYPE omx_index_long_term;
+
+ GST_OMX_INIT_STRUCT (&longterm);
+ longterm.nPortIndex = self->enc_in_port->index;
+
+ /* If long-term-ref is enabled then "omx-alg/insert-longterm" event
+ * marks the encoding picture as long term reference picture and
+ * "omx-alg/use-longterm" event informs the encoder that encoding picture
+ * should use existing long term picture in the dpb as reference for encoding process */
+
+ if (self->long_term_ref) {
+ if (gst_event_has_name (event, OMX_ALG_GST_EVENT_INSERT_LONGTERM)) {
+ GST_LOG_OBJECT (self, "received omx-alg/insert-longterm event");
+ omx_index_long_term =
+ (OMX_INDEXTYPE) OMX_ALG_IndexConfigVideoInsertLongTerm;
+ } else {
+ GST_LOG_OBJECT (self, "received omx-alg/use-longterm event");
+ omx_index_long_term = (OMX_INDEXTYPE) OMX_ALG_IndexConfigVideoUseLongTerm;
+ }
+
+ err =
+ gst_omx_component_set_config (self->enc, omx_index_long_term,
+ &longterm);
+
+ if (err != OMX_ErrorNone)
+ GST_ERROR_OBJECT (self,
+ "Failed to longterm events: %s (0x%08x)",
+ gst_omx_error_to_string (err), err);
+ } else {
+ GST_WARNING_OBJECT (self,
+ "LongTerm events are not handled because long_term_ref is disabled");
+ }
+
+ return TRUE;
+}
+#endif
+
+static gboolean
+gst_omx_video_enc_sink_event (GstVideoEncoder * encoder, GstEvent * event)
+{
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_CUSTOM_DOWNSTREAM:
+ {
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (encoder);
+ if (gst_event_has_name (event, OMX_ALG_GST_EVENT_INSERT_LONGTERM)
+ || gst_event_has_name (event, OMX_ALG_GST_EVENT_USE_LONGTERM))
+ return handle_longterm_event (self, event);
+#endif
+ }
+ default:
+ break;
+ }
+
+ return
+ GST_VIDEO_ENCODER_CLASS (gst_omx_video_enc_parent_class)->sink_event
+ (encoder, event);
+}
+
+static gboolean
+gst_omx_video_enc_decide_allocation (GstVideoEncoder * encoder,
+ GstQuery * query)
+{
+ GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (encoder);
+ guint min = 1;
+
+ if (!GST_VIDEO_ENCODER_CLASS
+ (gst_omx_video_enc_parent_class)->decide_allocation (encoder, query))
+ return FALSE;
+
+ if (gst_query_get_n_allocation_pools (query)) {
+ gst_query_parse_nth_allocation_pool (query, 0, NULL, NULL, &min, NULL);
+ GST_DEBUG_OBJECT (self,
+ "Downstream requested %d buffers, adjust number of output buffers accordingly",
+ min);
+ } else {
+ GST_DEBUG_OBJECT (self, "Downstream didn't set any allocation pool info");
+ }
+
+ self->nb_downstream_buffers = min;
+
+ return TRUE;
+}
diff --git a/subprojects/gst-omx/omx/gstomxvideoenc.h b/subprojects/gst-omx/omx/gstomxvideoenc.h
new file mode 100644
index 0000000000..51e2baf4f8
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxvideoenc.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_VIDEO_ENC_H__
+#define __GST_OMX_VIDEO_ENC_H__
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/video/gstvideoencoder.h>
+
+#include "gstomx.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_VIDEO_ENC \
+ (gst_omx_video_enc_get_type())
+#define GST_OMX_VIDEO_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_VIDEO_ENC,GstOMXVideoEnc))
+#define GST_OMX_VIDEO_ENC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_VIDEO_ENC,GstOMXVideoEncClass))
+#define GST_OMX_VIDEO_ENC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_VIDEO_ENC,GstOMXVideoEncClass))
+#define GST_IS_OMX_VIDEO_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_VIDEO_ENC))
+#define GST_IS_OMX_VIDEO_ENC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_VIDEO_ENC))
+
+typedef struct _GstOMXVideoEnc GstOMXVideoEnc;
+typedef struct _GstOMXVideoEncClass GstOMXVideoEncClass;
+
+struct _GstOMXVideoEnc
+{
+ GstVideoEncoder parent;
+
+ /* < protected > */
+ GstOMXComponent *enc;
+ GstOMXPort *enc_in_port, *enc_out_port;
+
+ /* < private > */
+ GstVideoCodecState *input_state;
+ /* TRUE if the component is configured and saw
+ * the first buffer */
+ gboolean started;
+ /* TRUE if the ports where disabled after being activated the first time. */
+ gboolean disabled;
+
+ GstClockTime last_upstream_ts;
+
+ /* Draining state */
+ GMutex drain_lock;
+ GCond drain_cond;
+ /* TRUE if EOS buffers shouldn't be forwarded */
+ gboolean draining; /* protected by drain_lock */
+
+ /* properties */
+ guint32 control_rate;
+ guint32 target_bitrate; /* protected by object lock */
+ guint32 quant_i_frames;
+ guint32 quant_p_frames;
+ guint32 quant_b_frames;
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ guint32 qp_mode;
+ guint32 min_qp;
+ guint32 max_qp;
+ guint32 gop_mode;
+ guint32 gdr_mode;
+ guint32 initial_delay;
+ guint32 cpb_size;
+ guint32 scaling_list;
+ gboolean low_bandwidth;
+ guint32 max_bitrate;
+ guint32 aspect_ratio;
+ gboolean filler_data;
+ guint32 num_slices;
+ guint32 slice_size;
+ gboolean dependent_slice;
+ gint default_roi_quality;
+ gboolean long_term_ref;
+ guint32 long_term_freq;
+ guint32 look_ahead;
+#endif
+
+ guint32 default_target_bitrate;
+
+ GstFlowReturn downstream_flow_ret;
+
+ GstOMXBufferAllocation input_allocation;
+ /* TRUE if encoder is passing dmabuf's fd directly to the OMX component */
+ gboolean input_dmabuf;
+ /* Number of buffers requested downstream */
+ guint nb_downstream_buffers;
+
+ /* TRUE if input buffers are from the pool we proposed to upstream */
+ gboolean in_pool_used;
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ GEnumClass *alg_roi_quality_enum_class;
+#endif
+};
+
+struct _GstOMXVideoEncClass
+{
+ GstVideoEncoderClass parent_class;
+
+ GstOMXClassData cdata;
+
+ gboolean (*set_format) (GstOMXVideoEnc * self, GstOMXPort * port, GstVideoCodecState * state);
+ GstCaps *(*get_caps) (GstOMXVideoEnc * self, GstOMXPort * port, GstVideoCodecState * state);
+ GstFlowReturn (*handle_output_frame) (GstOMXVideoEnc * self, GstOMXPort * port, GstOMXBuffer * buffer, GstVideoCodecFrame * frame);
+};
+
+GType gst_omx_video_enc_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_VIDEO_ENC_H__ */
diff --git a/subprojects/gst-omx/omx/gstomxvp8dec.c b/subprojects/gst-omx/omx/gstomxvp8dec.c
new file mode 100644
index 0000000000..fd2e5acddf
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxvp8dec.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2013, Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxvp8dec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_vp8_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_vp8_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_vp8_dec_is_format_change (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state);
+static gboolean gst_omx_vp8_dec_set_format (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state);
+
+enum
+{
+ PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_vp8_dec_debug_category, "omxvp8dec", 0, \
+ "debug category for gst-omx video decoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXVP8Dec, gst_omx_vp8_dec,
+ GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT);
+
+static void
+gst_omx_vp8_dec_class_init (GstOMXVP8DecClass * klass)
+{
+ GstOMXVideoDecClass *videodec_class = GST_OMX_VIDEO_DEC_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ videodec_class->is_format_change =
+ GST_DEBUG_FUNCPTR (gst_omx_vp8_dec_is_format_change);
+ videodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_vp8_dec_set_format);
+
+ videodec_class->cdata.default_sink_template_caps = "video/x-vp8, "
+ "width=(int) [1,MAX], " "height=(int) [1,MAX]";
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX VP8 Video Decoder",
+ "Codec/Decoder/Video/Hardware",
+ "Decode VP8 video streams",
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+ gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.vp8");
+}
+
+static void
+gst_omx_vp8_dec_init (GstOMXVP8Dec * self)
+{
+}
+
+static gboolean
+gst_omx_vp8_dec_is_format_change (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state)
+{
+ return FALSE;
+}
+
+static gboolean
+gst_omx_vp8_dec_set_format (GstOMXVideoDec * dec, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ gboolean ret;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+
+ gst_omx_port_get_port_definition (port, &port_def);
+ port_def.format.video.eCompressionFormat =
+ (OMX_VIDEO_CODINGTYPE) OMX_VIDEO_CodingVP8;
+ ret = gst_omx_port_update_port_definition (port, &port_def) == OMX_ErrorNone;
+
+ return ret;
+}
diff --git a/subprojects/gst-omx/omx/gstomxvp8dec.h b/subprojects/gst-omx/omx/gstomxvp8dec.h
new file mode 100644
index 0000000000..f99f4cebcb
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxvp8dec.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2013, Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * 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_OMX_VP8_DEC_H__
+#define __GST_OMX_VP8_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_VP8_DEC \
+ (gst_omx_vp8_dec_get_type())
+#define GST_OMX_VP8_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_VP8_DEC,GstOMXVP8Dec))
+#define GST_OMX_VP8_DEC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_VP8_DEC,GstOMXVP8DecClass))
+#define GST_OMX_VP8_DEC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_VP8_DEC,GstOMXVP8DecClass))
+#define GST_IS_OMX_VP8_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_VP8_DEC))
+#define GST_IS_OMX_VP8_DEC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_VP8_DEC))
+
+typedef struct _GstOMXVP8Dec GstOMXVP8Dec;
+typedef struct _GstOMXVP8DecClass GstOMXVP8DecClass;
+
+struct _GstOMXVP8Dec
+{
+ GstOMXVideoDec parent;
+};
+
+struct _GstOMXVP8DecClass
+{
+ GstOMXVideoDecClass parent_class;
+};
+
+GType gst_omx_vp8_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_VP8_DEC_H__ */
+
diff --git a/subprojects/gst-omx/omx/gstomxwmvdec.c b/subprojects/gst-omx/omx/gstomxwmvdec.c
new file mode 100644
index 0000000000..14758275f4
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxwmvdec.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxwmvdec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_wmv_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_wmv_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_wmv_dec_is_format_change (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state);
+static gboolean gst_omx_wmv_dec_set_format (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state);
+
+enum
+{
+ PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+ GST_DEBUG_CATEGORY_INIT (gst_omx_wmv_dec_debug_category, "omxwmvdec", 0, \
+ "debug category for gst-omx video decoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXWMVDec, gst_omx_wmv_dec,
+ GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT);
+
+static void
+gst_omx_wmv_dec_class_init (GstOMXWMVDecClass * klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GstOMXVideoDecClass *videodec_class = GST_OMX_VIDEO_DEC_CLASS (klass);
+
+ videodec_class->is_format_change =
+ GST_DEBUG_FUNCPTR (gst_omx_wmv_dec_is_format_change);
+ videodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_wmv_dec_set_format);
+
+ videodec_class->cdata.default_sink_template_caps = "video/x-wmv, "
+ "width=(int) [1,MAX], " "height=(int) [1,MAX]";
+
+ gst_element_class_set_static_metadata (element_class,
+ "OpenMAX WMV Video Decoder",
+ "Codec/Decoder/Video/Hardware",
+ "Decode WMV video streams",
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+
+ gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.wmv");
+}
+
+static void
+gst_omx_wmv_dec_init (GstOMXWMVDec * self)
+{
+}
+
+static gboolean
+gst_omx_wmv_dec_is_format_change (GstOMXVideoDec * dec,
+ GstOMXPort * port, GstVideoCodecState * state)
+{
+ return FALSE;
+}
+
+static gboolean
+gst_omx_wmv_dec_set_format (GstOMXVideoDec * dec, GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ gboolean ret;
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+
+ gst_omx_port_get_port_definition (port, &port_def);
+ port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingWMV;
+ ret = gst_omx_port_update_port_definition (port, &port_def) == OMX_ErrorNone;
+
+ return ret;
+}
diff --git a/subprojects/gst-omx/omx/gstomxwmvdec.h b/subprojects/gst-omx/omx/gstomxwmvdec.h
new file mode 100644
index 0000000000..9375dc5dfa
--- /dev/null
+++ b/subprojects/gst-omx/omx/gstomxwmvdec.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * 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
+ * version 2.1 of the License.
+ *
+ * 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_OMX_WMV_DEC_H__
+#define __GST_OMX_WMV_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_WMV_DEC \
+ (gst_omx_wmv_dec_get_type())
+#define GST_OMX_WMV_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_WMV_DEC,GstOMXWMVDec))
+#define GST_OMX_WMV_DEC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_WMV_DEC,GstOMXWMVDecClass))
+#define GST_OMX_WMV_DEC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_WMV_DEC,GstOMXWMVDecClass))
+#define GST_IS_OMX_WMV_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_WMV_DEC))
+#define GST_IS_OMX_WMV_DEC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_WMV_DEC))
+
+typedef struct _GstOMXWMVDec GstOMXWMVDec;
+typedef struct _GstOMXWMVDecClass GstOMXWMVDecClass;
+
+struct _GstOMXWMVDec
+{
+ GstOMXVideoDec parent;
+};
+
+struct _GstOMXWMVDecClass
+{
+ GstOMXVideoDecClass parent_class;
+};
+
+GType gst_omx_wmv_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_WMV_DEC_H__ */
+
diff --git a/subprojects/gst-omx/omx/meson.build b/subprojects/gst-omx/omx/meson.build
new file mode 100644
index 0000000000..becb72ff5b
--- /dev/null
+++ b/subprojects/gst-omx/omx/meson.build
@@ -0,0 +1,63 @@
+omx_sources = [
+ 'gstomx.c',
+ 'gstomxallocator.c',
+ 'gstomxbufferpool.c',
+ 'gstomxvideo.c',
+ 'gstomxvideodec.c',
+ 'gstomxvideoenc.c',
+ 'gstomxaudiodec.c',
+ 'gstomxaudioenc.c',
+ 'gstomxmjpegdec.c',
+ 'gstomxmpeg4videodec.c',
+ 'gstomxmpeg2videodec.c',
+ 'gstomxh264dec.c',
+ 'gstomxh264utils.c',
+ 'gstomxh263dec.c',
+ 'gstomxwmvdec.c',
+ 'gstomxmpeg4videoenc.c',
+ 'gstomxh264enc.c',
+ 'gstomxh263enc.c',
+ 'gstomxaacdec.c',
+ 'gstomxmp3dec.c',
+ 'gstomxaacenc.c',
+ 'gstomxamrdec.c',
+ 'gstomxaudiosink.c',
+ 'gstomxanalogaudiosink.c',
+ 'gstomxhdmiaudiosink.c',
+ 'gstomxmp3enc.c',
+]
+
+extra_c_args = []
+
+if have_omx_vp8
+ omx_sources += 'gstomxvp8dec.c'
+endif
+
+if have_omx_theora
+ omx_sources += 'gstomxtheoradec.c'
+endif
+
+if have_omx_hevc
+ omx_sources += 'gstomxh265utils.c'
+ omx_sources += 'gstomxh265enc.c'
+ omx_sources += 'gstomxh265dec.c'
+endif
+
+optional_deps = []
+if gstgl_dep.found()
+ optional_deps += gstgl_dep
+ extra_c_args += ['-DGST_USE_UNSTABLE_API']
+endif
+
+gstomx = library('gstomx',
+ omx_sources,
+ c_args : gst_omx_args + extra_c_args,
+# link_args : noseh_link_args,
+ include_directories : [configinc, omx_inc],
+ dependencies : [gstvideo_dep, gstaudio_dep, gstbase_dep, gstcontroller_dep,
+ libm, gmodule_dep, gstallocators_dep] + optional_deps,
+ install : true,
+ install_dir : plugins_install_dir,
+)
+
+plugins = [gstomx] \ No newline at end of file
diff --git a/subprojects/gst-omx/omx/openmax/OMX_Audio.h b/subprojects/gst-omx/omx/openmax/OMX_Audio.h
new file mode 100644
index 0000000000..04f1a9997b
--- /dev/null
+++ b/subprojects/gst-omx/omx/openmax/OMX_Audio.h
@@ -0,0 +1,1311 @@
+/*
+ * Copyright (c) 2008 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/** @file OMX_Audio.h - OpenMax IL version 1.1.2
+ * The structures needed by Audio components to exchange
+ * parameters and configuration data with the componenmilts.
+ */
+
+#ifndef OMX_Audio_h
+#define OMX_Audio_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* Each OMX header must include all required header files to allow the
+ * header to compile without errors. The includes below are required
+ * for this header file to compile successfully
+ */
+
+#include <OMX_Core.h>
+
+/** @defgroup midi MIDI
+ * @ingroup audio
+ */
+
+/** @defgroup effects Audio effects
+ * @ingroup audio
+ */
+
+/** @defgroup audio OpenMAX IL Audio Domain
+ * Structures for OpenMAX IL Audio domain
+ * @{
+ */
+
+/** Enumeration used to define the possible audio codings.
+ * If "OMX_AUDIO_CodingUnused" is selected, the coding selection must
+ * be done in a vendor specific way. Since this is for an audio
+ * processing element this enum is relevant. However, for another
+ * type of component other enums would be in this area.
+ */
+typedef enum OMX_AUDIO_CODINGTYPE {
+ OMX_AUDIO_CodingUnused = 0, /**< Placeholder value when coding is N/A */
+ OMX_AUDIO_CodingAutoDetect, /**< auto detection of audio format */
+ OMX_AUDIO_CodingPCM, /**< Any variant of PCM coding */
+ OMX_AUDIO_CodingADPCM, /**< Any variant of ADPCM encoded data */
+ OMX_AUDIO_CodingAMR, /**< Any variant of AMR encoded data */
+ OMX_AUDIO_CodingGSMFR, /**< Any variant of GSM fullrate (i.e. GSM610) */
+ OMX_AUDIO_CodingGSMEFR, /**< Any variant of GSM Enhanced Fullrate encoded data*/
+ OMX_AUDIO_CodingGSMHR, /**< Any variant of GSM Halfrate encoded data */
+ OMX_AUDIO_CodingPDCFR, /**< Any variant of PDC Fullrate encoded data */
+ OMX_AUDIO_CodingPDCEFR, /**< Any variant of PDC Enhanced Fullrate encoded data */
+ OMX_AUDIO_CodingPDCHR, /**< Any variant of PDC Halfrate encoded data */
+ OMX_AUDIO_CodingTDMAFR, /**< Any variant of TDMA Fullrate encoded data (TIA/EIA-136-420) */
+ OMX_AUDIO_CodingTDMAEFR, /**< Any variant of TDMA Enhanced Fullrate encoded data (TIA/EIA-136-410) */
+ OMX_AUDIO_CodingQCELP8, /**< Any variant of QCELP 8kbps encoded data */
+ OMX_AUDIO_CodingQCELP13, /**< Any variant of QCELP 13kbps encoded data */
+ OMX_AUDIO_CodingEVRC, /**< Any variant of EVRC encoded data */
+ OMX_AUDIO_CodingSMV, /**< Any variant of SMV encoded data */
+ OMX_AUDIO_CodingG711, /**< Any variant of G.711 encoded data */
+ OMX_AUDIO_CodingG723, /**< Any variant of G.723 dot 1 encoded data */
+ OMX_AUDIO_CodingG726, /**< Any variant of G.726 encoded data */
+ OMX_AUDIO_CodingG729, /**< Any variant of G.729 encoded data */
+ OMX_AUDIO_CodingAAC, /**< Any variant of AAC encoded data */
+ OMX_AUDIO_CodingMP3, /**< Any variant of MP3 encoded data */
+ OMX_AUDIO_CodingSBC, /**< Any variant of SBC encoded data */
+ OMX_AUDIO_CodingVORBIS, /**< Any variant of VORBIS encoded data */
+ OMX_AUDIO_CodingWMA, /**< Any variant of WMA encoded data */
+ OMX_AUDIO_CodingRA, /**< Any variant of RA encoded data */
+ OMX_AUDIO_CodingMIDI, /**< Any variant of MIDI encoded data */
+ OMX_AUDIO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_CodingMax = 0x7FFFFFFF
+} OMX_AUDIO_CODINGTYPE;
+
+
+/** The PortDefinition structure is used to define all of the parameters
+ * necessary for the compliant component to setup an input or an output audio
+ * path. If additional information is needed to define the parameters of the
+ * port (such as frequency), additional structures must be sent such as the
+ * OMX_AUDIO_PARAM_PCMMODETYPE structure to supply the extra parameters for the port.
+ */
+typedef struct OMX_AUDIO_PORTDEFINITIONTYPE {
+ OMX_STRING cMIMEType; /**< MIME type of data for the port */
+ OMX_NATIVE_DEVICETYPE pNativeRender; /** < platform specific reference
+ for an output device,
+ otherwise this field is 0 */
+ OMX_BOOL bFlagErrorConcealment; /**< Turns on error concealment if it is
+ supported by the OMX component */
+ OMX_AUDIO_CODINGTYPE eEncoding; /**< Type of data expected for this
+ port (e.g. PCM, AMR, MP3, etc) */
+} OMX_AUDIO_PORTDEFINITIONTYPE;
+
+
+/** Port format parameter. This structure is used to enumerate
+ * the various data input/output format supported by the port.
+ */
+typedef struct OMX_AUDIO_PARAM_PORTFORMATTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< Indicates which port to set */
+ OMX_U32 nIndex; /**< Indicates the enumeration index for the format from 0x0 to N-1 */
+ OMX_AUDIO_CODINGTYPE eEncoding; /**< Type of data expected for this port (e.g. PCM, AMR, MP3, etc) */
+} OMX_AUDIO_PARAM_PORTFORMATTYPE;
+
+
+/** PCM mode type */
+typedef enum OMX_AUDIO_PCMMODETYPE {
+ OMX_AUDIO_PCMModeLinear = 0, /**< Linear PCM encoded data */
+ OMX_AUDIO_PCMModeALaw, /**< A law PCM encoded data (G.711) */
+ OMX_AUDIO_PCMModeMULaw, /**< Mu law PCM encoded data (G.711) */
+ OMX_AUDIO_PCMModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_PCMModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_PCMModeMax = 0x7FFFFFFF
+} OMX_AUDIO_PCMMODETYPE;
+
+
+typedef enum OMX_AUDIO_CHANNELTYPE {
+ OMX_AUDIO_ChannelNone = 0x0, /**< Unused or empty */
+ OMX_AUDIO_ChannelLF = 0x1, /**< Left front */
+ OMX_AUDIO_ChannelRF = 0x2, /**< Right front */
+ OMX_AUDIO_ChannelCF = 0x3, /**< Center front */
+ OMX_AUDIO_ChannelLS = 0x4, /**< Left surround */
+ OMX_AUDIO_ChannelRS = 0x5, /**< Right surround */
+ OMX_AUDIO_ChannelLFE = 0x6, /**< Low frequency effects */
+ OMX_AUDIO_ChannelCS = 0x7, /**< Back surround */
+ OMX_AUDIO_ChannelLR = 0x8, /**< Left rear. */
+ OMX_AUDIO_ChannelRR = 0x9, /**< Right rear. */
+ OMX_AUDIO_ChannelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_ChannelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_ChannelMax = 0x7FFFFFFF
+} OMX_AUDIO_CHANNELTYPE;
+
+#define OMX_AUDIO_MAXCHANNELS 16 /**< maximum number distinct audio channels that a buffer may contain */
+#define OMX_MIN_PCMPAYLOAD_MSEC 5 /**< Minimum audio buffer payload size for uncompressed (PCM) audio */
+
+/** PCM format description */
+typedef struct OMX_AUDIO_PARAM_PCMMODETYPE {
+ OMX_U32 nSize; /**< Size of this structure, in Bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels (e.g. 2 for stereo) */
+ OMX_NUMERICALDATATYPE eNumData; /**< indicates PCM data as signed or unsigned */
+ OMX_ENDIANTYPE eEndian; /**< indicates PCM data as little or big endian */
+ OMX_BOOL bInterleaved; /**< True for normal interleaved data; false for
+ non-interleaved data (e.g. block data) */
+ OMX_U32 nBitPerSample; /**< Bit per sample */
+ OMX_U32 nSamplingRate; /**< Sampling rate of the source data. Use 0 for
+ variable or unknown sampling rate. */
+ OMX_AUDIO_PCMMODETYPE ePCMMode; /**< PCM mode enumeration */
+ OMX_AUDIO_CHANNELTYPE eChannelMapping[OMX_AUDIO_MAXCHANNELS]; /**< Slot i contains channel defined by eChannelMap[i] */
+
+} OMX_AUDIO_PARAM_PCMMODETYPE;
+
+
+/** Audio channel mode. This is used by both AAC and MP3, although the names are more appropriate
+ * for the MP3. For example, JointStereo for MP3 is CouplingChannels for AAC.
+ */
+typedef enum OMX_AUDIO_CHANNELMODETYPE {
+ OMX_AUDIO_ChannelModeStereo = 0, /**< 2 channels, the bitrate allocation between those
+ two channels changes accordingly to each channel information */
+ OMX_AUDIO_ChannelModeJointStereo, /**< mode that takes advantage of what is common between
+ 2 channels for higher compression gain */
+ OMX_AUDIO_ChannelModeDual, /**< 2 mono-channels, each channel is encoded with half
+ the bitrate of the overall bitrate */
+ OMX_AUDIO_ChannelModeMono, /**< Mono channel mode */
+ OMX_AUDIO_ChannelModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_ChannelModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_ChannelModeMax = 0x7FFFFFFF
+} OMX_AUDIO_CHANNELMODETYPE;
+
+
+typedef enum OMX_AUDIO_MP3STREAMFORMATTYPE {
+ OMX_AUDIO_MP3StreamFormatMP1Layer3 = 0, /**< MP3 Audio MPEG 1 Layer 3 Stream format */
+ OMX_AUDIO_MP3StreamFormatMP2Layer3, /**< MP3 Audio MPEG 2 Layer 3 Stream format */
+ OMX_AUDIO_MP3StreamFormatMP2_5Layer3, /**< MP3 Audio MPEG2.5 Layer 3 Stream format */
+ OMX_AUDIO_MP3StreamFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_MP3StreamFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_MP3StreamFormatMax = 0x7FFFFFFF
+} OMX_AUDIO_MP3STREAMFORMATTYPE;
+
+/** MP3 params */
+typedef struct OMX_AUDIO_PARAM_MP3TYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels */
+ OMX_U32 nBitRate; /**< Bit rate of the input data. Use 0 for variable
+ rate or unknown bit rates */
+ OMX_U32 nSampleRate; /**< Sampling rate of the source data. Use 0 for
+ variable or unknown sampling rate. */
+ OMX_U32 nAudioBandWidth; /**< Audio band width (in Hz) to which an encoder should
+ limit the audio signal. Use 0 to let encoder decide */
+ OMX_AUDIO_CHANNELMODETYPE eChannelMode; /**< Channel mode enumeration */
+ OMX_AUDIO_MP3STREAMFORMATTYPE eFormat; /**< MP3 stream format */
+} OMX_AUDIO_PARAM_MP3TYPE;
+
+
+typedef enum OMX_AUDIO_AACSTREAMFORMATTYPE {
+ OMX_AUDIO_AACStreamFormatMP2ADTS = 0, /**< AAC Audio Data Transport Stream 2 format */
+ OMX_AUDIO_AACStreamFormatMP4ADTS, /**< AAC Audio Data Transport Stream 4 format */
+ OMX_AUDIO_AACStreamFormatMP4LOAS, /**< AAC Low Overhead Audio Stream format */
+ OMX_AUDIO_AACStreamFormatMP4LATM, /**< AAC Low overhead Audio Transport Multiplex */
+ OMX_AUDIO_AACStreamFormatADIF, /**< AAC Audio Data Interchange Format */
+ OMX_AUDIO_AACStreamFormatMP4FF, /**< AAC inside MPEG-4/ISO File Format */
+ OMX_AUDIO_AACStreamFormatRAW, /**< AAC Raw Format */
+ OMX_AUDIO_AACStreamFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_AACStreamFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_AACStreamFormatMax = 0x7FFFFFFF
+} OMX_AUDIO_AACSTREAMFORMATTYPE;
+
+
+/** AAC mode type. Note that the term profile is used with the MPEG-2
+ * standard and the term object type and profile is used with MPEG-4 */
+typedef enum OMX_AUDIO_AACPROFILETYPE{
+ OMX_AUDIO_AACObjectNull = 0, /**< Null, not used */
+ OMX_AUDIO_AACObjectMain = 1, /**< AAC Main object */
+ OMX_AUDIO_AACObjectLC, /**< AAC Low Complexity object (AAC profile) */
+ OMX_AUDIO_AACObjectSSR, /**< AAC Scalable Sample Rate object */
+ OMX_AUDIO_AACObjectLTP, /**< AAC Long Term Prediction object */
+ OMX_AUDIO_AACObjectHE, /**< AAC High Efficiency (object type SBR, HE-AAC profile) */
+ OMX_AUDIO_AACObjectScalable, /**< AAC Scalable object */
+ OMX_AUDIO_AACObjectERLC = 17, /**< ER AAC Low Complexity object (Error Resilient AAC-LC) */
+ OMX_AUDIO_AACObjectLD = 23, /**< AAC Low Delay object (Error Resilient) */
+ OMX_AUDIO_AACObjectHE_PS = 29, /**< AAC High Efficiency with Parametric Stereo coding (HE-AAC v2, object type PS) */
+ OMX_AUDIO_AACObjectKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_AACObjectVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_AACObjectMax = 0x7FFFFFFF
+} OMX_AUDIO_AACPROFILETYPE;
+
+
+/** AAC tool usage (for nAACtools in OMX_AUDIO_PARAM_AACPROFILETYPE).
+ * Required for encoder configuration and optional as decoder info output.
+ * For MP3, OMX_AUDIO_CHANNELMODETYPE is sufficient. */
+#define OMX_AUDIO_AACToolNone 0x00000000 /**< no AAC tools allowed (encoder config) or active (decoder info output) */
+#define OMX_AUDIO_AACToolMS 0x00000001 /**< MS: Mid/side joint coding tool allowed or active */
+#define OMX_AUDIO_AACToolIS 0x00000002 /**< IS: Intensity stereo tool allowed or active */
+#define OMX_AUDIO_AACToolTNS 0x00000004 /**< TNS: Temporal Noise Shaping tool allowed or active */
+#define OMX_AUDIO_AACToolPNS 0x00000008 /**< PNS: MPEG-4 Perceptual Noise substitution tool allowed or active */
+#define OMX_AUDIO_AACToolLTP 0x00000010 /**< LTP: MPEG-4 Long Term Prediction tool allowed or active */
+#define OMX_AUDIO_AACToolAll 0x7FFFFFFF /**< all AAC tools allowed or active (*/
+
+/** MPEG-4 AAC error resilience (ER) tool usage (for nAACERtools in OMX_AUDIO_PARAM_AACPROFILETYPE).
+ * Required for ER encoder configuration and optional as decoder info output */
+#define OMX_AUDIO_AACERNone 0x00000000 /**< no AAC ER tools allowed/used */
+#define OMX_AUDIO_AACERVCB11 0x00000001 /**< VCB11: Virtual Code Books for AAC section data */
+#define OMX_AUDIO_AACERRVLC 0x00000002 /**< RVLC: Reversible Variable Length Coding */
+#define OMX_AUDIO_AACERHCR 0x00000004 /**< HCR: Huffman Codeword Reordering */
+#define OMX_AUDIO_AACERAll 0x7FFFFFFF /**< all AAC ER tools allowed/used */
+
+
+/** AAC params */
+typedef struct OMX_AUDIO_PARAM_AACPROFILETYPE {
+ OMX_U32 nSize; /**< Size of this structure, in Bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< Port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels */
+ OMX_U32 nSampleRate; /**< Sampling rate of the source data. Use 0 for
+ variable or unknown sampling rate. */
+ OMX_U32 nBitRate; /**< Bit rate of the input data. Use 0 for variable
+ rate or unknown bit rates */
+ OMX_U32 nAudioBandWidth; /**< Audio band width (in Hz) to which an encoder should
+ limit the audio signal. Use 0 to let encoder decide */
+ OMX_U32 nFrameLength; /**< Frame length (in audio samples per channel) of the codec.
+ Can be 1024 or 960 (AAC-LC), 2048 (HE-AAC), 480 or 512 (AAC-LD).
+ Use 0 to let encoder decide */
+ OMX_U32 nAACtools; /**< AAC tool usage */
+ OMX_U32 nAACERtools; /**< MPEG-4 AAC error resilience tool usage */
+ OMX_AUDIO_AACPROFILETYPE eAACProfile; /**< AAC profile enumeration */
+ OMX_AUDIO_AACSTREAMFORMATTYPE eAACStreamFormat; /**< AAC stream format enumeration */
+ OMX_AUDIO_CHANNELMODETYPE eChannelMode; /**< Channel mode enumeration */
+} OMX_AUDIO_PARAM_AACPROFILETYPE;
+
+
+/** VORBIS params */
+typedef struct OMX_AUDIO_PARAM_VORBISTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels */
+ OMX_U32 nBitRate; /**< Bit rate of the encoded data data. Use 0 for variable
+ rate or unknown bit rates. Encoding is set to the
+ bitrate closest to specified value (in bps) */
+ OMX_U32 nMinBitRate; /**< Sets minimum bitrate (in bps). */
+ OMX_U32 nMaxBitRate; /**< Sets maximum bitrate (in bps). */
+
+ OMX_U32 nSampleRate; /**< Sampling rate of the source data. Use 0 for
+ variable or unknown sampling rate. */
+ OMX_U32 nAudioBandWidth; /**< Audio band width (in Hz) to which an encoder should
+ limit the audio signal. Use 0 to let encoder decide */
+ OMX_S32 nQuality; /**< Sets encoding quality to n, between -1 (low) and 10 (high).
+ In the default mode of operation, teh quality level is 3.
+ Normal quality range is 0 - 10. */
+ OMX_BOOL bManaged; /**< Set bitrate management mode. This turns off the
+ normal VBR encoding, but allows hard or soft bitrate
+ constraints to be enforced by the encoder. This mode can
+ be slower, and may also be lower quality. It is
+ primarily useful for streaming. */
+ OMX_BOOL bDownmix; /**< Downmix input from stereo to mono (has no effect on
+ non-stereo streams). Useful for lower-bitrate encoding. */
+} OMX_AUDIO_PARAM_VORBISTYPE;
+
+
+/** WMA Version */
+typedef enum OMX_AUDIO_WMAFORMATTYPE {
+ OMX_AUDIO_WMAFormatUnused = 0, /**< format unused or unknown */
+ OMX_AUDIO_WMAFormat7, /**< Windows Media Audio format 7 */
+ OMX_AUDIO_WMAFormat8, /**< Windows Media Audio format 8 */
+ OMX_AUDIO_WMAFormat9, /**< Windows Media Audio format 9 */
+ OMX_AUDIO_WMAFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_WMAFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_WMAFormatMax = 0x7FFFFFFF
+} OMX_AUDIO_WMAFORMATTYPE;
+
+
+/** WMA Profile */
+typedef enum OMX_AUDIO_WMAPROFILETYPE {
+ OMX_AUDIO_WMAProfileUnused = 0, /**< profile unused or unknown */
+ OMX_AUDIO_WMAProfileL1, /**< Windows Media audio version 9 profile L1 */
+ OMX_AUDIO_WMAProfileL2, /**< Windows Media audio version 9 profile L2 */
+ OMX_AUDIO_WMAProfileL3, /**< Windows Media audio version 9 profile L3 */
+ OMX_AUDIO_WMAProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_WMAProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_WMAProfileMax = 0x7FFFFFFF
+} OMX_AUDIO_WMAPROFILETYPE;
+
+
+/** WMA params */
+typedef struct OMX_AUDIO_PARAM_WMATYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U16 nChannels; /**< Number of channels */
+ OMX_U32 nBitRate; /**< Bit rate of the input data. Use 0 for variable
+ rate or unknown bit rates */
+ OMX_AUDIO_WMAFORMATTYPE eFormat; /**< Version of WMA stream / data */
+ OMX_AUDIO_WMAPROFILETYPE eProfile; /**< Profile of WMA stream / data */
+ OMX_U32 nSamplingRate; /**< Sampling rate of the source data */
+ OMX_U16 nBlockAlign; /**< is the block alignment, or block size, in bytes of the audio codec */
+ OMX_U16 nEncodeOptions; /**< WMA Type-specific data */
+ OMX_U32 nSuperBlockAlign; /**< WMA Type-specific data */
+} OMX_AUDIO_PARAM_WMATYPE;
+
+/**
+ * RealAudio format
+ */
+typedef enum OMX_AUDIO_RAFORMATTYPE {
+ OMX_AUDIO_RAFormatUnused = 0, /**< Format unused or unknown */
+ OMX_AUDIO_RA8, /**< RealAudio 8 codec */
+ OMX_AUDIO_RA9, /**< RealAudio 9 codec */
+ OMX_AUDIO_RA10_AAC, /**< MPEG-4 AAC codec for bitrates of more than 128kbps */
+ OMX_AUDIO_RA10_CODEC, /**< RealAudio codec for bitrates less than 128 kbps */
+ OMX_AUDIO_RA10_LOSSLESS, /**< RealAudio Lossless */
+ OMX_AUDIO_RA10_MULTICHANNEL, /**< RealAudio Multichannel */
+ OMX_AUDIO_RA10_VOICE, /**< RealAudio Voice for bitrates below 15 kbps */
+ OMX_AUDIO_RAFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_RAFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_VIDEO_RAFormatMax = 0x7FFFFFFF
+} OMX_AUDIO_RAFORMATTYPE;
+
+/** RA (Real Audio) params */
+typedef struct OMX_AUDIO_PARAM_RATYPE {
+ OMX_U32 nSize; /**< Size of this structure, in Bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< Port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels */
+ OMX_U32 nSamplingRate; /**< is the sampling rate of the source data */
+ OMX_U32 nBitsPerFrame; /**< is the value for bits per frame */
+ OMX_U32 nSamplePerFrame; /**< is the value for samples per frame */
+ OMX_U32 nCouplingQuantBits; /**< is the number of coupling quantization bits in the stream */
+ OMX_U32 nCouplingStartRegion; /**< is the coupling start region in the stream */
+ OMX_U32 nNumRegions; /**< is the number of regions value */
+ OMX_AUDIO_RAFORMATTYPE eFormat; /**< is the RealAudio audio format */
+} OMX_AUDIO_PARAM_RATYPE;
+
+
+/** SBC Allocation Method Type */
+typedef enum OMX_AUDIO_SBCALLOCMETHODTYPE {
+ OMX_AUDIO_SBCAllocMethodLoudness, /**< Loudness allocation method */
+ OMX_AUDIO_SBCAllocMethodSNR, /**< SNR allocation method */
+ OMX_AUDIO_SBCAllocMethodKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_SBCAllocMethodVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_SBCAllocMethodMax = 0x7FFFFFFF
+} OMX_AUDIO_SBCALLOCMETHODTYPE;
+
+
+/** SBC params */
+typedef struct OMX_AUDIO_PARAM_SBCTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels */
+ OMX_U32 nBitRate; /**< Bit rate of the input data. Use 0 for variable
+ rate or unknown bit rates */
+ OMX_U32 nSampleRate; /**< Sampling rate of the source data. Use 0 for
+ variable or unknown sampling rate. */
+ OMX_U32 nBlocks; /**< Number of blocks */
+ OMX_U32 nSubbands; /**< Number of subbands */
+ OMX_U32 nBitPool; /**< Bitpool value */
+ OMX_BOOL bEnableBitrate; /**< Use bitrate value instead of bitpool */
+ OMX_AUDIO_CHANNELMODETYPE eChannelMode; /**< Channel mode enumeration */
+ OMX_AUDIO_SBCALLOCMETHODTYPE eSBCAllocType; /**< SBC Allocation method type */
+} OMX_AUDIO_PARAM_SBCTYPE;
+
+
+/** ADPCM stream format parameters */
+typedef struct OMX_AUDIO_PARAM_ADPCMTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels in the data stream (not
+ necessarily the same as the number of channels
+ to be rendered. */
+ OMX_U32 nBitsPerSample; /**< Number of bits in each sample */
+ OMX_U32 nSampleRate; /**< Sampling rate of the source data. Use 0 for
+ variable or unknown sampling rate. */
+} OMX_AUDIO_PARAM_ADPCMTYPE;
+
+
+/** G723 rate */
+typedef enum OMX_AUDIO_G723RATE {
+ OMX_AUDIO_G723ModeUnused = 0, /**< AMRNB Mode unused / unknown */
+ OMX_AUDIO_G723ModeLow, /**< 5300 bps */
+ OMX_AUDIO_G723ModeHigh, /**< 6300 bps */
+ OMX_AUDIO_G723ModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_G723ModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_G723ModeMax = 0x7FFFFFFF
+} OMX_AUDIO_G723RATE;
+
+
+/** G723 - Sample rate must be 8 KHz */
+typedef struct OMX_AUDIO_PARAM_G723TYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels in the data stream (not
+ necessarily the same as the number of channels
+ to be rendered. */
+ OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */
+ OMX_AUDIO_G723RATE eBitRate; /**< todo: Should this be moved to a config? */
+ OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */
+ OMX_BOOL bPostFilter; /**< Enable Post Filter */
+} OMX_AUDIO_PARAM_G723TYPE;
+
+
+/** ITU G726 (ADPCM) rate */
+typedef enum OMX_AUDIO_G726MODE {
+ OMX_AUDIO_G726ModeUnused = 0, /**< G726 Mode unused / unknown */
+ OMX_AUDIO_G726Mode16, /**< 16 kbps */
+ OMX_AUDIO_G726Mode24, /**< 24 kbps */
+ OMX_AUDIO_G726Mode32, /**< 32 kbps, most common rate, also G721 */
+ OMX_AUDIO_G726Mode40, /**< 40 kbps */
+ OMX_AUDIO_G726ModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_G726ModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_G726ModeMax = 0x7FFFFFFF
+} OMX_AUDIO_G726MODE;
+
+
+/** G.726 stream format parameters - must be at 8KHz */
+typedef struct OMX_AUDIO_PARAM_G726TYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels in the data stream (not
+ necessarily the same as the number of channels
+ to be rendered. */
+ OMX_AUDIO_G726MODE eG726Mode;
+} OMX_AUDIO_PARAM_G726TYPE;
+
+
+/** G729 coder type */
+typedef enum OMX_AUDIO_G729TYPE {
+ OMX_AUDIO_G729 = 0, /**< ITU G.729 encoded data */
+ OMX_AUDIO_G729A, /**< ITU G.729 annex A encoded data */
+ OMX_AUDIO_G729B, /**< ITU G.729 with annex B encoded data */
+ OMX_AUDIO_G729AB, /**< ITU G.729 annexes A and B encoded data */
+ OMX_AUDIO_G729KhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_G729VendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_G729Max = 0x7FFFFFFF
+} OMX_AUDIO_G729TYPE;
+
+
+/** G729 stream format parameters - fixed 6KHz sample rate */
+typedef struct OMX_AUDIO_PARAM_G729TYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels in the data stream (not
+ necessarily the same as the number of channels
+ to be rendered. */
+ OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */
+ OMX_AUDIO_G729TYPE eBitType;
+} OMX_AUDIO_PARAM_G729TYPE;
+
+
+/** AMR Frame format */
+typedef enum OMX_AUDIO_AMRFRAMEFORMATTYPE {
+ OMX_AUDIO_AMRFrameFormatConformance = 0, /**< Frame Format is AMR Conformance
+ (Standard) Format */
+ OMX_AUDIO_AMRFrameFormatIF1, /**< Frame Format is AMR Interface
+ Format 1 */
+ OMX_AUDIO_AMRFrameFormatIF2, /**< Frame Format is AMR Interface
+ Format 2*/
+ OMX_AUDIO_AMRFrameFormatFSF, /**< Frame Format is AMR File Storage
+ Format */
+ OMX_AUDIO_AMRFrameFormatRTPPayload, /**< Frame Format is AMR Real-Time
+ Transport Protocol Payload Format */
+ OMX_AUDIO_AMRFrameFormatITU, /**< Frame Format is ITU Format (added at Motorola request) */
+ OMX_AUDIO_AMRFrameFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_AMRFrameFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_AMRFrameFormatMax = 0x7FFFFFFF
+} OMX_AUDIO_AMRFRAMEFORMATTYPE;
+
+
+/** AMR band mode */
+typedef enum OMX_AUDIO_AMRBANDMODETYPE {
+ OMX_AUDIO_AMRBandModeUnused = 0, /**< AMRNB Mode unused / unknown */
+ OMX_AUDIO_AMRBandModeNB0, /**< AMRNB Mode 0 = 4750 bps */
+ OMX_AUDIO_AMRBandModeNB1, /**< AMRNB Mode 1 = 5150 bps */
+ OMX_AUDIO_AMRBandModeNB2, /**< AMRNB Mode 2 = 5900 bps */
+ OMX_AUDIO_AMRBandModeNB3, /**< AMRNB Mode 3 = 6700 bps */
+ OMX_AUDIO_AMRBandModeNB4, /**< AMRNB Mode 4 = 7400 bps */
+ OMX_AUDIO_AMRBandModeNB5, /**< AMRNB Mode 5 = 7950 bps */
+ OMX_AUDIO_AMRBandModeNB6, /**< AMRNB Mode 6 = 10200 bps */
+ OMX_AUDIO_AMRBandModeNB7, /**< AMRNB Mode 7 = 12200 bps */
+ OMX_AUDIO_AMRBandModeWB0, /**< AMRWB Mode 0 = 6600 bps */
+ OMX_AUDIO_AMRBandModeWB1, /**< AMRWB Mode 1 = 8850 bps */
+ OMX_AUDIO_AMRBandModeWB2, /**< AMRWB Mode 2 = 12650 bps */
+ OMX_AUDIO_AMRBandModeWB3, /**< AMRWB Mode 3 = 14250 bps */
+ OMX_AUDIO_AMRBandModeWB4, /**< AMRWB Mode 4 = 15850 bps */
+ OMX_AUDIO_AMRBandModeWB5, /**< AMRWB Mode 5 = 18250 bps */
+ OMX_AUDIO_AMRBandModeWB6, /**< AMRWB Mode 6 = 19850 bps */
+ OMX_AUDIO_AMRBandModeWB7, /**< AMRWB Mode 7 = 23050 bps */
+ OMX_AUDIO_AMRBandModeWB8, /**< AMRWB Mode 8 = 23850 bps */
+ OMX_AUDIO_AMRBandModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_AMRBandModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_AMRBandModeMax = 0x7FFFFFFF
+} OMX_AUDIO_AMRBANDMODETYPE;
+
+
+/** AMR Discontinuous Transmission mode */
+typedef enum OMX_AUDIO_AMRDTXMODETYPE {
+ OMX_AUDIO_AMRDTXModeOff = 0, /**< AMR Discontinuous Transmission Mode is disabled */
+ OMX_AUDIO_AMRDTXModeOnVAD1, /**< AMR Discontinuous Transmission Mode using
+ Voice Activity Detector 1 (VAD1) is enabled */
+ OMX_AUDIO_AMRDTXModeOnVAD2, /**< AMR Discontinuous Transmission Mode using
+ Voice Activity Detector 2 (VAD2) is enabled */
+ OMX_AUDIO_AMRDTXModeOnAuto, /**< The codec will automatically select between
+ Off, VAD1 or VAD2 modes */
+
+ OMX_AUDIO_AMRDTXasEFR, /**< DTX as EFR instead of AMR standard (3GPP 26.101, frame type =8,9,10) */
+
+ OMX_AUDIO_AMRDTXModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_AMRDTXModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_AMRDTXModeMax = 0x7FFFFFFF
+} OMX_AUDIO_AMRDTXMODETYPE;
+
+
+/** AMR params */
+typedef struct OMX_AUDIO_PARAM_AMRTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels */
+ OMX_U32 nBitRate; /**< Bit rate read only field */
+ OMX_AUDIO_AMRBANDMODETYPE eAMRBandMode; /**< AMR Band Mode enumeration */
+ OMX_AUDIO_AMRDTXMODETYPE eAMRDTXMode; /**< AMR DTX Mode enumeration */
+ OMX_AUDIO_AMRFRAMEFORMATTYPE eAMRFrameFormat; /**< AMR frame format enumeration */
+} OMX_AUDIO_PARAM_AMRTYPE;
+
+
+/** GSM_FR (ETSI 06.10, 3GPP 46.010) stream format parameters */
+typedef struct OMX_AUDIO_PARAM_GSMFRTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */
+ OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */
+} OMX_AUDIO_PARAM_GSMFRTYPE;
+
+
+/** GSM-HR (ETSI 06.20, 3GPP 46.020) stream format parameters */
+typedef struct OMX_AUDIO_PARAM_GSMHRTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */
+ OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */
+} OMX_AUDIO_PARAM_GSMHRTYPE;
+
+
+/** GSM-EFR (ETSI 06.60, 3GPP 46.060) stream format parameters */
+typedef struct OMX_AUDIO_PARAM_GSMEFRTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */
+ OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */
+} OMX_AUDIO_PARAM_GSMEFRTYPE;
+
+
+/** TDMA FR (TIA/EIA-136-420, VSELP 7.95kbps coder) stream format parameters */
+typedef struct OMX_AUDIO_PARAM_TDMAFRTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels in the data stream (not
+ necessarily the same as the number of channels
+ to be rendered. */
+ OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */
+ OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */
+} OMX_AUDIO_PARAM_TDMAFRTYPE;
+
+
+/** TDMA EFR (TIA/EIA-136-410, ACELP 7.4kbps coder) stream format parameters */
+typedef struct OMX_AUDIO_PARAM_TDMAEFRTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels in the data stream (not
+ necessarily the same as the number of channels
+ to be rendered. */
+ OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */
+ OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */
+} OMX_AUDIO_PARAM_TDMAEFRTYPE;
+
+
+/** PDC FR ( RCR-27, VSELP 6.7kbps coder) stream format parameters */
+typedef struct OMX_AUDIO_PARAM_PDCFRTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels in the data stream (not
+ necessarily the same as the number of channels
+ to be rendered. */
+ OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */
+ OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */
+} OMX_AUDIO_PARAM_PDCFRTYPE;
+
+
+/** PDC EFR ( RCR-27, ACELP 6.7kbps coder) stream format parameters */
+typedef struct OMX_AUDIO_PARAM_PDCEFRTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels in the data stream (not
+ necessarily the same as the number of channels
+ to be rendered. */
+ OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */
+ OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */
+} OMX_AUDIO_PARAM_PDCEFRTYPE;
+
+/** PDC HR ( RCR-27, PSI-CELP 3.45kbps coder) stream format parameters */
+typedef struct OMX_AUDIO_PARAM_PDCHRTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels in the data stream (not
+ necessarily the same as the number of channels
+ to be rendered. */
+ OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */
+ OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */
+} OMX_AUDIO_PARAM_PDCHRTYPE;
+
+
+/** CDMA Rate types */
+typedef enum OMX_AUDIO_CDMARATETYPE {
+ OMX_AUDIO_CDMARateBlank = 0, /**< CDMA encoded frame is blank */
+ OMX_AUDIO_CDMARateFull, /**< CDMA encoded frame in full rate */
+ OMX_AUDIO_CDMARateHalf, /**< CDMA encoded frame in half rate */
+ OMX_AUDIO_CDMARateQuarter, /**< CDMA encoded frame in quarter rate */
+ OMX_AUDIO_CDMARateEighth, /**< CDMA encoded frame in eighth rate (DTX)*/
+ OMX_AUDIO_CDMARateErasure, /**< CDMA erasure frame */
+ OMX_AUDIO_CDMARateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_CDMARateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_CDMARateMax = 0x7FFFFFFF
+} OMX_AUDIO_CDMARATETYPE;
+
+
+/** QCELP8 (TIA/EIA-96, up to 8kbps coder) stream format parameters */
+typedef struct OMX_AUDIO_PARAM_QCELP8TYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels in the data stream (not
+ necessarily the same as the number of channels
+ to be rendered. */
+ OMX_U32 nBitRate; /**< Bit rate of the input data. Use 0 for variable
+ rate or unknown bit rates */
+ OMX_AUDIO_CDMARATETYPE eCDMARate; /**< Frame rate */
+ OMX_U32 nMinBitRate; /**< minmal rate for the encoder = 1,2,3,4, default = 1 */
+ OMX_U32 nMaxBitRate; /**< maximal rate for the encoder = 1,2,3,4, default = 4 */
+} OMX_AUDIO_PARAM_QCELP8TYPE;
+
+
+/** QCELP13 ( CDMA, EIA/TIA-733, 13.3kbps coder) stream format parameters */
+typedef struct OMX_AUDIO_PARAM_QCELP13TYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels in the data stream (not
+ necessarily the same as the number of channels
+ to be rendered. */
+ OMX_AUDIO_CDMARATETYPE eCDMARate; /**< Frame rate */
+ OMX_U32 nMinBitRate; /**< minmal rate for the encoder = 1,2,3,4, default = 1 */
+ OMX_U32 nMaxBitRate; /**< maximal rate for the encoder = 1,2,3,4, default = 4 */
+} OMX_AUDIO_PARAM_QCELP13TYPE;
+
+
+/** EVRC ( CDMA, EIA/TIA-127, RCELP up to 8.55kbps coder) stream format parameters */
+typedef struct OMX_AUDIO_PARAM_EVRCTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels in the data stream (not
+ necessarily the same as the number of channels
+ to be rendered. */
+ OMX_AUDIO_CDMARATETYPE eCDMARate; /**< actual Frame rate */
+ OMX_BOOL bRATE_REDUCon; /**< RATE_REDUCtion is requested for this frame */
+ OMX_U32 nMinBitRate; /**< minmal rate for the encoder = 1,2,3,4, default = 1 */
+ OMX_U32 nMaxBitRate; /**< maximal rate for the encoder = 1,2,3,4, default = 4 */
+ OMX_BOOL bHiPassFilter; /**< Enable encoder's High Pass Filter */
+ OMX_BOOL bNoiseSuppressor; /**< Enable encoder's noise suppressor pre-processing */
+ OMX_BOOL bPostFilter; /**< Enable decoder's post Filter */
+} OMX_AUDIO_PARAM_EVRCTYPE;
+
+
+/** SMV ( up to 8.55kbps coder) stream format parameters */
+typedef struct OMX_AUDIO_PARAM_SMVTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannels; /**< Number of channels in the data stream (not
+ necessarily the same as the number of channels
+ to be rendered. */
+ OMX_AUDIO_CDMARATETYPE eCDMARate; /**< Frame rate */
+ OMX_BOOL bRATE_REDUCon; /**< RATE_REDUCtion is requested for this frame */
+ OMX_U32 nMinBitRate; /**< minmal rate for the encoder = 1,2,3,4, default = 1 ??*/
+ OMX_U32 nMaxBitRate; /**< maximal rate for the encoder = 1,2,3,4, default = 4 ??*/
+ OMX_BOOL bHiPassFilter; /**< Enable encoder's High Pass Filter ??*/
+ OMX_BOOL bNoiseSuppressor; /**< Enable encoder's noise suppressor pre-processing */
+ OMX_BOOL bPostFilter; /**< Enable decoder's post Filter ??*/
+} OMX_AUDIO_PARAM_SMVTYPE;
+
+
+/** MIDI Format
+ * @ingroup midi
+ */
+typedef enum OMX_AUDIO_MIDIFORMATTYPE
+{
+ OMX_AUDIO_MIDIFormatUnknown = 0, /**< MIDI Format unknown or don't care */
+ OMX_AUDIO_MIDIFormatSMF0, /**< Standard MIDI File Type 0 */
+ OMX_AUDIO_MIDIFormatSMF1, /**< Standard MIDI File Type 1 */
+ OMX_AUDIO_MIDIFormatSMF2, /**< Standard MIDI File Type 2 */
+ OMX_AUDIO_MIDIFormatSPMIDI, /**< SP-MIDI */
+ OMX_AUDIO_MIDIFormatXMF0, /**< eXtensible Music Format type 0 */
+ OMX_AUDIO_MIDIFormatXMF1, /**< eXtensible Music Format type 1 */
+ OMX_AUDIO_MIDIFormatMobileXMF, /**< Mobile XMF (eXtensible Music Format type 2) */
+ OMX_AUDIO_MIDIFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_MIDIFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_MIDIFormatMax = 0x7FFFFFFF
+} OMX_AUDIO_MIDIFORMATTYPE;
+
+
+/** MIDI params
+ * @ingroup midi
+ */
+typedef struct OMX_AUDIO_PARAM_MIDITYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nFileSize; /**< size of the MIDI file in bytes, where the entire
+ MIDI file passed in, otherwise if 0x0, the MIDI data
+ is merged and streamed (instead of passed as an
+ entire MIDI file) */
+ OMX_BU32 sMaxPolyphony; /**< Specifies the maximum simultaneous polyphonic
+ voices. A value of zero indicates that the default
+ polyphony of the device is used */
+ OMX_BOOL bLoadDefaultSound; /**< Whether to load default sound
+ bank at initialization */
+ OMX_AUDIO_MIDIFORMATTYPE eMidiFormat; /**< Version of the MIDI file */
+} OMX_AUDIO_PARAM_MIDITYPE;
+
+
+/** Type of the MIDI sound bank
+ * @ingroup midi
+ */
+typedef enum OMX_AUDIO_MIDISOUNDBANKTYPE {
+ OMX_AUDIO_MIDISoundBankUnused = 0, /**< unused/unknown soundbank type */
+ OMX_AUDIO_MIDISoundBankDLS1, /**< DLS version 1 */
+ OMX_AUDIO_MIDISoundBankDLS2, /**< DLS version 2 */
+ OMX_AUDIO_MIDISoundBankMobileDLSBase, /**< Mobile DLS, using the base functionality */
+ OMX_AUDIO_MIDISoundBankMobileDLSPlusOptions, /**< Mobile DLS, using the specification-defined optional feature set */
+ OMX_AUDIO_MIDISoundBankKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_MIDISoundBankVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_MIDISoundBankMax = 0x7FFFFFFF
+} OMX_AUDIO_MIDISOUNDBANKTYPE;
+
+
+/** Bank Layout describes how bank MSB & LSB are used in the DLS instrument definitions sound bank
+ * @ingroup midi
+ */
+typedef enum OMX_AUDIO_MIDISOUNDBANKLAYOUTTYPE {
+ OMX_AUDIO_MIDISoundBankLayoutUnused = 0, /**< unused/unknown soundbank type */
+ OMX_AUDIO_MIDISoundBankLayoutGM, /**< GS layout (based on bank MSB 0x00) */
+ OMX_AUDIO_MIDISoundBankLayoutGM2, /**< General MIDI 2 layout (using MSB 0x78/0x79, LSB 0x00) */
+ OMX_AUDIO_MIDISoundBankLayoutUser, /**< Does not conform to any bank numbering standards */
+ OMX_AUDIO_MIDISoundBankLayoutKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_MIDISoundBankLayoutVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_MIDISoundBankLayoutMax = 0x7FFFFFFF
+} OMX_AUDIO_MIDISOUNDBANKLAYOUTTYPE;
+
+
+/** MIDI params to load/unload user soundbank
+ * @ingroup midi
+ */
+typedef struct OMX_AUDIO_PARAM_MIDILOADUSERSOUNDTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nDLSIndex; /**< DLS file index to be loaded */
+ OMX_U32 nDLSSize; /**< Size in bytes */
+ OMX_PTR pDLSData; /**< Pointer to DLS file data */
+ OMX_AUDIO_MIDISOUNDBANKTYPE eMidiSoundBank; /**< Midi sound bank type enumeration */
+ OMX_AUDIO_MIDISOUNDBANKLAYOUTTYPE eMidiSoundBankLayout; /**< Midi sound bank layout enumeration */
+} OMX_AUDIO_PARAM_MIDILOADUSERSOUNDTYPE;
+
+
+/** Structure for Live MIDI events and MIP messages.
+ * (MIP = Maximum Instantaneous Polyphony; part of the SP-MIDI standard.)
+ * @ingroup midi
+ */
+typedef struct OMX_AUDIO_CONFIG_MIDIIMMEDIATEEVENTTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< Port that this structure applies to */
+ OMX_U32 nMidiEventSize; /**< Size of immediate MIDI events or MIP message in bytes */
+ OMX_U8 nMidiEvents[1]; /**< MIDI event array to be rendered immediately, or an
+ array for the MIP message buffer, where the size is
+ indicated by nMidiEventSize */
+} OMX_AUDIO_CONFIG_MIDIIMMEDIATEEVENTTYPE;
+
+
+/** MIDI sound bank/ program pair in a given channel
+ * @ingroup midi
+ */
+typedef struct OMX_AUDIO_CONFIG_MIDISOUNDBANKPROGRAMTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< Port that this structure applies to */
+ OMX_U32 nChannel; /**< Valid channel values range from 1 to 16 */
+ OMX_U16 nIDProgram; /**< Valid program ID range is 1 to 128 */
+ OMX_U16 nIDSoundBank; /**< Sound bank ID */
+ OMX_U32 nUserSoundBankIndex;/**< User soundbank index, easier to access soundbanks
+ by index if multiple banks are present */
+} OMX_AUDIO_CONFIG_MIDISOUNDBANKPROGRAMTYPE;
+
+
+/** MIDI control
+ * @ingroup midi
+ */
+typedef struct OMX_AUDIO_CONFIG_MIDICONTROLTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_BS32 sPitchTransposition; /**< Pitch transposition in semitones, stored as Q22.10
+ format based on JAVA MMAPI (JSR-135) requirement */
+ OMX_BU32 sPlayBackRate; /**< Relative playback rate, stored as Q14.17 fixed-point
+ number based on JSR-135 requirement */
+ OMX_BU32 sTempo ; /**< Tempo in beats per minute (BPM), stored as Q22.10
+ fixed-point number based on JSR-135 requirement */
+ OMX_U32 nMaxPolyphony; /**< Specifies the maximum simultaneous polyphonic
+ voices. A value of zero indicates that the default
+ polyphony of the device is used */
+ OMX_U32 nNumRepeat; /**< Number of times to repeat playback */
+ OMX_U32 nStopTime; /**< Time in milliseconds to indicate when playback
+ will stop automatically. Set to zero if not used */
+ OMX_U16 nChannelMuteMask; /**< 16 bit mask for channel mute status */
+ OMX_U16 nChannelSoloMask; /**< 16 bit mask for channel solo status */
+ OMX_U32 nTrack0031MuteMask; /**< 32 bit mask for track mute status. Note: This is for tracks 0-31 */
+ OMX_U32 nTrack3263MuteMask; /**< 32 bit mask for track mute status. Note: This is for tracks 32-63 */
+ OMX_U32 nTrack0031SoloMask; /**< 32 bit mask for track solo status. Note: This is for tracks 0-31 */
+ OMX_U32 nTrack3263SoloMask; /**< 32 bit mask for track solo status. Note: This is for tracks 32-63 */
+
+} OMX_AUDIO_CONFIG_MIDICONTROLTYPE;
+
+
+/** MIDI Playback States
+ * @ingroup midi
+ */
+typedef enum OMX_AUDIO_MIDIPLAYBACKSTATETYPE {
+ OMX_AUDIO_MIDIPlayBackStateUnknown = 0, /**< Unknown state or state does not map to
+ other defined states */
+ OMX_AUDIO_MIDIPlayBackStateClosedEngaged, /**< No MIDI resource is currently open.
+ The MIDI engine is currently processing
+ MIDI events. */
+ OMX_AUDIO_MIDIPlayBackStateParsing, /**< A MIDI resource is open and is being
+ primed. The MIDI engine is currently
+ processing MIDI events. */
+ OMX_AUDIO_MIDIPlayBackStateOpenEngaged, /**< A MIDI resource is open and primed but
+ not playing. The MIDI engine is currently
+ processing MIDI events. The transition to
+ this state is only possible from the
+ OMX_AUDIO_MIDIPlayBackStatePlaying state,
+ when the 'playback head' reaches the end
+ of media data or the playback stops due
+ to stop time set.*/
+ OMX_AUDIO_MIDIPlayBackStatePlaying, /**< A MIDI resource is open and currently
+ playing. The MIDI engine is currently
+ processing MIDI events.*/
+ OMX_AUDIO_MIDIPlayBackStatePlayingPartially, /**< Best-effort playback due to SP-MIDI/DLS
+ resource constraints */
+ OMX_AUDIO_MIDIPlayBackStatePlayingSilently, /**< Due to system resource constraints and
+ SP-MIDI content constraints, there is
+ no audible MIDI content during playback
+ currently. The situation may change if
+ resources are freed later.*/
+ OMX_AUDIO_MIDIPlayBackStateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_MIDIPlayBackStateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_MIDIPlayBackStateMax = 0x7FFFFFFF
+} OMX_AUDIO_MIDIPLAYBACKSTATETYPE;
+
+
+/** MIDI status
+ * @ingroup midi
+ */
+typedef struct OMX_AUDIO_CONFIG_MIDISTATUSTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U16 nNumTracks; /**< Number of MIDI tracks in the file, read only field.
+ NOTE: May not return a meaningful value until the entire
+ file is parsed and buffered. */
+ OMX_U32 nDuration; /**< The length of the currently open MIDI resource
+ in milliseconds. NOTE: May not return a meaningful value
+ until the entire file is parsed and buffered. */
+ OMX_U32 nPosition; /**< Current Position of the MIDI resource being played
+ in milliseconds */
+ OMX_BOOL bVibra; /**< Does Vibra track exist? NOTE: May not return a meaningful
+ value until the entire file is parsed and buffered. */
+ OMX_U32 nNumMetaEvents; /**< Total number of MIDI Meta Events in the currently
+ open MIDI resource. NOTE: May not return a meaningful value
+ until the entire file is parsed and buffered. */
+ OMX_U32 nNumActiveVoices; /**< Number of active voices in the currently playing
+ MIDI resource. NOTE: May not return a meaningful value until
+ the entire file is parsed and buffered. */
+ OMX_AUDIO_MIDIPLAYBACKSTATETYPE eMIDIPlayBackState; /**< MIDI playback state enumeration, read only field */
+} OMX_AUDIO_CONFIG_MIDISTATUSTYPE;
+
+
+/** MIDI Meta Event structure one per Meta Event.
+ * MIDI Meta Events are like audio metadata, except that they are interspersed
+ * with the MIDI content throughout the file and are not localized in the header.
+ * As such, it is necessary to retrieve information about these Meta Events from
+ * the engine, as it encounters these Meta Events within the MIDI content.
+ * For example, SMF files can have up to 14 types of MIDI Meta Events (copyright,
+ * author, default tempo, etc.) scattered throughout the file.
+ * @ingroup midi
+ */
+typedef struct OMX_AUDIO_CONFIG_MIDIMETAEVENTTYPE{
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nIndex; /**< Index of Meta Event */
+ OMX_U8 nMetaEventType; /**< Meta Event Type, 7bits (i.e. 0 - 127) */
+ OMX_U32 nMetaEventSize; /**< size of the Meta Event in bytes */
+ OMX_U32 nTrack; /**< track number for the meta event */
+ OMX_U32 nPosition; /**< Position of the meta-event in milliseconds */
+} OMX_AUDIO_CONFIG_MIDIMETAEVENTTYPE;
+
+
+/** MIDI Meta Event Data structure - one per Meta Event.
+ * @ingroup midi
+ */
+typedef struct OMX_AUDIO_CONFIG_MIDIMETAEVENTDATATYPE{
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nIndex; /**< Index of Meta Event */
+ OMX_U32 nMetaEventSize; /**< size of the Meta Event in bytes */
+ OMX_U8 nData[1]; /**< array of one or more bytes of meta data
+ as indicated by the nMetaEventSize field */
+} OMX_AUDIO_CONFIG__MIDIMETAEVENTDATATYPE;
+
+
+/** Audio Volume adjustment for a port */
+typedef struct OMX_AUDIO_CONFIG_VOLUMETYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< Port index indicating which port to
+ set. Select the input port to set
+ just that port's volume. Select the
+ output port to adjust the master
+ volume. */
+ OMX_BOOL bLinear; /**< Is the volume to be set in linear (0.100)
+ or logarithmic scale (mB) */
+ OMX_BS32 sVolume; /**< Volume linear setting in the 0..100 range, OR
+ Volume logarithmic setting for this port. The values
+ for volume are in mB (millibels = 1/100 dB) relative
+ to a gain of 1 (e.g. the output is the same as the
+ input level). Values are in mB from nMax
+ (maximum volume) to nMin mB (typically negative).
+ Since the volume is "voltage"
+ and not a "power", it takes a setting of
+ -600 mB to decrease the volume by 1/2. If
+ a component cannot accurately set the
+ volume to the requested value, it must
+ set the volume to the closest value BELOW
+ the requested value. When getting the
+ volume setting, the current actual volume
+ must be returned. */
+} OMX_AUDIO_CONFIG_VOLUMETYPE;
+
+
+/** Audio Volume adjustment for a channel */
+typedef struct OMX_AUDIO_CONFIG_CHANNELVOLUMETYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< Port index indicating which port to
+ set. Select the input port to set
+ just that port's volume. Select the
+ output port to adjust the master
+ volume. */
+ OMX_U32 nChannel; /**< channel to select from 0 to N-1,
+ using OMX_ALL to apply volume settings
+ to all channels */
+ OMX_BOOL bLinear; /**< Is the volume to be set in linear (0.100) or
+ logarithmic scale (mB) */
+ OMX_BS32 sVolume; /**< Volume linear setting in the 0..100 range, OR
+ Volume logarithmic setting for this port.
+ The values for volume are in mB
+ (millibels = 1/100 dB) relative to a gain
+ of 1 (e.g. the output is the same as the
+ input level). Values are in mB from nMax
+ (maximum volume) to nMin mB (typically negative).
+ Since the volume is "voltage"
+ and not a "power", it takes a setting of
+ -600 mB to decrease the volume by 1/2. If
+ a component cannot accurately set the
+ volume to the requested value, it must
+ set the volume to the closest value BELOW
+ the requested value. When getting the
+ volume setting, the current actual volume
+ must be returned. */
+ OMX_BOOL bIsMIDI; /**< TRUE if nChannel refers to a MIDI channel,
+ FALSE otherwise */
+} OMX_AUDIO_CONFIG_CHANNELVOLUMETYPE;
+
+
+/** Audio balance setting */
+typedef struct OMX_AUDIO_CONFIG_BALANCETYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< Port index indicating which port to
+ set. Select the input port to set
+ just that port's balance. Select the
+ output port to adjust the master
+ balance. */
+ OMX_S32 nBalance; /**< balance setting for this port
+ (-100 to 100, where -100 indicates
+ all left, and no right */
+} OMX_AUDIO_CONFIG_BALANCETYPE;
+
+
+/** Audio Port mute */
+typedef struct OMX_AUDIO_CONFIG_MUTETYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< Port index indicating which port to
+ set. Select the input port to set
+ just that port's mute. Select the
+ output port to adjust the master
+ mute. */
+ OMX_BOOL bMute; /**< Mute setting for this port */
+} OMX_AUDIO_CONFIG_MUTETYPE;
+
+
+/** Audio Channel mute */
+typedef struct OMX_AUDIO_CONFIG_CHANNELMUTETYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nChannel; /**< channel to select from 0 to N-1,
+ using OMX_ALL to apply mute settings
+ to all channels */
+ OMX_BOOL bMute; /**< Mute setting for this channel */
+ OMX_BOOL bIsMIDI; /**< TRUE if nChannel refers to a MIDI channel,
+ FALSE otherwise */
+} OMX_AUDIO_CONFIG_CHANNELMUTETYPE;
+
+
+
+/** Enable / Disable for loudness control, which boosts bass and to a
+ * smaller extent high end frequencies to compensate for hearing
+ * ability at the extreme ends of the audio spectrum
+ */
+typedef struct OMX_AUDIO_CONFIG_LOUDNESSTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_BOOL bLoudness; /**< Enable/disable for loudness */
+} OMX_AUDIO_CONFIG_LOUDNESSTYPE;
+
+
+/** Enable / Disable for bass, which controls low frequencies
+ */
+typedef struct OMX_AUDIO_CONFIG_BASSTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_BOOL bEnable; /**< Enable/disable for bass control */
+ OMX_S32 nBass; /**< bass setting for the port, as a
+ continuous value from -100 to 100
+ (0 means no change in bass level)*/
+} OMX_AUDIO_CONFIG_BASSTYPE;
+
+
+/** Enable / Disable for treble, which controls high frequencies tones
+ */
+typedef struct OMX_AUDIO_CONFIG_TREBLETYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_BOOL bEnable; /**< Enable/disable for treble control */
+ OMX_S32 nTreble; /**< treble setting for the port, as a
+ continuous value from -100 to 100
+ (0 means no change in treble level) */
+} OMX_AUDIO_CONFIG_TREBLETYPE;
+
+
+/** An equalizer is typically used for two reasons: to compensate for an
+ * sub-optimal frequency response of a system to make it sound more natural
+ * or to create intentionally some unnatural coloring to the sound to create
+ * an effect.
+ * @ingroup effects
+ */
+typedef struct OMX_AUDIO_CONFIG_EQUALIZERTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_BOOL bEnable; /**< Enable/disable for equalizer */
+ OMX_BU32 sBandIndex; /**< Band number to be set. Upper Limit is
+ N-1, where N is the number of bands, lower limit is 0 */
+ OMX_BU32 sCenterFreq; /**< Center frequecies in Hz. This is a
+ read only element and is used to determine
+ the lower, center and upper frequency of
+ this band. */
+ OMX_BS32 sBandLevel; /**< band level in millibels */
+} OMX_AUDIO_CONFIG_EQUALIZERTYPE;
+
+
+/** Stereo widening mode type
+ * @ingroup effects
+ */
+typedef enum OMX_AUDIO_STEREOWIDENINGTYPE {
+ OMX_AUDIO_StereoWideningHeadphones, /**< Stereo widening for loudspeakers */
+ OMX_AUDIO_StereoWideningLoudspeakers, /**< Stereo widening for closely spaced loudspeakers */
+ OMX_AUDIO_StereoWideningKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_StereoWideningVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_StereoWideningMax = 0x7FFFFFFF
+} OMX_AUDIO_STEREOWIDENINGTYPE;
+
+
+/** Control for stereo widening, which is a special 2-channel
+ * case of the audio virtualizer effect. For example, for 5.1-channel
+ * output, it translates to virtual surround sound.
+ * @ingroup effects
+ */
+typedef struct OMX_AUDIO_CONFIG_STEREOWIDENINGTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_BOOL bEnable; /**< Enable/disable for stereo widening control */
+ OMX_AUDIO_STEREOWIDENINGTYPE eWideningType; /**< Stereo widening algorithm type */
+ OMX_U32 nStereoWidening; /**< stereo widening setting for the port,
+ as a continuous value from 0 to 100 */
+} OMX_AUDIO_CONFIG_STEREOWIDENINGTYPE;
+
+
+/** The chorus effect (or ``choralizer'') is any signal processor which makes
+ * one sound source (such as a voice) sound like many such sources singing
+ * (or playing) in unison. Since performance in unison is never exact, chorus
+ * effects simulate this by making independently modified copies of the input
+ * signal. Modifications may include (1) delay, (2) frequency shift, and
+ * (3) amplitude modulation.
+ * @ingroup effects
+ */
+typedef struct OMX_AUDIO_CONFIG_CHORUSTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_BOOL bEnable; /**< Enable/disable for chorus */
+ OMX_BU32 sDelay; /**< average delay in milliseconds */
+ OMX_BU32 sModulationRate; /**< rate of modulation in millihertz */
+ OMX_U32 nModulationDepth; /**< depth of modulation as a percentage of
+ delay (i.e. 0 to 100) */
+ OMX_BU32 nFeedback; /**< Feedback from chorus output to input in percentage */
+} OMX_AUDIO_CONFIG_CHORUSTYPE;
+
+
+/** Reverberation is part of the reflected sound that follows the early
+ * reflections. In a typical room, this consists of a dense succession of
+ * echoes whose energy decays exponentially. The reverberation effect structure
+ * as defined here includes both (early) reflections as well as (late) reverberations.
+ * @ingroup effects
+ */
+typedef struct OMX_AUDIO_CONFIG_REVERBERATIONTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_BOOL bEnable; /**< Enable/disable for reverberation control */
+ OMX_BS32 sRoomLevel; /**< Intensity level for the whole room effect
+ (i.e. both early reflections and late
+ reverberation) in millibels */
+ OMX_BS32 sRoomHighFreqLevel; /**< Attenuation at high frequencies
+ relative to the intensity at low
+ frequencies in millibels */
+ OMX_BS32 sReflectionsLevel; /**< Intensity level of early reflections
+ (relative to room value), in millibels */
+ OMX_BU32 sReflectionsDelay; /**< Delay time of the first reflection relative
+ to the direct path, in milliseconds */
+ OMX_BS32 sReverbLevel; /**< Intensity level of late reverberation
+ relative to room level, in millibels */
+ OMX_BU32 sReverbDelay; /**< Time delay from the first early reflection
+ to the beginning of the late reverberation
+ section, in milliseconds */
+ OMX_BU32 sDecayTime; /**< Late reverberation decay time at low
+ frequencies, in milliseconds */
+ OMX_BU32 nDecayHighFreqRatio; /**< Ratio of high frequency decay time relative
+ to low frequency decay time in percent */
+ OMX_U32 nDensity; /**< Modal density in the late reverberation decay,
+ in percent (i.e. 0 - 100) */
+ OMX_U32 nDiffusion; /**< Echo density in the late reverberation decay,
+ in percent (i.e. 0 - 100) */
+ OMX_BU32 sReferenceHighFreq; /**< Reference high frequency in Hertz. This is
+ the frequency used as the reference for all
+ the high-frequency settings above */
+
+} OMX_AUDIO_CONFIG_REVERBERATIONTYPE;
+
+
+/** Possible settings for the Echo Cancelation structure to use
+ * @ingroup effects
+ */
+typedef enum OMX_AUDIO_ECHOCANTYPE {
+ OMX_AUDIO_EchoCanOff = 0, /**< Echo Cancellation is disabled */
+ OMX_AUDIO_EchoCanNormal, /**< Echo Cancellation normal operation -
+ echo from plastics and face */
+ OMX_AUDIO_EchoCanHFree, /**< Echo Cancellation optimized for
+ Hands Free operation */
+ OMX_AUDIO_EchoCanCarKit, /**< Echo Cancellation optimized for
+ Car Kit (longer echo) */
+ OMX_AUDIO_EchoCanKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_AUDIO_EchoCanVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_AUDIO_EchoCanMax = 0x7FFFFFFF
+} OMX_AUDIO_ECHOCANTYPE;
+
+
+/** Enable / Disable for echo cancelation, which removes undesired echo's
+ * from the audio
+ * @ingroup effects
+ */
+typedef struct OMX_AUDIO_CONFIG_ECHOCANCELATIONTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_AUDIO_ECHOCANTYPE eEchoCancelation; /**< Echo cancelation settings */
+} OMX_AUDIO_CONFIG_ECHOCANCELATIONTYPE;
+
+
+/** Enable / Disable for noise reduction, which undesired noise from
+ * the audio
+ * @ingroup effects
+ */
+typedef struct OMX_AUDIO_CONFIG_NOISEREDUCTIONTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_BOOL bNoiseReduction; /**< Enable/disable for noise reduction */
+} OMX_AUDIO_CONFIG_NOISEREDUCTIONTYPE;
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
+/* File EOF */
+
diff --git a/subprojects/gst-omx/omx/openmax/OMX_Component.h b/subprojects/gst-omx/omx/openmax/OMX_Component.h
new file mode 100644
index 0000000000..d5956405e2
--- /dev/null
+++ b/subprojects/gst-omx/omx/openmax/OMX_Component.h
@@ -0,0 +1,579 @@
+/*
+ * Copyright (c) 2008 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/** OMX_Component.h - OpenMax IL version 1.1.2
+ * The OMX_Component header file contains the definitions used to define
+ * the public interface of a component. This header file is intended to
+ * be used by both the application and the component.
+ */
+
+#ifndef OMX_Component_h
+#define OMX_Component_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+
+/* Each OMX header must include all required header files to allow the
+ * header to compile without errors. The includes below are required
+ * for this header file to compile successfully
+ */
+
+#include <OMX_Audio.h>
+#include <OMX_Video.h>
+#include <OMX_Image.h>
+#include <OMX_Other.h>
+
+/** @ingroup comp */
+typedef enum OMX_PORTDOMAINTYPE {
+ OMX_PortDomainAudio,
+ OMX_PortDomainVideo,
+ OMX_PortDomainImage,
+ OMX_PortDomainOther,
+ OMX_PortDomainKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_PortDomainVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_PortDomainMax = 0x7ffffff
+} OMX_PORTDOMAINTYPE;
+
+/** @ingroup comp */
+typedef struct OMX_PARAM_PORTDEFINITIONTYPE {
+ OMX_U32 nSize; /**< Size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< Port number the structure applies to */
+ OMX_DIRTYPE eDir; /**< Direction (input or output) of this port */
+ OMX_U32 nBufferCountActual; /**< The actual number of buffers allocated on this port */
+ OMX_U32 nBufferCountMin; /**< The minimum number of buffers this port requires */
+ OMX_U32 nBufferSize; /**< Size, in bytes, for buffers to be used for this channel */
+ OMX_BOOL bEnabled; /**< Ports default to enabled and are enabled/disabled by
+ OMX_CommandPortEnable/OMX_CommandPortDisable.
+ When disabled a port is unpopulated. A disabled port
+ is not populated with buffers on a transition to IDLE. */
+ OMX_BOOL bPopulated; /**< Port is populated with all of its buffers as indicated by
+ nBufferCountActual. A disabled port is always unpopulated.
+ An enabled port is populated on a transition to OMX_StateIdle
+ and unpopulated on a transition to loaded. */
+ OMX_PORTDOMAINTYPE eDomain; /**< Domain of the port. Determines the contents of metadata below. */
+ union {
+ OMX_AUDIO_PORTDEFINITIONTYPE audio;
+ OMX_VIDEO_PORTDEFINITIONTYPE video;
+ OMX_IMAGE_PORTDEFINITIONTYPE image;
+ OMX_OTHER_PORTDEFINITIONTYPE other;
+ } format;
+ OMX_BOOL bBuffersContiguous;
+ OMX_U32 nBufferAlignment;
+} OMX_PARAM_PORTDEFINITIONTYPE;
+
+/** @ingroup comp */
+typedef struct OMX_PARAM_U32TYPE {
+ OMX_U32 nSize; /**< Size of this structure, in Bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_U32 nU32; /**< U32 value */
+} OMX_PARAM_U32TYPE;
+
+/** @ingroup rpm */
+typedef enum OMX_SUSPENSIONPOLICYTYPE {
+ OMX_SuspensionDisabled, /**< No suspension; v1.0 behavior */
+ OMX_SuspensionEnabled, /**< Suspension allowed */
+ OMX_SuspensionPolicyKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_SuspensionPolicyStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_SuspensionPolicyMax = 0x7fffffff
+} OMX_SUSPENSIONPOLICYTYPE;
+
+/** @ingroup rpm */
+typedef struct OMX_PARAM_SUSPENSIONPOLICYTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_SUSPENSIONPOLICYTYPE ePolicy;
+} OMX_PARAM_SUSPENSIONPOLICYTYPE;
+
+/** @ingroup rpm */
+typedef enum OMX_SUSPENSIONTYPE {
+ OMX_NotSuspended, /**< component is not suspended */
+ OMX_Suspended, /**< component is suspended */
+ OMX_SuspensionKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_SuspensionVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_SuspendMax = 0x7FFFFFFF
+} OMX_SUSPENSIONTYPE;
+
+/** @ingroup rpm */
+typedef struct OMX_PARAM_SUSPENSIONTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_SUSPENSIONTYPE eType;
+} OMX_PARAM_SUSPENSIONTYPE ;
+
+typedef struct OMX_CONFIG_BOOLEANTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_BOOL bEnabled;
+} OMX_CONFIG_BOOLEANTYPE;
+
+/* Parameter specifying the content uri to use. */
+/** @ingroup cp */
+typedef struct OMX_PARAM_CONTENTURITYPE
+{
+ OMX_U32 nSize; /**< size of the structure in bytes, including
+ actual URI name */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U8 contentURI[1]; /**< The URI name */
+} OMX_PARAM_CONTENTURITYPE;
+
+/* Parameter specifying the pipe to use. */
+/** @ingroup cp */
+typedef struct OMX_PARAM_CONTENTPIPETYPE
+{
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_HANDLETYPE hPipe; /**< The pipe handle*/
+} OMX_PARAM_CONTENTPIPETYPE;
+
+/** @ingroup rpm */
+typedef struct OMX_RESOURCECONCEALMENTTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_BOOL bResourceConcealmentForbidden; /**< disallow the use of resource concealment
+ methods (like degrading algorithm quality to
+ lower resource consumption or functional bypass)
+ on a component as a resolution to resource conflicts. */
+} OMX_RESOURCECONCEALMENTTYPE;
+
+
+/** @ingroup metadata */
+typedef enum OMX_METADATACHARSETTYPE {
+ OMX_MetadataCharsetUnknown = 0,
+ OMX_MetadataCharsetASCII,
+ OMX_MetadataCharsetBinary,
+ OMX_MetadataCharsetCodePage1252,
+ OMX_MetadataCharsetUTF8,
+ OMX_MetadataCharsetJavaConformantUTF8,
+ OMX_MetadataCharsetUTF7,
+ OMX_MetadataCharsetImapUTF7,
+ OMX_MetadataCharsetUTF16LE,
+ OMX_MetadataCharsetUTF16BE,
+ OMX_MetadataCharsetGB12345,
+ OMX_MetadataCharsetHZGB2312,
+ OMX_MetadataCharsetGB2312,
+ OMX_MetadataCharsetGB18030,
+ OMX_MetadataCharsetGBK,
+ OMX_MetadataCharsetBig5,
+ OMX_MetadataCharsetISO88591,
+ OMX_MetadataCharsetISO88592,
+ OMX_MetadataCharsetISO88593,
+ OMX_MetadataCharsetISO88594,
+ OMX_MetadataCharsetISO88595,
+ OMX_MetadataCharsetISO88596,
+ OMX_MetadataCharsetISO88597,
+ OMX_MetadataCharsetISO88598,
+ OMX_MetadataCharsetISO88599,
+ OMX_MetadataCharsetISO885910,
+ OMX_MetadataCharsetISO885913,
+ OMX_MetadataCharsetISO885914,
+ OMX_MetadataCharsetISO885915,
+ OMX_MetadataCharsetShiftJIS,
+ OMX_MetadataCharsetISO2022JP,
+ OMX_MetadataCharsetISO2022JP1,
+ OMX_MetadataCharsetISOEUCJP,
+ OMX_MetadataCharsetSMS7Bit,
+ OMX_MetadataCharsetKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_MetadataCharsetVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_MetadataCharsetTypeMax= 0x7FFFFFFF
+} OMX_METADATACHARSETTYPE;
+
+/** @ingroup metadata */
+typedef enum OMX_METADATASCOPETYPE
+{
+ OMX_MetadataScopeAllLevels,
+ OMX_MetadataScopeTopLevel,
+ OMX_MetadataScopePortLevel,
+ OMX_MetadataScopeNodeLevel,
+ OMX_MetadataScopeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_MetadataScopeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_MetadataScopeTypeMax = 0x7fffffff
+} OMX_METADATASCOPETYPE;
+
+/** @ingroup metadata */
+typedef enum OMX_METADATASEARCHMODETYPE
+{
+ OMX_MetadataSearchValueSizeByIndex,
+ OMX_MetadataSearchItemByIndex,
+ OMX_MetadataSearchNextItemByKey,
+ OMX_MetadataSearchKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_MetadataSearchVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_MetadataSearchTypeMax = 0x7fffffff
+} OMX_METADATASEARCHMODETYPE;
+/** @ingroup metadata */
+typedef struct OMX_CONFIG_METADATAITEMCOUNTTYPE
+{
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_METADATASCOPETYPE eScopeMode;
+ OMX_U32 nScopeSpecifier;
+ OMX_U32 nMetadataItemCount;
+} OMX_CONFIG_METADATAITEMCOUNTTYPE;
+
+/** @ingroup metadata */
+typedef struct OMX_CONFIG_METADATAITEMTYPE
+{
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_METADATASCOPETYPE eScopeMode;
+ OMX_U32 nScopeSpecifier;
+ OMX_U32 nMetadataItemIndex;
+ OMX_METADATASEARCHMODETYPE eSearchMode;
+ OMX_METADATACHARSETTYPE eKeyCharset;
+ OMX_U8 nKeySizeUsed;
+ OMX_U8 nKey[128];
+ OMX_METADATACHARSETTYPE eValueCharset;
+ OMX_STRING sLanguageCountry;
+ OMX_U32 nValueMaxSize;
+ OMX_U32 nValueSizeUsed;
+ OMX_U8 nValue[1];
+} OMX_CONFIG_METADATAITEMTYPE;
+
+/* @ingroup metadata */
+typedef struct OMX_CONFIG_CONTAINERNODECOUNTTYPE
+{
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_BOOL bAllKeys;
+ OMX_U32 nParentNodeID;
+ OMX_U32 nNumNodes;
+} OMX_CONFIG_CONTAINERNODECOUNTTYPE;
+
+/** @ingroup metadata */
+typedef struct OMX_CONFIG_CONTAINERNODEIDTYPE
+{
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_BOOL bAllKeys;
+ OMX_U32 nParentNodeID;
+ OMX_U32 nNodeIndex;
+ OMX_U32 nNodeID;
+ OMX_STRING cNodeName;
+ OMX_BOOL bIsLeafType;
+} OMX_CONFIG_CONTAINERNODEIDTYPE;
+
+/** @ingroup metadata */
+typedef struct OMX_PARAM_METADATAFILTERTYPE
+{
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_BOOL bAllKeys; /* if true then this structure refers to all keys and
+ * the three key fields below are ignored */
+ OMX_METADATACHARSETTYPE eKeyCharset;
+ OMX_U32 nKeySizeUsed;
+ OMX_U8 nKey [128];
+ OMX_U32 nLanguageCountrySizeUsed;
+ OMX_U8 nLanguageCountry[128];
+ OMX_BOOL bEnabled; /* if true then key is part of filter (e.g.
+ * retained for query later). If false then
+ * key is not part of filter */
+} OMX_PARAM_METADATAFILTERTYPE;
+
+/** The OMX_HANDLETYPE structure defines the component handle. The component
+ * handle is used to access all of the component's public methods and also
+ * contains pointers to the component's private data area. The component
+ * handle is initialized by the OMX core (with help from the component)
+ * during the process of loading the component. After the component is
+ * successfully loaded, the application can safely access any of the
+ * component's public functions (although some may return an error because
+ * the state is inappropriate for the access).
+ *
+ * @ingroup comp
+ */
+typedef struct OMX_COMPONENTTYPE
+{
+ /** The size of this structure, in bytes. It is the responsibility
+ of the allocator of this structure to fill in this value. Since
+ this structure is allocated by the GetHandle function, this
+ function will fill in this value. */
+ OMX_U32 nSize;
+
+ /** nVersion is the version of the OMX specification that the structure
+ is built against. It is the responsibility of the creator of this
+ structure to initialize this value and every user of this structure
+ should verify that it knows how to use the exact version of
+ this structure found herein. */
+ OMX_VERSIONTYPE nVersion;
+
+ /** pComponentPrivate is a pointer to the component private data area.
+ This member is allocated and initialized by the component when the
+ component is first loaded. The application should not access this
+ data area. */
+ OMX_PTR pComponentPrivate;
+
+ /** pApplicationPrivate is a pointer that is a parameter to the
+ OMX_GetHandle method, and contains an application private value
+ provided by the IL client. This application private data is
+ returned to the IL Client by OMX in all callbacks */
+ OMX_PTR pApplicationPrivate;
+
+ /** refer to OMX_GetComponentVersion in OMX_core.h or the OMX IL
+ specification for details on the GetComponentVersion method.
+ */
+ OMX_ERRORTYPE (*GetComponentVersion)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_OUT OMX_STRING pComponentName,
+ OMX_OUT OMX_VERSIONTYPE* pComponentVersion,
+ OMX_OUT OMX_VERSIONTYPE* pSpecVersion,
+ OMX_OUT OMX_UUIDTYPE* pComponentUUID);
+
+ /** refer to OMX_SendCommand in OMX_core.h or the OMX IL
+ specification for details on the SendCommand method.
+ */
+ OMX_ERRORTYPE (*SendCommand)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_COMMANDTYPE Cmd,
+ OMX_IN OMX_U32 nParam1,
+ OMX_IN OMX_PTR pCmdData);
+
+ /** refer to OMX_GetParameter in OMX_core.h or the OMX IL
+ specification for details on the GetParameter method.
+ */
+ OMX_ERRORTYPE (*GetParameter)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_INDEXTYPE nParamIndex,
+ OMX_INOUT OMX_PTR pComponentParameterStructure);
+
+
+ /** refer to OMX_SetParameter in OMX_core.h or the OMX IL
+ specification for details on the SetParameter method.
+ */
+ OMX_ERRORTYPE (*SetParameter)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_INDEXTYPE nIndex,
+ OMX_IN OMX_PTR pComponentParameterStructure);
+
+
+ /** refer to OMX_GetConfig in OMX_core.h or the OMX IL
+ specification for details on the GetConfig method.
+ */
+ OMX_ERRORTYPE (*GetConfig)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_INDEXTYPE nIndex,
+ OMX_INOUT OMX_PTR pComponentConfigStructure);
+
+
+ /** refer to OMX_SetConfig in OMX_core.h or the OMX IL
+ specification for details on the SetConfig method.
+ */
+ OMX_ERRORTYPE (*SetConfig)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_INDEXTYPE nIndex,
+ OMX_IN OMX_PTR pComponentConfigStructure);
+
+
+ /** refer to OMX_GetExtensionIndex in OMX_core.h or the OMX IL
+ specification for details on the GetExtensionIndex method.
+ */
+ OMX_ERRORTYPE (*GetExtensionIndex)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_STRING cParameterName,
+ OMX_OUT OMX_INDEXTYPE* pIndexType);
+
+
+ /** refer to OMX_GetState in OMX_core.h or the OMX IL
+ specification for details on the GetState method.
+ */
+ OMX_ERRORTYPE (*GetState)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_OUT OMX_STATETYPE* pState);
+
+
+ /** The ComponentTunnelRequest method will interact with another OMX
+ component to determine if tunneling is possible and to setup the
+ tunneling. The return codes for this method can be used to
+ determine if tunneling is not possible, or if tunneling is not
+ supported.
+
+ Base profile components (i.e. non-interop) do not support this
+ method and should return OMX_ErrorNotImplemented
+
+ The interop profile component MUST support tunneling to another
+ interop profile component with a compatible port parameters.
+ A component may also support proprietary communication.
+
+ If proprietary communication is supported the negotiation of
+ proprietary communication is done outside of OMX in a vendor
+ specific way. It is only required that the proper result be
+ returned and the details of how the setup is done is left
+ to the component implementation.
+
+ When this method is invoked when nPort in an output port, the
+ component will:
+ 1. Populate the pTunnelSetup structure with the output port's
+ requirements and constraints for the tunnel.
+
+ When this method is invoked when nPort in an input port, the
+ component will:
+ 1. Query the necessary parameters from the output port to
+ determine if the ports are compatible for tunneling
+ 2. If the ports are compatible, the component should store
+ the tunnel step provided by the output port
+ 3. Determine which port (either input or output) is the buffer
+ supplier, and call OMX_SetParameter on the output port to
+ indicate this selection.
+
+ The component will return from this call within 5 msec.
+
+ @param [in] hComp
+ Handle of the component to be accessed. This is the component
+ handle returned by the call to the OMX_GetHandle method.
+ @param [in] nPort
+ nPort is used to select the port on the component to be used
+ for tunneling.
+ @param [in] hTunneledComp
+ Handle of the component to tunnel with. This is the component
+ handle returned by the call to the OMX_GetHandle method. When
+ this parameter is 0x0 the component should setup the port for
+ communication with the application / IL Client.
+ @param [in] nPortOutput
+ nPortOutput is used indicate the port the component should
+ tunnel with.
+ @param [in] pTunnelSetup
+ Pointer to the tunnel setup structure. When nPort is an output port
+ the component should populate the fields of this structure. When
+ When nPort is an input port the component should review the setup
+ provided by the component with the output port.
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup tun
+ */
+
+ OMX_ERRORTYPE (*ComponentTunnelRequest)(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_U32 nPort,
+ OMX_IN OMX_HANDLETYPE hTunneledComp,
+ OMX_IN OMX_U32 nTunneledPort,
+ OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup);
+
+ /** refer to OMX_UseBuffer in OMX_core.h or the OMX IL
+ specification for details on the UseBuffer method.
+ @ingroup buf
+ */
+ OMX_ERRORTYPE (*UseBuffer)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
+ OMX_IN OMX_U32 nPortIndex,
+ OMX_IN OMX_PTR pAppPrivate,
+ OMX_IN OMX_U32 nSizeBytes,
+ OMX_IN OMX_U8* pBuffer);
+
+ /** refer to OMX_AllocateBuffer in OMX_core.h or the OMX IL
+ specification for details on the AllocateBuffer method.
+ @ingroup buf
+ */
+ OMX_ERRORTYPE (*AllocateBuffer)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** ppBuffer,
+ OMX_IN OMX_U32 nPortIndex,
+ OMX_IN OMX_PTR pAppPrivate,
+ OMX_IN OMX_U32 nSizeBytes);
+
+ /** refer to OMX_FreeBuffer in OMX_core.h or the OMX IL
+ specification for details on the FreeBuffer method.
+ @ingroup buf
+ */
+ OMX_ERRORTYPE (*FreeBuffer)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_U32 nPortIndex,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ /** refer to OMX_EmptyThisBuffer in OMX_core.h or the OMX IL
+ specification for details on the EmptyThisBuffer method.
+ @ingroup buf
+ */
+ OMX_ERRORTYPE (*EmptyThisBuffer)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ /** refer to OMX_FillThisBuffer in OMX_core.h or the OMX IL
+ specification for details on the FillThisBuffer method.
+ @ingroup buf
+ */
+ OMX_ERRORTYPE (*FillThisBuffer)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ /** The SetCallbacks method is used by the core to specify the callback
+ structure from the application to the component. This is a blocking
+ call. The component will return from this call within 5 msec.
+ @param [in] hComponent
+ Handle of the component to be accessed. This is the component
+ handle returned by the call to the GetHandle function.
+ @param [in] pCallbacks
+ pointer to an OMX_CALLBACKTYPE structure used to provide the
+ callback information to the component
+ @param [in] pAppData
+ pointer to an application defined value. It is anticipated that
+ the application will pass a pointer to a data structure or a "this
+ pointer" in this area to allow the callback (in the application)
+ to determine the context of the call
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ */
+ OMX_ERRORTYPE (*SetCallbacks)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_CALLBACKTYPE* pCallbacks,
+ OMX_IN OMX_PTR pAppData);
+
+ /** ComponentDeInit method is used to deinitialize the component
+ providing a means to free any resources allocated at component
+ initialization. NOTE: After this call the component handle is
+ not valid for further use.
+ @param [in] hComponent
+ Handle of the component to be accessed. This is the component
+ handle returned by the call to the GetHandle function.
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ */
+ OMX_ERRORTYPE (*ComponentDeInit)(
+ OMX_IN OMX_HANDLETYPE hComponent);
+
+ /** @ingroup buf */
+ OMX_ERRORTYPE (*UseEGLImage)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
+ OMX_IN OMX_U32 nPortIndex,
+ OMX_IN OMX_PTR pAppPrivate,
+ OMX_IN void* eglImage);
+
+ OMX_ERRORTYPE (*ComponentRoleEnum)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_OUT OMX_U8 *cRole,
+ OMX_IN OMX_U32 nIndex);
+
+} OMX_COMPONENTTYPE;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
+/* File EOF */
diff --git a/subprojects/gst-omx/omx/openmax/OMX_ComponentExt.h b/subprojects/gst-omx/omx/openmax/OMX_ComponentExt.h
new file mode 100644
index 0000000000..e5aa74871c
--- /dev/null
+++ b/subprojects/gst-omx/omx/openmax/OMX_ComponentExt.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2010 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/** OMX_ComponentExt.h - OpenMax IL version 1.1.2
+ * The OMX_ComponentExt header file contains extensions to the definitions used
+ * by both the application and the component to access common items.
+ */
+
+#ifndef OMX_ComponentExt_h
+#define OMX_ComponentExt_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Each OMX header must include all required header files to allow the
+ * header to compile without errors. The includes below are required
+ * for this header file to compile successfully
+ */
+#include <OMX_Types.h>
+
+
+/** Set/query the commit mode */
+typedef struct OMX_CONFIG_COMMITMODETYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_BOOL bDeferred;
+} OMX_CONFIG_COMMITMODETYPE;
+
+/** Explicit commit */
+typedef struct OMX_CONFIG_COMMITTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+} OMX_CONFIG_COMMITTYPE;
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* OMX_ComponentExt_h */
diff --git a/subprojects/gst-omx/omx/openmax/OMX_ContentPipe.h b/subprojects/gst-omx/omx/openmax/OMX_ContentPipe.h
new file mode 100644
index 0000000000..5f6310c28a
--- /dev/null
+++ b/subprojects/gst-omx/omx/openmax/OMX_ContentPipe.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2008 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/** OMX_ContentPipe.h - OpenMax IL version 1.1.2
+ * The OMX_ContentPipe header file contains the definitions used to define
+ * the public interface for content piples. This header file is intended to
+ * be used by the component.
+ */
+
+#ifndef OMX_CONTENTPIPE_H
+#define OMX_CONTENTPIPE_H
+
+#ifndef KD_EACCES
+/* OpenKODE error codes. CPResult values may be zero (indicating success
+ or one of the following values) */
+#define KD_EACCES (1)
+#define KD_EADDRINUSE (2)
+#define KD_EAGAIN (5)
+#define KD_EBADF (7)
+#define KD_EBUSY (8)
+#define KD_ECONNREFUSED (9)
+#define KD_ECONNRESET (10)
+#define KD_EDEADLK (11)
+#define KD_EDESTADDRREQ (12)
+#define KD_ERANGE (35)
+#define KD_EEXIST (13)
+#define KD_EFBIG (14)
+#define KD_EHOSTUNREACH (15)
+#define KD_EINVAL (17)
+#define KD_EIO (18)
+#define KD_EISCONN (20)
+#define KD_EISDIR (21)
+#define KD_EMFILE (22)
+#define KD_ENAMETOOLONG (23)
+#define KD_ENOENT (24)
+#define KD_ENOMEM (25)
+#define KD_ENOSPC (26)
+#define KD_ENOSYS (27)
+#define KD_ENOTCONN (28)
+#define KD_EPERM (33)
+#define KD_ETIMEDOUT (36)
+#define KD_EILSEQ (19)
+#endif
+
+/** Map types from OMX standard types only here so interface is as generic as possible. */
+typedef OMX_U32 CPresult;
+typedef char * CPstring;
+typedef void * CPhandle;
+typedef OMX_U32 CPuint;
+typedef OMX_S32 CPint;
+typedef char CPbyte;
+typedef OMX_BOOL CPbool;
+
+/** enumeration of origin types used in the CP_PIPETYPE's Seek function
+ * @ingroup cp
+ */
+typedef enum CP_ORIGINTYPE {
+ CP_OriginBegin,
+ CP_OriginCur,
+ CP_OriginEnd,
+ CP_OriginKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ CP_OriginVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ CP_OriginMax = 0X7FFFFFFF
+} CP_ORIGINTYPE;
+
+/** enumeration of contact access types used in the CP_PIPETYPE's Open function
+ * @ingroup cp
+ */
+typedef enum CP_ACCESSTYPE {
+ CP_AccessRead,
+ CP_AccessWrite,
+ CP_AccessReadWrite ,
+ CP_AccessKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ CP_AccessVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ CP_AccessMax = 0X7FFFFFFF
+} CP_ACCESSTYPE;
+
+/** enumeration of results returned by the CP_PIPETYPE's CheckAvailableBytes function
+ * @ingroup cp
+ */
+typedef enum CP_CHECKBYTESRESULTTYPE
+{
+ CP_CheckBytesOk, /**< There are at least the request number
+ of bytes available */
+ CP_CheckBytesNotReady, /**< The pipe is still retrieving bytes
+ and presently lacks sufficient bytes.
+ Client will be called when they are
+ sufficient bytes are available. */
+ CP_CheckBytesInsufficientBytes , /**< The pipe has retrieved all bytes
+ but those available are less than those
+ requested */
+ CP_CheckBytesAtEndOfStream, /**< The pipe has reached the end of stream
+ and no more bytes are available. */
+ CP_CheckBytesOutOfBuffers, /**< All read/write buffers are currently in use. */
+ CP_CheckBytesKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ CP_CheckBytesVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ CP_CheckBytesMax = 0X7FFFFFFF
+} CP_CHECKBYTESRESULTTYPE;
+
+/** enumeration of content pipe events sent to the client callback.
+ * @ingroup cp
+ */
+typedef enum CP_EVENTTYPE{
+ CP_BytesAvailable, /** bytes requested in a CheckAvailableBytes call are now available*/
+ CP_Overflow, /** enumeration of content pipe events sent to the client callback*/
+ CP_PipeDisconnected , /** enumeration of content pipe events sent to the client callback*/
+ CP_EventKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ CP_EventVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ CP_EventMax = 0X7FFFFFFF
+} CP_EVENTTYPE;
+
+/** content pipe definition
+ * @ingroup cp
+ */
+typedef struct CP_PIPETYPE
+{
+ /** Open a content stream for reading or writing. */
+ CPresult (*Open)( CPhandle* hContent, CPstring szURI, CP_ACCESSTYPE eAccess );
+
+ /** Close a content stream. */
+ CPresult (*Close)( CPhandle hContent );
+
+ /** Create a content source and open it for writing. */
+ CPresult (*Create)( CPhandle *hContent, CPstring szURI );
+
+ /** Check the that specified number of bytes are available for reading or writing (depending on access type).*/
+ CPresult (*CheckAvailableBytes)( CPhandle hContent, CPuint nBytesRequested, CP_CHECKBYTESRESULTTYPE *eResult );
+
+ /** Seek to certain position in the content relative to the specified origin. */
+ CPresult (*SetPosition)( CPhandle hContent, CPint nOffset, CP_ORIGINTYPE eOrigin);
+
+ /** Retrieve the current position relative to the start of the content. */
+ CPresult (*GetPosition)( CPhandle hContent, CPuint *pPosition);
+
+ /** Retrieve data of the specified size from the content stream (advance content pointer by size of data).
+ Note: pipe client provides pointer. This function is appropriate for small high frequency reads. */
+ CPresult (*Read)( CPhandle hContent, CPbyte *pData, CPuint nSize);
+
+ /** Retrieve a buffer allocated by the pipe that contains the requested number of bytes.
+ Buffer contains the next block of bytes, as specified by nSize, of the content. nSize also
+ returns the size of the block actually read. Content pointer advances the by the returned size.
+ Note: pipe provides pointer. This function is appropriate for large reads. The client must call
+ ReleaseReadBuffer when done with buffer.
+
+ In some cases the requested block may not reside in contiguous memory within the
+ pipe implementation. For instance if the pipe leverages a circular buffer then the requested
+ block may straddle the boundary of the circular buffer. By default a pipe implementation
+ performs a copy in this case to provide the block to the pipe client in one contiguous buffer.
+ If, however, the client sets bForbidCopy, then the pipe returns only those bytes preceding the memory
+ boundary. Here the client may retrieve the data in segments over successive calls. */
+ CPresult (*ReadBuffer)( CPhandle hContent, CPbyte **ppBuffer, CPuint *nSize, CPbool bForbidCopy);
+
+ /** Release a buffer obtained by ReadBuffer back to the pipe. */
+ CPresult (*ReleaseReadBuffer)(CPhandle hContent, CPbyte *pBuffer);
+
+ /** Write data of the specified size to the content (advance content pointer by size of data).
+ Note: pipe client provides pointer. This function is appropriate for small high frequency writes. */
+ CPresult (*Write)( CPhandle hContent, CPbyte *data, CPuint nSize);
+
+ /** Retrieve a buffer allocated by the pipe used to write data to the content.
+ Client will fill buffer with output data. Note: pipe provides pointer. This function is appropriate
+ for large writes. The client must call WriteBuffer when done it has filled the buffer with data.*/
+ CPresult (*GetWriteBuffer)( CPhandle hContent, CPbyte **ppBuffer, CPuint nSize);
+
+ /** Deliver a buffer obtained via GetWriteBuffer to the pipe. Pipe will write the
+ the contents of the buffer to content and advance content pointer by the size of the buffer */
+ CPresult (*WriteBuffer)( CPhandle hContent, CPbyte *pBuffer, CPuint nFilledSize);
+
+ /** Register a per-handle client callback with the content pipe. */
+ CPresult (*RegisterCallback)( CPhandle hContent, CPresult (*ClientCallback)(CP_EVENTTYPE eEvent, CPuint iParam));
+
+} CP_PIPETYPE;
+
+#endif
+
diff --git a/subprojects/gst-omx/omx/openmax/OMX_Core.h b/subprojects/gst-omx/omx/openmax/OMX_Core.h
new file mode 100644
index 0000000000..a076f2f479
--- /dev/null
+++ b/subprojects/gst-omx/omx/openmax/OMX_Core.h
@@ -0,0 +1,1431 @@
+/*
+ * Copyright (c) 2008 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/** OMX_Core.h - OpenMax IL version 1.1.2
+ * The OMX_Core header file contains the definitions used by both the
+ * application and the component to access common items.
+ */
+
+#ifndef OMX_Core_h
+#define OMX_Core_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* Each OMX header shall include all required header files to allow the
+ * header to compile without errors. The includes below are required
+ * for this header file to compile successfully
+ */
+
+#include <OMX_Index.h>
+
+
+/** The OMX_COMMANDTYPE enumeration is used to specify the action in the
+ * OMX_SendCommand macro.
+ * @ingroup core
+ */
+typedef enum OMX_COMMANDTYPE
+{
+ OMX_CommandStateSet, /**< Change the component state */
+ OMX_CommandFlush, /**< Flush the data queue(s) of a component */
+ OMX_CommandPortDisable, /**< Disable a port on a component. */
+ OMX_CommandPortEnable, /**< Enable a port on a component. */
+ OMX_CommandMarkBuffer, /**< Mark a component/buffer for observation */
+ OMX_CommandKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_CommandVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_CommandMax = 0X7FFFFFFF
+} OMX_COMMANDTYPE;
+
+
+
+/** The OMX_STATETYPE enumeration is used to indicate or change the component
+ * state. This enumeration reflects the current state of the component when
+ * used with the OMX_GetState macro or becomes the parameter in a state change
+ * command when used with the OMX_SendCommand macro.
+ *
+ * The component will be in the Loaded state after the component is initially
+ * loaded into memory. In the Loaded state, the component is not allowed to
+ * allocate or hold resources other than to build it's internal parameter
+ * and configuration tables. The application will send one or more
+ * SetParameters/GetParameters and SetConfig/GetConfig commands to the
+ * component and the component will record each of these parameter and
+ * configuration changes for use later. When the application sends the
+ * Idle command, the component will acquire the resources needed for the
+ * specified configuration and will transition to the idle state if the
+ * allocation is successful. If the component cannot successfully
+ * transition to the idle state for any reason, the state of the component
+ * shall be fully rolled back to the Loaded state (e.g. all allocated
+ * resources shall be released). When the component receives the command
+ * to go to the Executing state, it shall begin processing buffers by
+ * sending all input buffers it holds to the application. While
+ * the component is in the Idle state, the application may also send the
+ * Pause command. If the component receives the pause command while in the
+ * Idle state, the component shall send all input buffers it holds to the
+ * application, but shall not begin processing buffers. This will allow the
+ * application to prefill buffers.
+ *
+ * @ingroup comp
+ */
+
+typedef enum OMX_STATETYPE
+{
+ OMX_StateInvalid, /**< component has detected that it's internal data
+ structures are corrupted to the point that
+ it cannot determine it's state properly */
+ OMX_StateLoaded, /**< component has been loaded but has not completed
+ initialization. The OMX_SetParameter macro
+ and the OMX_GetParameter macro are the only
+ valid macros allowed to be sent to the
+ component in this state. */
+ OMX_StateIdle, /**< component initialization has been completed
+ successfully and the component is ready to
+ to start. */
+ OMX_StateExecuting, /**< component has accepted the start command and
+ is processing data (if data is available) */
+ OMX_StatePause, /**< component has received pause command */
+ OMX_StateWaitForResources, /**< component is waiting for resources, either after
+ preemption or before it gets the resources requested.
+ See specification for complete details. */
+ OMX_StateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_StateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_StateMax = 0X7FFFFFFF
+} OMX_STATETYPE;
+
+/** The OMX_ERRORTYPE enumeration defines the standard OMX Errors. These
+ * errors should cover most of the common failure cases. However,
+ * vendors are free to add additional error messages of their own as
+ * long as they follow these rules:
+ * 1. Vendor error messages shall be in the range of 0x90000000 to
+ * 0x9000FFFF.
+ * 2. Vendor error messages shall be defined in a header file provided
+ * with the component. No error messages are allowed that are
+ * not defined.
+ */
+typedef enum OMX_ERRORTYPE
+{
+ OMX_ErrorNone = 0,
+
+ /** There were insufficient resources to perform the requested operation */
+ OMX_ErrorInsufficientResources = (OMX_S32) 0x80001000,
+
+ /** There was an error, but the cause of the error could not be determined */
+ OMX_ErrorUndefined = (OMX_S32) 0x80001001,
+
+ /** The component name string was not valid */
+ OMX_ErrorInvalidComponentName = (OMX_S32) 0x80001002,
+
+ /** No component with the specified name string was found */
+ OMX_ErrorComponentNotFound = (OMX_S32) 0x80001003,
+
+ /** The component specified did not have a "OMX_ComponentInit" or
+ "OMX_ComponentDeInit entry point */
+ OMX_ErrorInvalidComponent = (OMX_S32) 0x80001004,
+
+ /** One or more parameters were not valid */
+ OMX_ErrorBadParameter = (OMX_S32) 0x80001005,
+
+ /** The requested function is not implemented */
+ OMX_ErrorNotImplemented = (OMX_S32) 0x80001006,
+
+ /** The buffer was emptied before the next buffer was ready */
+ OMX_ErrorUnderflow = (OMX_S32) 0x80001007,
+
+ /** The buffer was not available when it was needed */
+ OMX_ErrorOverflow = (OMX_S32) 0x80001008,
+
+ /** The hardware failed to respond as expected */
+ OMX_ErrorHardware = (OMX_S32) 0x80001009,
+
+ /** The component is in the state OMX_StateInvalid */
+ OMX_ErrorInvalidState = (OMX_S32) 0x8000100A,
+
+ /** Stream is found to be corrupt */
+ OMX_ErrorStreamCorrupt = (OMX_S32) 0x8000100B,
+
+ /** Ports being connected are not compatible */
+ OMX_ErrorPortsNotCompatible = (OMX_S32) 0x8000100C,
+
+ /** Resources allocated to an idle component have been
+ lost resulting in the component returning to the loaded state */
+ OMX_ErrorResourcesLost = (OMX_S32) 0x8000100D,
+
+ /** No more indicies can be enumerated */
+ OMX_ErrorNoMore = (OMX_S32) 0x8000100E,
+
+ /** The component detected a version mismatch */
+ OMX_ErrorVersionMismatch = (OMX_S32) 0x8000100F,
+
+ /** The component is not ready to return data at this time */
+ OMX_ErrorNotReady = (OMX_S32) 0x80001010,
+
+ /** There was a timeout that occurred */
+ OMX_ErrorTimeout = (OMX_S32) 0x80001011,
+
+ /** This error occurs when trying to transition into the state you are already in */
+ OMX_ErrorSameState = (OMX_S32) 0x80001012,
+
+ /** Resources allocated to an executing or paused component have been
+ preempted, causing the component to return to the idle state */
+ OMX_ErrorResourcesPreempted = (OMX_S32) 0x80001013,
+
+ /** A non-supplier port sends this error to the IL client (via the EventHandler callback)
+ during the allocation of buffers (on a transition from the LOADED to the IDLE state or
+ on a port restart) when it deems that it has waited an unusually long time for the supplier
+ to send it an allocated buffer via a UseBuffer call. */
+ OMX_ErrorPortUnresponsiveDuringAllocation = (OMX_S32) 0x80001014,
+
+ /** A non-supplier port sends this error to the IL client (via the EventHandler callback)
+ during the deallocation of buffers (on a transition from the IDLE to LOADED state or
+ on a port stop) when it deems that it has waited an unusually long time for the supplier
+ to request the deallocation of a buffer header via a FreeBuffer call. */
+ OMX_ErrorPortUnresponsiveDuringDeallocation = (OMX_S32) 0x80001015,
+
+ /** A supplier port sends this error to the IL client (via the EventHandler callback)
+ during the stopping of a port (either on a transition from the IDLE to LOADED
+ state or a port stop) when it deems that it has waited an unusually long time for
+ the non-supplier to return a buffer via an EmptyThisBuffer or FillThisBuffer call. */
+ OMX_ErrorPortUnresponsiveDuringStop = (OMX_S32) 0x80001016,
+
+ /** Attempting a state transtion that is not allowed */
+ OMX_ErrorIncorrectStateTransition = (OMX_S32) 0x80001017,
+
+ /* Attempting a command that is not allowed during the present state. */
+ OMX_ErrorIncorrectStateOperation = (OMX_S32) 0x80001018,
+
+ /** The values encapsulated in the parameter or config structure are not supported. */
+ OMX_ErrorUnsupportedSetting = (OMX_S32) 0x80001019,
+
+ /** The parameter or config indicated by the given index is not supported. */
+ OMX_ErrorUnsupportedIndex = (OMX_S32) 0x8000101A,
+
+ /** The port index supplied is incorrect. */
+ OMX_ErrorBadPortIndex = (OMX_S32) 0x8000101B,
+
+ /** The port has lost one or more of its buffers and it thus unpopulated. */
+ OMX_ErrorPortUnpopulated = (OMX_S32) 0x8000101C,
+
+ /** Component suspended due to temporary loss of resources */
+ OMX_ErrorComponentSuspended = (OMX_S32) 0x8000101D,
+
+ /** Component suspended due to an inability to acquire dynamic resources */
+ OMX_ErrorDynamicResourcesUnavailable = (OMX_S32) 0x8000101E,
+
+ /** When the macroblock error reporting is enabled the component returns new error
+ for every frame that has errors */
+ OMX_ErrorMbErrorsInFrame = (OMX_S32) 0x8000101F,
+
+ /** A component reports this error when it cannot parse or determine the format of an input stream. */
+ OMX_ErrorFormatNotDetected = (OMX_S32) 0x80001020,
+
+ /** The content open operation failed. */
+ OMX_ErrorContentPipeOpenFailed = (OMX_S32) 0x80001021,
+
+ /** The content creation operation failed. */
+ OMX_ErrorContentPipeCreationFailed = (OMX_S32) 0x80001022,
+
+ /** Separate table information is being used */
+ OMX_ErrorSeperateTablesUsed = (OMX_S32) 0x80001023,
+
+ /** Tunneling is unsupported by the component*/
+ OMX_ErrorTunnelingUnsupported = (OMX_S32) 0x80001024,
+
+ OMX_ErrorKhronosExtensions = (OMX_S32)0x8F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_ErrorVendorStartUnused = (OMX_S32)0x90000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_ErrorMax = 0x7FFFFFFF
+} OMX_ERRORTYPE;
+
+/** @ingroup core */
+typedef OMX_ERRORTYPE (* OMX_COMPONENTINITTYPE)(OMX_IN OMX_HANDLETYPE hComponent);
+
+/** @ingroup core */
+typedef struct OMX_COMPONENTREGISTERTYPE
+{
+ const char * pName; /* Component name, 128 byte limit (including '\0') applies */
+ OMX_COMPONENTINITTYPE pInitialize; /* Component instance initialization function */
+} OMX_COMPONENTREGISTERTYPE;
+
+/** @ingroup core */
+extern OMX_COMPONENTREGISTERTYPE OMX_ComponentRegistered[];
+
+/** @ingroup rpm */
+typedef struct OMX_PRIORITYMGMTTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nGroupPriority; /**< Priority of the component group */
+ OMX_U32 nGroupID; /**< ID of the component group */
+} OMX_PRIORITYMGMTTYPE;
+
+/* Component name and Role names are limited to 128 characters including the terminating '\0'. */
+#define OMX_MAX_STRINGNAME_SIZE 128
+
+/** @ingroup comp */
+typedef struct OMX_PARAM_COMPONENTROLETYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U8 cRole[OMX_MAX_STRINGNAME_SIZE]; /**< name of standard component which defines component role */
+} OMX_PARAM_COMPONENTROLETYPE;
+
+/** End of Stream Buffer Flag:
+ *
+ * A component sets EOS when it has no more data to emit on a particular
+ * output port. Thus an output port shall set EOS on the last buffer it
+ * emits. A component's determination of when an output port should
+ * cease sending data is implemenation specific.
+ * @ingroup buf
+ */
+
+#define OMX_BUFFERFLAG_EOS 0x00000001
+
+/** Start Time Buffer Flag:
+ *
+ * The source of a stream (e.g. a demux component) sets the STARTTIME
+ * flag on the buffer that contains the starting timestamp for the
+ * stream. The starting timestamp corresponds to the first data that
+ * should be displayed at startup or after a seek.
+ * The first timestamp of the stream is not necessarily the start time.
+ * For instance, in the case of a seek to a particular video frame,
+ * the target frame may be an interframe. Thus the first buffer of
+ * the stream will be the intra-frame preceding the target frame and
+ * the starttime will occur with the target frame (with any other
+ * required frames required to reconstruct the target intervening).
+ *
+ * The STARTTIME flag is directly associated with the buffer's
+ * timestamp ' thus its association to buffer data and its
+ * propagation is identical to the timestamp's.
+ *
+ * When a Sync Component client receives a buffer with the
+ * STARTTIME flag it shall perform a SetConfig on its sync port
+ * using OMX_ConfigTimeClientStartTime and passing the buffer's
+ * timestamp.
+ *
+ * @ingroup buf
+ */
+
+#define OMX_BUFFERFLAG_STARTTIME 0x00000002
+
+
+
+/** Decode Only Buffer Flag:
+ *
+ * The source of a stream (e.g. a demux component) sets the DECODEONLY
+ * flag on any buffer that should shall be decoded but should not be
+ * displayed. This flag is used, for instance, when a source seeks to
+ * a target interframe that requires the decode of frames preceding the
+ * target to facilitate the target's reconstruction. In this case the
+ * source would emit the frames preceding the target downstream
+ * but mark them as decode only.
+ *
+ * The DECODEONLY is associated with buffer data and propagated in a
+ * manner identical to the buffer timestamp.
+ *
+ * A component that renders data should ignore all buffers with
+ * the DECODEONLY flag set.
+ *
+ * @ingroup buf
+ */
+
+#define OMX_BUFFERFLAG_DECODEONLY 0x00000004
+
+
+/* Data Corrupt Flag: This flag is set when the IL client believes the data in the associated buffer is corrupt
+ * @ingroup buf
+ */
+
+#define OMX_BUFFERFLAG_DATACORRUPT 0x00000008
+
+/* End of Frame: The buffer contains exactly one end of frame and no data
+ * occurs after the end of frame. This flag is an optional hint. The absence
+ * of this flag does not imply the absence of an end of frame within the buffer.
+ * @ingroup buf
+*/
+#define OMX_BUFFERFLAG_ENDOFFRAME 0x00000010
+
+/* Sync Frame Flag: This flag is set when the buffer content contains a coded sync frame '
+ * a frame that has no dependency on any other frame information
+ * @ingroup buf
+ */
+#define OMX_BUFFERFLAG_SYNCFRAME 0x00000020
+
+/* Extra data present flag: there is extra data appended to the data stream
+ * residing in the buffer
+ * @ingroup buf
+ */
+#define OMX_BUFFERFLAG_EXTRADATA 0x00000040
+
+/** Codec Config Buffer Flag:
+* OMX_BUFFERFLAG_CODECCONFIG is an optional flag that is set by an
+* output port when all bytes in the buffer form part or all of a set of
+* codec specific configuration data. Examples include SPS/PPS nal units
+* for OMX_VIDEO_CodingAVC or AudioSpecificConfig data for
+* OMX_AUDIO_CodingAAC. Any component that for a given stream sets
+* OMX_BUFFERFLAG_CODECCONFIG shall not mix codec configuration bytes
+* with frame data in the same buffer, and shall send all buffers
+* containing codec configuration bytes before any buffers containing
+* frame data that those configurations bytes describe.
+* If the stream format for a particular codec has a frame specific
+* header at the start of each frame, for example OMX_AUDIO_CodingMP3 or
+* OMX_AUDIO_CodingAAC in ADTS mode, then these shall be presented as
+* normal without setting OMX_BUFFERFLAG_CODECCONFIG.
+ * @ingroup buf
+ */
+#define OMX_BUFFERFLAG_CODECCONFIG 0x00000080
+
+
+
+/** @ingroup buf */
+typedef struct OMX_BUFFERHEADERTYPE
+{
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U8* pBuffer; /**< Pointer to actual block of memory
+ that is acting as the buffer */
+ OMX_U32 nAllocLen; /**< size of the buffer allocated, in bytes */
+ OMX_U32 nFilledLen; /**< number of bytes currently in the
+ buffer */
+ OMX_U32 nOffset; /**< start offset of valid data in bytes from
+ the start of the buffer */
+ OMX_PTR pAppPrivate; /**< pointer to any data the application
+ wants to associate with this buffer */
+ OMX_PTR pPlatformPrivate; /**< pointer to any data the platform
+ wants to associate with this buffer */
+ OMX_PTR pInputPortPrivate; /**< pointer to any data the input port
+ wants to associate with this buffer */
+ OMX_PTR pOutputPortPrivate; /**< pointer to any data the output port
+ wants to associate with this buffer */
+ OMX_HANDLETYPE hMarkTargetComponent; /**< The component that will generate a
+ mark event upon processing this buffer. */
+ OMX_PTR pMarkData; /**< Application specific data associated with
+ the mark sent on a mark event to disambiguate
+ this mark from others. */
+ OMX_U32 nTickCount; /**< Optional entry that the component and
+ application can update with a tick count
+ when they access the component. This
+ value should be in microseconds. Since
+ this is a value relative to an arbitrary
+ starting point, this value cannot be used
+ to determine absolute time. This is an
+ optional entry and not all components
+ will update it.*/
+ OMX_TICKS nTimeStamp; /**< Timestamp corresponding to the sample
+ starting at the first logical sample
+ boundary in the buffer. Timestamps of
+ successive samples within the buffer may
+ be inferred by adding the duration of the
+ of the preceding buffer to the timestamp
+ of the preceding buffer.*/
+ OMX_U32 nFlags; /**< buffer specific flags */
+ OMX_U32 nOutputPortIndex; /**< The index of the output port (if any) using
+ this buffer */
+ OMX_U32 nInputPortIndex; /**< The index of the input port (if any) using
+ this buffer */
+} OMX_BUFFERHEADERTYPE;
+
+/** The OMX_EXTRADATATYPE enumeration is used to define the
+ * possible extra data payload types.
+ * NB: this enum is binary backwards compatible with the previous
+ * OMX_EXTRADATA_QUANT define. This should be replaced with
+ * OMX_ExtraDataQuantization.
+ */
+typedef enum OMX_EXTRADATATYPE
+{
+ OMX_ExtraDataNone = 0, /**< Indicates that no more extra data sections follow */
+ OMX_ExtraDataQuantization, /**< The data payload contains quantization data */
+ OMX_ExtraDataKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_ExtraDataVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_ExtraDataMax = 0x7FFFFFFF
+} OMX_EXTRADATATYPE;
+
+
+typedef struct OMX_OTHER_EXTRADATATYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_EXTRADATATYPE eType; /* Extra Data type */
+ OMX_U32 nDataSize; /* Size of the supporting data to follow */
+ OMX_U8 data[1]; /* Supporting data hint */
+} OMX_OTHER_EXTRADATATYPE;
+
+/** @ingroup comp */
+typedef struct OMX_PORT_PARAM_TYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPorts; /**< The number of ports for this component */
+ OMX_U32 nStartPortNumber; /** first port number for this type of port */
+} OMX_PORT_PARAM_TYPE;
+
+/** @ingroup comp */
+typedef enum OMX_EVENTTYPE
+{
+ OMX_EventCmdComplete, /**< component has sucessfully completed a command */
+ OMX_EventError, /**< component has detected an error condition */
+ OMX_EventMark, /**< component has detected a buffer mark */
+ OMX_EventPortSettingsChanged, /**< component is reported a port settings change */
+ OMX_EventBufferFlag, /**< component has detected an EOS */
+ OMX_EventResourcesAcquired, /**< component has been granted resources and is
+ automatically starting the state change from
+ OMX_StateWaitForResources to OMX_StateIdle. */
+ OMX_EventComponentResumed, /**< Component resumed due to reacquisition of resources */
+ OMX_EventDynamicResourcesAvailable, /**< Component has acquired previously unavailable dynamic resources */
+ OMX_EventPortFormatDetected, /**< Component has detected a supported format. */
+ OMX_EventKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_EventVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_EventMax = 0x7FFFFFFF
+} OMX_EVENTTYPE;
+
+typedef struct OMX_CALLBACKTYPE
+{
+ /** The EventHandler method is used to notify the application when an
+ event of interest occurs. Events are defined in the OMX_EVENTTYPE
+ enumeration. Please see that enumeration for details of what will
+ be returned for each type of event. Callbacks should not return
+ an error to the component, so if an error occurs, the application
+ shall handle it internally. This is a blocking call.
+
+ The application should return from this call within 5 msec to avoid
+ blocking the component for an excessively long period of time.
+
+ @param hComponent
+ handle of the component to access. This is the component
+ handle returned by the call to the GetHandle function.
+ @param pAppData
+ pointer to an application defined value that was provided in the
+ pAppData parameter to the OMX_GetHandle method for the component.
+ This application defined value is provided so that the application
+ can have a component specific context when receiving the callback.
+ @param eEvent
+ Event that the component wants to notify the application about.
+ @param nData1
+ nData will be the OMX_ERRORTYPE for an error event and will be
+ an OMX_COMMANDTYPE for a command complete event and OMX_INDEXTYPE for a OMX_PortSettingsChanged event.
+ @param nData2
+ nData2 will hold further information related to the event. Can be OMX_STATETYPE for
+ a OMX_CommandStateSet command or port index for a OMX_PortSettingsChanged event.
+ Default value is 0 if not used. )
+ @param pEventData
+ Pointer to additional event-specific data (see spec for meaning).
+ */
+
+ OMX_ERRORTYPE (*EventHandler)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData);
+
+ /** The EmptyBufferDone method is used to return emptied buffers from an
+ input port back to the application for reuse. This is a blocking call
+ so the application should not attempt to refill the buffers during this
+ call, but should queue them and refill them in another thread. There
+ is no error return, so the application shall handle any errors generated
+ internally.
+
+ The application should return from this call within 5 msec.
+
+ @param hComponent
+ handle of the component to access. This is the component
+ handle returned by the call to the GetHandle function.
+ @param pAppData
+ pointer to an application defined value that was provided in the
+ pAppData parameter to the OMX_GetHandle method for the component.
+ This application defined value is provided so that the application
+ can have a component specific context when receiving the callback.
+ @param pBuffer
+ pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer
+ or AllocateBuffer indicating the buffer that was emptied.
+ @ingroup buf
+ */
+ OMX_ERRORTYPE (*EmptyBufferDone)(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer);
+
+ /** The FillBufferDone method is used to return filled buffers from an
+ output port back to the application for emptying and then reuse.
+ This is a blocking call so the application should not attempt to
+ empty the buffers during this call, but should queue the buffers
+ and empty them in another thread. There is no error return, so
+ the application shall handle any errors generated internally. The
+ application shall also update the buffer header to indicate the
+ number of bytes placed into the buffer.
+
+ The application should return from this call within 5 msec.
+
+ @param hComponent
+ handle of the component to access. This is the component
+ handle returned by the call to the GetHandle function.
+ @param pAppData
+ pointer to an application defined value that was provided in the
+ pAppData parameter to the OMX_GetHandle method for the component.
+ This application defined value is provided so that the application
+ can have a component specific context when receiving the callback.
+ @param pBuffer
+ pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer
+ or AllocateBuffer indicating the buffer that was filled.
+ @ingroup buf
+ */
+ OMX_ERRORTYPE (*FillBufferDone)(
+ OMX_OUT OMX_HANDLETYPE hComponent,
+ OMX_OUT OMX_PTR pAppData,
+ OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer);
+
+} OMX_CALLBACKTYPE;
+
+/** The OMX_BUFFERSUPPLIERTYPE enumeration is used to dictate port supplier
+ preference when tunneling between two ports.
+ @ingroup tun buf
+*/
+typedef enum OMX_BUFFERSUPPLIERTYPE
+{
+ OMX_BufferSupplyUnspecified = 0x0, /**< port supplying the buffers is unspecified,
+ or don't care */
+ OMX_BufferSupplyInput, /**< input port supplies the buffers */
+ OMX_BufferSupplyOutput, /**< output port supplies the buffers */
+ OMX_BufferSupplyKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_BufferSupplyVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_BufferSupplyMax = 0x7FFFFFFF
+} OMX_BUFFERSUPPLIERTYPE;
+
+
+/** buffer supplier parameter
+ * @ingroup tun
+ */
+typedef struct OMX_PARAM_BUFFERSUPPLIERTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_BUFFERSUPPLIERTYPE eBufferSupplier; /**< buffer supplier */
+} OMX_PARAM_BUFFERSUPPLIERTYPE;
+
+
+/**< indicates that buffers received by an input port of a tunnel
+ may not modify the data in the buffers
+ @ingroup tun
+ */
+#define OMX_PORTTUNNELFLAG_READONLY 0x00000001
+
+
+/** The OMX_TUNNELSETUPTYPE structure is used to pass data from an output
+ port to an input port as part the two ComponentTunnelRequest calls
+ resulting from a OMX_SetupTunnel call from the IL Client.
+ @ingroup tun
+ */
+typedef struct OMX_TUNNELSETUPTYPE
+{
+ OMX_U32 nTunnelFlags; /**< bit flags for tunneling */
+ OMX_BUFFERSUPPLIERTYPE eSupplier; /**< supplier preference */
+} OMX_TUNNELSETUPTYPE;
+
+/* OMX Component headers is included to enable the core to use
+ macros for functions into the component for OMX release 1.0.
+ Developers should not access any structures or data from within
+ the component header directly */
+/* TO BE REMOVED - #include <OMX_Component.h> */
+
+/** GetComponentVersion will return information about the component.
+ This is a blocking call. This macro will go directly from the
+ application to the component (via a core macro). The
+ component will return from this call within 5 msec.
+ @param [in] hComponent
+ handle of component to execute the command
+ @param [out] pComponentName
+ pointer to an empty string of length 128 bytes. The component
+ will write its name into this string. The name will be
+ terminated by a single zero byte. The name of a component will
+ be 127 bytes or less to leave room for the trailing zero byte.
+ An example of a valid component name is "OMX.ABC.ChannelMixer\0".
+ @param [out] pComponentVersion
+ pointer to an OMX Version structure that the component will fill
+ in. The component will fill in a value that indicates the
+ component version. NOTE: the component version is NOT the same
+ as the OMX Specification version (found in all structures). The
+ component version is defined by the vendor of the component and
+ its value is entirely up to the component vendor.
+ @param [out] pSpecVersion
+ pointer to an OMX Version structure that the component will fill
+ in. The SpecVersion is the version of the specification that the
+ component was built against. Please note that this value may or
+ may not match the structure's version. For example, if the
+ component was built against the 2.0 specification, but the
+ application (which creates the structure is built against the
+ 1.0 specification the versions would be different.
+ @param [out] pComponentUUID
+ pointer to the UUID of the component which will be filled in by
+ the component. The UUID is a unique identifier that is set at
+ RUN time for the component and is unique to each instantion of
+ the component.
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup comp
+ */
+#define OMX_GetComponentVersion( \
+ hComponent, \
+ pComponentName, \
+ pComponentVersion, \
+ pSpecVersion, \
+ pComponentUUID) \
+ ((OMX_COMPONENTTYPE*)hComponent)->GetComponentVersion( \
+ hComponent, \
+ pComponentName, \
+ pComponentVersion, \
+ pSpecVersion, \
+ pComponentUUID) /* Macro End */
+
+
+/** Send a command to the component. This call is a non-blocking call.
+ The component should check the parameters and then queue the command
+ to the component thread to be executed. The component thread shall
+ send the EventHandler() callback at the conclusion of the command.
+ This macro will go directly from the application to the component (via
+ a core macro). The component will return from this call within 5 msec.
+
+ When the command is "OMX_CommandStateSet" the component will queue a
+ state transition to the new state idenfied in nParam.
+
+ When the command is "OMX_CommandFlush", to flush a port's buffer queues,
+ the command will force the component to return all buffers NOT CURRENTLY
+ BEING PROCESSED to the application, in the order in which the buffers
+ were received.
+
+ When the command is "OMX_CommandPortDisable" or
+ "OMX_CommandPortEnable", the component's port (given by the value of
+ nParam) will be stopped or restarted.
+
+ When the command "OMX_CommandMarkBuffer" is used to mark a buffer, the
+ pCmdData will point to a OMX_MARKTYPE structure containing the component
+ handle of the component to examine the buffer chain for the mark. nParam1
+ contains the index of the port on which the buffer mark is applied.
+
+ Specification text for more details.
+
+ @param [in] hComponent
+ handle of component to execute the command
+ @param [in] Cmd
+ Command for the component to execute
+ @param [in] nParam
+ Parameter for the command to be executed. When Cmd has the value
+ OMX_CommandStateSet, value is a member of OMX_STATETYPE. When Cmd has
+ the value OMX_CommandFlush, value of nParam indicates which port(s)
+ to flush. -1 is used to flush all ports a single port index will
+ only flush that port. When Cmd has the value "OMX_CommandPortDisable"
+ or "OMX_CommandPortEnable", the component's port is given by
+ the value of nParam. When Cmd has the value "OMX_CommandMarkBuffer"
+ the components pot is given by the value of nParam.
+ @param [in] pCmdData
+ Parameter pointing to the OMX_MARKTYPE structure when Cmd has the value
+ "OMX_CommandMarkBuffer".
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup comp
+ */
+#define OMX_SendCommand( \
+ hComponent, \
+ Cmd, \
+ nParam, \
+ pCmdData) \
+ ((OMX_COMPONENTTYPE*)hComponent)->SendCommand( \
+ hComponent, \
+ Cmd, \
+ nParam, \
+ pCmdData) /* Macro End */
+
+
+/** The OMX_GetParameter macro will get one of the current parameter
+ settings from the component. This macro cannot only be invoked when
+ the component is in the OMX_StateInvalid state. The nParamIndex
+ parameter is used to indicate which structure is being requested from
+ the component. The application shall allocate the correct structure
+ and shall fill in the structure size and version information before
+ invoking this macro. When the parameter applies to a port, the
+ caller shall fill in the appropriate nPortIndex value indicating the
+ port on which the parameter applies. If the component has not had
+ any settings changed, then the component should return a set of
+ valid DEFAULT parameters for the component. This is a blocking
+ call.
+
+ The component should return from this call within 20 msec.
+
+ @param [in] hComponent
+ Handle of the component to be accessed. This is the component
+ handle returned by the call to the OMX_GetHandle function.
+ @param [in] nParamIndex
+ Index of the structure to be filled. This value is from the
+ OMX_INDEXTYPE enumeration.
+ @param [in,out] pComponentParameterStructure
+ Pointer to application allocated structure to be filled by the
+ component.
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup comp
+ */
+#define OMX_GetParameter( \
+ hComponent, \
+ nParamIndex, \
+ pComponentParameterStructure) \
+ ((OMX_COMPONENTTYPE*)hComponent)->GetParameter( \
+ hComponent, \
+ nParamIndex, \
+ pComponentParameterStructure) /* Macro End */
+
+
+/** The OMX_SetParameter macro will send an initialization parameter
+ structure to a component. Each structure shall be sent one at a time,
+ in a separate invocation of the macro. This macro can only be
+ invoked when the component is in the OMX_StateLoaded state, or the
+ port is disabled (when the parameter applies to a port). The
+ nParamIndex parameter is used to indicate which structure is being
+ passed to the component. The application shall allocate the
+ correct structure and shall fill in the structure size and version
+ information (as well as the actual data) before invoking this macro.
+ The application is free to dispose of this structure after the call
+ as the component is required to copy any data it shall retain. This
+ is a blocking call.
+
+ The component should return from this call within 20 msec.
+
+ @param [in] hComponent
+ Handle of the component to be accessed. This is the component
+ handle returned by the call to the OMX_GetHandle function.
+ @param [in] nIndex
+ Index of the structure to be sent. This value is from the
+ OMX_INDEXTYPE enumeration.
+ @param [in] pComponentParameterStructure
+ pointer to application allocated structure to be used for
+ initialization by the component.
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup comp
+ */
+#define OMX_SetParameter( \
+ hComponent, \
+ nParamIndex, \
+ pComponentParameterStructure) \
+ ((OMX_COMPONENTTYPE*)hComponent)->SetParameter( \
+ hComponent, \
+ nParamIndex, \
+ pComponentParameterStructure) /* Macro End */
+
+
+/** The OMX_GetConfig macro will get one of the configuration structures
+ from a component. This macro can be invoked anytime after the
+ component has been loaded. The nParamIndex call parameter is used to
+ indicate which structure is being requested from the component. The
+ application shall allocate the correct structure and shall fill in the
+ structure size and version information before invoking this macro.
+ If the component has not had this configuration parameter sent before,
+ then the component should return a set of valid DEFAULT values for the
+ component. This is a blocking call.
+
+ The component should return from this call within 5 msec.
+
+ @param [in] hComponent
+ Handle of the component to be accessed. This is the component
+ handle returned by the call to the OMX_GetHandle function.
+ @param [in] nIndex
+ Index of the structure to be filled. This value is from the
+ OMX_INDEXTYPE enumeration.
+ @param [in,out] pComponentConfigStructure
+ pointer to application allocated structure to be filled by the
+ component.
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup comp
+*/
+#define OMX_GetConfig( \
+ hComponent, \
+ nConfigIndex, \
+ pComponentConfigStructure) \
+ ((OMX_COMPONENTTYPE*)hComponent)->GetConfig( \
+ hComponent, \
+ nConfigIndex, \
+ pComponentConfigStructure) /* Macro End */
+
+
+/** The OMX_SetConfig macro will send one of the configuration
+ structures to a component. Each structure shall be sent one at a time,
+ each in a separate invocation of the macro. This macro can be invoked
+ anytime after the component has been loaded. The application shall
+ allocate the correct structure and shall fill in the structure size
+ and version information (as well as the actual data) before invoking
+ this macro. The application is free to dispose of this structure after
+ the call as the component is required to copy any data it shall retain.
+ This is a blocking call.
+
+ The component should return from this call within 5 msec.
+
+ @param [in] hComponent
+ Handle of the component to be accessed. This is the component
+ handle returned by the call to the OMX_GetHandle function.
+ @param [in] nConfigIndex
+ Index of the structure to be sent. This value is from the
+ OMX_INDEXTYPE enumeration above.
+ @param [in] pComponentConfigStructure
+ pointer to application allocated structure to be used for
+ initialization by the component.
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup comp
+ */
+#define OMX_SetConfig( \
+ hComponent, \
+ nConfigIndex, \
+ pComponentConfigStructure) \
+ ((OMX_COMPONENTTYPE*)hComponent)->SetConfig( \
+ hComponent, \
+ nConfigIndex, \
+ pComponentConfigStructure) /* Macro End */
+
+
+/** The OMX_GetExtensionIndex macro will invoke a component to translate
+ a vendor specific configuration or parameter string into an OMX
+ structure index. There is no requirement for the vendor to support
+ this command for the indexes already found in the OMX_INDEXTYPE
+ enumeration (this is done to save space in small components). The
+ component shall support all vendor supplied extension indexes not found
+ in the master OMX_INDEXTYPE enumeration. This is a blocking call.
+
+ The component should return from this call within 5 msec.
+
+ @param [in] hComponent
+ Handle of the component to be accessed. This is the component
+ handle returned by the call to the GetHandle function.
+ @param [in] cParameterName
+ OMX_STRING that shall be less than 128 characters long including
+ the trailing null byte. This is the string that will get
+ translated by the component into a configuration index.
+ @param [out] pIndexType
+ a pointer to a OMX_INDEXTYPE to receive the index value.
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup comp
+ */
+#define OMX_GetExtensionIndex( \
+ hComponent, \
+ cParameterName, \
+ pIndexType) \
+ ((OMX_COMPONENTTYPE*)hComponent)->GetExtensionIndex( \
+ hComponent, \
+ cParameterName, \
+ pIndexType) /* Macro End */
+
+
+/** The OMX_GetState macro will invoke the component to get the current
+ state of the component and place the state value into the location
+ pointed to by pState.
+
+ The component should return from this call within 5 msec.
+
+ @param [in] hComponent
+ Handle of the component to be accessed. This is the component
+ handle returned by the call to the OMX_GetHandle function.
+ @param [out] pState
+ pointer to the location to receive the state. The value returned
+ is one of the OMX_STATETYPE members
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup comp
+ */
+#define OMX_GetState( \
+ hComponent, \
+ pState) \
+ ((OMX_COMPONENTTYPE*)hComponent)->GetState( \
+ hComponent, \
+ pState) /* Macro End */
+
+
+/** The OMX_UseBuffer macro will request that the component use
+ a buffer (and allocate its own buffer header) already allocated
+ by another component, or by the IL Client. This is a blocking
+ call.
+
+ The component should return from this call within 20 msec.
+
+ @param [in] hComponent
+ Handle of the component to be accessed. This is the component
+ handle returned by the call to the OMX_GetHandle function.
+ @param [out] ppBuffer
+ pointer to an OMX_BUFFERHEADERTYPE structure used to receive the
+ pointer to the buffer header
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup comp buf
+ */
+
+#define OMX_UseBuffer( \
+ hComponent, \
+ ppBufferHdr, \
+ nPortIndex, \
+ pAppPrivate, \
+ nSizeBytes, \
+ pBuffer) \
+ ((OMX_COMPONENTTYPE*)hComponent)->UseBuffer( \
+ hComponent, \
+ ppBufferHdr, \
+ nPortIndex, \
+ pAppPrivate, \
+ nSizeBytes, \
+ pBuffer)
+
+
+/** The OMX_AllocateBuffer macro will request that the component allocate
+ a new buffer and buffer header. The component will allocate the
+ buffer and the buffer header and return a pointer to the buffer
+ header. This is a blocking call.
+
+ The component should return from this call within 5 msec.
+
+ @param [in] hComponent
+ Handle of the component to be accessed. This is the component
+ handle returned by the call to the OMX_GetHandle function.
+ @param [out] ppBuffer
+ pointer to an OMX_BUFFERHEADERTYPE structure used to receive
+ the pointer to the buffer header
+ @param [in] nPortIndex
+ nPortIndex is used to select the port on the component the buffer will
+ be used with. The port can be found by using the nPortIndex
+ value as an index into the Port Definition array of the component.
+ @param [in] pAppPrivate
+ pAppPrivate is used to initialize the pAppPrivate member of the
+ buffer header structure.
+ @param [in] nSizeBytes
+ size of the buffer to allocate. Used when bAllocateNew is true.
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup comp buf
+ */
+#define OMX_AllocateBuffer( \
+ hComponent, \
+ ppBuffer, \
+ nPortIndex, \
+ pAppPrivate, \
+ nSizeBytes) \
+ ((OMX_COMPONENTTYPE*)hComponent)->AllocateBuffer( \
+ hComponent, \
+ ppBuffer, \
+ nPortIndex, \
+ pAppPrivate, \
+ nSizeBytes) /* Macro End */
+
+
+/** The OMX_FreeBuffer macro will release a buffer header from the component
+ which was allocated using either OMX_AllocateBuffer or OMX_UseBuffer. If
+ the component allocated the buffer (see the OMX_UseBuffer macro) then
+ the component shall free the buffer and buffer header. This is a
+ blocking call.
+
+ The component should return from this call within 20 msec.
+
+ @param [in] hComponent
+ Handle of the component to be accessed. This is the component
+ handle returned by the call to the OMX_GetHandle function.
+ @param [in] nPortIndex
+ nPortIndex is used to select the port on the component the buffer will
+ be used with.
+ @param [in] pBuffer
+ pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer
+ or AllocateBuffer.
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup comp buf
+ */
+#define OMX_FreeBuffer( \
+ hComponent, \
+ nPortIndex, \
+ pBuffer) \
+ ((OMX_COMPONENTTYPE*)hComponent)->FreeBuffer( \
+ hComponent, \
+ nPortIndex, \
+ pBuffer) /* Macro End */
+
+
+/** The OMX_EmptyThisBuffer macro will send a buffer full of data to an
+ input port of a component. The buffer will be emptied by the component
+ and returned to the application via the EmptyBufferDone call back.
+ This is a non-blocking call in that the component will record the buffer
+ and return immediately and then empty the buffer, later, at the proper
+ time. As expected, this macro may be invoked only while the component
+ is in the OMX_StateExecuting. If nPortIndex does not specify an input
+ port, the component shall return an error.
+
+ The component should return from this call within 5 msec.
+
+ @param [in] hComponent
+ Handle of the component to be accessed. This is the component
+ handle returned by the call to the OMX_GetHandle function.
+ @param [in] pBuffer
+ pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer
+ or AllocateBuffer.
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup comp buf
+ */
+#define OMX_EmptyThisBuffer( \
+ hComponent, \
+ pBuffer) \
+ ((OMX_COMPONENTTYPE*)hComponent)->EmptyThisBuffer( \
+ hComponent, \
+ pBuffer) /* Macro End */
+
+
+/** The OMX_FillThisBuffer macro will send an empty buffer to an
+ output port of a component. The buffer will be filled by the component
+ and returned to the application via the FillBufferDone call back.
+ This is a non-blocking call in that the component will record the buffer
+ and return immediately and then fill the buffer, later, at the proper
+ time. As expected, this macro may be invoked only while the component
+ is in the OMX_ExecutingState. If nPortIndex does not specify an output
+ port, the component shall return an error.
+
+ The component should return from this call within 5 msec.
+
+ @param [in] hComponent
+ Handle of the component to be accessed. This is the component
+ handle returned by the call to the OMX_GetHandle function.
+ @param [in] pBuffer
+ pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer
+ or AllocateBuffer.
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup comp buf
+ */
+#define OMX_FillThisBuffer( \
+ hComponent, \
+ pBuffer) \
+ ((OMX_COMPONENTTYPE*)hComponent)->FillThisBuffer( \
+ hComponent, \
+ pBuffer) /* Macro End */
+
+
+
+/** The OMX_UseEGLImage macro will request that the component use
+ a EGLImage provided by EGL (and allocate its own buffer header)
+ This is a blocking call.
+
+ The component should return from this call within 20 msec.
+
+ @param [in] hComponent
+ Handle of the component to be accessed. This is the component
+ handle returned by the call to the OMX_GetHandle function.
+ @param [out] ppBuffer
+ pointer to an OMX_BUFFERHEADERTYPE structure used to receive the
+ pointer to the buffer header. Note that the memory location used
+ for this buffer is NOT visible to the IL Client.
+ @param [in] nPortIndex
+ nPortIndex is used to select the port on the component the buffer will
+ be used with. The port can be found by using the nPortIndex
+ value as an index into the Port Definition array of the component.
+ @param [in] pAppPrivate
+ pAppPrivate is used to initialize the pAppPrivate member of the
+ buffer header structure.
+ @param [in] eglImage
+ eglImage contains the handle of the EGLImage to use as a buffer on the
+ specified port. The component is expected to validate properties of
+ the EGLImage against the configuration of the port to ensure the component
+ can use the EGLImage as a buffer.
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup comp buf
+ */
+#define OMX_UseEGLImage( \
+ hComponent, \
+ ppBufferHdr, \
+ nPortIndex, \
+ pAppPrivate, \
+ eglImage) \
+ ((OMX_COMPONENTTYPE*)hComponent)->UseEGLImage( \
+ hComponent, \
+ ppBufferHdr, \
+ nPortIndex, \
+ pAppPrivate, \
+ eglImage)
+
+/** The OMX_Init method is used to initialize the OMX core. It shall be the
+ first call made into OMX and it should only be executed one time without
+ an interviening OMX_Deinit call.
+
+ The core should return from this call within 20 msec.
+
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup core
+ */
+OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void);
+
+
+/** The OMX_Deinit method is used to deinitialize the OMX core. It shall be
+ the last call made into OMX. In the event that the core determines that
+ thare are components loaded when this call is made, the core may return
+ with an error rather than try to unload the components.
+
+ The core should return from this call within 20 msec.
+
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup core
+ */
+OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void);
+
+
+/** The OMX_ComponentNameEnum method will enumerate through all the names of
+ recognised valid components in the system. This function is provided
+ as a means to detect all the components in the system run-time. There is
+ no strict ordering to the enumeration order of component names, although
+ each name will only be enumerated once. If the OMX core supports run-time
+ installation of new components, it is only requried to detect newly
+ installed components when the first call to enumerate component names
+ is made (i.e. when nIndex is 0x0).
+
+ The core should return from this call in 20 msec.
+
+ @param [out] cComponentName
+ pointer to a null terminated string with the component name. The
+ names of the components are strings less than 127 bytes in length
+ plus the trailing null for a maximum size of 128 bytes. An example
+ of a valid component name is "OMX.TI.AUDIO.DSP.MIXER\0". Names are
+ assigned by the vendor, but shall start with "OMX." and then have
+ the Vendor designation next.
+ @param [in] nNameLength
+ number of characters in the cComponentName string. With all
+ component name strings restricted to less than 128 characters
+ (including the trailing null) it is recomended that the caller
+ provide a input string for the cComponentName of 128 characters.
+ @param [in] nIndex
+ number containing the enumeration index for the component.
+ Multiple calls to OMX_ComponentNameEnum with increasing values
+ of nIndex will enumerate through the component names in the
+ system until OMX_ErrorNoMore is returned. The value of nIndex
+ is 0 to (N-1), where N is the number of valid installed components
+ in the system.
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. When the value of nIndex exceeds the number of
+ components in the system minus 1, OMX_ErrorNoMore will be
+ returned. Otherwise the appropriate OMX error will be returned.
+ @ingroup core
+ */
+OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum(
+ OMX_OUT OMX_STRING cComponentName,
+ OMX_IN OMX_U32 nNameLength,
+ OMX_IN OMX_U32 nIndex);
+
+
+/** The OMX_GetHandle method will locate the component specified by the
+ component name given, load that component into memory and then invoke
+ the component's methods to create an instance of the component.
+
+ The core should return from this call within 20 msec.
+
+ @param [out] pHandle
+ pointer to an OMX_HANDLETYPE pointer to be filled in by this method.
+ @param [in] cComponentName
+ pointer to a null terminated string with the component name. The
+ names of the components are strings less than 127 bytes in length
+ plus the trailing null for a maximum size of 128 bytes. An example
+ of a valid component name is "OMX.TI.AUDIO.DSP.MIXER\0". Names are
+ assigned by the vendor, but shall start with "OMX." and then have
+ the Vendor designation next.
+ @param [in] pAppData
+ pointer to an application defined value that will be returned
+ during callbacks so that the application can identify the source
+ of the callback.
+ @param [in] pCallBacks
+ pointer to a OMX_CALLBACKTYPE structure that will be passed to the
+ component to initialize it with.
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup core
+ */
+OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle(
+ OMX_OUT OMX_HANDLETYPE* pHandle,
+ OMX_IN OMX_STRING cComponentName,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_CALLBACKTYPE* pCallBacks);
+
+
+/** The OMX_FreeHandle method will free a handle allocated by the OMX_GetHandle
+ method. If the component reference count goes to zero, the component will
+ be unloaded from memory.
+
+ The core should return from this call within 20 msec when the component is
+ in the OMX_StateLoaded state.
+
+ @param [in] hComponent
+ Handle of the component to be accessed. This is the component
+ handle returned by the call to the GetHandle function.
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ @ingroup core
+ */
+OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle(
+ OMX_IN OMX_HANDLETYPE hComponent);
+
+
+
+/** The OMX_SetupTunnel method will handle the necessary calls to the components
+ to setup the specified tunnel the two components. NOTE: This is
+ an actual method (not a #define macro). This method will make calls into
+ the component ComponentTunnelRequest method to do the actual tunnel
+ connection.
+
+ The ComponentTunnelRequest method on both components will be called.
+ This method shall not be called unless the component is in the
+ OMX_StateLoaded state except when the ports used for the tunnel are
+ disabled. In this case, the component may be in the OMX_StateExecuting,
+ OMX_StatePause, or OMX_StateIdle states.
+
+ The core should return from this call within 20 msec.
+
+ @param [in] hOutput
+ Handle of the component to be accessed. Also this is the handle
+ of the component whose port, specified in the nPortOutput parameter
+ will be used the source for the tunnel. This is the component handle
+ returned by the call to the OMX_GetHandle function. There is a
+ requirement that hOutput be the source for the data when
+ tunelling (i.e. nPortOutput is an output port). If 0x0, the component
+ specified in hInput will have it's port specified in nPortInput
+ setup for communication with the application / IL client.
+ @param [in] nPortOutput
+ nPortOutput is used to select the source port on component to be
+ used in the tunnel.
+ @param [in] hInput
+ This is the component to setup the tunnel with. This is the handle
+ of the component whose port, specified in the nPortInput parameter
+ will be used the destination for the tunnel. This is the component handle
+ returned by the call to the OMX_GetHandle function. There is a
+ requirement that hInput be the destination for the data when
+ tunelling (i.e. nPortInut is an input port). If 0x0, the component
+ specified in hOutput will have it's port specified in nPortPOutput
+ setup for communication with the application / IL client.
+ @param [in] nPortInput
+ nPortInput is used to select the destination port on component to be
+ used in the tunnel.
+ @return OMX_ERRORTYPE
+ If the command successfully executes, the return code will be
+ OMX_ErrorNone. Otherwise the appropriate OMX error will be returned.
+ When OMX_ErrorNotImplemented is returned, one or both components is
+ a non-interop component and does not support tunneling.
+
+ On failure, the ports of both components are setup for communication
+ with the application / IL Client.
+ @ingroup core tun
+ */
+OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_SetupTunnel(
+ OMX_IN OMX_HANDLETYPE hOutput,
+ OMX_IN OMX_U32 nPortOutput,
+ OMX_IN OMX_HANDLETYPE hInput,
+ OMX_IN OMX_U32 nPortInput);
+
+/** @ingroup cp */
+OMX_API OMX_ERRORTYPE OMX_GetContentPipe(
+ OMX_OUT OMX_HANDLETYPE *hPipe,
+ OMX_IN OMX_STRING szURI);
+
+/** The OMX_GetComponentsOfRole method will return the number of components that support the given
+ role and (if the compNames field is non-NULL) the names of those components. The call will fail if
+ an insufficiently sized array of names is supplied. To ensure the array is sufficiently sized the
+ client should:
+ * first call this function with the compNames field NULL to determine the number of component names
+ * second call this function with the compNames field pointing to an array of names allocated
+ according to the number returned by the first call.
+
+ The core should return from this call within 5 msec.
+
+ @param [in] role
+ This is generic standard component name consisting only of component class
+ name and the type within that class (e.g. 'audio_decoder.aac').
+ @param [inout] pNumComps
+ This is used both as input and output.
+
+ If compNames is NULL, the input is ignored and the output specifies how many components support
+ the given role.
+
+ If compNames is not NULL, on input it bounds the size of the input structure and
+ on output, it specifies the number of components string names listed within the compNames parameter.
+ @param [inout] compNames
+ If NULL this field is ignored. If non-NULL this points to an array of 128-byte strings which accepts
+ a list of the names of all physical components that implement the specified standard component name.
+ Each name is NULL terminated. numComps indicates the number of names.
+ @ingroup core
+ */
+OMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole (
+ OMX_IN OMX_STRING role,
+ OMX_INOUT OMX_U32 *pNumComps,
+ OMX_INOUT OMX_U8 **compNames);
+
+/** The OMX_GetRolesOfComponent method will return the number of roles supported by the given
+ component and (if the roles field is non-NULL) the names of those roles. The call will fail if
+ an insufficiently sized array of names is supplied. To ensure the array is sufficiently sized the
+ client should:
+ * first call this function with the roles field NULL to determine the number of role names
+ * second call this function with the roles field pointing to an array of names allocated
+ according to the number returned by the first call.
+
+ The core should return from this call within 5 msec.
+
+ @param [in] compName
+ This is the name of the component being queried about.
+ @param [inout] pNumRoles
+ This is used both as input and output.
+
+ If roles is NULL, the input is ignored and the output specifies how many roles the component supports.
+
+ If compNames is not NULL, on input it bounds the size of the input structure and
+ on output, it specifies the number of roles string names listed within the roles parameter.
+ @param [out] roles
+ If NULL this field is ignored. If non-NULL this points to an array of 128-byte strings
+ which accepts a list of the names of all standard components roles implemented on the
+ specified component name. numComps indicates the number of names.
+ @ingroup core
+ */
+OMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent (
+ OMX_IN OMX_STRING compName,
+ OMX_INOUT OMX_U32 *pNumRoles,
+ OMX_OUT OMX_U8 **roles);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
+/* File EOF */
+
diff --git a/subprojects/gst-omx/omx/openmax/OMX_CoreExt.h b/subprojects/gst-omx/omx/openmax/OMX_CoreExt.h
new file mode 100644
index 0000000000..b7a5b62334
--- /dev/null
+++ b/subprojects/gst-omx/omx/openmax/OMX_CoreExt.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2010 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/** OMX_CoreExt.h - OpenMax IL version 1.1.2
+ * The OMX_CoreExt header file contains extensions to the definitions used
+ * by both the application and the component to access common items.
+ */
+
+#ifndef OMX_CoreExt_h
+#define OMX_CoreExt_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Each OMX header shall include all required header files to allow the
+ * header to compile without errors. The includes below are required
+ * for this header file to compile successfully
+ */
+#include <OMX_Core.h>
+
+/** Extensions to the standard IL errors. */
+typedef enum OMX_ERROREXTTYPE
+{
+ OMX_ErrorInvalidMode = (OMX_S32) (OMX_ErrorKhronosExtensions + 0x00000001),
+ OMX_ErrorExtMax = 0x7FFFFFFF
+} OMX_ERROREXTTYPE;
+
+
+/** Event type extensions. */
+typedef enum OMX_EVENTEXTTYPE
+{
+ OMX_EventIndexSettingChanged = OMX_EventKhronosExtensions, /**< component signals the IL client of a change
+ in a param, config, or extension */
+ OMX_EventExtMax = 0x7FFFFFFF
+} OMX_EVENTEXTTYPE;
+
+
+/** Enable or disable a callback event. */
+typedef struct OMX_CONFIG_CALLBACKREQUESTTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_INDEXTYPE nIndex; /**< the index the callback is requested for */
+ OMX_BOOL bEnable; /**< enable (OMX_TRUE) or disable (OMX_FALSE) the callback */
+} OMX_CONFIG_CALLBACKREQUESTTYPE;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* OMX_CoreExt_h */
+/* File EOF */
diff --git a/subprojects/gst-omx/omx/openmax/OMX_IVCommon.h b/subprojects/gst-omx/omx/openmax/OMX_IVCommon.h
new file mode 100644
index 0000000000..4c4995ce04
--- /dev/null
+++ b/subprojects/gst-omx/omx/openmax/OMX_IVCommon.h
@@ -0,0 +1,920 @@
+/**
+ * Copyright (c) 2008 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/**
+ * @file OMX_IVCommon.h - OpenMax IL version 1.1.2
+ * The structures needed by Video and Image components to exchange
+ * parameters and configuration data with the components.
+ */
+#ifndef OMX_IVCommon_h
+#define OMX_IVCommon_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * Each OMX header must include all required header files to allow the header
+ * to compile without errors. The includes below are required for this header
+ * file to compile successfully
+ */
+
+#include <OMX_Core.h>
+
+/** @defgroup iv OpenMAX IL Imaging and Video Domain
+ * Common structures for OpenMAX IL Imaging and Video domains
+ * @{
+ */
+
+
+/**
+ * Enumeration defining possible uncompressed image/video formats.
+ *
+ * ENUMS:
+ * Unused : Placeholder value when format is N/A
+ * Monochrome : black and white
+ * 8bitRGB332 : Red 7:5, Green 4:2, Blue 1:0
+ * 12bitRGB444 : Red 11:8, Green 7:4, Blue 3:0
+ * 16bitARGB4444 : Alpha 15:12, Red 11:8, Green 7:4, Blue 3:0
+ * 16bitARGB1555 : Alpha 15, Red 14:10, Green 9:5, Blue 4:0
+ * 16bitRGB565 : Red 15:11, Green 10:5, Blue 4:0
+ * 16bitBGR565 : Blue 15:11, Green 10:5, Red 4:0
+ * 18bitRGB666 : Red 17:12, Green 11:6, Blue 5:0
+ * 18bitARGB1665 : Alpha 17, Red 16:11, Green 10:5, Blue 4:0
+ * 19bitARGB1666 : Alpha 18, Red 17:12, Green 11:6, Blue 5:0
+ * 24bitRGB888 : Red 24:16, Green 15:8, Blue 7:0
+ * 24bitBGR888 : Blue 24:16, Green 15:8, Red 7:0
+ * 24bitARGB1887 : Alpha 23, Red 22:15, Green 14:7, Blue 6:0
+ * 25bitARGB1888 : Alpha 24, Red 23:16, Green 15:8, Blue 7:0
+ * 32bitBGRA8888 : Blue 31:24, Green 23:16, Red 15:8, Alpha 7:0
+ * 32bitARGB8888 : Alpha 31:24, Red 23:16, Green 15:8, Blue 7:0
+ * YUV411Planar : U,Y are subsampled by a factor of 4 horizontally
+ * YUV411PackedPlanar : packed per payload in planar slices
+ * YUV420Planar : Three arrays Y,U,V.
+ * YUV420PackedPlanar : packed per payload in planar slices
+ * YUV420SemiPlanar : Two arrays, one is all Y, the other is U and V
+ * YUV422Planar : Three arrays Y,U,V.
+ * YUV422PackedPlanar : packed per payload in planar slices
+ * YUV422SemiPlanar : Two arrays, one is all Y, the other is U and V
+ * YCbYCr : Organized as 16bit YUYV (i.e. YCbYCr)
+ * YCrYCb : Organized as 16bit YVYU (i.e. YCrYCb)
+ * CbYCrY : Organized as 16bit UYVY (i.e. CbYCrY)
+ * CrYCbY : Organized as 16bit VYUY (i.e. CrYCbY)
+ * YUV444Interleaved : Each pixel contains equal parts YUV
+ * RawBayer8bit : SMIA camera output format
+ * RawBayer10bit : SMIA camera output format
+ * RawBayer8bitcompressed : SMIA camera output format
+ */
+typedef enum OMX_COLOR_FORMATTYPE {
+ OMX_COLOR_FormatUnused,
+ OMX_COLOR_FormatMonochrome,
+ OMX_COLOR_Format8bitRGB332,
+ OMX_COLOR_Format12bitRGB444,
+ OMX_COLOR_Format16bitARGB4444,
+ OMX_COLOR_Format16bitARGB1555,
+ OMX_COLOR_Format16bitRGB565,
+ OMX_COLOR_Format16bitBGR565,
+ OMX_COLOR_Format18bitRGB666,
+ OMX_COLOR_Format18bitARGB1665,
+ OMX_COLOR_Format19bitARGB1666,
+ OMX_COLOR_Format24bitRGB888,
+ OMX_COLOR_Format24bitBGR888,
+ OMX_COLOR_Format24bitARGB1887,
+ OMX_COLOR_Format25bitARGB1888,
+ OMX_COLOR_Format32bitBGRA8888,
+ OMX_COLOR_Format32bitARGB8888,
+ OMX_COLOR_FormatYUV411Planar,
+ OMX_COLOR_FormatYUV411PackedPlanar,
+ OMX_COLOR_FormatYUV420Planar,
+ OMX_COLOR_FormatYUV420PackedPlanar,
+ OMX_COLOR_FormatYUV420SemiPlanar,
+ OMX_COLOR_FormatYUV422Planar,
+ OMX_COLOR_FormatYUV422PackedPlanar,
+ OMX_COLOR_FormatYUV422SemiPlanar,
+ OMX_COLOR_FormatYCbYCr,
+ OMX_COLOR_FormatYCrYCb,
+ OMX_COLOR_FormatCbYCrY,
+ OMX_COLOR_FormatCrYCbY,
+ OMX_COLOR_FormatYUV444Interleaved,
+ OMX_COLOR_FormatRawBayer8bit,
+ OMX_COLOR_FormatRawBayer10bit,
+ OMX_COLOR_FormatRawBayer8bitcompressed,
+ OMX_COLOR_FormatL2,
+ OMX_COLOR_FormatL4,
+ OMX_COLOR_FormatL8,
+ OMX_COLOR_FormatL16,
+ OMX_COLOR_FormatL24,
+ OMX_COLOR_FormatL32,
+ OMX_COLOR_FormatYUV420PackedSemiPlanar,
+ OMX_COLOR_FormatYUV422PackedSemiPlanar,
+ OMX_COLOR_Format18BitBGR666,
+ OMX_COLOR_Format24BitARGB6666,
+ OMX_COLOR_Format24BitABGR6666,
+ OMX_COLOR_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_COLOR_FormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_COLOR_FormatMax = 0x7FFFFFFF
+} OMX_COLOR_FORMATTYPE;
+
+
+/**
+ * Defines the matrix for conversion from RGB to YUV or vice versa.
+ * iColorMatrix should be initialized with the fixed point values
+ * used in converting between formats.
+ */
+typedef struct OMX_CONFIG_COLORCONVERSIONTYPE {
+ OMX_U32 nSize; /**< Size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version info */
+ OMX_U32 nPortIndex; /**< Port that this struct applies to */
+ OMX_S32 xColorMatrix[3][3]; /**< Stored in signed Q16 format */
+ OMX_S32 xColorOffset[4]; /**< Stored in signed Q16 format */
+}OMX_CONFIG_COLORCONVERSIONTYPE;
+
+
+/**
+ * Structure defining percent to scale each frame dimension. For example:
+ * To make the width 50% larger, use fWidth = 1.5 and to make the width
+ * 1/2 the original size, use fWidth = 0.5
+ */
+typedef struct OMX_CONFIG_SCALEFACTORTYPE {
+ OMX_U32 nSize; /**< Size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version info */
+ OMX_U32 nPortIndex; /**< Port that this struct applies to */
+ OMX_S32 xWidth; /**< Fixed point value stored as Q16 */
+ OMX_S32 xHeight; /**< Fixed point value stored as Q16 */
+}OMX_CONFIG_SCALEFACTORTYPE;
+
+
+/**
+ * Enumeration of possible image filter types
+ */
+typedef enum OMX_IMAGEFILTERTYPE {
+ OMX_ImageFilterNone,
+ OMX_ImageFilterNoise,
+ OMX_ImageFilterEmboss,
+ OMX_ImageFilterNegative,
+ OMX_ImageFilterSketch,
+ OMX_ImageFilterOilPaint,
+ OMX_ImageFilterHatch,
+ OMX_ImageFilterGpen,
+ OMX_ImageFilterAntialias,
+ OMX_ImageFilterDeRing,
+ OMX_ImageFilterSolarize,
+ OMX_ImageFilterKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_ImageFilterVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_ImageFilterMax = 0x7FFFFFFF
+} OMX_IMAGEFILTERTYPE;
+
+
+/**
+ * Image filter configuration
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * eImageFilter : Image filter type enumeration
+ */
+typedef struct OMX_CONFIG_IMAGEFILTERTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_IMAGEFILTERTYPE eImageFilter;
+} OMX_CONFIG_IMAGEFILTERTYPE;
+
+
+/**
+ * Customized U and V for color enhancement
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * bColorEnhancement : Enable/disable color enhancement
+ * nCustomizedU : Practical values: 16-240, range: 0-255, value set for
+ * U component
+ * nCustomizedV : Practical values: 16-240, range: 0-255, value set for
+ * V component
+ */
+typedef struct OMX_CONFIG_COLORENHANCEMENTTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_BOOL bColorEnhancement;
+ OMX_U8 nCustomizedU;
+ OMX_U8 nCustomizedV;
+} OMX_CONFIG_COLORENHANCEMENTTYPE;
+
+
+/**
+ * Define color key and color key mask
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nARGBColor : 32bit Alpha, Red, Green, Blue Color
+ * nARGBMask : 32bit Mask for Alpha, Red, Green, Blue channels
+ */
+typedef struct OMX_CONFIG_COLORKEYTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nARGBColor;
+ OMX_U32 nARGBMask;
+} OMX_CONFIG_COLORKEYTYPE;
+
+
+/**
+ * List of color blend types for pre/post processing
+ *
+ * ENUMS:
+ * None : No color blending present
+ * AlphaConstant : Function is (alpha_constant * src) +
+ * (1 - alpha_constant) * dst)
+ * AlphaPerPixel : Function is (alpha * src) + (1 - alpha) * dst)
+ * Alternate : Function is alternating pixels from src and dst
+ * And : Function is (src & dst)
+ * Or : Function is (src | dst)
+ * Invert : Function is ~src
+ */
+typedef enum OMX_COLORBLENDTYPE {
+ OMX_ColorBlendNone,
+ OMX_ColorBlendAlphaConstant,
+ OMX_ColorBlendAlphaPerPixel,
+ OMX_ColorBlendAlternate,
+ OMX_ColorBlendAnd,
+ OMX_ColorBlendOr,
+ OMX_ColorBlendInvert,
+ OMX_ColorBlendKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_ColorBlendVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_ColorBlendMax = 0x7FFFFFFF
+} OMX_COLORBLENDTYPE;
+
+
+/**
+ * Color blend configuration
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nRGBAlphaConstant : Constant global alpha values when global alpha is used
+ * eColorBlend : Color blend type enumeration
+ */
+typedef struct OMX_CONFIG_COLORBLENDTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nRGBAlphaConstant;
+ OMX_COLORBLENDTYPE eColorBlend;
+} OMX_CONFIG_COLORBLENDTYPE;
+
+
+/**
+ * Hold frame dimension
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nWidth : Frame width in pixels
+ * nHeight : Frame height in pixels
+ */
+typedef struct OMX_FRAMESIZETYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nWidth;
+ OMX_U32 nHeight;
+} OMX_FRAMESIZETYPE;
+
+
+/**
+ * Rotation configuration
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nRotation : +/- integer rotation value
+ */
+typedef struct OMX_CONFIG_ROTATIONTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_S32 nRotation;
+} OMX_CONFIG_ROTATIONTYPE;
+
+
+/**
+ * Possible mirroring directions for pre/post processing
+ *
+ * ENUMS:
+ * None : No mirroring
+ * Vertical : Vertical mirroring, flip on X axis
+ * Horizontal : Horizontal mirroring, flip on Y axis
+ * Both : Both vertical and horizontal mirroring
+ */
+typedef enum OMX_MIRRORTYPE {
+ OMX_MirrorNone = 0,
+ OMX_MirrorVertical,
+ OMX_MirrorHorizontal,
+ OMX_MirrorBoth,
+ OMX_MirrorKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_MirrorVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_MirrorMax = 0x7FFFFFFF
+} OMX_MIRRORTYPE;
+
+
+/**
+ * Mirroring configuration
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * eMirror : Mirror type enumeration
+ */
+typedef struct OMX_CONFIG_MIRRORTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_MIRRORTYPE eMirror;
+} OMX_CONFIG_MIRRORTYPE;
+
+
+/**
+ * Position information only
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nX : X coordinate for the point
+ * nY : Y coordinate for the point
+ */
+typedef struct OMX_CONFIG_POINTTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_S32 nX;
+ OMX_S32 nY;
+} OMX_CONFIG_POINTTYPE;
+
+
+/**
+ * Frame size plus position
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nLeft : X Coordinate of the top left corner of the rectangle
+ * nTop : Y Coordinate of the top left corner of the rectangle
+ * nWidth : Width of the rectangle
+ * nHeight : Height of the rectangle
+ */
+typedef struct OMX_CONFIG_RECTTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_S32 nLeft;
+ OMX_S32 nTop;
+ OMX_U32 nWidth;
+ OMX_U32 nHeight;
+} OMX_CONFIG_RECTTYPE;
+
+
+/**
+ * Deblocking state; it is required to be set up before starting the codec
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * bDeblocking : Enable/disable deblocking mode
+ */
+typedef struct OMX_PARAM_DEBLOCKINGTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_BOOL bDeblocking;
+} OMX_PARAM_DEBLOCKINGTYPE;
+
+
+/**
+ * Stabilization state
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * bStab : Enable/disable frame stabilization state
+ */
+typedef struct OMX_CONFIG_FRAMESTABTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_BOOL bStab;
+} OMX_CONFIG_FRAMESTABTYPE;
+
+
+/**
+ * White Balance control type
+ *
+ * STRUCT MEMBERS:
+ * SunLight : Referenced in JSR-234
+ * Flash : Optimal for device's integrated flash
+ */
+typedef enum OMX_WHITEBALCONTROLTYPE {
+ OMX_WhiteBalControlOff = 0,
+ OMX_WhiteBalControlAuto,
+ OMX_WhiteBalControlSunLight,
+ OMX_WhiteBalControlCloudy,
+ OMX_WhiteBalControlShade,
+ OMX_WhiteBalControlTungsten,
+ OMX_WhiteBalControlFluorescent,
+ OMX_WhiteBalControlIncandescent,
+ OMX_WhiteBalControlFlash,
+ OMX_WhiteBalControlHorizon,
+ OMX_WhiteBalControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_WhiteBalControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_WhiteBalControlMax = 0x7FFFFFFF
+} OMX_WHITEBALCONTROLTYPE;
+
+
+/**
+ * White Balance control configuration
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * eWhiteBalControl : White balance enumeration
+ */
+typedef struct OMX_CONFIG_WHITEBALCONTROLTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_WHITEBALCONTROLTYPE eWhiteBalControl;
+} OMX_CONFIG_WHITEBALCONTROLTYPE;
+
+
+/**
+ * Exposure control type
+ */
+typedef enum OMX_EXPOSURECONTROLTYPE {
+ OMX_ExposureControlOff = 0,
+ OMX_ExposureControlAuto,
+ OMX_ExposureControlNight,
+ OMX_ExposureControlBackLight,
+ OMX_ExposureControlSpotLight,
+ OMX_ExposureControlSports,
+ OMX_ExposureControlSnow,
+ OMX_ExposureControlBeach,
+ OMX_ExposureControlLargeAperture,
+ OMX_ExposureControlSmallApperture,
+ OMX_ExposureControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_ExposureControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_ExposureControlMax = 0x7FFFFFFF
+} OMX_EXPOSURECONTROLTYPE;
+
+
+/**
+ * White Balance control configuration
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * eExposureControl : Exposure control enumeration
+ */
+typedef struct OMX_CONFIG_EXPOSURECONTROLTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_EXPOSURECONTROLTYPE eExposureControl;
+} OMX_CONFIG_EXPOSURECONTROLTYPE;
+
+
+/**
+ * Defines sensor supported mode.
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nFrameRate : Single shot mode is indicated by a 0
+ * bOneShot : Enable for single shot, disable for streaming
+ * sFrameSize : Framesize
+ */
+typedef struct OMX_PARAM_SENSORMODETYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nFrameRate;
+ OMX_BOOL bOneShot;
+ OMX_FRAMESIZETYPE sFrameSize;
+} OMX_PARAM_SENSORMODETYPE;
+
+
+/**
+ * Defines contrast level
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nContrast : Values allowed for contrast -100 to 100, zero means no change
+ */
+typedef struct OMX_CONFIG_CONTRASTTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_S32 nContrast;
+} OMX_CONFIG_CONTRASTTYPE;
+
+
+/**
+ * Defines brightness level
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nBrightness : 0-100%
+ */
+typedef struct OMX_CONFIG_BRIGHTNESSTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nBrightness;
+} OMX_CONFIG_BRIGHTNESSTYPE;
+
+
+/**
+ * Defines backlight level configuration for a video sink, e.g. LCD panel
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nBacklight : Values allowed for backlight 0-100%
+ * nTimeout : Number of milliseconds before backlight automatically turns
+ * off. A value of 0x0 disables backight timeout
+ */
+typedef struct OMX_CONFIG_BACKLIGHTTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nBacklight;
+ OMX_U32 nTimeout;
+} OMX_CONFIG_BACKLIGHTTYPE;
+
+
+/**
+ * Defines setting for Gamma
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nGamma : Values allowed for gamma -100 to 100, zero means no change
+ */
+typedef struct OMX_CONFIG_GAMMATYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_S32 nGamma;
+} OMX_CONFIG_GAMMATYPE;
+
+
+/**
+ * Define for setting saturation
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nSaturation : Values allowed for saturation -100 to 100, zero means
+ * no change
+ */
+typedef struct OMX_CONFIG_SATURATIONTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_S32 nSaturation;
+} OMX_CONFIG_SATURATIONTYPE;
+
+
+/**
+ * Define for setting Lightness
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nLightness : Values allowed for lightness -100 to 100, zero means no
+ * change
+ */
+typedef struct OMX_CONFIG_LIGHTNESSTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_S32 nLightness;
+} OMX_CONFIG_LIGHTNESSTYPE;
+
+
+/**
+ * Plane blend configuration
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Index of input port associated with the plane.
+ * nDepth : Depth of the plane in relation to the screen. Higher
+ * numbered depths are "behind" lower number depths.
+ * This number defaults to the Port Index number.
+ * nAlpha : Transparency blending component for the entire plane.
+ * See blending modes for more detail.
+ */
+typedef struct OMX_CONFIG_PLANEBLENDTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nDepth;
+ OMX_U32 nAlpha;
+} OMX_CONFIG_PLANEBLENDTYPE;
+
+
+/**
+ * Define interlace type
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * bEnable : Enable control variable for this functionality
+ * (see below)
+ * nInterleavePortIndex : Index of input or output port associated with
+ * the interleaved plane.
+ * pPlanarPortIndexes[4] : Index of input or output planar ports.
+ */
+typedef struct OMX_PARAM_INTERLEAVETYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_BOOL bEnable;
+ OMX_U32 nInterleavePortIndex;
+} OMX_PARAM_INTERLEAVETYPE;
+
+
+/**
+ * Defines the picture effect used for an input picture
+ */
+typedef enum OMX_TRANSITIONEFFECTTYPE {
+ OMX_EffectNone,
+ OMX_EffectFadeFromBlack,
+ OMX_EffectFadeToBlack,
+ OMX_EffectUnspecifiedThroughConstantColor,
+ OMX_EffectDissolve,
+ OMX_EffectWipe,
+ OMX_EffectUnspecifiedMixOfTwoScenes,
+ OMX_EffectKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_EffectVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_EffectMax = 0x7FFFFFFF
+} OMX_TRANSITIONEFFECTTYPE;
+
+
+/**
+ * Structure used to configure current transition effect
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * eEffect : Effect to enable
+ */
+typedef struct OMX_CONFIG_TRANSITIONEFFECTTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_TRANSITIONEFFECTTYPE eEffect;
+} OMX_CONFIG_TRANSITIONEFFECTTYPE;
+
+
+/**
+ * Defines possible data unit types for encoded video data. The data unit
+ * types are used both for encoded video input for playback as well as
+ * encoded video output from recording.
+ */
+typedef enum OMX_DATAUNITTYPE {
+ OMX_DataUnitCodedPicture,
+ OMX_DataUnitVideoSegment,
+ OMX_DataUnitSeveralSegments,
+ OMX_DataUnitArbitraryStreamSection,
+ OMX_DataUnitKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_DataUnitVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_DataUnitMax = 0x7FFFFFFF
+} OMX_DATAUNITTYPE;
+
+
+/**
+ * Defines possible encapsulation types for coded video data unit. The
+ * encapsulation information is used both for encoded video input for
+ * playback as well as encoded video output from recording.
+ */
+typedef enum OMX_DATAUNITENCAPSULATIONTYPE {
+ OMX_DataEncapsulationElementaryStream,
+ OMX_DataEncapsulationGenericPayload,
+ OMX_DataEncapsulationRtpPayload,
+ OMX_DataEncapsulationKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_DataEncapsulationVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_DataEncapsulationMax = 0x7FFFFFFF
+} OMX_DATAUNITENCAPSULATIONTYPE;
+
+
+/**
+ * Structure used to configure the type of being decoded/encoded
+ */
+typedef struct OMX_PARAM_DATAUNITTYPE {
+ OMX_U32 nSize; /**< Size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< Port that this structure applies to */
+ OMX_DATAUNITTYPE eUnitType;
+ OMX_DATAUNITENCAPSULATIONTYPE eEncapsulationType;
+} OMX_PARAM_DATAUNITTYPE;
+
+
+/**
+ * Defines dither types
+ */
+typedef enum OMX_DITHERTYPE {
+ OMX_DitherNone,
+ OMX_DitherOrdered,
+ OMX_DitherErrorDiffusion,
+ OMX_DitherOther,
+ OMX_DitherKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_DitherVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_DitherMax = 0x7FFFFFFF
+} OMX_DITHERTYPE;
+
+
+/**
+ * Structure used to configure current type of dithering
+ */
+typedef struct OMX_CONFIG_DITHERTYPE {
+ OMX_U32 nSize; /**< Size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< Port that this structure applies to */
+ OMX_DITHERTYPE eDither; /**< Type of dithering to use */
+} OMX_CONFIG_DITHERTYPE;
+
+typedef struct OMX_CONFIG_CAPTUREMODETYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex; /**< Port that this structure applies to */
+ OMX_BOOL bContinuous; /**< If true then ignore frame rate and emit capture
+ * data as fast as possible (otherwise obey port's frame rate). */
+ OMX_BOOL bFrameLimited; /**< If true then terminate capture after the port emits the
+ * specified number of frames (otherwise the port does not
+ * terminate the capture until instructed to do so by the client).
+ * Even if set, the client may manually terminate the capture prior
+ * to reaching the limit. */
+ OMX_U32 nFrameLimit; /**< Limit on number of frames emitted during a capture (only
+ * valid if bFrameLimited is set). */
+} OMX_CONFIG_CAPTUREMODETYPE;
+
+typedef enum OMX_METERINGTYPE {
+
+ OMX_MeteringModeAverage, /**< Center-weighted average metering. */
+ OMX_MeteringModeSpot, /**< Spot (partial) metering. */
+ OMX_MeteringModeMatrix, /**< Matrix or evaluative metering. */
+
+ OMX_MeteringKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_MeteringVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_EVModeMax = 0x7fffffff
+} OMX_METERINGTYPE;
+
+typedef struct OMX_CONFIG_EXPOSUREVALUETYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_METERINGTYPE eMetering;
+ OMX_S32 xEVCompensation; /**< Fixed point value stored as Q16 */
+ OMX_U32 nApertureFNumber; /**< e.g. nApertureFNumber = 2 implies "f/2" - Q16 format */
+ OMX_BOOL bAutoAperture; /**< Whether aperture number is defined automatically */
+ OMX_U32 nShutterSpeedMsec; /**< Shutterspeed in milliseconds */
+ OMX_BOOL bAutoShutterSpeed; /**< Whether shutter speed is defined automatically */
+ OMX_U32 nSensitivity; /**< e.g. nSensitivity = 100 implies "ISO 100" */
+ OMX_BOOL bAutoSensitivity; /**< Whether sensitivity is defined automatically */
+} OMX_CONFIG_EXPOSUREVALUETYPE;
+
+/**
+ * Focus region configuration
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * bCenter : Use center region as focus region of interest
+ * bLeft : Use left region as focus region of interest
+ * bRight : Use right region as focus region of interest
+ * bTop : Use top region as focus region of interest
+ * bBottom : Use bottom region as focus region of interest
+ * bTopLeft : Use top left region as focus region of interest
+ * bTopRight : Use top right region as focus region of interest
+ * bBottomLeft : Use bottom left region as focus region of interest
+ * bBottomRight : Use bottom right region as focus region of interest
+ */
+typedef struct OMX_CONFIG_FOCUSREGIONTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_BOOL bCenter;
+ OMX_BOOL bLeft;
+ OMX_BOOL bRight;
+ OMX_BOOL bTop;
+ OMX_BOOL bBottom;
+ OMX_BOOL bTopLeft;
+ OMX_BOOL bTopRight;
+ OMX_BOOL bBottomLeft;
+ OMX_BOOL bBottomRight;
+} OMX_CONFIG_FOCUSREGIONTYPE;
+
+/**
+ * Focus Status type
+ */
+typedef enum OMX_FOCUSSTATUSTYPE {
+ OMX_FocusStatusOff = 0,
+ OMX_FocusStatusRequest,
+ OMX_FocusStatusReached,
+ OMX_FocusStatusUnableToReach,
+ OMX_FocusStatusLost,
+ OMX_FocusStatusKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_FocusStatusVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_FocusStatusMax = 0x7FFFFFFF
+} OMX_FOCUSSTATUSTYPE;
+
+/**
+ * Focus status configuration
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * eFocusStatus : Specifies the focus status
+ * bCenterStatus : Use center region as focus region of interest
+ * bLeftStatus : Use left region as focus region of interest
+ * bRightStatus : Use right region as focus region of interest
+ * bTopStatus : Use top region as focus region of interest
+ * bBottomStatus : Use bottom region as focus region of interest
+ * bTopLeftStatus : Use top left region as focus region of interest
+ * bTopRightStatus : Use top right region as focus region of interest
+ * bBottomLeftStatus : Use bottom left region as focus region of interest
+ * bBottomRightStatus : Use bottom right region as focus region of interest
+ */
+typedef struct OMX_PARAM_FOCUSSTATUSTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_FOCUSSTATUSTYPE eFocusStatus;
+ OMX_BOOL bCenterStatus;
+ OMX_BOOL bLeftStatus;
+ OMX_BOOL bRightStatus;
+ OMX_BOOL bTopStatus;
+ OMX_BOOL bBottomStatus;
+ OMX_BOOL bTopLeftStatus;
+ OMX_BOOL bTopRightStatus;
+ OMX_BOOL bBottomLeftStatus;
+ OMX_BOOL bBottomRightStatus;
+} OMX_PARAM_FOCUSSTATUSTYPE;
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
+/* File EOF */
diff --git a/subprojects/gst-omx/omx/openmax/OMX_Image.h b/subprojects/gst-omx/omx/openmax/OMX_Image.h
new file mode 100644
index 0000000000..a6d4666c03
--- /dev/null
+++ b/subprojects/gst-omx/omx/openmax/OMX_Image.h
@@ -0,0 +1,328 @@
+/**
+ * Copyright (c) 2008 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file OMX_Image.h - OpenMax IL version 1.1.2
+ * The structures needed by Image components to exchange parameters and
+ * configuration data with the components.
+ */
+#ifndef OMX_Image_h
+#define OMX_Image_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/**
+ * Each OMX header must include all required header files to allow the
+ * header to compile without errors. The includes below are required
+ * for this header file to compile successfully
+ */
+
+#include <OMX_IVCommon.h>
+
+/** @defgroup imaging OpenMAX IL Imaging Domain
+ * @ingroup iv
+ * Structures for OpenMAX IL Imaging domain
+ * @{
+ */
+
+/**
+ * Enumeration used to define the possible image compression coding.
+ */
+typedef enum OMX_IMAGE_CODINGTYPE {
+ OMX_IMAGE_CodingUnused, /**< Value when format is N/A */
+ OMX_IMAGE_CodingAutoDetect, /**< Auto detection of image format */
+ OMX_IMAGE_CodingJPEG, /**< JPEG/JFIF image format */
+ OMX_IMAGE_CodingJPEG2K, /**< JPEG 2000 image format */
+ OMX_IMAGE_CodingEXIF, /**< EXIF image format */
+ OMX_IMAGE_CodingTIFF, /**< TIFF image format */
+ OMX_IMAGE_CodingGIF, /**< Graphics image format */
+ OMX_IMAGE_CodingPNG, /**< PNG image format */
+ OMX_IMAGE_CodingLZW, /**< LZW image format */
+ OMX_IMAGE_CodingBMP, /**< Windows Bitmap format */
+ OMX_IMAGE_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_IMAGE_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_IMAGE_CodingMax = 0x7FFFFFFF
+} OMX_IMAGE_CODINGTYPE;
+
+
+/**
+ * Data structure used to define an image path. The number of image paths
+ * for input and output will vary by type of the image component.
+ *
+ * Input (aka Source) : Zero Inputs, one Output,
+ * Splitter : One Input, 2 or more Outputs,
+ * Processing Element : One Input, one output,
+ * Mixer : 2 or more inputs, one output,
+ * Output (aka Sink) : One Input, zero outputs.
+ *
+ * The PortDefinition structure is used to define all of the parameters
+ * necessary for the compliant component to setup an input or an output
+ * image path. If additional vendor specific data is required, it should
+ * be transmitted to the component using the CustomCommand function.
+ * Compliant components will prepopulate this structure with optimal
+ * values during the OMX_GetParameter() command.
+ *
+ * STRUCT MEMBERS:
+ * cMIMEType : MIME type of data for the port
+ * pNativeRender : Platform specific reference for a display if a
+ * sync, otherwise this field is 0
+ * nFrameWidth : Width of frame to be used on port if
+ * uncompressed format is used. Use 0 for
+ * unknown, don't care or variable
+ * nFrameHeight : Height of frame to be used on port if
+ * uncompressed format is used. Use 0 for
+ * unknown, don't care or variable
+ * nStride : Number of bytes per span of an image (i.e.
+ * indicates the number of bytes to get from
+ * span N to span N+1, where negative stride
+ * indicates the image is bottom up
+ * nSliceHeight : Height used when encoding in slices
+ * bFlagErrorConcealment : Turns on error concealment if it is supported by
+ * the OMX component
+ * eCompressionFormat : Compression format used in this instance of
+ * the component. When OMX_IMAGE_CodingUnused is
+ * specified, eColorFormat is valid
+ * eColorFormat : Decompressed format used by this component
+ * pNativeWindow : Platform specific reference for a window object if a
+ * display sink , otherwise this field is 0x0.
+ */
+typedef struct OMX_IMAGE_PORTDEFINITIONTYPE {
+ OMX_STRING cMIMEType;
+ OMX_NATIVE_DEVICETYPE pNativeRender;
+ OMX_U32 nFrameWidth;
+ OMX_U32 nFrameHeight;
+ OMX_S32 nStride;
+ OMX_U32 nSliceHeight;
+ OMX_BOOL bFlagErrorConcealment;
+ OMX_IMAGE_CODINGTYPE eCompressionFormat;
+ OMX_COLOR_FORMATTYPE eColorFormat;
+ OMX_NATIVE_WINDOWTYPE pNativeWindow;
+} OMX_IMAGE_PORTDEFINITIONTYPE;
+
+
+/**
+ * Port format parameter. This structure is used to enumerate the various
+ * data input/output format supported by the port.
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Indicates which port to set
+ * nIndex : Indicates the enumeration index for the format from
+ * 0x0 to N-1
+ * eCompressionFormat : Compression format used in this instance of the
+ * component. When OMX_IMAGE_CodingUnused is specified,
+ * eColorFormat is valid
+ * eColorFormat : Decompressed format used by this component
+ */
+typedef struct OMX_IMAGE_PARAM_PORTFORMATTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nIndex;
+ OMX_IMAGE_CODINGTYPE eCompressionFormat;
+ OMX_COLOR_FORMATTYPE eColorFormat;
+} OMX_IMAGE_PARAM_PORTFORMATTYPE;
+
+
+/**
+ * Flash control type
+ *
+ * ENUMS
+ * Torch : Flash forced constantly on
+ */
+typedef enum OMX_IMAGE_FLASHCONTROLTYPE {
+ OMX_IMAGE_FlashControlOn = 0,
+ OMX_IMAGE_FlashControlOff,
+ OMX_IMAGE_FlashControlAuto,
+ OMX_IMAGE_FlashControlRedEyeReduction,
+ OMX_IMAGE_FlashControlFillin,
+ OMX_IMAGE_FlashControlTorch,
+ OMX_IMAGE_FlashControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_IMAGE_FlashControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_IMAGE_FlashControlMax = 0x7FFFFFFF
+} OMX_IMAGE_FLASHCONTROLTYPE;
+
+
+/**
+ * Flash control configuration
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * eFlashControl : Flash control type
+ */
+typedef struct OMX_IMAGE_PARAM_FLASHCONTROLTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_IMAGE_FLASHCONTROLTYPE eFlashControl;
+} OMX_IMAGE_PARAM_FLASHCONTROLTYPE;
+
+
+/**
+ * Focus control type
+ */
+typedef enum OMX_IMAGE_FOCUSCONTROLTYPE {
+ OMX_IMAGE_FocusControlOn = 0,
+ OMX_IMAGE_FocusControlOff,
+ OMX_IMAGE_FocusControlAuto,
+ OMX_IMAGE_FocusControlAutoLock,
+ OMX_IMAGE_FocusControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_IMAGE_FocusControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_IMAGE_FocusControlMax = 0x7FFFFFFF
+} OMX_IMAGE_FOCUSCONTROLTYPE;
+
+
+/**
+ * Focus control configuration
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * eFocusControl : Focus control
+ * nFocusSteps : Focus can take on values from 0 mm to infinity.
+ * Interest is only in number of steps over this range.
+ * nFocusStepIndex : Current focus step index
+ */
+typedef struct OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_IMAGE_FOCUSCONTROLTYPE eFocusControl;
+ OMX_U32 nFocusSteps;
+ OMX_U32 nFocusStepIndex;
+} OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE;
+
+
+/**
+ * Q Factor for JPEG compression, which controls the tradeoff between image
+ * quality and size. Q Factor provides a more simple means of controlling
+ * JPEG compression quality, without directly programming Quantization
+ * tables for chroma and luma
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nQFactor : JPEG Q factor value in the range of 1-100. A factor of 1
+ * produces the smallest, worst quality images, and a factor
+ * of 100 produces the largest, best quality images. A
+ * typical default is 75 for small good quality images
+ */
+typedef struct OMX_IMAGE_PARAM_QFACTORTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nQFactor;
+} OMX_IMAGE_PARAM_QFACTORTYPE;
+
+/**
+ * Quantization table type
+ */
+
+typedef enum OMX_IMAGE_QUANTIZATIONTABLETYPE {
+ OMX_IMAGE_QuantizationTableLuma = 0,
+ OMX_IMAGE_QuantizationTableChroma,
+ OMX_IMAGE_QuantizationTableChromaCb,
+ OMX_IMAGE_QuantizationTableChromaCr,
+ OMX_IMAGE_QuantizationTableKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_IMAGE_QuantizationTableVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_IMAGE_QuantizationTableMax = 0x7FFFFFFF
+} OMX_IMAGE_QUANTIZATIONTABLETYPE;
+
+/**
+ * JPEG quantization tables are used to determine DCT compression for
+ * YUV data, as an alternative to specifying Q factor, providing exact
+ * control of compression
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * eQuantizationTable : Quantization table type
+ * nQuantizationMatrix[64] : JPEG quantization table of coefficients stored
+ * in increasing columns then by rows of data (i.e.
+ * row 1, ... row 8). Quantization values are in
+ * the range 0-255 and stored in linear order
+ * (i.e. the component will zig-zag the
+ * quantization table data if required internally)
+ */
+typedef struct OMX_IMAGE_PARAM_QUANTIZATIONTABLETYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_IMAGE_QUANTIZATIONTABLETYPE eQuantizationTable;
+ OMX_U8 nQuantizationMatrix[64];
+} OMX_IMAGE_PARAM_QUANTIZATIONTABLETYPE;
+
+
+/**
+ * Huffman table type, the same Huffman table is applied for chroma and
+ * luma component
+ */
+typedef enum OMX_IMAGE_HUFFMANTABLETYPE {
+ OMX_IMAGE_HuffmanTableAC = 0,
+ OMX_IMAGE_HuffmanTableDC,
+ OMX_IMAGE_HuffmanTableACLuma,
+ OMX_IMAGE_HuffmanTableACChroma,
+ OMX_IMAGE_HuffmanTableDCLuma,
+ OMX_IMAGE_HuffmanTableDCChroma,
+ OMX_IMAGE_HuffmanTableKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_IMAGE_HuffmanTableVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_IMAGE_HuffmanTableMax = 0x7FFFFFFF
+} OMX_IMAGE_HUFFMANTABLETYPE;
+
+/**
+ * JPEG Huffman table
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * eHuffmanTable : Huffman table type
+ * nNumberOfHuffmanCodeOfLength[16] : 0-16, number of Huffman codes of each
+ * possible length
+ * nHuffmanTable[256] : 0-255, the size used for AC and DC
+ * HuffmanTable are 16 and 162
+ */
+typedef struct OMX_IMAGE_PARAM_HUFFMANTTABLETYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_IMAGE_HUFFMANTABLETYPE eHuffmanTable;
+ OMX_U8 nNumberOfHuffmanCodeOfLength[16];
+ OMX_U8 nHuffmanTable[256];
+}OMX_IMAGE_PARAM_HUFFMANTTABLETYPE;
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
+/* File EOF */
diff --git a/subprojects/gst-omx/omx/openmax/OMX_Index.h b/subprojects/gst-omx/omx/openmax/OMX_Index.h
new file mode 100644
index 0000000000..44d4ea76d2
--- /dev/null
+++ b/subprojects/gst-omx/omx/openmax/OMX_Index.h
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2008 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/** @file OMX_Index.h - OpenMax IL version 1.1.2
+ * The OMX_Index header file contains the definitions for both applications
+ * and components .
+ */
+
+
+#ifndef OMX_Index_h
+#define OMX_Index_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* Each OMX header must include all required header files to allow the
+ * header to compile without errors. The includes below are required
+ * for this header file to compile successfully
+ */
+#include <OMX_Types.h>
+
+
+/** The OMX_INDEXTYPE enumeration is used to select a structure when either
+ * getting or setting parameters and/or configuration data. Each entry in
+ * this enumeration maps to an OMX specified structure. When the
+ * OMX_GetParameter, OMX_SetParameter, OMX_GetConfig or OMX_SetConfig methods
+ * are used, the second parameter will always be an entry from this enumeration
+ * and the third entry will be the structure shown in the comments for the entry.
+ * For example, if the application is initializing a cropping function, the
+ * OMX_SetConfig command would have OMX_IndexConfigCommonInputCrop as the second parameter
+ * and would send a pointer to an initialized OMX_RECTTYPE structure as the
+ * third parameter.
+ *
+ * The enumeration entries named with the OMX_Config prefix are sent using
+ * the OMX_SetConfig command and the enumeration entries named with the
+ * OMX_PARAM_ prefix are sent using the OMX_SetParameter command.
+ */
+typedef enum OMX_INDEXTYPE {
+
+ OMX_IndexComponentStartUnused = 0x01000000,
+ OMX_IndexParamPriorityMgmt, /**< reference: OMX_PRIORITYMGMTTYPE */
+ OMX_IndexParamAudioInit, /**< reference: OMX_PORT_PARAM_TYPE */
+ OMX_IndexParamImageInit, /**< reference: OMX_PORT_PARAM_TYPE */
+ OMX_IndexParamVideoInit, /**< reference: OMX_PORT_PARAM_TYPE */
+ OMX_IndexParamOtherInit, /**< reference: OMX_PORT_PARAM_TYPE */
+ OMX_IndexParamNumAvailableStreams, /**< reference: OMX_PARAM_U32TYPE */
+ OMX_IndexParamActiveStream, /**< reference: OMX_PARAM_U32TYPE */
+ OMX_IndexParamSuspensionPolicy, /**< reference: OMX_PARAM_SUSPENSIONPOLICYTYPE */
+ OMX_IndexParamComponentSuspended, /**< reference: OMX_PARAM_SUSPENSIONTYPE */
+ OMX_IndexConfigCapturing, /**< reference: OMX_CONFIG_BOOLEANTYPE */
+ OMX_IndexConfigCaptureMode, /**< reference: OMX_CONFIG_CAPTUREMODETYPE */
+ OMX_IndexAutoPauseAfterCapture, /**< reference: OMX_CONFIG_BOOLEANTYPE */
+ OMX_IndexParamContentURI, /**< reference: OMX_PARAM_CONTENTURITYPE */
+ OMX_IndexParamCustomContentPipe, /**< reference: OMX_PARAM_CONTENTPIPETYPE */
+ OMX_IndexParamDisableResourceConcealment, /**< reference: OMX_RESOURCECONCEALMENTTYPE */
+ OMX_IndexConfigMetadataItemCount, /**< reference: OMX_CONFIG_METADATAITEMCOUNTTYPE */
+ OMX_IndexConfigContainerNodeCount, /**< reference: OMX_CONFIG_CONTAINERNODECOUNTTYPE */
+ OMX_IndexConfigMetadataItem, /**< reference: OMX_CONFIG_METADATAITEMTYPE */
+ OMX_IndexConfigCounterNodeID, /**< reference: OMX_CONFIG_CONTAINERNODEIDTYPE */
+ OMX_IndexParamMetadataFilterType, /**< reference: OMX_PARAM_METADATAFILTERTYPE */
+ OMX_IndexParamMetadataKeyFilter, /**< reference: OMX_PARAM_METADATAFILTERTYPE */
+ OMX_IndexConfigPriorityMgmt, /**< reference: OMX_PRIORITYMGMTTYPE */
+ OMX_IndexParamStandardComponentRole, /**< reference: OMX_PARAM_COMPONENTROLETYPE */
+
+ OMX_IndexPortStartUnused = 0x02000000,
+ OMX_IndexParamPortDefinition, /**< reference: OMX_PARAM_PORTDEFINITIONTYPE */
+ OMX_IndexParamCompBufferSupplier, /**< reference: OMX_PARAM_BUFFERSUPPLIERTYPE */
+ OMX_IndexReservedStartUnused = 0x03000000,
+
+ /* Audio parameters and configurations */
+ OMX_IndexAudioStartUnused = 0x04000000,
+ OMX_IndexParamAudioPortFormat, /**< reference: OMX_AUDIO_PARAM_PORTFORMATTYPE */
+ OMX_IndexParamAudioPcm, /**< reference: OMX_AUDIO_PARAM_PCMMODETYPE */
+ OMX_IndexParamAudioAac, /**< reference: OMX_AUDIO_PARAM_AACPROFILETYPE */
+ OMX_IndexParamAudioRa, /**< reference: OMX_AUDIO_PARAM_RATYPE */
+ OMX_IndexParamAudioMp3, /**< reference: OMX_AUDIO_PARAM_MP3TYPE */
+ OMX_IndexParamAudioAdpcm, /**< reference: OMX_AUDIO_PARAM_ADPCMTYPE */
+ OMX_IndexParamAudioG723, /**< reference: OMX_AUDIO_PARAM_G723TYPE */
+ OMX_IndexParamAudioG729, /**< reference: OMX_AUDIO_PARAM_G729TYPE */
+ OMX_IndexParamAudioAmr, /**< reference: OMX_AUDIO_PARAM_AMRTYPE */
+ OMX_IndexParamAudioWma, /**< reference: OMX_AUDIO_PARAM_WMATYPE */
+ OMX_IndexParamAudioSbc, /**< reference: OMX_AUDIO_PARAM_SBCTYPE */
+ OMX_IndexParamAudioMidi, /**< reference: OMX_AUDIO_PARAM_MIDITYPE */
+ OMX_IndexParamAudioGsm_FR, /**< reference: OMX_AUDIO_PARAM_GSMFRTYPE */
+ OMX_IndexParamAudioMidiLoadUserSound, /**< reference: OMX_AUDIO_PARAM_MIDILOADUSERSOUNDTYPE */
+ OMX_IndexParamAudioG726, /**< reference: OMX_AUDIO_PARAM_G726TYPE */
+ OMX_IndexParamAudioGsm_EFR, /**< reference: OMX_AUDIO_PARAM_GSMEFRTYPE */
+ OMX_IndexParamAudioGsm_HR, /**< reference: OMX_AUDIO_PARAM_GSMHRTYPE */
+ OMX_IndexParamAudioPdc_FR, /**< reference: OMX_AUDIO_PARAM_PDCFRTYPE */
+ OMX_IndexParamAudioPdc_EFR, /**< reference: OMX_AUDIO_PARAM_PDCEFRTYPE */
+ OMX_IndexParamAudioPdc_HR, /**< reference: OMX_AUDIO_PARAM_PDCHRTYPE */
+ OMX_IndexParamAudioTdma_FR, /**< reference: OMX_AUDIO_PARAM_TDMAFRTYPE */
+ OMX_IndexParamAudioTdma_EFR, /**< reference: OMX_AUDIO_PARAM_TDMAEFRTYPE */
+ OMX_IndexParamAudioQcelp8, /**< reference: OMX_AUDIO_PARAM_QCELP8TYPE */
+ OMX_IndexParamAudioQcelp13, /**< reference: OMX_AUDIO_PARAM_QCELP13TYPE */
+ OMX_IndexParamAudioEvrc, /**< reference: OMX_AUDIO_PARAM_EVRCTYPE */
+ OMX_IndexParamAudioSmv, /**< reference: OMX_AUDIO_PARAM_SMVTYPE */
+ OMX_IndexParamAudioVorbis, /**< reference: OMX_AUDIO_PARAM_VORBISTYPE */
+
+ OMX_IndexConfigAudioMidiImmediateEvent, /**< reference: OMX_AUDIO_CONFIG_MIDIIMMEDIATEEVENTTYPE */
+ OMX_IndexConfigAudioMidiControl, /**< reference: OMX_AUDIO_CONFIG_MIDICONTROLTYPE */
+ OMX_IndexConfigAudioMidiSoundBankProgram, /**< reference: OMX_AUDIO_CONFIG_MIDISOUNDBANKPROGRAMTYPE */
+ OMX_IndexConfigAudioMidiStatus, /**< reference: OMX_AUDIO_CONFIG_MIDISTATUSTYPE */
+ OMX_IndexConfigAudioMidiMetaEvent, /**< reference: OMX_AUDIO_CONFIG_MIDIMETAEVENTTYPE */
+ OMX_IndexConfigAudioMidiMetaEventData, /**< reference: OMX_AUDIO_CONFIG_MIDIMETAEVENTDATATYPE */
+ OMX_IndexConfigAudioVolume, /**< reference: OMX_AUDIO_CONFIG_VOLUMETYPE */
+ OMX_IndexConfigAudioBalance, /**< reference: OMX_AUDIO_CONFIG_BALANCETYPE */
+ OMX_IndexConfigAudioChannelMute, /**< reference: OMX_AUDIO_CONFIG_CHANNELMUTETYPE */
+ OMX_IndexConfigAudioMute, /**< reference: OMX_AUDIO_CONFIG_MUTETYPE */
+ OMX_IndexConfigAudioLoudness, /**< reference: OMX_AUDIO_CONFIG_LOUDNESSTYPE */
+ OMX_IndexConfigAudioEchoCancelation, /**< reference: OMX_AUDIO_CONFIG_ECHOCANCELATIONTYPE */
+ OMX_IndexConfigAudioNoiseReduction, /**< reference: OMX_AUDIO_CONFIG_NOISEREDUCTIONTYPE */
+ OMX_IndexConfigAudioBass, /**< reference: OMX_AUDIO_CONFIG_BASSTYPE */
+ OMX_IndexConfigAudioTreble, /**< reference: OMX_AUDIO_CONFIG_TREBLETYPE */
+ OMX_IndexConfigAudioStereoWidening, /**< reference: OMX_AUDIO_CONFIG_STEREOWIDENINGTYPE */
+ OMX_IndexConfigAudioChorus, /**< reference: OMX_AUDIO_CONFIG_CHORUSTYPE */
+ OMX_IndexConfigAudioEqualizer, /**< reference: OMX_AUDIO_CONFIG_EQUALIZERTYPE */
+ OMX_IndexConfigAudioReverberation, /**< reference: OMX_AUDIO_CONFIG_REVERBERATIONTYPE */
+ OMX_IndexConfigAudioChannelVolume, /**< reference: OMX_AUDIO_CONFIG_CHANNELVOLUMETYPE */
+
+ /* Image specific parameters and configurations */
+ OMX_IndexImageStartUnused = 0x05000000,
+ OMX_IndexParamImagePortFormat, /**< reference: OMX_IMAGE_PARAM_PORTFORMATTYPE */
+ OMX_IndexParamFlashControl, /**< reference: OMX_IMAGE_PARAM_FLASHCONTROLTYPE */
+ OMX_IndexConfigFocusControl, /**< reference: OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE */
+ OMX_IndexParamQFactor, /**< reference: OMX_IMAGE_PARAM_QFACTORTYPE */
+ OMX_IndexParamQuantizationTable, /**< reference: OMX_IMAGE_PARAM_QUANTIZATIONTABLETYPE */
+ OMX_IndexParamHuffmanTable, /**< reference: OMX_IMAGE_PARAM_HUFFMANTTABLETYPE */
+ OMX_IndexConfigFlashControl, /**< reference: OMX_IMAGE_PARAM_FLASHCONTROLTYPE */
+
+ /* Video specific parameters and configurations */
+ OMX_IndexVideoStartUnused = 0x06000000,
+ OMX_IndexParamVideoPortFormat, /**< reference: OMX_VIDEO_PARAM_PORTFORMATTYPE */
+ OMX_IndexParamVideoQuantization, /**< reference: OMX_VIDEO_PARAM_QUANTIZATIONTYPE */
+ OMX_IndexParamVideoFastUpdate, /**< reference: OMX_VIDEO_PARAM_VIDEOFASTUPDATETYPE */
+ OMX_IndexParamVideoBitrate, /**< reference: OMX_VIDEO_PARAM_BITRATETYPE */
+ OMX_IndexParamVideoMotionVector, /**< reference: OMX_VIDEO_PARAM_MOTIONVECTORTYPE */
+ OMX_IndexParamVideoIntraRefresh, /**< reference: OMX_VIDEO_PARAM_INTRAREFRESHTYPE */
+ OMX_IndexParamVideoErrorCorrection, /**< reference: OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE */
+ OMX_IndexParamVideoVBSMC, /**< reference: OMX_VIDEO_PARAM_VBSMCTYPE */
+ OMX_IndexParamVideoMpeg2, /**< reference: OMX_VIDEO_PARAM_MPEG2TYPE */
+ OMX_IndexParamVideoMpeg4, /**< reference: OMX_VIDEO_PARAM_MPEG4TYPE */
+ OMX_IndexParamVideoWmv, /**< reference: OMX_VIDEO_PARAM_WMVTYPE */
+ OMX_IndexParamVideoRv, /**< reference: OMX_VIDEO_PARAM_RVTYPE */
+ OMX_IndexParamVideoAvc, /**< reference: OMX_VIDEO_PARAM_AVCTYPE */
+ OMX_IndexParamVideoH263, /**< reference: OMX_VIDEO_PARAM_H263TYPE */
+ OMX_IndexParamVideoProfileLevelQuerySupported, /**< reference: OMX_VIDEO_PARAM_PROFILELEVELTYPE */
+ OMX_IndexParamVideoProfileLevelCurrent, /**< reference: OMX_VIDEO_PARAM_PROFILELEVELTYPE */
+ OMX_IndexConfigVideoBitrate, /**< reference: OMX_VIDEO_CONFIG_BITRATETYPE */
+ OMX_IndexConfigVideoFramerate, /**< reference: OMX_CONFIG_FRAMERATETYPE */
+ OMX_IndexConfigVideoIntraVOPRefresh, /**< reference: OMX_CONFIG_INTRAREFRESHVOPTYPE */
+ OMX_IndexConfigVideoIntraMBRefresh, /**< reference: OMX_CONFIG_MACROBLOCKERRORMAPTYPE */
+ OMX_IndexConfigVideoMBErrorReporting, /**< reference: OMX_CONFIG_MBERRORREPORTINGTYPE */
+ OMX_IndexParamVideoMacroblocksPerFrame, /**< reference: OMX_PARAM_MACROBLOCKSTYPE */
+ OMX_IndexConfigVideoMacroBlockErrorMap, /**< reference: OMX_CONFIG_MACROBLOCKERRORMAPTYPE */
+ OMX_IndexParamVideoSliceFMO, /**< reference: OMX_VIDEO_PARAM_AVCSLICEFMO */
+ OMX_IndexConfigVideoAVCIntraPeriod, /**< reference: OMX_VIDEO_CONFIG_AVCINTRAPERIOD */
+ OMX_IndexConfigVideoNalSize, /**< reference: OMX_VIDEO_CONFIG_NALSIZE */
+
+ /* Image & Video common Configurations */
+ OMX_IndexCommonStartUnused = 0x07000000,
+ OMX_IndexParamCommonDeblocking, /**< reference: OMX_PARAM_DEBLOCKINGTYPE */
+ OMX_IndexParamCommonSensorMode, /**< reference: OMX_PARAM_SENSORMODETYPE */
+ OMX_IndexParamCommonInterleave, /**< reference: OMX_PARAM_INTERLEAVETYPE */
+ OMX_IndexConfigCommonColorFormatConversion, /**< reference: OMX_CONFIG_COLORCONVERSIONTYPE */
+ OMX_IndexConfigCommonScale, /**< reference: OMX_CONFIG_SCALEFACTORTYPE */
+ OMX_IndexConfigCommonImageFilter, /**< reference: OMX_CONFIG_IMAGEFILTERTYPE */
+ OMX_IndexConfigCommonColorEnhancement, /**< reference: OMX_CONFIG_COLORENHANCEMENTTYPE */
+ OMX_IndexConfigCommonColorKey, /**< reference: OMX_CONFIG_COLORKEYTYPE */
+ OMX_IndexConfigCommonColorBlend, /**< reference: OMX_CONFIG_COLORBLENDTYPE */
+ OMX_IndexConfigCommonFrameStabilisation,/**< reference: OMX_CONFIG_FRAMESTABTYPE */
+ OMX_IndexConfigCommonRotate, /**< reference: OMX_CONFIG_ROTATIONTYPE */
+ OMX_IndexConfigCommonMirror, /**< reference: OMX_CONFIG_MIRRORTYPE */
+ OMX_IndexConfigCommonOutputPosition, /**< reference: OMX_CONFIG_POINTTYPE */
+ OMX_IndexConfigCommonInputCrop, /**< reference: OMX_CONFIG_RECTTYPE */
+ OMX_IndexConfigCommonOutputCrop, /**< reference: OMX_CONFIG_RECTTYPE */
+ OMX_IndexConfigCommonDigitalZoom, /**< reference: OMX_CONFIG_SCALEFACTORTYPE */
+ OMX_IndexConfigCommonOpticalZoom, /**< reference: OMX_CONFIG_SCALEFACTORTYPE*/
+ OMX_IndexConfigCommonWhiteBalance, /**< reference: OMX_CONFIG_WHITEBALCONTROLTYPE */
+ OMX_IndexConfigCommonExposure, /**< reference: OMX_CONFIG_EXPOSURECONTROLTYPE */
+ OMX_IndexConfigCommonContrast, /**< reference: OMX_CONFIG_CONTRASTTYPE */
+ OMX_IndexConfigCommonBrightness, /**< reference: OMX_CONFIG_BRIGHTNESSTYPE */
+ OMX_IndexConfigCommonBacklight, /**< reference: OMX_CONFIG_BACKLIGHTTYPE */
+ OMX_IndexConfigCommonGamma, /**< reference: OMX_CONFIG_GAMMATYPE */
+ OMX_IndexConfigCommonSaturation, /**< reference: OMX_CONFIG_SATURATIONTYPE */
+ OMX_IndexConfigCommonLightness, /**< reference: OMX_CONFIG_LIGHTNESSTYPE */
+ OMX_IndexConfigCommonExclusionRect, /**< reference: OMX_CONFIG_RECTTYPE */
+ OMX_IndexConfigCommonDithering, /**< reference: OMX_CONFIG_DITHERTYPE */
+ OMX_IndexConfigCommonPlaneBlend, /**< reference: OMX_CONFIG_PLANEBLENDTYPE */
+ OMX_IndexConfigCommonExposureValue, /**< reference: OMX_CONFIG_EXPOSUREVALUETYPE */
+ OMX_IndexConfigCommonOutputSize, /**< reference: OMX_FRAMESIZETYPE */
+ OMX_IndexParamCommonExtraQuantData, /**< reference: OMX_OTHER_EXTRADATATYPE */
+ OMX_IndexConfigCommonFocusRegion, /**< reference: OMX_CONFIG_FOCUSREGIONTYPE */
+ OMX_IndexConfigCommonFocusStatus, /**< reference: OMX_PARAM_FOCUSSTATUSTYPE */
+ OMX_IndexConfigCommonTransitionEffect, /**< reference: OMX_CONFIG_TRANSITIONEFFECTTYPE */
+
+ /* Reserved Configuration range */
+ OMX_IndexOtherStartUnused = 0x08000000,
+ OMX_IndexParamOtherPortFormat, /**< reference: OMX_OTHER_PARAM_PORTFORMATTYPE */
+ OMX_IndexConfigOtherPower, /**< reference: OMX_OTHER_CONFIG_POWERTYPE */
+ OMX_IndexConfigOtherStats, /**< reference: OMX_OTHER_CONFIG_STATSTYPE */
+
+
+ /* Reserved Time range */
+ OMX_IndexTimeStartUnused = 0x09000000,
+ OMX_IndexConfigTimeScale, /**< reference: OMX_TIME_CONFIG_SCALETYPE */
+ OMX_IndexConfigTimeClockState, /**< reference: OMX_TIME_CONFIG_CLOCKSTATETYPE */
+ OMX_IndexConfigTimeActiveRefClock, /**< reference: OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE */
+ OMX_IndexConfigTimeCurrentMediaTime, /**< reference: OMX_TIME_CONFIG_TIMESTAMPTYPE (read only) */
+ OMX_IndexConfigTimeCurrentWallTime, /**< reference: OMX_TIME_CONFIG_TIMESTAMPTYPE (read only) */
+ OMX_IndexConfigTimeCurrentAudioReference, /**< reference: OMX_TIME_CONFIG_TIMESTAMPTYPE (write only) */
+ OMX_IndexConfigTimeCurrentVideoReference, /**< reference: OMX_TIME_CONFIG_TIMESTAMPTYPE (write only) */
+ OMX_IndexConfigTimeMediaTimeRequest, /**< reference: OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE (write only) */
+ OMX_IndexConfigTimeClientStartTime, /**<reference: OMX_TIME_CONFIG_TIMESTAMPTYPE (write only) */
+ OMX_IndexConfigTimePosition, /**< reference: OMX_TIME_CONFIG_TIMESTAMPTYPE */
+ OMX_IndexConfigTimeSeekMode, /**< reference: OMX_TIME_CONFIG_SEEKMODETYPE */
+
+
+ OMX_IndexKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ /* Vendor specific area */
+ OMX_IndexVendorStartUnused = 0x7F000000,
+ /* Vendor specific structures should be in the range of 0x7F000000
+ to 0x7FFFFFFE. This range is not broken out by vendor, so
+ private indexes are not guaranteed unique and therefore should
+ only be sent to the appropriate component. */
+
+ OMX_IndexMax = 0x7FFFFFFF
+
+} OMX_INDEXTYPE;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
+/* File EOF */
diff --git a/subprojects/gst-omx/omx/openmax/OMX_IndexExt.h b/subprojects/gst-omx/omx/openmax/OMX_IndexExt.h
new file mode 100644
index 0000000000..8d05faa480
--- /dev/null
+++ b/subprojects/gst-omx/omx/openmax/OMX_IndexExt.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2010 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/** @file OMX_IndexExt.h - OpenMax IL version 1.1.2
+ * The OMX_IndexExt header file contains extensions to the definitions
+ * for both applications and components .
+ */
+
+#ifndef OMX_IndexExt_h
+#define OMX_IndexExt_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Each OMX header shall include all required header files to allow the
+ * header to compile without errors. The includes below are required
+ * for this header file to compile successfully
+ */
+#include <OMX_Index.h>
+
+
+/** Khronos standard extension indices.
+
+This enum lists the current Khronos extension indices to OpenMAX IL.
+*/
+typedef enum OMX_INDEXEXTTYPE {
+
+ /* Component parameters and configurations */
+ OMX_IndexExtComponentStartUnused = OMX_IndexKhronosExtensions + 0x00100000,
+ OMX_IndexConfigCallbackRequest, /**< reference: OMX_CONFIG_CALLBACKREQUESTTYPE */
+ OMX_IndexConfigCommitMode, /**< reference: OMX_CONFIG_COMMITMODETYPE */
+ OMX_IndexConfigCommit, /**< reference: OMX_CONFIG_COMMITTYPE */
+
+ /* Port parameters and configurations */
+ OMX_IndexExtPortStartUnused = OMX_IndexKhronosExtensions + 0x00200000,
+
+ /* Audio parameters and configurations */
+ OMX_IndexExtAudioStartUnused = OMX_IndexKhronosExtensions + 0x00400000,
+
+ /* Image parameters and configurations */
+ OMX_IndexExtImageStartUnused = OMX_IndexKhronosExtensions + 0x00500000,
+
+ /* Video parameters and configurations */
+ OMX_IndexExtVideoStartUnused = OMX_IndexKhronosExtensions + 0x00600000,
+ OMX_IndexParamNalStreamFormatSupported, /**< reference: OMX_NALSTREAMFORMATTYPE */
+ OMX_IndexParamNalStreamFormat, /**< reference: OMX_NALSTREAMFORMATTYPE */
+ OMX_IndexParamNalStreamFormatSelect, /**< reference: OMX_NALSTREAMFORMATTYPE */
+
+ /* Image & Video common configurations */
+ OMX_IndexExtCommonStartUnused = OMX_IndexKhronosExtensions + 0x00700000,
+
+ /* Other configurations */
+ OMX_IndexExtOtherStartUnused = OMX_IndexKhronosExtensions + 0x00800000,
+
+ /* Time configurations */
+ OMX_IndexExtTimeStartUnused = OMX_IndexKhronosExtensions + 0x00900000,
+
+ OMX_IndexExtMax = 0x7FFFFFFF
+} OMX_INDEXEXTTYPE;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* OMX_IndexExt_h */
+/* File EOF */
diff --git a/subprojects/gst-omx/omx/openmax/OMX_Other.h b/subprojects/gst-omx/omx/openmax/OMX_Other.h
new file mode 100644
index 0000000000..caf7f38448
--- /dev/null
+++ b/subprojects/gst-omx/omx/openmax/OMX_Other.h
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 2008 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/** @file OMX_Other.h - OpenMax IL version 1.1.2
+ * The structures needed by Other components to exchange
+ * parameters and configuration data with the components.
+ */
+
+#ifndef OMX_Other_h
+#define OMX_Other_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* Each OMX header must include all required header files to allow the
+ * header to compile without errors. The includes below are required
+ * for this header file to compile successfully
+ */
+
+#include <OMX_Core.h>
+
+
+/**
+ * Enumeration of possible data types which match to multiple domains or no
+ * domain at all. For types which are vendor specific, a value above
+ * OMX_OTHER_VENDORTSTART should be used.
+ */
+typedef enum OMX_OTHER_FORMATTYPE {
+ OMX_OTHER_FormatTime = 0, /**< Transmission of various timestamps, elapsed time,
+ time deltas, etc */
+ OMX_OTHER_FormatPower, /**< Perhaps used for enabling/disabling power
+ management, setting clocks? */
+ OMX_OTHER_FormatStats, /**< Could be things such as frame rate, frames
+ dropped, etc */
+ OMX_OTHER_FormatBinary, /**< Arbitrary binary data */
+ OMX_OTHER_FormatVendorReserved = 1000, /**< Starting value for vendor specific
+ formats */
+
+ OMX_OTHER_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_OTHER_FormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_OTHER_FormatMax = 0x7FFFFFFF
+} OMX_OTHER_FORMATTYPE;
+
+/**
+ * Enumeration of seek modes.
+ */
+typedef enum OMX_TIME_SEEKMODETYPE {
+ OMX_TIME_SeekModeFast = 0, /**< Prefer seeking to an approximation
+ * of the requested seek position over
+ * the actual seek position if it
+ * results in a faster seek. */
+ OMX_TIME_SeekModeAccurate, /**< Prefer seeking to the actual seek
+ * position over an approximation
+ * of the requested seek position even
+ * if it results in a slower seek. */
+ OMX_TIME_SeekModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_TIME_SeekModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_TIME_SeekModeMax = 0x7FFFFFFF
+} OMX_TIME_SEEKMODETYPE;
+
+/* Structure representing the seekmode of the component */
+typedef struct OMX_TIME_CONFIG_SEEKMODETYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_TIME_SEEKMODETYPE eType; /**< The seek mode */
+} OMX_TIME_CONFIG_SEEKMODETYPE;
+
+/** Structure representing a time stamp used with the following configs
+ * on the Clock Component (CC):
+ *
+ * OMX_IndexConfigTimeCurrentWallTime: query of the CC’s current wall
+ * time
+ * OMX_IndexConfigTimeCurrentMediaTime: query of the CC’s current media
+ * time
+ * OMX_IndexConfigTimeCurrentAudioReference and
+ * OMX_IndexConfigTimeCurrentVideoReference: audio/video reference
+ * clock sending SC its reference time
+ * OMX_IndexConfigTimeClientStartTime: a Clock Component client sends
+ * this structure to the Clock Component via a SetConfig on its
+ * client port when it receives a buffer with
+ * OMX_BUFFERFLAG_STARTTIME set. It must use the timestamp
+ * specified by that buffer for nStartTimestamp.
+ *
+ * It’s also used with the following config on components in general:
+ *
+ * OMX_IndexConfigTimePosition: IL client querying component position
+ * (GetConfig) or commanding a component to seek to the given location
+ * (SetConfig)
+ */
+typedef struct OMX_TIME_CONFIG_TIMESTAMPTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version
+ * information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_TICKS nTimestamp; /**< timestamp .*/
+} OMX_TIME_CONFIG_TIMESTAMPTYPE;
+
+/** Enumeration of possible reference clocks to the media time. */
+typedef enum OMX_TIME_UPDATETYPE {
+ OMX_TIME_UpdateRequestFulfillment, /**< Update is the fulfillment of a media time request. */
+ OMX_TIME_UpdateScaleChanged, /**< Update was generated because the scale chagned. */
+ OMX_TIME_UpdateClockStateChanged, /**< Update was generated because the clock state changed. */
+ OMX_TIME_UpdateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_TIME_UpdateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_TIME_UpdateMax = 0x7FFFFFFF
+} OMX_TIME_UPDATETYPE;
+
+/** Enumeration of possible reference clocks to the media time. */
+typedef enum OMX_TIME_REFCLOCKTYPE {
+ OMX_TIME_RefClockNone, /**< Use no references. */
+ OMX_TIME_RefClockAudio, /**< Use references sent through OMX_IndexConfigTimeCurrentAudioReference */
+ OMX_TIME_RefClockVideo, /**< Use references sent through OMX_IndexConfigTimeCurrentVideoReference */
+ OMX_TIME_RefClockKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_TIME_RefClockVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_TIME_RefClockMax = 0x7FFFFFFF
+} OMX_TIME_REFCLOCKTYPE;
+
+/** Enumeration of clock states. */
+typedef enum OMX_TIME_CLOCKSTATE {
+ OMX_TIME_ClockStateRunning, /**< Clock running. */
+ OMX_TIME_ClockStateWaitingForStartTime, /**< Clock waiting until the
+ * prescribed clients emit their
+ * start time. */
+ OMX_TIME_ClockStateStopped, /**< Clock stopped. */
+ OMX_TIME_ClockStateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_TIME_ClockStateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_TIME_ClockStateMax = 0x7FFFFFFF
+} OMX_TIME_CLOCKSTATE;
+
+/** Structure representing a media time request to the clock component.
+ *
+ * A client component sends this structure to the Clock Component via a SetConfig
+ * on its client port to specify a media timestamp the Clock Component
+ * should emit. The Clock Component should fulfill the request by sending a
+ * OMX_TIME_MEDIATIMETYPE when its media clock matches the requested
+ * timestamp.
+ *
+ * The client may require a media time request be fulfilled slightly
+ * earlier than the media time specified. In this case the client specifies
+ * an offset which is equal to the difference between wall time corresponding
+ * to the requested media time and the wall time when it will be
+ * fulfilled.
+ *
+ * A client component may uses these requests and the OMX_TIME_MEDIATIMETYPE to
+ * time events according to timestamps. If a client must perform an operation O at
+ * a time T (e.g. deliver a video frame at its corresponding timestamp), it makes a
+ * media time request at T (perhaps specifying an offset to ensure the request fulfillment
+ * is a little early). When the clock component passes the resulting OMX_TIME_MEDIATIMETYPE
+ * structure back to the client component, the client may perform operation O (perhaps having
+ * to wait a slight amount more time itself as specified by the return values).
+ */
+
+typedef struct OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< port that this structure applies to */
+ OMX_PTR pClientPrivate; /**< Client private data to disabiguate this media time
+ * from others (e.g. the number of the frame to deliver).
+ * Duplicated in the media time structure that fulfills
+ * this request. A value of zero is reserved for time scale
+ * updates. */
+ OMX_TICKS nMediaTimestamp; /**< Media timestamp requested.*/
+ OMX_TICKS nOffset; /**< Amount of wall clock time by which this
+ * request should be fulfilled early */
+} OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE;
+
+/**< Structure sent from the clock component client either when fulfilling
+ * a media time request or when the time scale has changed.
+ *
+ * In the former case the Clock Component fills this structure and times its emission
+ * to a client component (via the client port) according to the corresponding media
+ * time request sent by the client. The Clock Component should time the emission to occur
+ * when the requested timestamp matches the Clock Component's media time but also the
+ * prescribed offset early.
+ *
+ * Upon scale changes the clock component clears the nClientPrivate data, sends the current
+ * media time and sets the nScale to the new scale via the client port. It emits a
+ * OMX_TIME_MEDIATIMETYPE to all clients independent of any requests. This allows clients to
+ * alter processing to accomodate scaling. For instance a video component might skip inter-frames
+ * in the case of extreme fastforward. Likewise an audio component might add or remove samples
+ * from an audio frame to scale audio data.
+ *
+ * It is expected that some clock components may not be able to fulfill requests
+ * at exactly the prescribed time. This is acceptable so long as the request is
+ * fulfilled at least as early as described and not later. This structure provides
+ * fields the client may use to wait for the remaining time.
+ *
+ * The client may use either the nOffset or nWallTimeAtMedia fields to determine the
+ * wall time until the nMediaTimestamp actually occurs. In the latter case the
+ * client can get a more accurate value for offset by getting the current wall
+ * from the cloc component and subtracting it from nWallTimeAtMedia.
+ */
+
+typedef struct OMX_TIME_MEDIATIMETYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nClientPrivate; /**< Client private data to disabiguate this media time
+ * from others. Copied from the media time request.
+ * A value of zero is reserved for time scale updates. */
+ OMX_TIME_UPDATETYPE eUpdateType; /**< Reason for the update */
+ OMX_TICKS nMediaTimestamp; /**< Media time requested. If no media time was
+ * requested then this is the current media time. */
+ OMX_TICKS nOffset; /**< Amount of wall clock time by which this
+ * request was actually fulfilled early */
+
+ OMX_TICKS nWallTimeAtMediaTime; /**< Wall time corresponding to nMediaTimeStamp.
+ * A client may compare this value to current
+ * media time obtained from the Clock Component to determine
+ * the wall time until the media timestamp is really
+ * current. */
+ OMX_S32 xScale; /**< Current media time scale in Q16 format. */
+ OMX_TIME_CLOCKSTATE eState; /* Seeking Change. Added 7/12.*/
+ /**< State of the media time. */
+} OMX_TIME_MEDIATIMETYPE;
+
+/** Structure representing the current media time scale factor. Applicable only to clock
+ * component, other components see scale changes via OMX_TIME_MEDIATIMETYPE buffers sent via
+ * the clock component client ports. Upon recieving this config the clock component changes
+ * the rate by which the media time increases or decreases effectively implementing trick modes.
+ */
+typedef struct OMX_TIME_CONFIG_SCALETYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_S32 xScale; /**< This is a value in Q16 format which is used for
+ * scaling the media time */
+} OMX_TIME_CONFIG_SCALETYPE;
+
+/** Bits used to identify a clock port. Used in OMX_TIME_CONFIG_CLOCKSTATETYPE’s nWaitMask field */
+#define OMX_CLOCKPORT0 0x00000001
+#define OMX_CLOCKPORT1 0x00000002
+#define OMX_CLOCKPORT2 0x00000004
+#define OMX_CLOCKPORT3 0x00000008
+#define OMX_CLOCKPORT4 0x00000010
+#define OMX_CLOCKPORT5 0x00000020
+#define OMX_CLOCKPORT6 0x00000040
+#define OMX_CLOCKPORT7 0x00000080
+
+/** Structure representing the current mode of the media clock.
+ * IL Client uses this config to change or query the mode of the
+ * media clock of the clock component. Applicable only to clock
+ * component.
+ *
+ * On a SetConfig if eState is OMX_TIME_ClockStateRunning media time
+ * starts immediately at the prescribed start time. If
+ * OMX_TIME_ClockStateWaitingForStartTime the Clock Component ignores
+ * the given nStartTime and waits for all clients specified in the
+ * nWaitMask to send starttimes (via
+ * OMX_IndexConfigTimeClientStartTime). The Clock Component then starts
+ * the media clock using the earliest start time supplied. */
+typedef struct OMX_TIME_CONFIG_CLOCKSTATETYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version
+ * information */
+ OMX_TIME_CLOCKSTATE eState; /**< State of the media time. */
+ OMX_TICKS nStartTime; /**< Start time of the media time. */
+ OMX_TICKS nOffset; /**< Time to offset the media time by
+ * (e.g. preroll). Media time will be
+ * reported to be nOffset ticks earlier.
+ */
+ OMX_U32 nWaitMask; /**< Mask of OMX_CLOCKPORT values. */
+} OMX_TIME_CONFIG_CLOCKSTATETYPE;
+
+/** Structure representing the reference clock currently being used to
+ * compute media time. IL client uses this config to change or query the
+ * clock component's active reference clock */
+typedef struct OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_TIME_REFCLOCKTYPE eClock; /**< Reference clock used to compute media time */
+} OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE;
+
+/** Descriptor for setting specifics of power type.
+ * Note: this structure is listed for backwards compatibility. */
+typedef struct OMX_OTHER_CONFIG_POWERTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_BOOL bEnablePM; /**< Flag to enable Power Management */
+} OMX_OTHER_CONFIG_POWERTYPE;
+
+
+/** Descriptor for setting specifics of stats type.
+ * Note: this structure is listed for backwards compatibility. */
+typedef struct OMX_OTHER_CONFIG_STATSTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ /* what goes here */
+} OMX_OTHER_CONFIG_STATSTYPE;
+
+
+/**
+ * The PortDefinition structure is used to define all of the parameters
+ * necessary for the compliant component to setup an input or an output other
+ * path.
+ */
+typedef struct OMX_OTHER_PORTDEFINITIONTYPE {
+ OMX_OTHER_FORMATTYPE eFormat; /**< Type of data expected for this channel */
+} OMX_OTHER_PORTDEFINITIONTYPE;
+
+/** Port format parameter. This structure is used to enumerate
+ * the various data input/output format supported by the port.
+ */
+typedef struct OMX_OTHER_PARAM_PORTFORMATTYPE {
+ OMX_U32 nSize; /**< size of the structure in bytes */
+ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
+ OMX_U32 nPortIndex; /**< Indicates which port to set */
+ OMX_U32 nIndex; /**< Indicates the enumeration index for the format from 0x0 to N-1 */
+ OMX_OTHER_FORMATTYPE eFormat; /**< Type of data expected for this channel */
+} OMX_OTHER_PARAM_PORTFORMATTYPE;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
+/* File EOF */
diff --git a/subprojects/gst-omx/omx/openmax/OMX_Types.h b/subprojects/gst-omx/omx/openmax/OMX_Types.h
new file mode 100644
index 0000000000..8698358786
--- /dev/null
+++ b/subprojects/gst-omx/omx/openmax/OMX_Types.h
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) 2008 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/** OMX_Types.h - OpenMax IL version 1.1.2
+ * The OMX_Types header file contains the primitive type definitions used by
+ * the core, the application and the component. This file may need to be
+ * modified to be used on systems that do not have "char" set to 8 bits,
+ * "short" set to 16 bits and "long" set to 32 bits.
+ */
+
+#ifndef OMX_Types_h
+#define OMX_Types_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/** The OMX_API and OMX_APIENTRY are platform specific definitions used
+ * to declare OMX function prototypes. They are modified to meet the
+ * requirements for a particular platform */
+#ifdef __SYMBIAN32__
+# ifdef __OMX_EXPORTS
+# define OMX_API __declspec(dllexport)
+# else
+# ifdef _WIN32
+# define OMX_API __declspec(dllexport)
+# else
+# define OMX_API __declspec(dllimport)
+# endif
+# endif
+#else
+# ifdef _WIN32
+# ifdef __OMX_EXPORTS
+# define OMX_API __declspec(dllexport)
+# else
+# define OMX_API __declspec(dllimport)
+# endif
+# else
+# ifdef __OMX_EXPORTS
+# define OMX_API
+# else
+# define OMX_API extern
+# endif
+# endif
+#endif
+
+#ifndef OMX_APIENTRY
+#define OMX_APIENTRY
+#endif
+
+/** OMX_IN is used to identify inputs to an OMX function. This designation
+ will also be used in the case of a pointer that points to a parameter
+ that is used as an output. */
+#ifndef OMX_IN
+#define OMX_IN
+#endif
+
+/** OMX_OUT is used to identify outputs from an OMX function. This
+ designation will also be used in the case of a pointer that points
+ to a parameter that is used as an input. */
+#ifndef OMX_OUT
+#define OMX_OUT
+#endif
+
+
+/** OMX_INOUT is used to identify parameters that may be either inputs or
+ outputs from an OMX function at the same time. This designation will
+ also be used in the case of a pointer that points to a parameter that
+ is used both as an input and an output. */
+#ifndef OMX_INOUT
+#define OMX_INOUT
+#endif
+
+/** OMX_ALL is used to as a wildcard to select all entities of the same type
+ * when specifying the index, or referring to a object by an index. (i.e.
+ * use OMX_ALL to indicate all N channels). When used as a port index
+ * for a config or parameter this OMX_ALL denotes that the config or
+ * parameter applies to the entire component not just one port. */
+#define OMX_ALL 0xFFFFFFFF
+
+/** In the following we define groups that help building doxygen documentation */
+
+/** @defgroup core OpenMAX IL core
+ * Functions and structure related to the OMX IL core
+ */
+
+ /** @defgroup comp OpenMAX IL component
+ * Functions and structure related to the OMX IL component
+ */
+
+/** @defgroup rpm Resource and Policy Management
+ * Structures for resource and policy management of components
+ */
+
+/** @defgroup buf Buffer Management
+ * Buffer handling functions and structures
+ */
+
+/** @defgroup tun Tunneling
+ * @ingroup core comp
+ * Structures and functions to manage tunnels among component ports
+ */
+
+/** @defgroup cp Content Pipes
+ * @ingroup core
+ */
+
+ /** @defgroup metadata Metadata handling
+ *
+ */
+
+/** OMX_U8 is an 8 bit unsigned quantity that is byte aligned */
+typedef unsigned char OMX_U8;
+
+/** OMX_S8 is an 8 bit signed quantity that is byte aligned */
+typedef signed char OMX_S8;
+
+/** OMX_U16 is a 16 bit unsigned quantity that is 16 bit word aligned */
+typedef unsigned short OMX_U16;
+
+/** OMX_S16 is a 16 bit signed quantity that is 16 bit word aligned */
+typedef signed short OMX_S16;
+
+/** OMX_U32 is a 32 bit unsigned quantity that is 32 bit word aligned */
+typedef unsigned long OMX_U32;
+
+/** OMX_S32 is a 32 bit signed quantity that is 32 bit word aligned */
+typedef signed long OMX_S32;
+
+
+/* Users with compilers that cannot accept the "long long" designation should
+ define the OMX_SKIP64BIT macro. It should be noted that this may cause
+ some components to fail to compile if the component was written to require
+ 64 bit integral types. However, these components would NOT compile anyway
+ since the compiler does not support the way the component was written.
+*/
+#ifndef OMX_SKIP64BIT
+#ifdef __SYMBIAN32__
+/** OMX_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */
+typedef unsigned long long OMX_U64;
+
+/** OMX_S64 is a 64 bit signed quantity that is 64 bit word aligned */
+typedef signed long long OMX_S64;
+
+#elif defined(WIN32)
+
+/** OMX_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */
+typedef unsigned __int64 OMX_U64;
+
+/** OMX_S64 is a 64 bit signed quantity that is 64 bit word aligned */
+typedef signed __int64 OMX_S64;
+
+#else /* WIN32 */
+
+/** OMX_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */
+typedef unsigned long long OMX_U64;
+
+/** OMX_S64 is a 64 bit signed quantity that is 64 bit word aligned */
+typedef signed long long OMX_S64;
+
+#endif /* WIN32 */
+#endif
+
+
+/** The OMX_BOOL type is intended to be used to represent a true or a false
+ value when passing parameters to and from the OMX core and components. The
+ OMX_BOOL is a 32 bit quantity and is aligned on a 32 bit word boundary.
+ */
+typedef enum OMX_BOOL {
+ OMX_FALSE = 0,
+ OMX_TRUE = !OMX_FALSE,
+ OMX_BOOL_MAX = 0x7FFFFFFF
+} OMX_BOOL;
+
+/** The OMX_PTR type is intended to be used to pass pointers between the OMX
+ applications and the OMX Core and components. This is a 32 bit pointer and
+ is aligned on a 32 bit boundary.
+ */
+typedef void* OMX_PTR;
+
+/** The OMX_STRING type is intended to be used to pass "C" type strings between
+ the application and the core and component. The OMX_STRING type is a 32
+ bit pointer to a zero terminated string. The pointer is word aligned and
+ the string is byte aligned.
+ */
+typedef char* OMX_STRING;
+
+/** The OMX_BYTE type is intended to be used to pass arrays of bytes such as
+ buffers between the application and the component and core. The OMX_BYTE
+ type is a 32 bit pointer to a zero terminated string. The pointer is word
+ aligned and the string is byte aligned.
+ */
+typedef unsigned char* OMX_BYTE;
+
+/** OMX_UUIDTYPE is a very long unique identifier to uniquely identify
+ at runtime. This identifier should be generated by a component in a way
+ that guarantees that every instance of the identifier running on the system
+ is unique. */
+typedef unsigned char OMX_UUIDTYPE[128];
+
+/** The OMX_DIRTYPE enumeration is used to indicate if a port is an input or
+ an output port. This enumeration is common across all component types.
+ */
+typedef enum OMX_DIRTYPE
+{
+ OMX_DirInput, /**< Port is an input port */
+ OMX_DirOutput, /**< Port is an output port */
+ OMX_DirMax = 0x7FFFFFFF
+} OMX_DIRTYPE;
+
+/** The OMX_ENDIANTYPE enumeration is used to indicate the bit ordering
+ for numerical data (i.e. big endian, or little endian).
+ */
+typedef enum OMX_ENDIANTYPE
+{
+ OMX_EndianBig, /**< big endian */
+ OMX_EndianLittle, /**< little endian */
+ OMX_EndianMax = 0x7FFFFFFF
+} OMX_ENDIANTYPE;
+
+
+/** The OMX_NUMERICALDATATYPE enumeration is used to indicate if data
+ is signed or unsigned
+ */
+typedef enum OMX_NUMERICALDATATYPE
+{
+ OMX_NumericalDataSigned, /**< signed data */
+ OMX_NumericalDataUnsigned, /**< unsigned data */
+ OMX_NumercialDataMax = 0x7FFFFFFF
+} OMX_NUMERICALDATATYPE;
+
+
+/** Unsigned bounded value type */
+typedef struct OMX_BU32 {
+ OMX_U32 nValue; /**< actual value */
+ OMX_U32 nMin; /**< minimum for value (i.e. nValue >= nMin) */
+ OMX_U32 nMax; /**< maximum for value (i.e. nValue <= nMax) */
+} OMX_BU32;
+
+
+/** Signed bounded value type */
+typedef struct OMX_BS32 {
+ OMX_S32 nValue; /**< actual value */
+ OMX_S32 nMin; /**< minimum for value (i.e. nValue >= nMin) */
+ OMX_S32 nMax; /**< maximum for value (i.e. nValue <= nMax) */
+} OMX_BS32;
+
+
+/** Structure representing some time or duration in microseconds. This structure
+ * must be interpreted as a signed 64 bit value. The quantity is signed to accommodate
+ * negative deltas and preroll scenarios. The quantity is represented in microseconds
+ * to accomodate high resolution timestamps (e.g. DVD presentation timestamps based
+ * on a 90kHz clock) and to allow more accurate and synchronized delivery (e.g.
+ * individual audio samples delivered at 192 kHz). The quantity is 64 bit to
+ * accommodate a large dynamic range (signed 32 bit values would allow only for plus
+ * or minus 35 minutes).
+ *
+ * Implementations with limited precision may convert the signed 64 bit value to
+ * a signed 32 bit value internally but risk loss of precision.
+ */
+#ifndef OMX_SKIP64BIT
+typedef OMX_S64 OMX_TICKS;
+#else
+typedef struct OMX_TICKS
+{
+ OMX_U32 nLowPart; /** low bits of the signed 64 bit tick value */
+ OMX_U32 nHighPart; /** high bits of the signed 64 bit tick value */
+} OMX_TICKS;
+#endif
+#define OMX_TICKS_PER_SECOND 1000000
+
+/** Define the public interface for the OMX Handle. The core will not use
+ this value internally, but the application should only use this value.
+ */
+typedef void* OMX_HANDLETYPE;
+
+typedef struct OMX_MARKTYPE
+{
+ OMX_HANDLETYPE hMarkTargetComponent; /**< The component that will
+ generate a mark event upon
+ processing the mark. */
+ OMX_PTR pMarkData; /**< Application specific data associated with
+ the mark sent on a mark event to disambiguate
+ this mark from others. */
+} OMX_MARKTYPE;
+
+
+/** OMX_NATIVE_DEVICETYPE is used to map a OMX video port to the
+ * platform & operating specific object used to reference the display
+ * or can be used by a audio port for native audio rendering */
+typedef void* OMX_NATIVE_DEVICETYPE;
+
+/** OMX_NATIVE_WINDOWTYPE is used to map a OMX video port to the
+ * platform & operating specific object used to reference the window */
+typedef void* OMX_NATIVE_WINDOWTYPE;
+
+
+/** Define the OMX IL version that corresponds to this set of header files.
+ * We also define a combined version that can be used to write or compare
+ * values of the 32bit nVersion field, assuming a little endian architecture */
+#define OMX_VERSION_MAJOR 1
+#define OMX_VERSION_MINOR 1
+#define OMX_VERSION_REVISION 2
+#define OMX_VERSION_STEP 0
+
+#define OMX_VERSION ((OMX_VERSION_STEP<<24) | (OMX_VERSION_REVISION<<16) | (OMX_VERSION_MINOR<<8) | OMX_VERSION_MAJOR)
+
+
+/** The OMX_VERSIONTYPE union is used to specify the version for
+ a structure or component. For a component, the version is entirely
+ specified by the component vendor. Components doing the same function
+ from different vendors may or may not have the same version. For
+ structures, the version shall be set by the entity that allocates the
+ structure. For structures specified in the OMX 1.1 specification, the
+ value of the version shall be set to 1.1.0.0 in all cases. Access to the
+ OMX_VERSIONTYPE can be by a single 32 bit access (e.g. by nVersion) or
+ by accessing one of the structure elements to, for example, check only
+ the Major revision.
+ */
+typedef union OMX_VERSIONTYPE
+{
+ struct
+ {
+ OMX_U8 nVersionMajor; /**< Major version accessor element */
+ OMX_U8 nVersionMinor; /**< Minor version accessor element */
+ OMX_U8 nRevision; /**< Revision version accessor element */
+ OMX_U8 nStep; /**< Step version accessor element */
+ } s;
+ OMX_U32 nVersion; /**< 32 bit value to make accessing the
+ version easily done in a single word
+ size copy/compare operation */
+} OMX_VERSIONTYPE;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
+/* File EOF */
diff --git a/subprojects/gst-omx/omx/openmax/OMX_Video.h b/subprojects/gst-omx/omx/openmax/OMX_Video.h
new file mode 100644
index 0000000000..163e45081f
--- /dev/null
+++ b/subprojects/gst-omx/omx/openmax/OMX_Video.h
@@ -0,0 +1,1060 @@
+/**
+ * Copyright (c) 2008 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/**
+ * @file OMX_Video.h - OpenMax IL version 1.1.2
+ * The structures is needed by Video components to exchange parameters
+ * and configuration data with OMX components.
+ */
+#ifndef OMX_Video_h
+#define OMX_Video_h
+
+/** @defgroup video OpenMAX IL Video Domain
+ * @ingroup iv
+ * Structures for OpenMAX IL Video domain
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/**
+ * Each OMX header must include all required header files to allow the
+ * header to compile without errors. The includes below are required
+ * for this header file to compile successfully
+ */
+
+#include <OMX_IVCommon.h>
+
+
+/**
+ * Enumeration used to define the possible video compression codings.
+ * NOTE: This essentially refers to file extensions. If the coding is
+ * being used to specify the ENCODE type, then additional work
+ * must be done to configure the exact flavor of the compression
+ * to be used. For decode cases where the user application can
+ * not differentiate between MPEG-4 and H.264 bit streams, it is
+ * up to the codec to handle this.
+ */
+typedef enum OMX_VIDEO_CODINGTYPE {
+ OMX_VIDEO_CodingUnused, /**< Value when coding is N/A */
+ OMX_VIDEO_CodingAutoDetect, /**< Autodetection of coding type */
+ OMX_VIDEO_CodingMPEG2, /**< AKA: H.262 */
+ OMX_VIDEO_CodingH263, /**< H.263 */
+ OMX_VIDEO_CodingMPEG4, /**< MPEG-4 */
+ OMX_VIDEO_CodingWMV, /**< all versions of Windows Media Video */
+ OMX_VIDEO_CodingRV, /**< all versions of Real Video */
+ OMX_VIDEO_CodingAVC, /**< H.264/AVC */
+ OMX_VIDEO_CodingMJPEG, /**< Motion JPEG */
+ OMX_VIDEO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_VIDEO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_VIDEO_CodingMax = 0x7FFFFFFF
+} OMX_VIDEO_CODINGTYPE;
+
+
+/**
+ * Data structure used to define a video path. The number of Video paths for
+ * input and output will vary by type of the Video component.
+ *
+ * Input (aka Source) : zero Inputs, one Output,
+ * Splitter : one Input, 2 or more Outputs,
+ * Processing Element : one Input, one output,
+ * Mixer : 2 or more inputs, one output,
+ * Output (aka Sink) : one Input, zero outputs.
+ *
+ * The PortDefinition structure is used to define all of the parameters
+ * necessary for the compliant component to setup an input or an output video
+ * path. If additional vendor specific data is required, it should be
+ * transmitted to the component using the CustomCommand function. Compliant
+ * components will prepopulate this structure with optimal values during the
+ * GetDefaultInitParams command.
+ *
+ * STRUCT MEMBERS:
+ * cMIMEType : MIME type of data for the port
+ * pNativeRender : Platform specific reference for a display if a
+ * sync, otherwise this field is 0
+ * nFrameWidth : Width of frame to be used on channel if
+ * uncompressed format is used. Use 0 for unknown,
+ * don't care or variable
+ * nFrameHeight : Height of frame to be used on channel if
+ * uncompressed format is used. Use 0 for unknown,
+ * don't care or variable
+ * nStride : Number of bytes per span of an image
+ * (i.e. indicates the number of bytes to get
+ * from span N to span N+1, where negative stride
+ * indicates the image is bottom up
+ * nSliceHeight : Height used when encoding in slices
+ * nBitrate : Bit rate of frame to be used on channel if
+ * compressed format is used. Use 0 for unknown,
+ * don't care or variable
+ * xFramerate : Frame rate to be used on channel if uncompressed
+ * format is used. Use 0 for unknown, don't care or
+ * variable. Units are Q16 frames per second.
+ * bFlagErrorConcealment : Turns on error concealment if it is supported by
+ * the OMX component
+ * eCompressionFormat : Compression format used in this instance of the
+ * component. When OMX_VIDEO_CodingUnused is
+ * specified, eColorFormat is used
+ * eColorFormat : Decompressed format used by this component
+ * pNativeWindow : Platform specific reference for a window object if a
+ * display sink , otherwise this field is 0x0.
+ */
+typedef struct OMX_VIDEO_PORTDEFINITIONTYPE {
+ OMX_STRING cMIMEType;
+ OMX_NATIVE_DEVICETYPE pNativeRender;
+ OMX_U32 nFrameWidth;
+ OMX_U32 nFrameHeight;
+ OMX_S32 nStride;
+ OMX_U32 nSliceHeight;
+ OMX_U32 nBitrate;
+ OMX_U32 xFramerate;
+ OMX_BOOL bFlagErrorConcealment;
+ OMX_VIDEO_CODINGTYPE eCompressionFormat;
+ OMX_COLOR_FORMATTYPE eColorFormat;
+ OMX_NATIVE_WINDOWTYPE pNativeWindow;
+} OMX_VIDEO_PORTDEFINITIONTYPE;
+
+/**
+ * Port format parameter. This structure is used to enumerate the various
+ * data input/output format supported by the port.
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Indicates which port to set
+ * nIndex : Indicates the enumeration index for the format from
+ * 0x0 to N-1
+ * eCompressionFormat : Compression format used in this instance of the
+ * component. When OMX_VIDEO_CodingUnused is specified,
+ * eColorFormat is used
+ * eColorFormat : Decompressed format used by this component
+ * xFrameRate : Indicates the video frame rate in Q16 format
+ */
+typedef struct OMX_VIDEO_PARAM_PORTFORMATTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nIndex;
+ OMX_VIDEO_CODINGTYPE eCompressionFormat;
+ OMX_COLOR_FORMATTYPE eColorFormat;
+ OMX_U32 xFramerate;
+} OMX_VIDEO_PARAM_PORTFORMATTYPE;
+
+
+/**
+ * This is a structure for configuring video compression quantization
+ * parameter values. Codecs may support different QP values for different
+ * frame types.
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version info
+ * nPortIndex : Port that this structure applies to
+ * nQpI : QP value to use for index frames
+ * nQpP : QP value to use for P frames
+ * nQpB : QP values to use for bidirectional frames
+ */
+typedef struct OMX_VIDEO_PARAM_QUANTIZATIONTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nQpI;
+ OMX_U32 nQpP;
+ OMX_U32 nQpB;
+} OMX_VIDEO_PARAM_QUANTIZATIONTYPE;
+
+
+/**
+ * Structure for configuration of video fast update parameters.
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version info
+ * nPortIndex : Port that this structure applies to
+ * bEnableVFU : Enable/Disable video fast update
+ * nFirstGOB : Specifies the number of the first macroblock row
+ * nFirstMB : specifies the first MB relative to the specified first GOB
+ * nNumMBs : Specifies the number of MBs to be refreshed from nFirstGOB
+ * and nFirstMB
+ */
+typedef struct OMX_VIDEO_PARAM_VIDEOFASTUPDATETYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_BOOL bEnableVFU;
+ OMX_U32 nFirstGOB;
+ OMX_U32 nFirstMB;
+ OMX_U32 nNumMBs;
+} OMX_VIDEO_PARAM_VIDEOFASTUPDATETYPE;
+
+
+/**
+ * Enumeration of possible bitrate control types
+ */
+typedef enum OMX_VIDEO_CONTROLRATETYPE {
+ OMX_Video_ControlRateDisable,
+ OMX_Video_ControlRateVariable,
+ OMX_Video_ControlRateConstant,
+ OMX_Video_ControlRateVariableSkipFrames,
+ OMX_Video_ControlRateConstantSkipFrames,
+ OMX_Video_ControlRateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_Video_ControlRateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_Video_ControlRateMax = 0x7FFFFFFF
+} OMX_VIDEO_CONTROLRATETYPE;
+
+
+/**
+ * Structure for configuring bitrate mode of a codec.
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the struct in bytes
+ * nVersion : OMX spec version info
+ * nPortIndex : Port that this struct applies to
+ * eControlRate : Control rate type enum
+ * nTargetBitrate : Target bitrate to encode with
+ */
+typedef struct OMX_VIDEO_PARAM_BITRATETYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_VIDEO_CONTROLRATETYPE eControlRate;
+ OMX_U32 nTargetBitrate;
+} OMX_VIDEO_PARAM_BITRATETYPE;
+
+
+/**
+ * Enumeration of possible motion vector (MV) types
+ */
+typedef enum OMX_VIDEO_MOTIONVECTORTYPE {
+ OMX_Video_MotionVectorPixel,
+ OMX_Video_MotionVectorHalfPel,
+ OMX_Video_MotionVectorQuarterPel,
+ OMX_Video_MotionVectorEighthPel,
+ OMX_Video_MotionVectorKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_Video_MotionVectorVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_Video_MotionVectorMax = 0x7FFFFFFF
+} OMX_VIDEO_MOTIONVECTORTYPE;
+
+
+/**
+ * Structure for configuring the number of motion vectors used as well
+ * as their accuracy.
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the struct in bytes
+ * nVersion : OMX spec version info
+ * nPortIndex : port that this structure applies to
+ * eAccuracy : Enumerated MV accuracy
+ * bUnrestrictedMVs : Allow unrestricted MVs
+ * bFourMV : Allow use of 4 MVs
+ * sXSearchRange : Search range in horizontal direction for MVs
+ * sYSearchRange : Search range in vertical direction for MVs
+ */
+typedef struct OMX_VIDEO_PARAM_MOTIONVECTORTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_VIDEO_MOTIONVECTORTYPE eAccuracy;
+ OMX_BOOL bUnrestrictedMVs;
+ OMX_BOOL bFourMV;
+ OMX_S32 sXSearchRange;
+ OMX_S32 sYSearchRange;
+} OMX_VIDEO_PARAM_MOTIONVECTORTYPE;
+
+
+/**
+ * Enumeration of possible methods to use for Intra Refresh
+ */
+typedef enum OMX_VIDEO_INTRAREFRESHTYPE {
+ OMX_VIDEO_IntraRefreshCyclic,
+ OMX_VIDEO_IntraRefreshAdaptive,
+ OMX_VIDEO_IntraRefreshBoth,
+ OMX_VIDEO_IntraRefreshKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_VIDEO_IntraRefreshVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_VIDEO_IntraRefreshMax = 0x7FFFFFFF
+} OMX_VIDEO_INTRAREFRESHTYPE;
+
+
+/**
+ * Structure for configuring intra refresh mode
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * eRefreshMode : Cyclic, Adaptive, or Both
+ * nAirMBs : Number of intra macroblocks to refresh in a frame when
+ * AIR is enabled
+ * nAirRef : Number of times a motion marked macroblock has to be
+ * intra coded
+ * nCirMBs : Number of consecutive macroblocks to be coded as "intra"
+ * when CIR is enabled
+ */
+typedef struct OMX_VIDEO_PARAM_INTRAREFRESHTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_VIDEO_INTRAREFRESHTYPE eRefreshMode;
+ OMX_U32 nAirMBs;
+ OMX_U32 nAirRef;
+ OMX_U32 nCirMBs;
+} OMX_VIDEO_PARAM_INTRAREFRESHTYPE;
+
+
+/**
+ * Structure for enabling various error correction methods for video
+ * compression.
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * bEnableHEC : Enable/disable header extension codes (HEC)
+ * bEnableResync : Enable/disable resynchronization markers
+ * nResynchMarkerSpacing : Resynch markers interval (in bits) to be
+ * applied in the stream
+ * bEnableDataPartitioning : Enable/disable data partitioning
+ * bEnableRVLC : Enable/disable reversible variable length
+ * coding
+ */
+typedef struct OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_BOOL bEnableHEC;
+ OMX_BOOL bEnableResync;
+ OMX_U32 nResynchMarkerSpacing;
+ OMX_BOOL bEnableDataPartitioning;
+ OMX_BOOL bEnableRVLC;
+} OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE;
+
+
+/**
+ * Configuration of variable block-size motion compensation (VBSMC)
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * b16x16 : Enable inter block search 16x16
+ * b16x8 : Enable inter block search 16x8
+ * b8x16 : Enable inter block search 8x16
+ * b8x8 : Enable inter block search 8x8
+ * b8x4 : Enable inter block search 8x4
+ * b4x8 : Enable inter block search 4x8
+ * b4x4 : Enable inter block search 4x4
+ */
+typedef struct OMX_VIDEO_PARAM_VBSMCTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_BOOL b16x16;
+ OMX_BOOL b16x8;
+ OMX_BOOL b8x16;
+ OMX_BOOL b8x8;
+ OMX_BOOL b8x4;
+ OMX_BOOL b4x8;
+ OMX_BOOL b4x4;
+} OMX_VIDEO_PARAM_VBSMCTYPE;
+
+
+/**
+ * H.263 profile types, each profile indicates support for various
+ * performance bounds and different annexes.
+ *
+ * ENUMS:
+ * Baseline : Baseline Profile: H.263 (V1), no optional modes
+ * H320 Coding : H.320 Coding Efficiency Backward Compatibility
+ * Profile: H.263+ (V2), includes annexes I, J, L.4
+ * and T
+ * BackwardCompatible : Backward Compatibility Profile: H.263 (V1),
+ * includes annex F
+ * ISWV2 : Interactive Streaming Wireless Profile: H.263+
+ * (V2), includes annexes I, J, K and T
+ * ISWV3 : Interactive Streaming Wireless Profile: H.263++
+ * (V3), includes profile 3 and annexes V and W.6.3.8
+ * HighCompression : Conversational High Compression Profile: H.263++
+ * (V3), includes profiles 1 & 2 and annexes D and U
+ * Internet : Conversational Internet Profile: H.263++ (V3),
+ * includes profile 5 and annex K
+ * Interlace : Conversational Interlace Profile: H.263++ (V3),
+ * includes profile 5 and annex W.6.3.11
+ * HighLatency : High Latency Profile: H.263++ (V3), includes
+ * profile 6 and annexes O.1 and P.5
+ */
+typedef enum OMX_VIDEO_H263PROFILETYPE {
+ OMX_VIDEO_H263ProfileBaseline = 0x01,
+ OMX_VIDEO_H263ProfileH320Coding = 0x02,
+ OMX_VIDEO_H263ProfileBackwardCompatible = 0x04,
+ OMX_VIDEO_H263ProfileISWV2 = 0x08,
+ OMX_VIDEO_H263ProfileISWV3 = 0x10,
+ OMX_VIDEO_H263ProfileHighCompression = 0x20,
+ OMX_VIDEO_H263ProfileInternet = 0x40,
+ OMX_VIDEO_H263ProfileInterlace = 0x80,
+ OMX_VIDEO_H263ProfileHighLatency = 0x100,
+ OMX_VIDEO_H263ProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_VIDEO_H263ProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_VIDEO_H263ProfileMax = 0x7FFFFFFF
+} OMX_VIDEO_H263PROFILETYPE;
+
+
+/**
+ * H.263 level types, each level indicates support for various frame sizes,
+ * bit rates, decoder frame rates.
+ */
+typedef enum OMX_VIDEO_H263LEVELTYPE {
+ OMX_VIDEO_H263Level10 = 0x01,
+ OMX_VIDEO_H263Level20 = 0x02,
+ OMX_VIDEO_H263Level30 = 0x04,
+ OMX_VIDEO_H263Level40 = 0x08,
+ OMX_VIDEO_H263Level45 = 0x10,
+ OMX_VIDEO_H263Level50 = 0x20,
+ OMX_VIDEO_H263Level60 = 0x40,
+ OMX_VIDEO_H263Level70 = 0x80,
+ OMX_VIDEO_H263LevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_VIDEO_H263LevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_VIDEO_H263LevelMax = 0x7FFFFFFF
+} OMX_VIDEO_H263LEVELTYPE;
+
+
+/**
+ * Specifies the picture type. These values should be OR'd to signal all
+ * pictures types which are allowed.
+ *
+ * ENUMS:
+ * Generic Picture Types: I, P and B
+ * H.263 Specific Picture Types: SI and SP
+ * H.264 Specific Picture Types: EI and EP
+ * MPEG-4 Specific Picture Types: S
+ */
+typedef enum OMX_VIDEO_PICTURETYPE {
+ OMX_VIDEO_PictureTypeI = 0x01,
+ OMX_VIDEO_PictureTypeP = 0x02,
+ OMX_VIDEO_PictureTypeB = 0x04,
+ OMX_VIDEO_PictureTypeSI = 0x08,
+ OMX_VIDEO_PictureTypeSP = 0x10,
+ OMX_VIDEO_PictureTypeEI = 0x11,
+ OMX_VIDEO_PictureTypeEP = 0x12,
+ OMX_VIDEO_PictureTypeS = 0x14,
+ OMX_VIDEO_PictureTypeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_VIDEO_PictureTypeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_VIDEO_PictureTypeMax = 0x7FFFFFFF
+} OMX_VIDEO_PICTURETYPE;
+
+
+/**
+ * H.263 Params
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nPFrames : Number of P frames between each I frame
+ * nBFrames : Number of B frames between each I frame
+ * eProfile : H.263 profile(s) to use
+ * eLevel : H.263 level(s) to use
+ * bPLUSPTYPEAllowed : Indicating that it is allowed to use PLUSPTYPE
+ * (specified in the 1998 version of H.263) to
+ * indicate custom picture sizes or clock
+ * frequencies
+ * nAllowedPictureTypes : Specifies the picture types allowed in the
+ * bitstream
+ * bForceRoundingTypeToZero : value of the RTYPE bit (bit 6 of MPPTYPE) is
+ * not constrained. It is recommended to change
+ * the value of the RTYPE bit for each reference
+ * picture in error-free communication
+ * nPictureHeaderRepetition : Specifies the frequency of picture header
+ * repetition
+ * nGOBHeaderInterval : Specifies the interval of non-empty GOB
+ * headers in units of GOBs
+ */
+typedef struct OMX_VIDEO_PARAM_H263TYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nPFrames;
+ OMX_U32 nBFrames;
+ OMX_VIDEO_H263PROFILETYPE eProfile;
+ OMX_VIDEO_H263LEVELTYPE eLevel;
+ OMX_BOOL bPLUSPTYPEAllowed;
+ OMX_U32 nAllowedPictureTypes;
+ OMX_BOOL bForceRoundingTypeToZero;
+ OMX_U32 nPictureHeaderRepetition;
+ OMX_U32 nGOBHeaderInterval;
+} OMX_VIDEO_PARAM_H263TYPE;
+
+
+/**
+ * MPEG-2 profile types, each profile indicates support for various
+ * performance bounds and different annexes.
+ */
+typedef enum OMX_VIDEO_MPEG2PROFILETYPE {
+ OMX_VIDEO_MPEG2ProfileSimple = 0, /**< Simple Profile */
+ OMX_VIDEO_MPEG2ProfileMain, /**< Main Profile */
+ OMX_VIDEO_MPEG2Profile422, /**< 4:2:2 Profile */
+ OMX_VIDEO_MPEG2ProfileSNR, /**< SNR Profile */
+ OMX_VIDEO_MPEG2ProfileSpatial, /**< Spatial Profile */
+ OMX_VIDEO_MPEG2ProfileHigh, /**< High Profile */
+ OMX_VIDEO_MPEG2ProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_VIDEO_MPEG2ProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_VIDEO_MPEG2ProfileMax = 0x7FFFFFFF
+} OMX_VIDEO_MPEG2PROFILETYPE;
+
+
+/**
+ * MPEG-2 level types, each level indicates support for various frame
+ * sizes, bit rates, decoder frame rates. No need
+ */
+typedef enum OMX_VIDEO_MPEG2LEVELTYPE {
+ OMX_VIDEO_MPEG2LevelLL = 0, /**< Low Level */
+ OMX_VIDEO_MPEG2LevelML, /**< Main Level */
+ OMX_VIDEO_MPEG2LevelH14, /**< High 1440 */
+ OMX_VIDEO_MPEG2LevelHL, /**< High Level */
+ OMX_VIDEO_MPEG2LevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_VIDEO_MPEG2LevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_VIDEO_MPEG2LevelMax = 0x7FFFFFFF
+} OMX_VIDEO_MPEG2LEVELTYPE;
+
+
+/**
+ * MPEG-2 params
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nPFrames : Number of P frames between each I frame
+ * nBFrames : Number of B frames between each I frame
+ * eProfile : MPEG-2 profile(s) to use
+ * eLevel : MPEG-2 levels(s) to use
+ */
+typedef struct OMX_VIDEO_PARAM_MPEG2TYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nPFrames;
+ OMX_U32 nBFrames;
+ OMX_VIDEO_MPEG2PROFILETYPE eProfile;
+ OMX_VIDEO_MPEG2LEVELTYPE eLevel;
+} OMX_VIDEO_PARAM_MPEG2TYPE;
+
+
+/**
+ * MPEG-4 profile types, each profile indicates support for various
+ * performance bounds and different annexes.
+ *
+ * ENUMS:
+ * - Simple Profile, Levels 1-3
+ * - Simple Scalable Profile, Levels 1-2
+ * - Core Profile, Levels 1-2
+ * - Main Profile, Levels 2-4
+ * - N-bit Profile, Level 2
+ * - Scalable Texture Profile, Level 1
+ * - Simple Face Animation Profile, Levels 1-2
+ * - Simple Face and Body Animation (FBA) Profile, Levels 1-2
+ * - Basic Animated Texture Profile, Levels 1-2
+ * - Hybrid Profile, Levels 1-2
+ * - Advanced Real Time Simple Profiles, Levels 1-4
+ * - Core Scalable Profile, Levels 1-3
+ * - Advanced Coding Efficiency Profile, Levels 1-4
+ * - Advanced Core Profile, Levels 1-2
+ * - Advanced Scalable Texture, Levels 2-3
+ */
+typedef enum OMX_VIDEO_MPEG4PROFILETYPE {
+ OMX_VIDEO_MPEG4ProfileSimple = 0x01,
+ OMX_VIDEO_MPEG4ProfileSimpleScalable = 0x02,
+ OMX_VIDEO_MPEG4ProfileCore = 0x04,
+ OMX_VIDEO_MPEG4ProfileMain = 0x08,
+ OMX_VIDEO_MPEG4ProfileNbit = 0x10,
+ OMX_VIDEO_MPEG4ProfileScalableTexture = 0x20,
+ OMX_VIDEO_MPEG4ProfileSimpleFace = 0x40,
+ OMX_VIDEO_MPEG4ProfileSimpleFBA = 0x80,
+ OMX_VIDEO_MPEG4ProfileBasicAnimated = 0x100,
+ OMX_VIDEO_MPEG4ProfileHybrid = 0x200,
+ OMX_VIDEO_MPEG4ProfileAdvancedRealTime = 0x400,
+ OMX_VIDEO_MPEG4ProfileCoreScalable = 0x800,
+ OMX_VIDEO_MPEG4ProfileAdvancedCoding = 0x1000,
+ OMX_VIDEO_MPEG4ProfileAdvancedCore = 0x2000,
+ OMX_VIDEO_MPEG4ProfileAdvancedScalable = 0x4000,
+ OMX_VIDEO_MPEG4ProfileAdvancedSimple = 0x8000,
+ OMX_VIDEO_MPEG4ProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_VIDEO_MPEG4ProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_VIDEO_MPEG4ProfileMax = 0x7FFFFFFF
+} OMX_VIDEO_MPEG4PROFILETYPE;
+
+
+/**
+ * MPEG-4 level types, each level indicates support for various frame
+ * sizes, bit rates, decoder frame rates. No need
+ */
+typedef enum OMX_VIDEO_MPEG4LEVELTYPE {
+ OMX_VIDEO_MPEG4Level0 = 0x01, /**< Level 0 */
+ OMX_VIDEO_MPEG4Level0b = 0x02, /**< Level 0b */
+ OMX_VIDEO_MPEG4Level1 = 0x04, /**< Level 1 */
+ OMX_VIDEO_MPEG4Level2 = 0x08, /**< Level 2 */
+ OMX_VIDEO_MPEG4Level3 = 0x10, /**< Level 3 */
+ OMX_VIDEO_MPEG4Level4 = 0x20, /**< Level 4 */
+ OMX_VIDEO_MPEG4Level4a = 0x40, /**< Level 4a */
+ OMX_VIDEO_MPEG4Level5 = 0x80, /**< Level 5 */
+ OMX_VIDEO_MPEG4LevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_VIDEO_MPEG4LevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_VIDEO_MPEG4LevelMax = 0x7FFFFFFF
+} OMX_VIDEO_MPEG4LEVELTYPE;
+
+
+/**
+ * MPEG-4 configuration. This structure handles configuration options
+ * which are specific to MPEG4 algorithms
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nSliceHeaderSpacing : Number of macroblocks between slice header (H263+
+ * Annex K). Put zero if not used
+ * bSVH : Enable Short Video Header mode
+ * bGov : Flag to enable GOV
+ * nPFrames : Number of P frames between each I frame (also called
+ * GOV period)
+ * nBFrames : Number of B frames between each I frame
+ * nIDCVLCThreshold : Value of intra DC VLC threshold
+ * bACPred : Flag to use ac prediction
+ * nMaxPacketSize : Maximum size of packet in bytes.
+ * nTimeIncRes : Used to pass VOP time increment resolution for MPEG4.
+ * Interpreted as described in MPEG4 standard.
+ * eProfile : MPEG-4 profile(s) to use.
+ * eLevel : MPEG-4 level(s) to use.
+ * nAllowedPictureTypes : Specifies the picture types allowed in the bitstream
+ * nHeaderExtension : Specifies the number of consecutive video packet
+ * headers within a VOP
+ * bReversibleVLC : Specifies whether reversible variable length coding
+ * is in use
+ */
+typedef struct OMX_VIDEO_PARAM_MPEG4TYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nSliceHeaderSpacing;
+ OMX_BOOL bSVH;
+ OMX_BOOL bGov;
+ OMX_U32 nPFrames;
+ OMX_U32 nBFrames;
+ OMX_U32 nIDCVLCThreshold;
+ OMX_BOOL bACPred;
+ OMX_U32 nMaxPacketSize;
+ OMX_U32 nTimeIncRes;
+ OMX_VIDEO_MPEG4PROFILETYPE eProfile;
+ OMX_VIDEO_MPEG4LEVELTYPE eLevel;
+ OMX_U32 nAllowedPictureTypes;
+ OMX_U32 nHeaderExtension;
+ OMX_BOOL bReversibleVLC;
+} OMX_VIDEO_PARAM_MPEG4TYPE;
+
+
+/**
+ * WMV Versions
+ */
+typedef enum OMX_VIDEO_WMVFORMATTYPE {
+ OMX_VIDEO_WMVFormatUnused = 0x01, /**< Format unused or unknown */
+ OMX_VIDEO_WMVFormat7 = 0x02, /**< Windows Media Video format 7 */
+ OMX_VIDEO_WMVFormat8 = 0x04, /**< Windows Media Video format 8 */
+ OMX_VIDEO_WMVFormat9 = 0x08, /**< Windows Media Video format 9 */
+ OMX_VIDEO_WMFFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_VIDEO_WMFFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_VIDEO_WMVFormatMax = 0x7FFFFFFF
+} OMX_VIDEO_WMVFORMATTYPE;
+
+
+/**
+ * WMV Params
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * eFormat : Version of WMV stream / data
+ */
+typedef struct OMX_VIDEO_PARAM_WMVTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_VIDEO_WMVFORMATTYPE eFormat;
+} OMX_VIDEO_PARAM_WMVTYPE;
+
+
+/**
+ * Real Video Version
+ */
+typedef enum OMX_VIDEO_RVFORMATTYPE {
+ OMX_VIDEO_RVFormatUnused = 0, /**< Format unused or unknown */
+ OMX_VIDEO_RVFormat8, /**< Real Video format 8 */
+ OMX_VIDEO_RVFormat9, /**< Real Video format 9 */
+ OMX_VIDEO_RVFormatG2, /**< Real Video Format G2 */
+ OMX_VIDEO_RVFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_VIDEO_RVFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_VIDEO_RVFormatMax = 0x7FFFFFFF
+} OMX_VIDEO_RVFORMATTYPE;
+
+
+/**
+ * Real Video Params
+ *
+ * STUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * eFormat : Version of RV stream / data
+ * nBitsPerPixel : Bits per pixel coded in the frame
+ * nPaddedWidth : Padded width in pixel of a video frame
+ * nPaddedHeight : Padded Height in pixels of a video frame
+ * nFrameRate : Rate of video in frames per second
+ * nBitstreamFlags : Flags which internal information about the bitstream
+ * nBitstreamVersion : Bitstream version
+ * nMaxEncodeFrameSize: Max encoded frame size
+ * bEnablePostFilter : Turn on/off post filter
+ * bEnableTemporalInterpolation : Turn on/off temporal interpolation
+ * bEnableLatencyMode : When enabled, the decoder does not display a decoded
+ * frame until it has detected that no enhancement layer
+ * frames or dependent B frames will be coming. This
+ * detection usually occurs when a subsequent non-B
+ * frame is encountered
+ */
+typedef struct OMX_VIDEO_PARAM_RVTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_VIDEO_RVFORMATTYPE eFormat;
+ OMX_U16 nBitsPerPixel;
+ OMX_U16 nPaddedWidth;
+ OMX_U16 nPaddedHeight;
+ OMX_U32 nFrameRate;
+ OMX_U32 nBitstreamFlags;
+ OMX_U32 nBitstreamVersion;
+ OMX_U32 nMaxEncodeFrameSize;
+ OMX_BOOL bEnablePostFilter;
+ OMX_BOOL bEnableTemporalInterpolation;
+ OMX_BOOL bEnableLatencyMode;
+} OMX_VIDEO_PARAM_RVTYPE;
+
+
+/**
+ * AVC profile types, each profile indicates support for various
+ * performance bounds and different annexes.
+ */
+typedef enum OMX_VIDEO_AVCPROFILETYPE {
+ OMX_VIDEO_AVCProfileBaseline = 0x01, /**< Baseline profile */
+ OMX_VIDEO_AVCProfileMain = 0x02, /**< Main profile */
+ OMX_VIDEO_AVCProfileExtended = 0x04, /**< Extended profile */
+ OMX_VIDEO_AVCProfileHigh = 0x08, /**< High profile */
+ OMX_VIDEO_AVCProfileHigh10 = 0x10, /**< High 10 profile */
+ OMX_VIDEO_AVCProfileHigh422 = 0x20, /**< High 4:2:2 profile */
+ OMX_VIDEO_AVCProfileHigh444 = 0x40, /**< High 4:4:4 profile */
+ OMX_VIDEO_AVCProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_VIDEO_AVCProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_VIDEO_AVCProfileMax = 0x7FFFFFFF
+} OMX_VIDEO_AVCPROFILETYPE;
+
+
+/**
+ * AVC level types, each level indicates support for various frame sizes,
+ * bit rates, decoder frame rates. No need
+ */
+typedef enum OMX_VIDEO_AVCLEVELTYPE {
+ OMX_VIDEO_AVCLevel1 = 0x01, /**< Level 1 */
+ OMX_VIDEO_AVCLevel1b = 0x02, /**< Level 1b */
+ OMX_VIDEO_AVCLevel11 = 0x04, /**< Level 1.1 */
+ OMX_VIDEO_AVCLevel12 = 0x08, /**< Level 1.2 */
+ OMX_VIDEO_AVCLevel13 = 0x10, /**< Level 1.3 */
+ OMX_VIDEO_AVCLevel2 = 0x20, /**< Level 2 */
+ OMX_VIDEO_AVCLevel21 = 0x40, /**< Level 2.1 */
+ OMX_VIDEO_AVCLevel22 = 0x80, /**< Level 2.2 */
+ OMX_VIDEO_AVCLevel3 = 0x100, /**< Level 3 */
+ OMX_VIDEO_AVCLevel31 = 0x200, /**< Level 3.1 */
+ OMX_VIDEO_AVCLevel32 = 0x400, /**< Level 3.2 */
+ OMX_VIDEO_AVCLevel4 = 0x800, /**< Level 4 */
+ OMX_VIDEO_AVCLevel41 = 0x1000, /**< Level 4.1 */
+ OMX_VIDEO_AVCLevel42 = 0x2000, /**< Level 4.2 */
+ OMX_VIDEO_AVCLevel5 = 0x4000, /**< Level 5 */
+ OMX_VIDEO_AVCLevel51 = 0x8000, /**< Level 5.1 */
+ OMX_VIDEO_AVCLevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_VIDEO_AVCLevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_VIDEO_AVCLevelMax = 0x7FFFFFFF
+} OMX_VIDEO_AVCLEVELTYPE;
+
+
+/**
+ * AVC loop filter modes
+ *
+ * OMX_VIDEO_AVCLoopFilterEnable : Enable
+ * OMX_VIDEO_AVCLoopFilterDisable : Disable
+ * OMX_VIDEO_AVCLoopFilterDisableSliceBoundary : Disabled on slice boundaries
+ */
+typedef enum OMX_VIDEO_AVCLOOPFILTERTYPE {
+ OMX_VIDEO_AVCLoopFilterEnable = 0,
+ OMX_VIDEO_AVCLoopFilterDisable,
+ OMX_VIDEO_AVCLoopFilterDisableSliceBoundary,
+ OMX_VIDEO_AVCLoopFilterKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_VIDEO_AVCLoopFilterVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_VIDEO_AVCLoopFilterMax = 0x7FFFFFFF
+} OMX_VIDEO_AVCLOOPFILTERTYPE;
+
+
+/**
+ * AVC params
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nSliceHeaderSpacing : Number of macroblocks between slice header, put
+ * zero if not used
+ * nPFrames : Number of P frames between each I frame
+ * nBFrames : Number of B frames between each I frame
+ * bUseHadamard : Enable/disable Hadamard transform
+ * nRefFrames : Max number of reference frames to use for inter
+ * motion search (1-16)
+ * nRefIdxTrailing : Pic param set ref frame index (index into ref
+ * frame buffer of trailing frames list), B frame
+ * support
+ * nRefIdxForward : Pic param set ref frame index (index into ref
+ * frame buffer of forward frames list), B frame
+ * support
+ * bEnableUEP : Enable/disable unequal error protection. This
+ * is only valid of data partitioning is enabled.
+ * bEnableFMO : Enable/disable flexible macroblock ordering
+ * bEnableASO : Enable/disable arbitrary slice ordering
+ * bEnableRS : Enable/disable sending of redundant slices
+ * eProfile : AVC profile(s) to use
+ * eLevel : AVC level(s) to use
+ * nAllowedPictureTypes : Specifies the picture types allowed in the
+ * bitstream
+ * bFrameMBsOnly : specifies that every coded picture of the
+ * coded video sequence is a coded frame
+ * containing only frame macroblocks
+ * bMBAFF : Enable/disable switching between frame and
+ * field macroblocks within a picture
+ * bEntropyCodingCABAC : Entropy decoding method to be applied for the
+ * syntax elements for which two descriptors appear
+ * in the syntax tables
+ * bWeightedPPrediction : Enable/disable weighted prediction shall not
+ * be applied to P and SP slices
+ * nWeightedBipredicitonMode : Default weighted prediction is applied to B
+ * slices
+ * bconstIpred : Enable/disable intra prediction
+ * bDirect8x8Inference : Specifies the method used in the derivation
+ * process for luma motion vectors for B_Skip,
+ * B_Direct_16x16 and B_Direct_8x8 as specified
+ * in subclause 8.4.1.2 of the AVC spec
+ * bDirectSpatialTemporal : Flag indicating spatial or temporal direct
+ * mode used in B slice coding (related to
+ * bDirect8x8Inference) . Spatial direct mode is
+ * more common and should be the default.
+ * nCabacInitIdx : Index used to init CABAC contexts
+ * eLoopFilterMode : Enable/disable loop filter
+ */
+typedef struct OMX_VIDEO_PARAM_AVCTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nSliceHeaderSpacing;
+ OMX_U32 nPFrames;
+ OMX_U32 nBFrames;
+ OMX_BOOL bUseHadamard;
+ OMX_U32 nRefFrames;
+ OMX_U32 nRefIdx10ActiveMinus1;
+ OMX_U32 nRefIdx11ActiveMinus1;
+ OMX_BOOL bEnableUEP;
+ OMX_BOOL bEnableFMO;
+ OMX_BOOL bEnableASO;
+ OMX_BOOL bEnableRS;
+ OMX_VIDEO_AVCPROFILETYPE eProfile;
+ OMX_VIDEO_AVCLEVELTYPE eLevel;
+ OMX_U32 nAllowedPictureTypes;
+ OMX_BOOL bFrameMBsOnly;
+ OMX_BOOL bMBAFF;
+ OMX_BOOL bEntropyCodingCABAC;
+ OMX_BOOL bWeightedPPrediction;
+ OMX_U32 nWeightedBipredicitonMode;
+ OMX_BOOL bconstIpred ;
+ OMX_BOOL bDirect8x8Inference;
+ OMX_BOOL bDirectSpatialTemporal;
+ OMX_U32 nCabacInitIdc;
+ OMX_VIDEO_AVCLOOPFILTERTYPE eLoopFilterMode;
+} OMX_VIDEO_PARAM_AVCTYPE;
+
+typedef struct OMX_VIDEO_PARAM_PROFILELEVELTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 eProfile; /**< type is OMX_VIDEO_AVCPROFILETYPE, OMX_VIDEO_H263PROFILETYPE,
+ or OMX_VIDEO_MPEG4PROFILETYPE depending on context */
+ OMX_U32 eLevel; /**< type is OMX_VIDEO_AVCLEVELTYPE, OMX_VIDEO_H263LEVELTYPE,
+ or OMX_VIDEO_MPEG4PROFILETYPE depending on context */
+ OMX_U32 nProfileIndex; /**< Used to query for individual profile support information,
+ This parameter is valid only for
+ OMX_IndexParamVideoProfileLevelQuerySupported index,
+ For all other indices this parameter is to be ignored. */
+} OMX_VIDEO_PARAM_PROFILELEVELTYPE;
+
+/**
+ * Structure for dynamically configuring bitrate mode of a codec.
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the struct in bytes
+ * nVersion : OMX spec version info
+ * nPortIndex : Port that this struct applies to
+ * nEncodeBitrate : Target average bitrate to be generated in bps
+ */
+typedef struct OMX_VIDEO_CONFIG_BITRATETYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nEncodeBitrate;
+} OMX_VIDEO_CONFIG_BITRATETYPE;
+
+/**
+ * Defines Encoder Frame Rate setting
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * xEncodeFramerate : Encoding framerate represented in Q16 format
+ */
+typedef struct OMX_CONFIG_FRAMERATETYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 xEncodeFramerate; /* Q16 format */
+} OMX_CONFIG_FRAMERATETYPE;
+
+typedef struct OMX_CONFIG_INTRAREFRESHVOPTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_BOOL IntraRefreshVOP;
+} OMX_CONFIG_INTRAREFRESHVOPTYPE;
+
+typedef struct OMX_CONFIG_MACROBLOCKERRORMAPTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nErrMapSize; /* Size of the Error Map in bytes */
+ OMX_U8 ErrMap[1]; /* Error map hint */
+} OMX_CONFIG_MACROBLOCKERRORMAPTYPE;
+
+typedef struct OMX_CONFIG_MBERRORREPORTINGTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_BOOL bEnabled;
+} OMX_CONFIG_MBERRORREPORTINGTYPE;
+
+typedef struct OMX_PARAM_MACROBLOCKSTYPE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nMacroblocks;
+} OMX_PARAM_MACROBLOCKSTYPE;
+
+/**
+ * AVC Slice Mode modes
+ *
+ * OMX_VIDEO_SLICEMODE_AVCDefault : Normal frame encoding, one slice per frame
+ * OMX_VIDEO_SLICEMODE_AVCMBSlice : NAL mode, number of MBs per frame
+ * OMX_VIDEO_SLICEMODE_AVCByteSlice : NAL mode, number of bytes per frame
+ */
+typedef enum OMX_VIDEO_AVCSLICEMODETYPE {
+ OMX_VIDEO_SLICEMODE_AVCDefault = 0,
+ OMX_VIDEO_SLICEMODE_AVCMBSlice,
+ OMX_VIDEO_SLICEMODE_AVCByteSlice,
+ OMX_VIDEO_SLICEMODE_AVCKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+ OMX_VIDEO_SLICEMODE_AVCVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_VIDEO_SLICEMODE_AVCLevelMax = 0x7FFFFFFF
+} OMX_VIDEO_AVCSLICEMODETYPE;
+
+/**
+ * AVC FMO Slice Mode Params
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nNumSliceGroups : Specifies the number of slice groups
+ * nSliceGroupMapType : Specifies the type of slice groups
+ * eSliceMode : Specifies the type of slice
+ */
+typedef struct OMX_VIDEO_PARAM_AVCSLICEFMO {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U8 nNumSliceGroups;
+ OMX_U8 nSliceGroupMapType;
+ OMX_VIDEO_AVCSLICEMODETYPE eSliceMode;
+} OMX_VIDEO_PARAM_AVCSLICEFMO;
+
+/**
+ * AVC IDR Period Configs
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nIDRPeriod : Specifies periodicity of IDR frames
+ * nPFrames : Specifies internal of coding Intra frames
+ */
+typedef struct OMX_VIDEO_CONFIG_AVCINTRAPERIOD {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nIDRPeriod;
+ OMX_U32 nPFrames;
+} OMX_VIDEO_CONFIG_AVCINTRAPERIOD;
+
+/**
+ * AVC NAL Size Configs
+ *
+ * STRUCT MEMBERS:
+ * nSize : Size of the structure in bytes
+ * nVersion : OMX specification version information
+ * nPortIndex : Port that this structure applies to
+ * nNaluBytes : Specifies the NAL unit size
+ */
+typedef struct OMX_VIDEO_CONFIG_NALSIZE {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_U32 nNaluBytes;
+} OMX_VIDEO_CONFIG_NALSIZE;
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
+/* File EOF */
+
diff --git a/subprojects/gst-omx/omx/openmax/OMX_VideoExt.h b/subprojects/gst-omx/omx/openmax/OMX_VideoExt.h
new file mode 100644
index 0000000000..a9b5d458b9
--- /dev/null
+++ b/subprojects/gst-omx/omx/openmax/OMX_VideoExt.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2010 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/** OMX_VideoExt.h - OpenMax IL version 1.1.2
+ * The OMX_VideoExt header file contains extensions to the
+ * definitions used by both the application and the component to
+ * access video items.
+ */
+
+#ifndef OMX_VideoExt_h
+#define OMX_VideoExt_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Each OMX header shall include all required header files to allow the
+ * header to compile without errors. The includes below are required
+ * for this header file to compile successfully
+ */
+#include <OMX_Core.h>
+
+/** NALU Formats */
+typedef enum OMX_NALUFORMATSTYPE {
+ OMX_NaluFormatStartCodes = 1,
+ OMX_NaluFormatOneNaluPerBuffer = 2,
+ OMX_NaluFormatOneByteInterleaveLength = 4,
+ OMX_NaluFormatTwoByteInterleaveLength = 8,
+ OMX_NaluFormatFourByteInterleaveLength = 16,
+ OMX_NaluFormatCodingMax = 0x7FFFFFFF
+} OMX_NALUFORMATSTYPE;
+
+
+/** NAL Stream Format */
+typedef struct OMX_NALSTREAMFORMATTYPE{
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_NALUFORMATSTYPE eNaluFormat;
+} OMX_NALSTREAMFORMATTYPE;
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* OMX_VideoExt_h */
+/* File EOF */
diff --git a/subprojects/gst-omx/scripts/extract-release-date-from-doap-file.py b/subprojects/gst-omx/scripts/extract-release-date-from-doap-file.py
new file mode 100755
index 0000000000..f09b60e9d0
--- /dev/null
+++ b/subprojects/gst-omx/scripts/extract-release-date-from-doap-file.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+#
+# extract-release-date-from-doap-file.py VERSION DOAP-FILE
+#
+# Extract release date for the given release version from a DOAP file
+#
+# Copyright (C) 2020 Tim-Philipp Müller <tim centricular com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+import sys
+import xml.etree.ElementTree as ET
+
+if len(sys.argv) != 3:
+ sys.exit('Usage: {} VERSION DOAP-FILE'.format(sys.argv[0]))
+
+release_version = sys.argv[1]
+doap_fn = sys.argv[2]
+
+tree = ET.parse(doap_fn)
+root = tree.getroot()
+
+namespaces = {'doap': 'http://usefulinc.com/ns/doap#'}
+
+for v in root.findall('doap:release/doap:Version', namespaces=namespaces):
+ if v.findtext('doap:revision', namespaces=namespaces) == release_version:
+ release_date = v.findtext('doap:created', namespaces=namespaces)
+ if release_date:
+ print(release_date)
+ sys.exit(0)
+
+sys.exit('Could not find a release with version {} in {}'.format(release_version, doap_fn))
diff --git a/subprojects/gst-omx/tests/check/generic/states.c b/subprojects/gst-omx/tests/check/generic/states.c
new file mode 100644
index 0000000000..415ac543c2
--- /dev/null
+++ b/subprojects/gst-omx/tests/check/generic/states.c
@@ -0,0 +1,225 @@
+/* GStreamer
+ *
+ * unit test for state changes on all elements
+ *
+ * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include <gst/check/gstcheck.h>
+
+static GList *elements = NULL;
+
+static void
+setup (void)
+{
+ GList *features, *f;
+ GList *plugins, *p;
+ gchar **ignorelist = NULL;
+ const gchar *STATE_IGNORE_ELEMENTS = NULL;
+ GstRegistry *def;
+
+ GST_DEBUG ("getting elements for package %s", PACKAGE);
+ STATE_IGNORE_ELEMENTS = g_getenv ("GST_STATE_IGNORE_ELEMENTS");
+ if (!g_getenv ("GST_NO_STATE_IGNORE_ELEMENTS") && STATE_IGNORE_ELEMENTS) {
+ GST_DEBUG ("Will ignore element factories: '%s'", STATE_IGNORE_ELEMENTS);
+ ignorelist = g_strsplit (STATE_IGNORE_ELEMENTS, " ", 0);
+ }
+
+ def = gst_registry_get ();
+
+ plugins = gst_registry_get_plugin_list (def);
+
+ for (p = plugins; p; p = p->next) {
+ GstPlugin *plugin = p->data;
+
+ if (strcmp (gst_plugin_get_source (plugin), PACKAGE) != 0)
+ continue;
+
+ features =
+ gst_registry_get_feature_list_by_plugin (def,
+ gst_plugin_get_name (plugin));
+
+ for (f = features; f; f = f->next) {
+ GstPluginFeature *feature = f->data;
+ const gchar *name = gst_plugin_feature_get_name (feature);
+ gboolean ignore = FALSE;
+
+ if (!GST_IS_ELEMENT_FACTORY (feature))
+ continue;
+
+ if (ignorelist) {
+ gchar **s;
+
+ for (s = ignorelist; s && *s; ++s) {
+ if (g_str_has_prefix (name, *s)) {
+ GST_DEBUG ("ignoring element %s", name);
+ ignore = TRUE;
+ }
+ }
+ if (ignore)
+ continue;
+ }
+
+ GST_DEBUG ("adding element %s", name);
+ elements = g_list_prepend (elements, (gpointer) g_strdup (name));
+ }
+ gst_plugin_feature_list_free (features);
+ }
+ gst_plugin_list_free (plugins);
+ g_strfreev (ignorelist);
+}
+
+static void
+teardown (void)
+{
+ GList *e;
+
+ for (e = elements; e; e = e->next) {
+ g_free (e->data);
+ }
+ g_list_free (elements);
+ elements = NULL;
+}
+
+
+GST_START_TEST (test_state_changes_up_and_down_seq)
+{
+ GstElement *element;
+ GList *e;
+
+ for (e = elements; e; e = e->next) {
+ const gchar *name = e->data;
+
+ GST_INFO ("testing element %s", name);
+ element = gst_element_factory_make (name, name);
+ fail_if (element == NULL, "Could not make element from factory %s", name);
+
+ if (GST_IS_PIPELINE (element)) {
+ GST_DEBUG ("element %s is a pipeline", name);
+ }
+
+ gst_element_set_state (element, GST_STATE_READY);
+ gst_element_set_state (element, GST_STATE_PAUSED);
+ gst_element_set_state (element, GST_STATE_PLAYING);
+ gst_element_set_state (element, GST_STATE_PAUSED);
+ gst_element_set_state (element, GST_STATE_READY);
+ gst_element_set_state (element, GST_STATE_NULL);
+ gst_element_set_state (element, GST_STATE_PAUSED);
+ gst_element_set_state (element, GST_STATE_READY);
+ gst_element_set_state (element, GST_STATE_PLAYING);
+ gst_element_set_state (element, GST_STATE_PAUSED);
+ gst_element_set_state (element, GST_STATE_NULL);
+ gst_object_unref (GST_OBJECT (element));
+ }
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_state_changes_up_seq)
+{
+ GstElement *element;
+ GList *e;
+
+ for (e = elements; e; e = e->next) {
+ const gchar *name = e->data;
+
+ GST_INFO ("testing element %s", name);
+ element = gst_element_factory_make (name, name);
+ fail_if (element == NULL, "Could not make element from factory %s", name);
+
+ if (GST_IS_PIPELINE (element)) {
+ GST_DEBUG ("element %s is a pipeline", name);
+ }
+
+ gst_element_set_state (element, GST_STATE_READY);
+
+ gst_element_set_state (element, GST_STATE_PAUSED);
+ gst_element_set_state (element, GST_STATE_READY);
+
+ gst_element_set_state (element, GST_STATE_PAUSED);
+ gst_element_set_state (element, GST_STATE_PLAYING);
+ gst_element_set_state (element, GST_STATE_PAUSED);
+ gst_element_set_state (element, GST_STATE_READY);
+
+ gst_element_set_state (element, GST_STATE_NULL);
+ gst_object_unref (GST_OBJECT (element));
+ }
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_state_changes_down_seq)
+{
+ GstElement *element;
+ GList *e;
+
+ for (e = elements; e; e = e->next) {
+ const gchar *name = e->data;
+
+ GST_INFO ("testing element %s", name);
+ element = gst_element_factory_make (name, name);
+ fail_if (element == NULL, "Could not make element from factory %s", name);
+
+ if (GST_IS_PIPELINE (element)) {
+ GST_DEBUG ("element %s is a pipeline", name);
+ }
+
+ gst_element_set_state (element, GST_STATE_READY);
+ gst_element_set_state (element, GST_STATE_PAUSED);
+ gst_element_set_state (element, GST_STATE_PLAYING);
+
+ gst_element_set_state (element, GST_STATE_PAUSED);
+ gst_element_set_state (element, GST_STATE_PLAYING);
+
+ gst_element_set_state (element, GST_STATE_PAUSED);
+ gst_element_set_state (element, GST_STATE_READY);
+ gst_element_set_state (element, GST_STATE_PAUSED);
+ gst_element_set_state (element, GST_STATE_PLAYING);
+
+ gst_element_set_state (element, GST_STATE_PAUSED);
+ gst_element_set_state (element, GST_STATE_READY);
+ gst_element_set_state (element, GST_STATE_NULL);
+ gst_object_unref (GST_OBJECT (element));
+ }
+}
+
+GST_END_TEST;
+
+
+static Suite *
+states_suite (void)
+{
+ Suite *s = suite_create ("states_omx");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_checked_fixture (tc_chain, setup, teardown);
+ tcase_add_test (tc_chain, test_state_changes_up_and_down_seq);
+ tcase_add_test (tc_chain, test_state_changes_up_seq);
+ tcase_add_test (tc_chain, test_state_changes_down_seq);
+
+ return s;
+}
+
+GST_CHECK_MAIN (states);
diff --git a/subprojects/gst-omx/tests/check/meson.build b/subprojects/gst-omx/tests/check/meson.build
new file mode 100644
index 0000000000..b43a51709d
--- /dev/null
+++ b/subprojects/gst-omx/tests/check/meson.build
@@ -0,0 +1,56 @@
+# name, condition when to skip the test and extra dependencies
+omx_tests = [
+ [ 'generic/states' ],
+]
+
+test_defines = [
+ '-UG_DISABLE_ASSERT',
+ '-UG_DISABLE_CAST_CHECKS',
+ '-DGST_CHECK_TEST_ENVIRONMENT_BEACON="GST_PLUGIN_LOADING_WHITELIST"',
+]
+
+pluginsdirs = []
+if gst_dep.type_name() == 'pkgconfig'
+ pbase = dependency('gstreamer-plugins-base-' + api_version, required : false)
+ pluginsdirs = [gst_dep.get_pkgconfig_variable('pluginsdir'),
+ pbase.get_pkgconfig_variable('pluginsdir')]
+endif
+
+state_ignore_elements=''
+
+# FIXME: check, also + PTHREAD_CFLAGS
+test_deps = [gst_dep, gstbase_dep, glib_dep, gstcheck_dep]
+
+# FIXME: add valgrind suppression common/gst.supp gst-plugins-good.supp
+foreach t : omx_tests
+ fname = '@0@.c'.format(t.get(0))
+ test_name = t.get(0).underscorify()
+ extra_deps = [ ]
+ if t.length() == 3
+ extra_deps = t.get(2)
+ skip_test = t.get(1)
+ elif t.length() == 2
+ skip_test = t.get(1)
+ else
+ skip_test = false
+ endif
+ if not skip_test
+ env = environment()
+ env.set('GST_PLUGIN_SYSTEM_PATH_1_0', '')
+ env.set('GST_STATE_IGNORE_ELEMENTS', state_ignore_elements)
+ env.set('CK_DEFAULT_TIMEOUT', '20')
+ env.set('GST_PLUGIN_LOADING_WHITELIST', 'gstreamer', 'gst-plugins-base',
+ 'gst-plugins-good', 'gst-omx@' + meson.build_root(), separator: ':')
+ env.set('GST_PLUGIN_PATH_1_0', [meson.build_root()] + pluginsdirs)
+ env.set('GSETTINGS_BACKEND', 'memory')
+ env.set('GST_OMX_CONFIG_DIR', omx_config_dir)
+
+ env.set('GST_REGISTRY', '@0@/@1@.registry'.format(meson.current_build_dir(), test_name))
+ exe = executable(test_name, fname,
+ include_directories : [configinc],
+ c_args : ['-DHAVE_CONFIG_H=1' ] + test_defines,
+ dependencies : [libm] + test_deps + extra_deps,
+ )
+ test(test_name, exe, env: env, timeout: 3 * 60)
+ endif
+endforeach
diff --git a/subprojects/gst-omx/tests/meson.build b/subprojects/gst-omx/tests/meson.build
new file mode 100644
index 0000000000..76b079162c
--- /dev/null
+++ b/subprojects/gst-omx/tests/meson.build
@@ -0,0 +1,4 @@
+# FIXME: make check work on windows
+if host_machine.system() != 'windows'
+subdir('check')
+endif
diff --git a/subprojects/gst-omx/tools/listcomponents.c b/subprojects/gst-omx/tools/listcomponents.c
new file mode 100644
index 0000000000..3933564b26
--- /dev/null
+++ b/subprojects/gst-omx/tools/listcomponents.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2012 Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <gmodule.h>
+
+#ifdef GST_OMX_STRUCT_PACKING
+# if GST_OMX_STRUCT_PACKING == 1
+# pragma pack(1)
+# elif GST_OMX_STRUCT_PACKING == 2
+# pragma pack(2)
+# elif GST_OMX_STRUCT_PACKING == 4
+# pragma pack(4)
+# elif GST_OMX_STRUCT_PACKING == 8
+# pragma pack(8)
+# else
+# error "Unsupported struct packing value"
+# endif
+#endif
+
+#include <OMX_Core.h>
+#include <OMX_Component.h>
+
+#ifdef GST_OMX_STRUCT_PACKING
+#pragma pack()
+#endif
+
+gint
+main (gint argc, gchar ** argv)
+{
+ gchar *filename;
+ GModule *core_module;
+ OMX_ERRORTYPE err;
+ OMX_ERRORTYPE (*omx_init) (void);
+ OMX_ERRORTYPE (*omx_component_name_enum) (OMX_STRING cComponentName,
+ OMX_U32 nNameLength, OMX_U32 nIndex);
+ OMX_ERRORTYPE (*omx_get_roles_of_component) (OMX_STRING compName,
+ OMX_U32 * pNumRoles, OMX_U8 ** roles);
+ guint32 i;
+
+ if (argc != 2) {
+ g_printerr ("Usage: %s /path/to/libopenmaxil.so\n", argv[0]);
+ return -1;
+ }
+
+ filename = argv[1];
+
+ if (!g_path_is_absolute (filename)) {
+ g_printerr ("'%s' is not an absolute filename\n", filename);
+ return -1;
+ }
+
+ /* Hack for the Broadcom OpenMAX IL implementation */
+ if (g_str_has_suffix (filename, "vc/lib/libopenmaxil.so")) {
+ gchar *bcm_host_filename;
+ gchar *bcm_host_path;
+ GModule *bcm_host_module;
+ void (*bcm_host_init) (void);
+
+ bcm_host_path = g_path_get_dirname (filename);
+ bcm_host_filename =
+ g_build_filename (bcm_host_path, "libbcm_host.so", NULL);
+
+ bcm_host_module = g_module_open (bcm_host_filename, G_MODULE_BIND_LAZY);
+
+ g_free (bcm_host_filename);
+ g_free (bcm_host_path);
+
+ if (!bcm_host_module) {
+ g_printerr ("Failed to load 'libbcm_host.so'\n");
+ return -1;
+ }
+
+ if (!g_module_symbol (bcm_host_module, "bcm_host_init",
+ (gpointer *) & bcm_host_init)) {
+ g_printerr ("Failed to find 'bcm_host_init' in 'libbcm_host.so'\n");
+ return -1;
+ }
+
+ bcm_host_init ();
+ }
+
+ core_module = g_module_open (filename, G_MODULE_BIND_LAZY);
+ if (!core_module) {
+ g_printerr ("Failed to load '%s'\n", filename);
+ return -1;
+ }
+
+ if (!g_module_symbol (core_module, "OMX_Init", (gpointer *) & omx_init)) {
+ g_printerr ("Failed to find '%s' in '%s'\n", "OMX_Init", filename);
+ return -1;
+ }
+
+ if (!g_module_symbol (core_module, "OMX_ComponentNameEnum",
+ (gpointer *) & omx_component_name_enum)) {
+ g_printerr ("Failed to find '%s' in '%s'\n", "OMX_ComponentNameEnum",
+ filename);
+ return -1;
+ }
+
+ if (!g_module_symbol (core_module, "OMX_GetRolesOfComponent",
+ (gpointer *) & omx_get_roles_of_component)) {
+ g_printerr ("Failed to find '%s' in '%s'\n", "OMX_GetRolesOfComponent",
+ filename);
+ return -1;
+ }
+
+
+ if ((err = omx_init ()) != OMX_ErrorNone) {
+ g_printerr ("Failed to initialize core: %d\n", err);
+ return -1;
+ }
+
+ i = 0;
+ while (err == OMX_ErrorNone) {
+ gchar component_name[1024];
+
+ err = omx_component_name_enum (component_name, sizeof (component_name), i);
+ if (err == OMX_ErrorNone || err == OMX_ErrorNoMore) {
+ guint32 nroles;
+
+ g_print ("Component %d: %s\n", i, component_name);
+
+ if (omx_get_roles_of_component (component_name, (OMX_U32 *) & nroles,
+ NULL) == OMX_ErrorNone && nroles > 0) {
+ gchar **roles = g_new (gchar *, nroles);
+ gint j;
+
+ roles[0] = g_new0 (gchar, 129 * nroles);
+ for (j = 1; j < nroles; j++) {
+ roles[j] = roles[j - 1] + 129;
+ }
+
+ if (omx_get_roles_of_component (component_name, (OMX_U32 *) & nroles,
+ (OMX_U8 **) roles) == OMX_ErrorNone) {
+ for (j = 0; j < nroles; j++) {
+ g_print (" Role %d: %s\n", j, roles[j]);
+ }
+ }
+ g_free (roles[0]);
+ g_free (roles);
+ }
+ }
+ i++;
+ }
+
+ return 0;
+}
diff --git a/subprojects/gst-omx/tools/meson.build b/subprojects/gst-omx/tools/meson.build
new file mode 100644
index 0000000000..7f6a6704b6
--- /dev/null
+++ b/subprojects/gst-omx/tools/meson.build
@@ -0,0 +1,8 @@
+executable('listcomponents',
+ 'listcomponents.c',
+ install: false,
+ include_directories : [configinc, omx_inc],
+ dependencies : [glib_dep, gmodule_dep],
+ link_with: [],
+ c_args : gst_omx_args + extra_c_args,
+)