diff --git a/gst-omx/.gitignore b/gst-omx/.gitignore new file mode 100644 index 0000000000..d4cb069593 --- /dev/null +++ b/gst-omx/.gitignore @@ -0,0 +1,3 @@ +*~ +*.bak +*.swp diff --git a/gst-omx/AUTHORS b/gst-omx/AUTHORS new file mode 100644 index 0000000000..3d3e8d7e9c --- /dev/null +++ b/gst-omx/AUTHORS @@ -0,0 +1,2 @@ +Sebastian Dröge + diff --git a/gst-omx/COPYING b/gst-omx/COPYING new file mode 100644 index 0000000000..4362b49151 --- /dev/null +++ b/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. + + + Copyright (C) + + 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. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/gst-omx/ChangeLog b/gst-omx/ChangeLog new file mode 100644 index 0000000000..068fd2735f --- /dev/null +++ b/gst-omx/ChangeLog @@ -0,0 +1,8230 @@ +=== release 1.20.4 === + +2022-10-12 16:39:47 +0100 Tim-Philipp Müller + + * NEWS: + * RELEASE: + * gst-omx.doap: + * meson.build: + Release 1.20.4 + +2022-10-12 16:39:40 +0100 Tim-Philipp Müller + + * ChangeLog: + Update ChangeLogs for 1.20.4 + +2022-06-29 10:55:13 +0100 Tim-Philipp Müller + + * meson.build: + coding style: allow declarations after statement + See https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1243/ + and https://gitlab.freedesktop.org/gstreamer/gstreamer-project/-/issues/78 + Part-of: + +2022-06-16 00:59:00 +0100 Tim-Philipp Müller + + * meson.build: + Back to development + Part-of: + +=== release 1.20.3 === + +2022-06-15 23:36:18 +0100 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * gst-omx.doap: + * meson.build: + Release 1.20.3 + +2022-06-15 23:36:10 +0100 Tim-Philipp Müller + + * ChangeLog: + Update ChangeLogs for 1.20.3 + +2022-05-03 00:39:09 +0100 Tim-Philipp Müller + + * meson.build: + Back to development + Part-of: + +=== release 1.20.2 === + +2022-05-02 23:29:25 +0100 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * gst-omx.doap: + * meson.build: + Release 1.20.2 + +2022-05-02 23:29:19 +0100 Tim-Philipp Müller + + * ChangeLog: + Update ChangeLogs for 1.20.2 + +2022-03-14 14:48:01 +0000 Tim-Philipp Müller + + * meson.build: + Back to development + +=== release 1.20.1 === + +2022-03-14 11:33:33 +0000 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * gst-omx.doap: + * meson.build: + Release 1.20.1 + +2022-03-14 11:33:25 +0000 Tim-Philipp Müller + + * ChangeLog: + Update ChangeLogs for 1.20.1 + +2022-02-07 16:17:28 +0000 Tim-Philipp Müller + + * meson.build: + Back to development + +=== release 1.20.0 === + +2022-02-03 19:53:25 +0000 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * gst-omx.doap: + * meson.build: + Release 1.20.0 + +2022-02-03 19:53:18 +0000 Tim-Philipp Müller + + * ChangeLog: + Update ChangeLogs for 1.20.0 + +=== release 1.19.90 === + +2022-01-28 14:28:35 +0000 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * gst-omx.doap: + * meson.build: + Release 1.19.90 + +2022-01-28 14:28:28 +0000 Tim-Philipp Müller + + * ChangeLog: + Update ChangeLogs for 1.19.90 + +2022-01-05 02:07:59 +0530 Nirbheek Chauhan + + * meson.build: + meson: Add explicit check: kwarg to all run_command() calls + This is required since Meson 0.61.0, and causes a warning to be + emitted otherwise: + https://github.com/mesonbuild/meson/commit/2c079d855ed87488bdcc6c5c06f59abdb9b85b6c + https://github.com/mesonbuild/meson/issues/9300 + This exposed a bunch of places where we had broken run_command() + calls, unnecessary run_command() calls, and places where check: true + should be used. + Part-of: + +2021-11-03 18:44:03 +0000 Tim-Philipp Müller + + * meson.build: + Back to development + +=== release 1.19.3 === + +2021-11-03 15:43:36 +0000 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * gst-omx.doap: + * meson.build: + Release 1.19.3 + +2021-11-03 15:43:32 +0000 Tim-Philipp Müller + + * ChangeLog: + Update ChangeLogs for 1.19.3 + +2021-10-18 15:47:00 +0100 Tim-Philipp Müller + + * tests/check/meson.build: + meson: update for meson.build_root() and .build_source() deprecation + -> use meson.project_build_root() or .global_build_root() instead. + Part-of: + +2021-10-18 00:40:14 +0100 Tim-Philipp Müller + + * docs/meson.build: + * meson.build: + * tests/check/meson.build: + meson: update for dep.get_pkgconfig_variable() deprecation + ... in favour of dep.get_variable('foo', ..) which in some + cases allows for further cleanups in future since we can + extract variables from pkg-config dependencies as well as + internal dependencies using this mechanism. + Part-of: + +2021-10-14 18:38:26 +0100 Tim-Philipp Müller + + * meson.build: + meson: bump meson requirement to >= 0.59 + For monorepo build and ugly/bad, for advanced feature + option API like get_option('xyz').required(..) which + we use in combination with the 'gpl' option. + For rest of modules for consistency (people will likely + use newer features based on the top-level requirement). + Part-of: + +2021-09-28 10:11:15 +1000 Brad Hards + + * RELEASE: + doc: update IRC links to OFTC + Part-of: + +2021-09-26 01:07:02 +0100 Tim-Philipp Müller + + * meson.build: + Back to development + Part-of: + +=== release 1.19.2 === + +2021-09-23 01:36:02 +0100 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * gst-omx.doap: + * meson.build: + Release 1.19.2 + +2021-07-09 15:14:15 +0200 Guillaume Desmottes + + * omx/gstomxvideodec.c: + omxvideodec: fix OMX flags on header buffer + The header (SPS/PPS) buffer should have the CODECONFIG flag + Part-of: + +2021-07-09 14:52:59 +0200 Guillaume Desmottes + + * 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: + +2018-09-06 21:56:57 +0000 Nicolas Dufresne + + * 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: + +2021-06-01 15:29:18 +0100 Tim-Philipp Müller + + * meson.build: + Back to development + +=== release 1.19.1 === + +2021-06-01 00:16:41 +0100 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * gst-omx.doap: + * meson.build: + Release 1.19.1 + +2020-11-04 18:48:13 +0530 Nirbheek Chauhan + + * 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: + +2020-10-16 12:45:09 +0200 Stéphane Cerveau + + * 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: + +2020-10-05 12:32:10 +0200 Guillaume Desmottes + + * 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: + +2020-09-08 17:31:06 +0100 Tim-Philipp Müller + + * .gitlab-ci.yml: + ci: include template from gst-ci master branch again + +2020-09-08 16:59:09 +0100 Tim-Philipp Müller + + * meson.build: + Back to development + +=== release 1.18.0 === + +2020-09-08 00:10:02 +0100 Tim-Philipp Müller + + * .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 + + * 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 + + * ChangeLog: + * NEWS: + * RELEASE: + * gst-omx.doap: + * meson.build: + Release 1.17.90 + +2020-07-08 17:39:20 +0100 Tim-Philipp Müller + + * gst-omx.doap: + * meson.build: + * scripts/extract-release-date-from-doap-file.py: + meson: set release date from .doap file for releases + Part-of: + +2020-07-03 02:04:16 +0100 Tim-Philipp Müller + + * meson.build: + Back to development + +=== release 1.17.2 === + +2020-07-03 00:37:06 +0100 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * gst-omx.doap: + * meson.build: + Release 1.17.2 + +2020-06-20 00:28:37 +0100 Tim-Philipp Müller + + * meson.build: + Back to development + +=== release 1.17.1 === + +2020-06-19 19:27:38 +0100 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * gst-omx.doap: + * meson.build: + Release 1.17.1 + +2020-06-16 01:20:27 +0530 Nirbheek Chauhan + + * docs/gst_plugins_cache.json: + docs: Update plugin cache json + https://gitlab.freedesktop.org/alatiera/gst-ci/-/jobs/3109574 + Part-of: + +2020-06-03 22:24:09 -0400 Thibault Saunier + + * docs/gst_plugins_cache.json: + docs: Update documentation cache + +2019-12-23 18:23:55 -0800 Dylan Yip + + * 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 + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenc: factor out gst_omx_video_enc_allocate_out_buffers() + No semantic change. + Part-of: + +2020-04-10 11:47:03 +0200 Guillaume Desmottes + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: add support of alternate interlace mode on zynq + +2020-02-06 10:11:13 +0530 Guillaume Desmottes + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomx.c: + omx: remove useless double negations + flush and port->flushing are both gboolean. + +2019-12-20 22:19:06 -0800 Julien Isorce + + * 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 + + * omx/gstomxh265enc.c: + * omx/gstomxh265enc.h: + omxh265enc: handle CODECCONFIG buffers + Exact same code as omxh264enc. + +2019-05-16 10:38:49 +0200 Guillaume Desmottes + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenc: use subframe base class API + Use subframe base class support. + +2018-09-04 19:34:59 +0000 Nicolas Dufresne + + * omx/gstomx.c: + * omx/gstomx.h: + omx: Add helper to enable/disable/read subframe mode + +2019-12-19 13:51:17 +0530 Guillaume Desmottes + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * .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 + + * omx/gstomxallocator.c: + omxallocator: fix leak with a proper chaining finalize + +2019-09-20 15:02:24 +0530 Guillaume Desmottes + + * 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 + + * 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 + + * 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 + + * omx/gstomx.c: + omx: log the number of pending buffers when port is EOS + +2019-08-28 15:49:00 +0530 Guillaume Desmottes + + * omx/gstomx.c: + omx: log when an output port is eos + +2019-08-27 15:47:28 +0530 Guillaume Desmottes + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenc: Remove unnecessary gst_video_frame_unmap() + +2019-07-25 16:30:13 +0530 Guillaume Desmottes + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * RELEASE: + * configure.ac: + * meson.build: + Back to development + +=== release 1.16.0 === + +2019-04-19 00:38:44 +0100 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gst-omx.doap: + * meson.build: + Release 1.16.0 + +2019-04-16 12:23:10 -0700 Julien Isorce + + * 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 + + * 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 + + * examples/egl/testegl.c: + testelg: include eglext.h + Neded for the declaration of eglSaneChooseConfigBRCM(). + +2018-05-18 10:38:33 +0200 Guillaume Desmottes + + * 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 + + * 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 + + * meson.build: + meson: add -Wundef as additional warning flag + +2019-04-10 00:16:27 +0100 Tim-Philipp Müller + + * 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 + + * .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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * NEWS: + * RELEASE: + * configure.ac: + * meson.build: + Back to development + +=== release 1.15.2 === + +2019-02-26 12:02:23 +0000 Tim-Philipp Müller + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gst-omx.doap: + * meson.build: + Release 1.15.1 + +2018-02-20 10:57:42 -0800 Varunkumar Allagadapa + + * 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 + + * 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 + + * 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 + + * common: + Automatic update of common submodule + From ed78bee to 59cb678 + +2018-11-23 12:57:15 +0100 Guillaume Desmottes + + * 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 + + * .gitmodules: + * gst-omx.doap: + Update git locations to gitlab + +2018-09-18 16:50:11 +0200 Guillaume Desmottes + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * common: + Automatic update of common submodule + From 3fa2c9e to ed78bee + +2018-03-14 14:53:50 +0100 Guillaume Desmottes + + * 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 + + * 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 + + * 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 + + * NEWS: + * RELEASE: + * configure.ac: + * meson.build: + Back to development + +=== release 1.14.0 === + +2018-03-19 20:31:02 +0000 Tim-Philipp Müller + + * 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 + + * 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 + + * meson.build: + meson: fix typo in package name define + +2018-02-27 15:42:53 +0100 Guillaume Desmottes + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Fix CodecState leak + +=== release 1.13.90 === + +2018-03-03 23:00:59 +0000 Tim-Philipp Müller + + * 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 + + * config/Makefile.am: + config: dist tizonia config files + +2018-03-02 11:06:08 -0500 Nicolas Dufresne + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * configure.ac: + * meson.build: + Back to development + +=== release 1.13.1 === + +2018-02-15 17:50:14 +0000 Tim-Philipp Müller + + * Makefile.am: + * NEWS: + * configure.ac: + * gst-omx.doap: + * meson.build: + Release 1.13.1 + +2017-06-30 15:15:06 +0200 Guillaume Desmottes + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * common: + Automatic update of common submodule + From e8c7a71 to 3fa2c9e + +2017-12-13 12:06:40 +0000 Julien Isorce + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * common: + Automatic update of common submodule + From 3f4aa96 to e8c7a71 + +2017-11-23 15:03:48 +0100 Guillaume Desmottes + + * 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 + + * .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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * common: + Automatic update of common submodule + From 48a5d85 to 3f4aa96 + +2017-08-10 12:16:53 -0400 Guillaume Desmottes + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: fix file permissions + Introduced by ebc9b4903cbdac2793c24b05a1bb7acc3b67fae5 + +2017-06-29 23:17:26 +0100 Julien Isorce + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * .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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + Signed-off-by: Julien Isorce + +2017-05-16 14:39:04 -0400 Nicolas Dufresne + + * 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 + + * 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 + + * 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 + + * 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 + + * configure.ac: + * meson.build: + Back to development + +=== release 1.12.0 === + +2017-05-04 15:48:56 +0300 Sebastian Dröge + + * 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 + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gst-omx.doap: + * meson.build: + Release 1.11.91 + +2017-04-17 17:02:48 +0200 Guillaume Desmottes + + * 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 + + * common: + Automatic update of common submodule + From 60aeef6 to 48a5d85 + +2017-04-10 23:51:00 +0100 Tim-Philipp Müller + + * 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 + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gst-omx.doap: + * meson.build: + Release 1.11.90 + +2017-04-07 14:27:23 +0300 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenc: Add a mapping for OMX_COLOR_FormatYUV420PackedSemiPlanar + The RaspberryPi + +2017-03-14 02:40:24 +1100 Jan Schmidt + + * 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 + + * 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 + + * meson.build: + meson: Update version + +2017-02-24 15:38:17 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.11.2 === + +2017-02-24 15:10:17 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gst-omx.doap: + Release 1.11.2 + +2017-02-15 18:22:53 +0000 Tim-Philipp Müller + + * 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 + + * 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 + + * 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 + + * examples/egl/testegl.c: + examples/testegl: update for libgstgl changes + +2017-01-12 16:33:09 +0200 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.11.1 === + +2017-01-12 16:26:55 +0200 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * gst-omx.doap: + Release 1.11.1 + +2017-01-10 15:29:08 +0000 Vincent Penquerc'h + + * omx/gstomxaudioenc.c: + omxaudioenc: set base class format instead of just source pad caps + +2016-12-18 19:46:55 +0000 Graham Leggett + + * 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 + + * omx/gstomx.c: + Fix broken build due to syntax error + Problem was introduced by 8716c23e2b0553db2982eb84c437f493c974385e + +2016-12-12 11:12:48 +0000 Graham Leggett + + * 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 + + * 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 + + * 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 + + * 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 + + * common: + Automatic update of common submodule + From ac2f647 to 39ac2f5 + +2016-11-26 11:27:58 +0000 Tim-Philipp Müller + + * .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 + + * 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 + + * 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 + + * configure.ac: + Back to development + +=== release 1.10.0 === + +2016-11-01 18:20:48 +0200 Sebastian Dröge + + * 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 + + * ChangeLog: + * NEWS: + * RELEASE: + * common: + * configure.ac: + * gst-omx.doap: + Release 1.9.90 + +2016-09-14 11:33:13 +0200 Sebastian Dröge + + * configure.ac: + configure: Depend on gstreamer 1.9.2.1 + +2016-09-12 14:09:46 +0200 Sebastian Dröge + + * 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 + + * autogen.sh: + * common: + Automatic update of common submodule + From b18d820 to f980fd9 + +2016-09-10 09:58:16 +1000 Jan Schmidt + + * autogen.sh: + * common: + Automatic update of common submodule + From ac2f647 to b18d820 + +2016-09-01 12:36:09 +0300 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.9.2 === + +2016-09-01 12:35:58 +0300 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * common: + * configure.ac: + * gst-omx.doap: + Release 1.9.2 + +2016-07-11 21:15:48 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From ac2f647 to f49c55e + +2016-07-06 13:51:24 +0300 Sebastian Dröge + + * configure.ac: + Back to development + +=== release 1.9.1 === + +2016-07-06 13:48:45 +0300 Sebastian Dröge + + * ChangeLog: + * NEWS: + * RELEASE: + * common: + * configure.ac: + * gst-omx.doap: + Release 1.9.1 + +2016-06-29 16:37:43 +0900 Kazunori Kobayashi + + * 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 + + * common: + Automatic update of common submodule + From ac2f647 to f363b32 + +2016-06-21 11:43:13 +0200 Aurélien Zanelli + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * common: + Automatic update of common submodule + From 6f2d209 to ac2f647 + +2016-02-26 12:42:41 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From b64f03f to 6f2d209 + +2016-02-17 20:51:03 +1100 Matthew Waters + + * 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 + + * autogen.sh: + * common: + Automatic update of common submodule + From 86e4663 to b64f03f + +2015-12-21 00:43:49 +0100 Koop Mast + + * 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 + + * autogen.sh: + * common: + Automatic update of common submodule + From b319909 to 86e4663 + +2015-11-18 13:00:28 +0000 Enrique Ocaña González + + * 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 + + * 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 + + * omx/gstomx.c: + omx: fix hacks leak on class init + +2015-10-21 14:37:13 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From b99800a to b319909 + +2015-10-21 14:28:41 +0300 Sebastian Dröge + + * common: + Automatic update of common submodule + From 9aed1d7 to b99800a + +2015-09-01 16:08:11 -0300 Thiago Santos + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * common: + Automatic update of common submodule + From f74b2df to 9aed1d7 + +2015-06-16 17:50:14 -0400 Nicolas Dufresne + + * common: + Automatic update of common submodule + From 6015d26 to f74b2df + +2015-06-09 11:30:49 +0200 Edward Hervey + + * common: + Automatic update of common submodule + From d9a3353 to 6015d26 + +2015-06-08 23:08:28 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From d37af32 to d9a3353 + +2015-06-07 23:07:22 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From 21ba2e5 to d37af32 + +2015-06-07 17:32:25 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From c408583 to 21ba2e5 + +2015-06-07 17:16:43 +0200 Stefan Sauer + + * autogen.sh: + * common: + Automatic update of common submodule + From c8fb372 to c408583 + +2015-05-19 18:21:40 +0300 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * .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 + + * INSTALL: + * autogen.sh: + Update autogen.sh to latest version + +2015-04-03 18:58:17 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From bc76a8b to c8fb372 + +2015-03-06 12:12:49 +0000 Luis de Bethencourt + + * omx/gstomxaacdec.c: + omxaudiodec: add comment explaining duplicate code path + +2015-03-06 12:09:06 +0000 Luis de Bethencourt + + * omx/gstomxaacdec.c: + Revert "omxaudiodec: remove duplicate code path" + This reverts commit a8d26ff27a8b43f589424a59294f9057641b2a46. + +2015-03-06 12:03:56 +0000 Luis de Bethencourt + + * 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 + + * 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 + + * 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 + + * omx/gstomxaacdec.c: + omxaudiodec: remove duplicate code path + +2014-12-19 11:19:55 +0200 George Kiagiadakis + + * 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 + + * 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 + + * common: + Automatic update of common submodule + From f2c6b95 to bc76a8b + +2014-12-18 10:56:15 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From ef1ffdc to f2c6b95 + +2014-11-27 17:12:42 +0100 Edward Hervey + + * common: + Automatic update of common submodule + From 7bb2bce to ef1ffdc + +2014-11-13 09:55:02 +0900 Jun Ji + + * 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 + + * common: + Automatic update of common submodule + From 84d06cd to 7bb2bce + +2014-10-21 13:03:44 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From a8c8939 to 84d06cd + +2014-10-21 13:00:10 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From 1f5d3c3 to a8c8939 + +2014-09-30 10:47:20 +0300 Sebastian Dröge + + * omx/gstomxaudiodec.c: + omxaudiodec: Clean up code a bit to get rid of useless NULL checks + +2014-09-30 10:50:07 +0900 junji + + * 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 + + * 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 + + * omx/gstomxaudioenc.c: + omxaudioenc: Implement the hack flag GST_OMX_HACK_NO_COMPONENT_RECONFIGURE + +2014-08-28 10:43:22 +0300 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * examples/egl/testegl.c: + examples: #define GST_USE_UNSTABLE_API for libgstgl + +2014-06-29 19:10:19 +0200 Sebastian Dröge + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenc: Implement flush() instead of the deprecated reset() + +2014-06-25 17:14:18 +0200 Sebastian Dröge + + * config/rpi/gstomx.conf: + rpi: It's 44100Hz, not 41400Hz + +2014-06-25 11:12:51 +0100 Julien Isorce + + * configure.ac: + configure.ac: require gstgl >= 1.3.3 + +2014-04-25 13:25:05 +0100 Julien Isorce + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxbufferpool.c: + omxbufferpool: Fix format string compiler warning + +2014-06-22 21:11:45 +0000 Michal Lazo + + * omx/gstomxbufferpool.c: + omxbufferpool: Initialize debug category + +2014-06-24 12:42:22 +0200 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomxvideo.h: + omxvideo: Include the separate headers too for compatibility with 1.0.x + +2014-03-24 16:09:40 +0800 Zhao, Halley + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: add missing stream unlock in error path + +2014-05-31 15:12:05 +0200 Sebastian Dröge + + * 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 + + * 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 + + * common: + Automatic update of common submodule + From 211fa5f to 1f5d3c3 + +2014-05-19 09:10:07 +0200 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: Don't forget to unref codec state + CID 1214603 + +2014-05-19 09:08:33 +0200 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Make output buffer pointer always initialized + CID 1214605 + +2014-05-19 09:06:42 +0200 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Check return value of gst_buffer_map() + CID 1214599 + +2014-05-19 09:04:09 +0200 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxaudioenc.c: + omxaudioenc: Correctly scale nTickCount by OMX_TICKS_PER_SECOND + +2014-05-10 22:48:23 +0200 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * omx/gstomxaudiosink.c: + omxaudiosink: Fix format string compiler warnings + +2014-04-04 14:11:58 +0200 Josep Torra + + * 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 + + * common: + Automatic update of common submodule + From bcb1518 to 211fa5f + +2014-04-29 15:16:16 +0100 Julien Isorce + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: simplify color format conversion in fill_buffer function + +2014-04-09 18:51:41 +0200 Aurélien Zanelli + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: add missing unlock in the error path + Signed-off-by: Christian König + https://bugzilla.gnome.org/show_bug.cgi?id=726958 + +2014-03-18 23:36:59 +0100 Michal Lazo + + * omx/gstomxh264enc.c: + * omx/gstomxh264enc.h: + fix filemode + +2014-03-17 09:57:11 +0000 Julien Isorce + + * 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 + + * omx/gstomxh264enc.c: + omxh264enc: Fix compiler warnings + +2014-03-16 17:19:08 +0100 Michal Lazo + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideo.c: + omx: Copy old copyright notice into the new file + +2014-03-12 12:47:34 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * omx/gstomxbufferpool.h: + omxbufferpool: Fix header include guard + +2014-03-05 11:41:02 +0100 Christian König + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + +2014-03-01 18:48:17 +0100 Christian König + + * 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 + +2014-02-28 09:36:13 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From fe1672e to bcb1518 + +2014-02-26 22:15:00 +0100 Stefan Sauer + + * common: + Automatic update of common submodule + From 1a07da9 to fe1672e + +2014-01-30 10:45:18 +0100 Edward Hervey + + * common: + Automatic update of common submodule + From d48bed3 to 1a07da9 + +2014-01-25 17:44:14 +0100 Sebastian Dröge + + * 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 + + * common: + Automatic update of common submodule + From dbedaa0 to d48bed3 + +2013-11-05 11:22:02 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 865aa20 to dbedaa0 + +2013-09-28 13:32:37 +0200 Josep Torra + + * 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 + + * 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 + + * common: + Automatic update of common submodule + From 6b03ba7 to 865aa20 + +2013-09-24 18:48:24 +0200 Josep Torra + + * 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 + + * config/rpi/gstomx.conf: + rpi: fix a copy paste error in the config file + +2013-09-20 17:09:52 +0200 Josep Torra + + * 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 + + * examples/egl/testegl.c: + examples: display QoS statistics + +2013-09-20 09:34:37 +0200 Josep Torra + + * 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 + + * 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 + + * examples/egl/Makefile.am: + examples: drop remnants of initial appsink attempt + +2013-09-20 16:18:18 +0200 Edward Hervey + + * common: + Automatic update of common submodule + From b613661 to 6b03ba7 + +2013-09-19 18:45:36 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 74a6857 to b613661 + +2013-09-19 17:38:30 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 01a7a46 to 74a6857 + +2013-08-20 16:00:07 +0100 Tim-Philipp Müller + + * 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 + + * 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 + + * examples/egl/testegl.c: + examples: enable audio in testegl example + +2013-06-12 09:38:22 +0200 Sebastian Dröge + + * configure.ac: + configure: Allow build without gstreamer-egl + +2013-06-07 12:39:18 +0700 Ilya Smelykh + + * 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 + + * common: + Automatic update of common submodule + From 098c0d7 to 01a7a46 + +2013-05-20 12:06:34 +0200 Josep Torra + + * 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 + + * common: + Automatic update of common submodule + From 5edcd85 to 098c0d7 + +2013-04-11 17:35:19 +0200 Josep Torra + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * common: + Automatic update of common submodule + From 3cb3d3c to 5edcd85 + +2013-04-18 22:07:28 +0000 Tim-Philipp Müller + + * 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 + + * omx/gstomx.c: + omx: fixes unused variable 'comp' when GStreamer is built without debug + +2013-04-18 16:03:56 +0200 Josep Torra + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: fixes 'port' may be used uninitialized in this function + +2013-04-18 12:03:31 +0200 Josep Torra + + * omx/gstomxvideodec.c: + omxvideodec: silence warnings building for RPI related to 'vcos_*' + +2013-04-18 11:19:52 +0200 Josep Torra + + * omx/gstomxvideodec.c: + omxvideodec: Use new type from libgstvideo + +2013-04-16 14:50:49 +0530 jitendra + + * 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 + + * configure.ac: + gst: Add better support for static plugins + +2013-04-14 17:57:34 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From aed87ae to 3cb3d3c + +2013-04-12 17:58:30 +0100 Tim-Philipp Müller + + * configure.ac: + configure: add --disable-fatal-warnings for disabling -Werror + +2013-04-09 21:02:09 +0200 Stefan Sauer + + * common: + Automatic update of common submodule + From 04c7a1e to aed87ae + +2013-04-08 17:02:32 +0100 Tim-Philipp Müller + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: use the correct printf format in a debug message + +2013-04-08 16:31:33 +0200 Josep Torra + + * 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 + + * 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 + + * 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 + + * configure.ac: + Back to development + +2013-03-22 19:23:14 +0000 Tim-Philipp Müller + + * 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 + + * 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 + + * omx/gstomxtheoradec.h: + * omx/gstomxvp8dec.h: + omx: fix typo in copyright headers + +2013-03-19 13:46:33 +0100 Sebastian Dröge + + * config/rpi/gstomx.conf: + rpi: Fix commit that added the VC1 decoder + +2013-03-19 13:27:35 +0100 Sebastian Dröge + + * 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 + + * 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 + + * config/rpi/gstomx.conf: + rpi: Add MJPEG decoder + +2013-03-19 12:56:50 +0100 Sebastian Dröge + + * config/rpi/gstomx.conf: + rpi: Add VP8 decoder + +2013-03-19 12:55:09 +0100 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Set ENDOFFRAME flag for the end of frames + +2013-03-19 12:28:50 +0100 Sebastian Dröge + + * config/rpi/gstomx.conf: + rpi: Add Theora decoder to the config + +2013-03-19 09:36:18 +0100 Sebastian Dröge + + * 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 + + * omx/gstomx.c: + omx: Remove additional comma + +2013-03-18 16:34:21 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomx.c: + omx: minor stylistic change for consistency with other similar code + +2013-03-16 10:00:24 +0100 Josep Torra + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenec: Don't forget propagate flow return value upstream + +2013-03-15 13:16:39 +0000 Tim-Philipp Müller + + * omx/gstomx.c: + omx: improve debug logging some more + +2013-03-15 14:09:45 +0100 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomx.c: + omx: Reset EOS flag in more places + +2013-03-15 10:38:43 +0100 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Deallocate output buffers with the right function + +2013-03-15 01:06:05 +0000 Tim-Philipp Müller + + * 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 + + * omx/gstomx.c: + * omx/gstomx.h: + omx: log states as strings + +2013-03-15 00:28:02 +0000 Tim-Philipp Müller + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomx.c: + omx: Reset some more buffer fields as required + +2013-03-14 17:01:08 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Simplify bufferpool implementation + +2013-03-13 13:23:35 +0100 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Improve min/max buffer counts handling + +2013-03-14 12:49:42 +0100 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenc: Properly check the nVersion field + +2013-03-13 09:34:43 +0100 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: RPi returns garbage for OMX_IndexParamVideoBitrate, work around that + +2013-03-12 20:02:53 +0100 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Make sure to always get the right buffer + +2013-03-12 19:35:39 +0100 Sebastian Dröge + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Drop too late frames instead of finishing them + +2013-03-12 19:16:46 +0100 Sebastian Dröge + + * omx/gstomxvideodec.c: + omx: Release buffers to the correct port + +2013-03-13 09:37:02 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenc: Always allocate output buffers from the loop function + +2013-03-11 13:12:57 +0100 Sebastian Dröge + + * omx/gstomxh264enc.c: + omxh264enc: The h264 encoders are supposed to output byte-stream/au + +2013-03-11 11:47:42 +0100 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomxaudioenc.c: + omxaudioenc: Disable output port when setting a new format + +2013-03-11 10:29:30 +0100 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: Disable output port when setting a new format + +2013-03-11 10:22:07 +0100 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Disable output port when setting a new format + Based on a patch by Josep Torra + +2013-03-11 10:04:10 +0100 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenc: Store correct input state + +2013-03-10 11:27:34 +0100 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: Allocate output buffers as early as possible + +2013-03-10 11:01:57 +0100 Sebastian Dröge + + * omx/gstomx.c: + omx: Log unknown events + +2013-03-09 14:14:40 +0100 Josep Torra + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: fix printf format identifier + +2013-03-09 13:07:59 +0100 Josep Torra + + * omx/gstomxvideodec.c: + omx: Minor changes on debuging info + +2013-03-09 13:00:33 +0100 Josep Torra + + * omx/gstomxvideodec.c: + omxvideodec: avoid a deadlock + +2013-03-08 15:56:40 +0100 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Don't forget to populate output port + +2013-03-08 15:11:27 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomx.c: + omx: Also wait for disabled output ports to be reconfigured + +2013-03-07 14:10:12 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: fixes reconfiguration + Avoid having fixed fields from previous caps on reconfiguration. + +2013-03-07 11:02:39 +0100 Josep Torra + + * 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 + + * common: + Automatic update of common submodule + From 2de221c to 04c7a1e + +2013-03-01 15:32:47 +0100 Josep Torra + + * omx/gstomxvideoenc.h: + omxvideoenc: drop unused data member + +2013-03-01 12:23:54 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomx.c: + * omx/gstomx.h: + omx: Handle errors more gracefully + +2013-02-28 15:48:53 +0100 Sebastian Dröge + + * 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 + + * omx/gstomx.c: + omx: Return port definition update errors + +2013-02-28 13:57:43 +0100 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomx.c: + omx: Invert assertion to let it express what was intended + +2013-02-28 11:19:07 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: initialize param structure before using it + +2013-02-27 10:21:39 +0100 Josep Torra + + * omx/gstomxvideoenc.c: + omxvideoenc: prevent a NULL pointer access + +2013-02-26 17:25:49 +0100 Josep Torra + + * omx/gstomxvideodec.c: + omxvideodec: prevent a NULL pointer access + +2013-02-25 13:11:16 +0100 Sebastian Dröge + + * omx/gstomx.c: + omx: Fix deadlock during reconfiguration + +2013-02-25 12:38:27 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxaacenc.c: + * omx/gstomxaudioenc.c: + * omx/gstomxaudioenc.h: + omxaudioenc: Rename component variable + +2013-02-25 09:15:46 +0100 Sebastian Dröge + + * 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 + + * omx/gstomxvideodec.c: + * omx/gstomxvideodec.h: + omxvideodec: Rename component variable + +2013-02-22 16:27:33 +0100 Josep Torra + + * omx/gstomxvideoenc.c: + omxvideoenc: remove duplicated line + +2013-02-22 10:42:08 +0100 Sebastian Dröge + + * 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 + + * config/bellagio/Makefile.am: + Add missing file from last commit + +2013-02-21 11:01:28 +0100 Sebastian Dröge + + * 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 + + * configure.ac: + * omx/Makefile.am: + Allow using external OpenMAX IL headers + +2013-02-21 10:14:12 +0100 Sebastian Dröge + + * .gitignore: + Update .gitignore + +2013-02-21 10:13:16 +0100 Sebastian Dröge + + * 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 + + * 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 + + * configure.ac: + Add configure parameter for setting the OpenMAX IL target + +2013-02-12 11:55:39 +0100 Sebastian Dröge + + * omx/gstomx.c: + omx: Add FIXME for the future + +2013-02-12 11:49:21 +0100 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomx.c: + omx: Mark an array as const + +2013-02-12 11:41:43 +0100 Sebastian Dröge + + * 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 + + * omx/gstomx.c: + omx: Flushing is also allowed in Paused state + +2013-02-12 11:28:36 +0100 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: Set stride, slice height and buffer size + +2013-02-12 11:09:30 +0100 Sebastian Dröge + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenc: Properly negotiate OMX color format with the component + +2013-02-12 10:53:24 +0100 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: Implement getcaps() vfunc + +2013-01-29 21:32:53 +0000 Tim-Philipp Müller + + * 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 + + * common: + Automatic update of common submodule + From a942293 to 2de221c + +2013-01-24 14:02:36 +0100 Julian Scheel + + * 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 + +2013-01-18 16:47:04 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * common: + Automatic update of common submodule + From a72faea to a942293 + +2013-01-15 14:34:45 +0100 Sebastian Dröge + + * omx/gstomx.c: + omx: Update port definition when changing some port setting + +2013-01-14 11:41:57 +0100 Sebastian Dröge + + * 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 + + * omx/gstomx.c: + omx: Add a method to send message + +2013-01-11 15:44:38 +0100 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenc: Don't forget to unmap frame in error cases + +2013-01-11 12:29:20 +0100 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: Fix copying of the video frames to the OMX buffers + +2013-01-11 12:24:13 +0100 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Fix copying of the video frames from the OMX buffers + +2013-01-10 14:44:33 +0100 Sebastian Dröge + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Set the OMX buffer nFilledLength field properly + +2012-12-20 18:48:21 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxaudioenc.c: + * omx/gstomxvideodec.c: + * omx/gstomxvideoenc.c: + omx: Improve debug output + +2012-12-20 12:02:30 +0100 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Don't forget to free a GList + +2012-12-20 11:56:29 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomx.h: + omx: Also initialize nStep field of the OMX structures + +2012-12-19 13:03:37 +0100 Sebastian Dröge + + * omx/gstomx.h: + omx: Initialize struct version with the OMX version we compiled with + +2012-12-19 12:44:31 +0100 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Extract data from the input buffer, not the codec data + +2012-12-19 12:19:12 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + +2012-12-19 11:22:16 +0100 Sebastian Dröge + + * 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 + + * configure.ac: + configure: Require GStreamer 1.0.0 + +2012-04-20 17:13:52 +0300 George Kiagiadakis + + * omx/gstomx.h: + omx: Initialize structures to version 1.1.2 + +2012-12-19 09:51:22 +0000 Sebastian Dröge + + * 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 + + * omx/gstomx-raspberry.conf: + raspberry: Add a gstomx.conf for the Raspberry Pi + +2012-12-12 17:45:39 +0000 Sebastian Dröge + + * 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 + + * common: + Automatic update of common submodule + From 6bb6951 to a72faea + +2012-11-12 15:14:09 +0100 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + * omx/gstomxvideoenc.c: + omx: Use open/close vfuncs + +2012-10-22 14:28:04 +0200 Sebastian Dröge + + * omx/gstomxvideodec.c: + * omx/gstomxvideoenc.c: + omx: Handle video meta correctly + +2012-06-20 13:11:58 +0100 Sebastian Dröge + + * 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 + + * 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 + + * common: + Automatic update of common submodule + From 6c0b52c to 6bb6951 + +2012-09-22 16:10:38 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 4f962f7 to 6c0b52c + +2012-06-21 20:22:13 +0300 George Kiagiadakis + + * omx/gstomx.c: + omx: fix debug statement + +2012-06-21 20:21:03 +0300 George Kiagiadakis + + * 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 + + * common: + Automatic update of common submodule + From 668acee to 4f962f7 + +2012-08-05 16:42:43 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 94ccf4c to 668acee + +2012-08-03 19:32:13 +0100 Tim-Philipp Müller + + * omx/gstomx.c: + omx: fix plugin name for new GST_PLUGIN_DEFINE API + +2012-07-23 08:47:32 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 98e386f to 94ccf4c + +2012-07-10 09:57:09 +0200 Sebastian Dröge + + * omx/gstbasevideodecoder.c: + omx: Update for allocation query API changes + +2012-06-20 11:09:13 +0100 Sebastian Dröge + + * 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 + + * common: + Automatic update of common submodule + From 03a0e57 to 98e386f + +2012-06-06 18:20:18 +0200 Edward Hervey + + * common: + Automatic update of common submodule + From 1fab359 to 03a0e57 + +2012-06-01 10:30:27 +0200 Edward Hervey + + * common: + Automatic update of common submodule + From f1b5a96 to 1fab359 + +2012-05-31 13:10:33 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 92b7266 to f1b5a96 + +2012-05-30 12:47:59 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From ec1c4a8 to 92b7266 + +2012-05-30 11:26:30 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 3429ba6 to ec1c4a8 + +2012-05-13 15:58:10 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From dc70203 to 3429ba6 + +2012-05-08 16:13:32 +0300 George Kiagiadakis + + * omx/gstomx.c: + omx: Fix spelling mistake found by lintian: s/Seperate/Separate/ + +2012-04-30 23:58:43 +0300 George Kiagiadakis + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Fix coding style in the drain-may-not-return hack code + +2012-04-25 19:03:48 +0530 Arun Raghavan + + * omx/gstomx.c: + omx: Fix trivial debug print bug + +2012-04-25 19:01:32 +0530 Arun Raghavan + + * 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 + + * 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 + + * 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 + + * 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 + + * common: + Automatic update of common submodule + +2012-04-16 08:34:56 +0200 Sebastian Dröge + + * 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 + + * omx/Makefile.am: + Fix relative/absolute path glitch + Signed-off-by: Reynaldo H. Verdejo Pinochet + +2012-04-12 15:57:32 -0400 Olivier Crête + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenc: Fix deadlock when using the EOS hack + +2011-12-12 14:26:48 +0100 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: Remove workaround for basevideocodec bug + +2011-12-12 14:26:34 +0100 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Remove workaround for basevideocodec bug + +2011-12-05 17:57:01 +0000 Matej Knopp + + * 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 + + * 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 + + * omx/gstomxaacenc.c: + omxaacenc: Generate and set codec_data on the caps for raw AAC + +2011-10-31 11:36:06 +0100 Alessandro Decina + + * omx/gstbasevideoencoder.c: + basevideoencoder: handle failures in start() and stop() + +2011-08-26 10:50:38 +0100 Vincent Penquerc'h + + * 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 + + * omx/gstbasevideoencoder.c: + basevideoencoder: Only make the header buffer metadata writable, not the buffer + +2011-12-08 10:18:36 +0100 Sebastian Dröge + + * omx/gstbasevideoencoder.c: + basevideoencoder: Fix handling of force-keyunit events + +2011-12-06 13:28:41 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomx.c: + omx: Improve debugging of buffer handling + +2011-12-05 08:12:48 +0100 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomxh264enc.c: + omxh264enc: Add support for resending headers after a forced-keyframe + +2011-11-29 12:12:33 +0100 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstbasevideoencoder.c: + basevideoencoder: Use new force-keyunit event API from gst-plugins-base + +2011-11-29 09:18:19 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstbasevideodecoder.c: + basevideodecoder: some more debug logging + +2011-11-23 20:03:32 +0000 Tim-Philipp Müller + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxaudioenc.c: + omxaudioenc: Signal the drain GCond even if downstream returned an error + +2011-11-17 11:26:20 -0800 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: Signal the drain GCond even if downstream returned an error + +2011-11-17 11:25:52 -0800 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Signal the drain GCond even if downstream returned an error + +2011-11-17 10:34:19 -0800 Sebastian Dröge + + * omx/gstbasevideoencoder.c: + basevideoencoder: Only call ::reset once in READY->PAUSED + +2011-11-17 10:19:35 -0800 Sebastian Dröge + + * omx/gstomxaudioenc.c: + omxaudioenc: Shutdown component in PAUSED->READY and deallocate buffers + +2011-11-17 10:19:30 -0800 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: Shutdown component in PAUSED->READY and deallocate buffers + +2011-11-17 10:19:10 -0800 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Shutdown component in PAUSED->READY and deallocate buffers + +2011-11-16 12:02:08 -0800 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Don't release buffers twice if dropping because of QoS + +2011-11-14 09:13:06 -0800 Sebastian Dröge + + * omx/gstomx.c: + omx: Add XXX to the nOffset reset hack comment for QCOM + +2011-11-10 15:18:08 +0100 Sebastian Dröge + + * omx/gstomxaudioenc.c: + omxaudioenc: Make srcpad caps setting threadsafe + +2011-11-10 15:17:56 +0100 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: Make srcpad caps setting threadsafe + +2011-11-10 15:17:41 +0100 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Make srcpad caps setting threadsafe + +2011-11-10 15:10:14 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenc: Fix minor race condition when draining after upstream signalled EOS + +2011-11-10 14:56:19 +0100 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomxaudioenc.c: + omxaudioenc: Improve debugging of EOS and draining + +2011-11-10 14:54:17 +0100 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: Improve debugging of EOS and draining + +2011-11-10 14:51:06 +0100 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Log if acquiring buffer for EOS failed + +2011-11-10 14:42:13 +0100 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: The component is not started in READY + +2011-11-10 14:39:40 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Fix minor race condition when draining after upstream signalled EOS + +2011-11-09 15:44:11 +0100 Sebastian Dröge + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Improve debugging of EOS and draining + +2011-11-09 15:42:46 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Improve debugging in case of QoS-related frame drops + +2011-11-08 12:46:31 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Implement dropping of too late frames via QoS + +2011-11-08 08:31:58 +0100 Sebastian Dröge + + * omx/gstomxaudioenc.c: + omxaudioenc: Minor code refactoring + +2011-11-08 08:31:43 +0100 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: Minor code refactoring + +2011-11-08 08:31:32 +0100 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Make sure to always release buffers back to OMX + +2011-11-08 08:24:19 +0100 Sebastian Dröge + + * omx/gstomx.c: + omx: Also properly release buffers when in error state + +2011-11-08 08:22:08 +0100 Jonas Larsson + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Free pending frames after draining component + +2011-11-07 14:00:35 +0100 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: Free pending frames after draining the component + +2011-11-07 11:07:01 +0100 Sebastian Dröge + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenc: Fix deadlock between srcpad stream lock and ::reset() + +2011-11-07 11:04:27 +0100 Sebastian Dröge + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenc: Free all pending frames after draining the component + +2011-11-07 10:58:24 +0100 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Always free all pending frames when caps changes require reconfiguration + +2011-11-04 09:43:48 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenc: Make unsupported bitrate/quantizer settings less fatal + +2011-11-02 10:39:50 +0100 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenc: Forward downstream flow returns to upstream + +2011-11-01 13:58:38 +0100 Sebastian Dröge + + * omx/gstomxvideodec.c: + * omx/gstomxvideodec.h: + omxvideodec: Forward downstream flow returns to upstream + +2011-10-25 14:23:38 +0200 Sebastian Dröge + + * README: + omx: Add minimal README file + +2011-10-20 15:21:07 +0200 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Move locking at the correct place + +2011-10-14 10:27:47 +0200 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomx.c: + omx: Change a g_assert() into a GST_WARNING_OBJECT() + +2011-09-26 13:04:18 +0200 Sebastian Dröge + + * 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 + + * omx/gstomxaudioenc.c: + omxaudioenc: Add a check to prevent a zero-sized OMX buffer + +2011-09-23 17:02:19 +0200 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: Add some more checks for correct OMX buffer sizes + +2011-09-23 15:53:49 +0200 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Add some more checks for OMX buffer sizes + +2011-09-14 10:15:38 +0200 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstbasevideodecoder.c: + basevideodecoder: Fix deadlock + +2011-08-18 10:03:20 +0200 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstbaseaudiodecoder.c: + baseaudiodecoder: Delay sending of serialized events to finish_frame() + +2011-08-17 14:33:31 +0200 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomxaudioenc.c: + omxaudioenc: Handle inbuf==NULL properly in ::handle_frame() + +2011-08-17 13:04:19 +0200 Sebastian Dröge + + * omx/gstomxaacenc.c: + omxaacenc: Implement ::get_num_samples() vfunc + +2011-08-17 13:03:50 +0200 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * omx/gstbaseaudioencoder.c: + baseaudioencoder: Taking the OBJECT lock in reset() is not needed + +2011-08-16 11:03:24 +0200 Sebastian Dröge + + * omx/gstomxaudioenc.c: + omxaudioenc: Remove hack that only applies to the video encoder class + +2011-08-16 10:49:21 +0200 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstbaseaudioencoder.c: + baseaudioencoder: Delay sending of serialized events to finish_frame() + +2011-08-15 13:06:51 +0200 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * omx/gstbasevideoencoder.h: + basevideoencoder: Remove old ::getcaps() comment + +2011-08-12 12:06:23 +0200 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomxmpeg4videodec.c: + omxmpeg4videodec: Don't require width/height on sink pad caps + +2011-08-10 10:11:37 +0200 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * omx/gstomx.c: + omx: Move some code + +2011-08-10 09:23:10 +0200 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomx.c: + omx: Free component structure + +2011-08-10 09:02:52 +0200 Sebastian Dröge + + * omx/gstomx.c: + omx: Make component destruction safer + +2011-08-10 08:53:05 +0200 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * omx/gstomx.h: + omx: Add parenthesis at correct places in the struct init macro + +2011-08-08 12:12:58 +0200 Sebastian Dröge + + * 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 + + * omx/gstbasevideodecoder.c: + basevideodecoder: Use the cached video frame size instead of recalculating it + +2011-08-03 15:35:01 +0200 Sebastian Dröge + + * omx/gstomx.c: + omx: Improve debugging in param/config getter/setter wrappers + +2011-08-03 13:10:33 +0200 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstbasevideoencoder.c: + basevideoencoder: Make access to the list of frames threadsafe + +2011-08-01 13:22:05 +0200 Sebastian Dröge + + * 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 + + * omx/gstomx.c: + omx: Add workaround for QCOM 7x30 race condition + +2011-07-29 12:06:21 +0200 Sebastian Dröge + + * 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 + + * omx/gstomxmpeg4videoenc.c: + omxmpeg4videoenc: Add support for setting profile/level via caps + +2011-07-28 14:14:45 +0200 Sebastian Dröge + + * omx/gstomxh264enc.c: + omxh264enc: Add support for setting profile/level via caps + +2011-07-28 12:58:25 +0200 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * omx/gstomx.c: + * omx/gstomx.h: + omx: Add macro to initialize OpenMAX structures + +2011-07-28 09:08:38 +0200 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: Don't output 0-byte buffers + +2011-07-25 15:05:08 +0200 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Try harder to deallocate the buffers after errors happened + +2011-07-25 10:47:28 +0200 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: Try harder to deallocate the buffers after errors happened + +2011-07-25 10:46:49 +0200 Sebastian Dröge + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenc: Add initial support for stride conversion + +2011-07-21 10:38:26 +0200 Sebastian Dröge + + * 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 + + * omx/gstomx.c: + omx: Failure to set the component role is fatal + +2011-07-21 07:53:25 +0200 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: Add support for setting codec_data on the srcpad caps + +2011-07-21 07:44:34 +0200 Sebastian Dröge + + * omx/gstomxvideoenc.c: + omxvideoenc: Free/drop GstVideoFrames that resulted in an empty buffer + +2011-07-21 07:44:10 +0200 Sebastian Dröge + + * 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 + + * omx/gstomxvideoenc.c: + omxvideoenc: Remove obsolete TODO comment + +2011-07-20 11:09:54 +0200 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomx.c: + * omx/gstomxvideodec.c: + omx: Improve debug output a bit + +2011-07-19 10:33:54 +0200 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Add support for converting between omx and gst rowstrides + +2011-07-14 10:34:09 +0200 Sebastian Dröge + + * omx/gstomx.c: + omx: Provide all buffers to output ports after enabling them + +2011-07-14 08:29:03 +0200 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Add support for NV12 / OMX_COLOR_FormatYUV420SemiPlanar + +2011-07-14 07:58:41 +0200 Sebastian Dröge + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Only change states downwards if an upper state was reached + +2011-07-13 20:37:02 +0200 Sebastian Dröge + + * 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 + + * 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 + + * Makefile.am: + build: Dist autogen.sh + +2011-07-13 14:35:51 +0200 Sebastian Dröge + + * 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 + + * omx/Makefile.am: + build: Dist gstomx.conf + +2011-07-13 14:04:20 +0200 Sebastian Dröge + + * Makefile.am: + build: Clean _stdint.h on "make distclean" + +2011-07-13 14:02:50 +0200 Sebastian Dröge + + * omx/gstomxvideodec.c: + omxvideodec: Fix typo + +2011-07-13 13:59:50 +0200 Sebastian Dröge + + * omx/Makefile.am: + omx: Dist gstomx.h + +2011-07-13 12:46:50 +0200 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxh264dec.c: + omxh264dec: It's called H.264, not H264 + +2011-07-12 11:36:42 +0200 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * omx/gstomxh264videodec.c: + omxh264videodec: Require alignment=au and stream-format={avc,bytestream} + +2011-07-11 12:59:07 +0200 Sebastian Dröge + + * 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 + + * omx/gstbasevideodecoder.c: + basevideodecoder: Track present position on discont before resetting it + +2011-07-11 11:52:33 +0200 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstbasevideodecoder.c: + basevideodecoder: Set the correct lists to NULL after freeing + +2011-07-11 08:54:53 +0200 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomxmpeg4videodec.c: + omxmpeg4videodec: Fix debug category name + +2011-07-09 11:41:42 +0200 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Use the destroy notify to free the coder_hook + +2011-07-09 10:57:52 +0200 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Fix some minor memory leaks + +2011-07-08 15:25:07 +0200 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomx.h: + omx: Clarify GQueue/GPtrArray element types + +2011-07-07 12:23:24 +0200 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Don't leak the codec_data after sending it + +2011-07-07 10:27:31 +0200 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Remove reconfiguration test hack + +2011-07-06 13:27:12 +0200 Sebastian Dröge + + * omx/gstomx.c: + omx: Improve debug output a bit + +2011-07-06 13:26:51 +0200 Sebastian Dröge + + * 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 + + * omx/gstomx.c: + omx: Use G_USEC_PER_SEC for clarity instead of 1000000 + +2011-07-06 13:19:15 +0200 Sebastian Dröge + + * 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 + + * 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 + + * omx/gstomxvideodec.c: + omxvideodec: Remove obsolete FIXME comment + +2011-07-06 10:29:54 +0200 Sebastian Dröge + + * omx/gstomx.c: + * omx/gstomx.h: + omx: Improve error handling and reporting + +2011-07-06 08:48:37 +0200 Sebastian Dröge + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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/gst-omx/NEWS b/gst-omx/NEWS new file mode 100644 index 0000000000..6aa0a9e3ed --- /dev/null +++ b/gst-omx/NEWS @@ -0,0 +1,2804 @@ +GStreamer 1.20 Release Notes + +GStreamer 1.20.0 was originally released on 3 February 2022. + +The latest bug-fix release in the 1.20 series is 1.20.4 and was released +on 12 October 2022. + +See https://gstreamer.freedesktop.org/releases/1.20/ for the latest +version of this document. + +Last updated: Wednesday 12 October 2022, 15: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 + +- Development in GitLab was switched to a single git repository + containing all the modules +- GstPlay: new high-level playback library, replaces GstPlayer +- WebM Alpha decoding support +- Encoding profiles can now be tweaked with additional + application-specified element properties +- Compositor: multi-threaded video conversion and mixing +- RTP header extensions: unified support in RTP depayloader and + payloader base classes +- SMPTE 2022-1 2-D Forward Error Correction support +- Smart encoding (pass through) support for VP8, VP9, H.265 in + encodebin and transcodebin +- Runtime compatibility support for libsoup2 and libsoup3 (libsoup3 + support experimental) +- Video decoder subframe support +- Video decoder automatic packet-loss, data corruption, and keyframe + request handling for RTP / WebRTC / RTSP +- mp4 and Matroska muxers now support profile/level/resolution changes + for H.264/H.265 input streams (i.e. codec data changing on the fly) +- mp4 muxing mode that initially creates a fragmented mp4 which is + converted to a regular mp4 on EOS +- Audio support for the WebKit Port for Embedded (WPE) web page source + element +- CUDA based video color space convert and rescale elements and + upload/download elements +- NVIDIA memory:NVMM support for OpenGL glupload and gldownload + elements +- Many WebRTC improvements +- The new VA-API plugin implementation fleshed out with more decoders + and new postproc elements +- AppSink API to retrieve events in addition to buffers and buffer + lists +- AppSrc gained more configuration options for the internal queue + (leakiness, limits in buffers and time, getters to read current + levels) +- Updated Rust bindings and many new Rust plugins +- Improved support for custom minimal GStreamer builds +- Support build against FFmpeg 5.0 +- Linux Stateless CODEC support gained MPEG-2 and VP9 +- Windows Direct3D11/DXVA decoder gained AV1 and MPEG-2 support +- Lots of new plugins, features, performance improvements and bug + fixes + +Major new features and changes + +Noteworthy new features and API + +- gst_element_get_request_pad() has been deprecated in favour of the + newly-added gst_element_request_pad_simple() which does the exact + same thing but has a less confusing name that hopefully makes clear + that the function request a new pad rather than just retrieves an + already-existing request pad. + +Development in GitLab was switched to a single git repository containing all the modules + +The GStreamer multimedia framework is a set of libraries and plugins +split into a number of distinct modules which are released independently +and which have so far been developed in separate git repositories in +freedesktop.org GitLab. + +In addition to these separate git repositories there was a gst-build +module that would use the Meson build system’s subproject feature to +download each individual module and then build everything in one go. It +would also provide an uninstalled development environment that made it +easy to work on GStreamer and use or test versions other than the +system-installed GStreamer version. + +All of these modules have now (as of 28 September 2021) been merged into +a single git repository (“Mono repository” or “monorepo”) which should +simplify development workflows and continuous integration, especially +where changes need to be made to multiple modules at once. + +This mono repository merge will primarily affect GStreamer developers +and contributors and anyone who has workflows based on the GStreamer git +repositories. + +The Rust bindings and Rust plugins modules have not been merged into the +mono repository at this time because they follow a different release +cycle. + +The mono repository lives in the existing GStreamer core git repository +in GitLab in the new main branch and all future development will happen +on this branch. + +Modules will continue to be released as separate tarballs. + +For more details, please see the GStreamer mono repository FAQ. + +GstPlay: new high-level playback library replacing GstPlayer + +- GstPlay is a new high-level playback library that replaces the older + GstPlayer API. It is basically the same API as GstPlayer but + refactored to use bus messages for application notifications instead + of GObject signals. There is still a signal adapter object for those + who prefer signals. Since the existing GstPlayer API is already in + use in various applications, it didn’t seem like a good idea to + break it entirely. Instead a new API was added, and it is expected + that this new GstPlay API will be moved to gst-plugins-base in + future. + +- The existing GstPlayer API is scheduled for deprecation and will be + removed at some point in the future (e.g. in GStreamer 1.24), so + application developers are urged to migrate to the new GstPlay API + at their earliest convenience. + +WebM alpha decoding + +- Implement WebM alpha decoding (VP8/VP9 with alpha), which required + support and additions in various places. This is supported both with + software decoders and hardware-accelerated decoders. + +- VP8/VP9 don’t support alpha components natively in the codec, so the + way this is implemented in WebM is by encoding the alpha plane with + transparency data as a separate VP8/VP9 stream. Inside the WebM + container (a variant of Matroska) this is coded as a single video + track with the “normal” VP8/VP9 video data making up the main video + data and each frame of video having an encoded alpha frame attached + to it as extra data ("BlockAdditional"). + +- matroskademux has been extended extract this per-frame alpha side + data and attach it in form of a GstVideoCodecAlphaMeta to the + regular video buffers. Note that this new meta is specific to this + VP8/VP9 alpha support and can’t be used to just add alpha support to + other codecs that don’t support it. Lastly, matroskademux also + advertises the fact that the streams contain alpha in the caps. + +- The new codecalpha plugin contains various bits of infrastructure to + support autoplugging and debugging: + + - codecalphademux splits out the alpha stream from the metas on + the regular VP8/VP9 buffers + - alphacombine takes two decoded raw video streams (one alpha, one + the regular video) and combines it into a video stream with + alpha + - vp8alphadecodebin + vp9alphadecodebin are wrapper bins that use + the regular vp8dec and vp9dec software decoders to decode + regular and alpha streams and combine them again. To decodebin + these look like regular decoders. + - The V4L2 CODEC plugin has stateless VP8/VP9 decoders that can + decode both alpha and non-alpha stream with a single decoder + instance + +- A new AV12 video format was added which is basically NV12 with an + alpha plane, which is more convenient for many hardware-accelerated + decoders. + +- Watch Nicolas Dufresne’s LCA 2022 talk “Bringing WebM Alpha support + to GStreamer” for all the details and a demo. + +RTP Header Extensions Base Class and Automatic Header Extension Handling in RTP Payloaders and Depayloaders + +- RTP Header Extensions are specified in RFC 5285 and provide a way to + add small pieces of data to RTP packets in between the RTP header + and the RTP payload. This is often used for per-frame metadata, + extended timestamps or other application-specific extra data. There + are several commonly-used extensions specified in various RFCs, but + senders are free to put any kind of data in there, as long as sender + and receiver both know what that data is. Receivers that don’t know + about the header extensions will just skip the extra data without + ever looking at it. These header extensions can often be combined + with any kind of payload format, so may need to be supported by many + RTP payloader and depayloader elements. + +- Inserting and extracting RTP header extension data has so far been a + bit inconvenient in GStreamer: There are functions to add and + retrieve RTP header extension data from RTP packets, but nothing + works automatically, even for common extensions. People would have + to do the insertion/extraction either in custom elements + before/after the RTP payloader/depayloader, or inside pad probes, + which isn’t very nice. + +- This release adds various pieces of new infrastructure for generic + RTP header extension handling, as well as some implementations for + common extensions: + + - GstRTPHeaderExtension is a new helper base class for reading and + writing RTP header extensions. Nominally this subclasses + GstElement, but only so these extensions are stored in the + registry where they can be looked up by URI or name. They don’t + have pads and don’t get added to the pipeline graph as an + element. + + - "add-extension" and "clear-extension" action signals on RTP + payloaders and depayloaders for manual extension management + + - The "request-extension" signal will be emitted if an extension + is encountered that requires explicit mapping by the application + + - new "auto-header-extension" property on RTP payloaders and + depayloaders for automatic handling of known header extensions. + This is enabled by default. The extensions must be signalled via + caps / SDP. + + - RTP header extension implementations: + + - rtphdrextclientaudiolevel: Client-to-Mixer Audio Level + Indication (RFC 6464) (also see below) + - rtphdrextcolorspace: Color Space extension, extends RTP + packets with color space and high dynamic range (HDR) + information + - rtphdrexttwcc: Transport Wide Congestion Control support + +- gst_rtp_buffer_remove_extension_data() is a new helper function to + remove an RTP header extension from an RTP buffer + +- The existing gst_rtp_buffer_set_extension_data() now also supports + shrinking the extension data in size + +AppSink and AppSrc improvements + +- appsink: new API to pull events out of appsink in addition to + buffers and buffer lists. + + There was previously no way for users to receive incoming events + from appsink properly serialised with the data flow, even if they + are serialised events. The reason for that is that the only way to + intercept events was via a pad probe on the appsink sink pad, but + there is also internal queuing inside of appsink, so it’s difficult + to ascertain the right order of everything in all cases. + + There is now a new "new-serialized-event" signal which will be + emitted when there’s a new event pending (just like the existing + "new-sample" signal). The "emit-signals" property must be set to + TRUE in order to activate this (but it’s also fine to just pull from + the application thread without using the signals). + + gst_app_sink_pull_object() and gst_app_sink_try_pull_object() can be + used to pull out either an event or a new sample carrying a buffer + or buffer list, whatever is next in the queue. + + EOS events will be filtered and will not be returned. EOS handling + can be done the usual way, same as with _pull_sample(). + +- appsrc: allow configuration of internal queue limits in time and + buffers and add leaky mode. + + There is internal queuing inside appsrc so the application thread + can push data into the element which will then be picked up by the + source element’s streaming thread and pushed into the pipeline from + that streaming thread. This queue is unlimited by default and until + now it was only possible to set a maximum size limit in bytes. When + that byte limit is reached, the pushing thread (application thread) + would be blocked until more space becomes available. + + A limit in bytes is not particularly useful for many use cases, so + now it is possible to also configure limits in time and buffers + using the new "max-time" and "max-buffers" properties. Of course + there are also matching new read-only"current-level-buffers" and + "current-level-time properties" properties to query the current fill + level of the internal queue in time and buffers. + + And as if that wasn’t enough the internal queue can also be + configured as leaky using the new "leaky-type" property. That way + when the queue is full the application thread won’t be blocked when + it tries to push in more data, but instead either the new buffer + will be dropped or the oldest data in the queue will be dropped. + +Better string serialization of nested GstCaps and GstStructures + +- New string serialisation format for structs and caps that can handle + nested structs and caps properly by using brackets to delimit nested + items (e.g. some-struct, some-field=[nested-struct, nested=true]). + Unlike the default format the new variant can also support more than + one level of nesting. For backwards-compatibility reasons the old + format is still output by default when serialising caps and structs + using the existing API. The new functions gst_caps_serialize() and + gst_structure_serialize() can be used to output strings in the new + format. + +Convenience API for custom GstMetas + +- New convenience API to register and create custom GstMetas: + gst_meta_register_custom() and gst_buffer_add_custom_meta(). Such + custom meta is backed by a GstStructure and does not require that + users of the API expose their GstMeta implementation as public API + for other components to make use of it. In addition, it provides a + simpler interface by ignoring the impl vs. api distinction that the + regular API exposes. This new API is meant to be the meta + counterpart to custom events and messages, and to be more convenient + than the lower-level API when the absolute best performance isn’t a + requirement. The reason it’s less performant than a “proper” meta is + that a proper meta is just a C struct in the end whereas this goes + through the GstStructure API which has a bit more overhead, which + for most scenarios is negligible however. This new API is useful for + experimentation or proprietary metas, but also has some limitations: + it can only be used if there’s a single producer of these metas; + registering the same custom meta multiple times or from multiple + places is not allowed. + +Additional Element Properties on Encoding Profiles + +- GstEncodingProfile: The new "element-properties" and + gst_encoding_profile_set_element_properties() API allows + applications to set additional element properties on encoding + profiles to configure muxers and encoders. So far the encoding + profile template was the only place where this could be specified, + but often what applications want to do is take a ready-made encoding + profile shipped by GStreamer or the application and then tweak the + settings on top of that, which is now possible with this API. Since + applications can’t always know in advance what encoder element will + be used in the end, it’s even possible to specify properties on a + per-element basis. + + Encoding Profiles are used in the encodebin, transcodebin and + camerabin elements and APIs to configure output formats (containers + and elementary streams). + +Audio Level Indication Meta for RFC 6464 + +- New GstAudioLevelMeta containing Audio Level Indication as per RFC + 6464 + +- The level element has been updated to add GstAudioLevelMeta on + buffers if the "audio-level-meta" property is set to TRUE. This can + then in turn be picked up by RTP payloaders to signal the audio + level to receivers through RTP header extensions (see above). + +- New Client-to-Mixer Audio Level Indication (RFC6464) RTP Header + Extension which should be automatically created and used by RTP + payloaders and depayloaders if their "auto-header-extension" + property is enabled and if the extension is part of the RTP caps. + +Automatic packet loss, data corruption and keyframe request handling for video decoders + +- The GstVideoDecoder base class has gained various new APIs to + automatically handle packet loss and data corruption better by + default, especially in RTP, RTSP and WebRTC streaming scenarios, and + to give subclasses more control about how they want to handle + missing data: + + - Video decoder subclasses can mark output frames as corrupted via + the new GST_VIDEO_CODEC_FRAME_FLAG_CORRUPTED flag + + - A new "discard-corrupted-frames" property allows applications to + configure decoders so that corrupted frames are directly + discarded instead of being forwarded inside the pipeline. This + is a replacement for the "output-corrupt" property of the FFmpeg + decoders. + + - RTP depayloaders can now signal to decoders that data is missing + when sending GAP events for lost packets. GAP events can be sent + for various reason in a GStreamer pipeline. Often they are just + used to let downstream elements know that there isn’t a buffer + available at the moment, so downstream elements can move on + instead of waiting for one. They are also sent by RTP + depayloaders in the case that packets are missing, however, and + so far a decoder was not able to differentiate the two cases. + This has been remedied now: GAP events can be decorated with + gst_event_set_gap_flags() and GST_GAP_FLAG_MISSING_DATA to let + decoders now what happened, and decoders can then use that in + some cases to handle missing data better. + + - The GstVideoDecoder::handle_missing_data vfunc was added to + inform subclasses about packet loss or missing data and let them + handle it in their own way if they like. + + - gst_video_decoder_set_needs_sync_point() lets subclasses signal + that they need the stream to start with a sync point. If + enabled, the base class will discard all non-sync point frames + in the beginning and after a flush and does not pass them to the + subclass. Furthermore, if the first frame is not a sync point, + the base class will try and request a sync frame from upstream + by sending a force-key-unit event (see next items). + + - New "automatic-request-sync-points" and + "automatic-request-sync-point-flags" properties to automatically + request sync points when needed, e.g. on packet loss or if the + first frame is not a keyframe. Applications may want to enable + this on decoders operating in e.g. RTP/WebRTC/RTSP receiver + pipelines. + + - The new "min-force-key-unit-interval" property can be used to + ensure there’s a minimal interval between keyframe requests to + upstream (and/or the sender) and we’re not flooding the sender + with key unit requests. + + - gst_video_decoder_request_sync_point() allows subclasses to + request a new sync point (e.g. if they choose to do their own + missing data handling). This will still honour the + "min-force-key-unit-interval" property if set. + +Improved support for custom minimal GStreamer builds + +- Element registration and registration of other plugin features + inside plugin init functions has been improved in order to + facilitate minimal custom GStreamer builds. + +- A number of new macros have been added to declare and create + per-element and per-plugin feature register functions in all + plugins, and then call those from the per-plugin plugin_init + functions: + + - GST_ELEMENT_REGISTER_DEFINE, + GST_DEVICE_PROVIDER_REGISTER_DEFINE, + GST_DYNAMIC_TYPE_REGISTER_DEFINE, GST_TYPE_FIND_REGISTER_DEFINE + for the actual registration call with GStreamer + - GST_ELEMENT_REGISTER, GST_DEVICE_PROVIDER_REGISTER, + GST_DYNAMIC_TYPE_REGISTER, GST_PLUGIN_STATIC_REGISTER, + GST_TYPE_FIND_REGISTER to call the registration function defined + by the REGISTER_DEFINE macro + - GST_ELEMENT_REGISTER_DECLARE, + GST_DEVICE_PROVIDER_REGISTER_DECLARE, + GST_DYNAMIC_TYPE_REGISTER_DECLARE, + GST_TYPE_FIND_REGISTER_DECLARE to declare the registration + function defined by the REGISTER_DEFINE macro + - and various variants for advanced use cases. + +- This means that applications can call the per-element and per-plugin + feature registration functions for only the elements they need + instead of registering plugins as a whole with all kinds of elements + that may not be required (e.g. encoder and decoder instead of just + decoder). In case of static linking all unused functions and their + dependencies would be removed in this case by the linker, which + helps minimise binary size for custom builds. + +- gst_init() will automatically call a gst_init_static_plugins() + function if one exists. + +- See the GStreamer static build documentation and Stéphane’s blog + post Generate a minimal GStreamer build, tailored to your needs for + more details. + +New elements + +- New aesdec and aesenc elements for AES encryption and decryption in + a custom format. + +- New encodebin2 element with dynamic/sometimes source pads in order + to support the option of doing the muxing outside of encodebin, + e.g. in combination with a splitmuxsink. + +- New fakeaudiosink and videocodectestsink elements for testing and + debugging (see below for more details) + +- rtpisacpay, rtpisacdepay: new RTP payloader and depayloader for iSAC + audio codec + +- rtpst2022-1-fecdec, rtpst2022-1-fecenc: new elements providing SMPTE + 2022-1 2-D Forward Error Correction. More details in Mathieu’s blog + post. + +- isac: new plugin wrapping the Internet Speech Audio Codec reference + encoder and decoder from the WebRTC project. + +- asio: plugin for Steinberg ASIO (Audio Streaming Input/Output) API + +- gssrc, gssink: add source and sink for Google Cloud Storage + +- onnx: new plugin to apply ONNX neural network models to video + +- openaptx: aptX and aptX-HD codecs using libopenaptx (v0.2.0) + +- qroverlay, debugqroverlay: new elements that allow overlaying data + on top of video in the form of a QR code + +- cvtracker: new OpenCV-based tracker element + +- av1parse, vp9parse: new parsers for AV1 and VP9 video + +- va: work on the new VA-API plugin implementation for + hardware-accelerated video decoding and encoding has continued at + pace, with various new decoders and filters having joined the + initial vah264dec: + + - vah265dec: VA-API H.265 decoder + - vavp8dec: VA-API VP8 decoder + - vavp9dec: VA-API VP9 decoder + - vaav1dec: VA-API AV1 decoder + - vampeg2dec: VA-API MPEG-2 decoder + - vadeinterlace: : VA-API deinterlace filter + - vapostproc: : VA-API postproc filter (color conversion, + resizing, cropping, color balance, video rotation, skin tone + enhancement, denoise, sharpen) + + See Víctor’s blog post “GstVA in GStreamer 1.20” for more details + and what’s coming up next. + +- vaapiav1dec: new AV1 decoder element (in gstreamer-vaapi) + +- msdkav1dec: hardware-accelerated AV1 decoder using the Intel Media + SDK / oneVPL + +- nvcodec plugin for NVIDIA NVCODEC API for hardware-accelerated video + encoding and decoding: + + - cudaconvert, cudascale: new CUDA based video color space convert + and rescale elements + - cudaupload, cudadownload: new helper elements for memory + transfer between CUDA and system memory spaces + - nvvp8sldec, nvvp9sldec: new GstCodecs-based VP8/VP9 decoders + +- Various new hardware-accelerated elements for Windows: + + - d3d11screencapturesrc: new desktop capture element, including a + GstDeviceProvider implementation to enumerate/select target + monitors for capture. + - d3d11av1dec and d3d11mpeg2dec: AV1 and MPEG-2 decoders + - d3d11deinterlace: deinterlacing filter + - d3d11compositor: video composing element + - see Windows section below for more details + +- new Rust plugins: + + - audiornnoise: Removes noise from an audio stream + - awstranscribeparse: Parses AWS audio transcripts into timed text + buffers + - ccdetect: Detects if valid closed captions are present in a + closed captions stream + - cea608tojson: Converts CEA-608 Closed Captions to a JSON + representation + - cmafmux: CMAF fragmented mp4 muxer + - dashmp4mux: DASH fragmented mp4 muxer + - isofmp4mux: ISO fragmented mp4 muxer + - ebur128level: EBU R128 Loudness Level Measurement + - ffv1dec: FFV1 video decoder + - gtk4paintablesink: GTK4 video sink, which provides a + GdkPaintable that can be rendered in various widgets + - hlssink3: HTTP Live Streaming sink + - hrtfrender: Head-Related Transfer Function (HRTF) renderer + - hsvdetector: HSV colorspace detector + - hsvfilter: HSV colorspace filter + - jsongstenc: Wraps buffers containing any valid top-level JSON + structures into higher level JSON objects, and outputs those as + ndjson + - jsongstparse: Parses ndjson as output by jsongstenc + - jsontovtt: converts JSON to WebVTT subtitles + - regex: Applies regular expression operations on text + - roundedcorners: Adds rounded corners to video + - spotifyaudiosrc: Spotify source + - textahead: Display upcoming text buffers ahead (e.g. for + Karaoke) + - transcriberbin: passthrough bin that transcribes raw audio to + closed captions using awstranscriber and puts the captions as + metas onto the video + - tttojson: Converts timed text to a JSON representation + - uriplaylistbin: Playlist source bin + - webpdec-rs: WebP image decoder with animation support + +- New plugin codecalpha with elements to assist with WebM Alpha + decoding + + - codecalphademux: Split stream with GstVideoCodecAlphaMeta into + two streams + - alphacombine: Combine two raw video stream (I420 or NV12) as one + stream with alpha channel (A420 or AV12) + - vp8alphadecodebin: A bin to handle software decoding of VP8 with + alpha + - vp9alphadecodebin: A bin to handle software decoding of VP9 with + alpha + +- New hardware accelerated elements for Linux: + + - v4l2slmpeg2dec: Support for Linux Stateless MPEG-2 decoders + - v4l2slvp9dec: Support for Linux Stateless VP9 decoders + - v4l2slvp8alphadecodebin: Support HW accelerated VP8 with alpha + layer decoding + - v4l2slvp9alphadecodebin: Support HW accelerated VP9 with alpha + layer decoding + +New element features and additions + +- assrender: handle more font mime types; better interaction with + matroskademux for embedded fonts + +- audiobuffersplit: Add support for specifying output buffer size in + bytes (not just duration) + +- audiolatency: new "samplesperbuffer" property so users can configure + the number of samples per buffer. The default value is 240 samples + which is equivalent to 5ms latency with a sample rate of 48000, + which might be larger than actual buffer size of audio capture + device. + +- audiomixer, audiointerleave, GstAudioAggregator: now keep a count of + samples that are dropped or processed as statistic and can be made + to post QoS messages on the bus whenever samples are dropped by + setting the "qos-messages" property on input pads. + +- audiomixer, compositor: improved handling of new inputs added at + runtime. New API was added to the GstAggregator base class to allow + subclasses to opt into an aggregation mode where inactive pads are + ignored when processing input buffers + (gst_aggregator_set_ignore_inactive_pads(), + gst_aggregator_pad_is_inactive()). An “inactive pad” in this context + is a pad which, in live mode, hasn’t yet received a first buffer, + but has been waited on at least once. What would happen usually in + this case is that the aggregator would wait for data on this pad + every time, up to the maximum configured latency. This would + inadvertently push mixer elements in live mode to the configured + latency envelope and delay processing when new inputs are added at + runtime until these inputs have actually produced data. This is + usually undesirable. With this new API, new inputs can be added + (requested) and configured and they won’t delay the data processing. + Applications can opt into this new behaviour by setting the + "ignore-inactive-pads" property on compositor, audiomixer or other + GstAudioAggregator-based elements. + +- cccombiner: implement “scheduling” of captions. So far cccombiner’s + behaviour was essentially that of a funnel: it strictly looked at + input timestamps to associate together video and caption buffers. + Now it will try to smoothly schedule caption buffers in order to + have exactly one per output video buffer. This might involve + rewriting input captions, for example when the input is CDP then + sequence counters are rewritten, time codes are dropped and + potentially re-injected if the input video frame had a time code + meta. This can also lead to the input drifting from synchronisation, + when there isn’t enough padding in the input stream to catch up. In + that case the element will start dropping old caption buffers once + the number of buffers in its internal queue reaches a certain limit + (configurable via the "max-scheduled" property). The new original + funnel-like behaviour can be restored by setting the "scheduling" + property to FALSE. + +- ccconverter: new "cdp-mode" property to specify which sections to + include in CDP packets (timecode, CC data, service info). Various + software, including FFmpeg’s Decklink support, fails parsing CDP + packets that contain anything but CC data in the CDP packets. + +- clocksync: new "sync-to-first" property for automatic timestamp + offset setup: if set clocksync will set up the "ts-offset" value + based on the first buffer and the pipeline’s running time when the + first buffer arrived. The newly configured "ts-offset" in this case + would be the value that allows outputting the first buffer without + waiting on the clock. This is useful for example to feed a non-live + input into an already-running pipeline. + +- compositor: + + - multi-threaded input conversion and compositing. Set the + "max-threads" property to activate this. + - new "sizing-policy" property to support display aspect ratio + (DAR)-aware scaling. By default the image is scaled to fill the + configured destination rectangle without padding and without + keeping the aspect ratio. With sizing-policy=keep-aspect-ratio + the input image is scaled to fit the destination rectangle + specified by GstCompositorPad:{xpos, ypos, width, height} + properties preserving the aspect ratio. As a result, the image + will be centered in the destination rectangle with padding if + necessary. + - new "zero-size-is-unscaled" property on input pads. By default + pad width=0 or pad height=0 mean that the stream should not be + scaled in that dimension. But if the "zero-size-is-unscaled" + property is set to FALSE a width or height of 0 is instead + interpreted to mean that the input image on that pad should not + be composited, which is useful when creating animations where an + input image is made smaller and smaller until it disappears. + - improved handling of new inputs at runtime via + "ignore-inactive-pads"property (see above for details) + - allow output format with alpha even if none of the inputs have + alpha (also glvideomixer and other GstVideoAggregator + subclasses) + +- dashsink: add H.265 codec support and signals for allowing custom + playlist/fragment output + +- decodebin3: + + - improved decoder selection, especially for hardware decoders + - make input activation “atomic” when adding inputs dynamically + - better interleave handling: take into account decoder latency + for interleave size + +- decklink: + + - Updated DeckLink SDK to 11.2 to support DeckLink 8K Pro + - decklinkvideosrc: + - More accurate and stable capture timestamps: use the + hardware reference clock time when the frame was finished + being captured instead of a clock time much further down the + road. + - Automatically detect widescreen vs. normal NTSC/PAL + +- encodebin: + + - add “smart encoding” support for H.265, VP8 and VP9 (i.e. only + re-encode where needed and otherwise pass through encoded video + as-is). + - H.264/H.265 smart encoding improvements: respect user-specified + stream-format, but if not specified default to avc3/hvc1 with + in-band SPS/PPS/VPS signalling for more flexibility. + - new encodebin2 element with dynamic/sometimes source pads in + order to support the option of doing the muxing outside of + encodebin, e.g. in combination with splitmuxsink. + - add APIs to set element properties on encoding profiles (see + below) + +- errorignore: new "ignore-eos" property to also ignore FLOW_EOS from + downstream elements + +- giosrc: add support for growing source files: applications can + specify that the underlying file being read is growing by setting + the "is-growing" property. If set, the source won’t EOS when it + reaches the end of the file, but will instead start monitoring it + and will start reading data again whenever a change is detected. The + new "waiting-data" and "done-waiting-data" signals keep the + application informed about the current state. + +- gtksink, gtkglsink: + + - scroll event support: forwarded as navigation events into the + pipeline + - "video-aspect-ratio-override" property to force a specific + aspect ratio + - "rotate-method" property and support automatic rotation based on + image tags + +- identity: new "stats" property allows applications to retrieve the + number of bytes and buffers that have passed through so far. + +- interlace: add support for more formats, esp 10-bit, 12-bit and + 16-bit ones + +- jack: new "low-latency" property for automatic latency-optimized + setting and "port-names" property to select ports explicitly + +- jpegdec: support output conversion to RGB using libjpeg-turbo (for + certain input files) + +- line21dec: + + - "mode" property to control whether and how detected closed + captions should be inserted in the list of existing close + caption metas on the input frame (if any): add, drop, or + replace. + - "ntsc-only" property to only look for captions if video has NTSC + resolution + +- line21enc: new "remove-caption-meta" to remove metas from output + buffers after encoding the captions into the video data; support for + CDP closed captions + +- matroskademux, matroskamux: Add support for ffv1, a lossless + intra-frame video coding format. + +- matroskamux: accept in-band SPS/PPS/VPS for H.264 and H.265 + (i.e. stream-format avc3 and hev1) which allows on-the-fly + profile/level changes, and from 1.20.4 onwards also resolution + changes. + +- matroskamux: new "cluster-timestamp-offset" property, useful for use + cases where the container timestamps should map to some absolute + wall clock time, for example. + +- rtpsrc: add "caps" property to allow explicit setting of the caps + where needed + +- mpegts: support SCTE-35 pass-through via new "send-scte35-events" + property on MPEG-TS demuxer tsdemux. When enabled, SCTE 35 sections + (e.g. ad placement opportunities) are forwarded as events downstream + where they can be picked up again by mpegtsmux. This required a + semantic change in the SCTE-35 section API: timestamps are now in + running time instead of muxer pts. + +- tsdemux: Handle PCR-less MPEG-TS streams; more robust timestamp + handling in certain corner cases and for poorly muxed streams. + +- mpegtsmux: + + - More conformance improvements to make MPEG-TS analysers happy: + - PCR timing accuracy: Improvements to the way mpegtsmux + outputs PCR observations in CBR mode, so that a PCR + observation is always inserted when needed, so that we never + miss the configured pcr-interval, as that triggers various + MPEG-TS analyser errors. + - Improved PCR/SI scheduling + - Don’t write PCR until PAT/PMT are output to make sure streams + start cleanly with a PAT/PMT. + - Allow overriding the automatic PMT PID selection via + application-supplied PMT_%d fields in the prog-map + structure/property. + +- mp4mux: + + - new "first-moov-then-finalise" mode for fragmented output where + the output will start with a self-contained moov atom for the + first fragment, and then produce regular fragments. Then at the + end when the file is finalised, the initial moov is invalidated + and a new moov is written covering the entire file. This way the + file is a “fragmented mp4” file while it is still being written + out, and remains playable at all times, but at the end it is + turned into a regular mp4 file (with former fragment headers + remaining as unused junk data in the file). + - support H.264 avc3 and H.265 hvc1 stream formats as input where + the codec data is signalled in-band inside the bitstream instead + of caps/file headers. + - support profile/level/resolution changes for H.264/H.265 input + streams (i.e. codec data changing on the fly). Each codec_data + is put into its own SampleTableEntry inside the stsd, unless the + input is in avc3 stream format in which case it’s written + in-band and not in the headers. + +- multifilesink: new ""min-keyframe-distance"" property to make + minimum distance between keyframes in next-file=key-frame mode + configurable instead of hard-coding it to 10 seconds. + +- mxfdemux has seen a big refactoring to support non-frame wrappings + and more accurate timestamp/seek handling for some formats + +- msdk plugin for hardware-accelerated video encoding and decoding + using the Intel Media SDK: + + - oneVPL support (Intel oneAPI Video Processing Library) + - AV1 decoding support + - H.264 decoder now supports constrained-high and progressive-high + profiles + - H.264 encoder: + - more configuration options (properties): + "intra-refresh-type", "min-qp" , "max-qp", "p-pyramid", + "dblk-idc" + - H.265 encoder: + - can output main-still-picture profile + - now inserts HDR SEIs (mastering display colour volume and + content light level) + - more configuration options (properties): + "intra-refresh-type", "min-qp" , "max-qp", "p-pyramid", + "b-pyramid", "dblk-idc", "transform-skip" + - support for RGB 10bit format + - External bitrate control in encoders + - Video post proc element msdkvpp gained support for 12-bit pixel + formats P012_LE, Y212_LE and Y412_LE + +- nvh264sldec: interlaced stream support + +- openh264enc: support main, high, constrained-high and + progressive-high profiles + +- openjpeg: support for multithreaded decoding and encoding + +- rtspsrc: now supports IPv6 also for tunneled mode (RTSP-over-HTTP); + new "ignore-x-server-reply" property to ignore the + x-server-ip-address server header reply in case of HTTP tunneling, + as it is often broken. + +- souphttpsrc: Runtime compatibility support for libsoup2 and + libsoup3. libsoup3 is the latest major version of libsoup, but + libsoup2 and libsoup3 can’t co-exist in the same process because + there is no namespacing or versioning for GObject types. As a + result, it would be awkward if the GStreamer souphttpsrc plugin + linked to a specific version of libsoup, because it would only work + with applications that use the same version of libsoup. To make this + work, the soup plugin now tries to determine the libsoup version + used by the application (and its other dependencies) at runtime on + systems where GStreamer is linked dynamically. libsoup3 support is + still considered somewhat experimental at this point. Distro + packagers please take note of the souphttpsrc plugin dependency + changes mentioned in the build and dependencies section below. + +- srtsrc, srtsink: add signals for the application to accept/reject + incoming connections + +- timeoverlay: new elapsed-running-time time mode which shows the + running time since the first running time (and each flush-stop). + +- udpsrc: new timestamping mode to retrieve packet receive timestamps + from the kernel via socket control messages (SO_TIMESTAMPNS) on + supported platforms + +- uritranscodebin: new setup-source and element-setup signals for + applications to configure elements used + +- v4l2codecs plugin gained support for 4x4 and 32x32 tile formats + enabling some platforms or direct renders. Important memory usage + improvement. + +- v4l2slh264dec now implements the final Linux uAPI as shipped on + Linux 5.11 and later. + +- valve: add "drop-mode" property and provide two new modes of + operation: in drop-mode=forward-sticky-events sticky events + (stream-start, segment, tags, caps, etc.) are forwarded downstream + even when dropping is enabled; drop-mode=transform-to-gap will in + addition also convert buffers into gap events when dropping is + enabled, which lets downstream elements know that time is advancing + and might allow for preroll in many scenarios. By default all events + and all buffers are dropped when dropping is enabled, which can + cause problems with caps negotiation not progressing or branches not + prerolling when dropping is enabled. + +- videocrop: support for many more pixel formats, e.g. planar YUV + formats with > 8bits and GBR* video formats; can now also accept + video not backed by system memory as long as downstream supports the + GstCropMeta + +- videotestsrc: new smpte-rp-219 pattern for SMPTE75 RP-219 conformant + color bars + +- vp8enc: finish support for temporal scalability: two new properties + ("temporal-scalability-layer-flags", + "temporal-scalability-layer-sync-flags") and a unit change on the + "temporal-scalability-target-bitrate” property (now expects bps); + also make temporal scalability details available to RTP payloaders + as buffer metadata. + +- vp9enc: new properties to tweak encoder performance: + + - "aq-mode" to configure adaptive quantization modes + - "frame-parallel-decoding" to configure whether to create a + bitstream that reduces decoding dependencies between frames + which allows staged parallel processing of more than one video + frames in the decoder. (Defaults to TRUE) + - "row-mt", "tile-columns" and "tile-rows" so multithreading can + be enabled on a per-tile basis, instead of on a per tile-column + basis. In combination with the new "tile-rows" property, this + allows the encoder to make much better use of the available CPU + power. + +- vp9dec, vp9enc: add support for 10-bit 4:2:0 and 4:2:2 YUV, as well + as 8-bit 4:4:4 + +- vp8enc, vp9enc now default to “good quality” for the deadline + property rather then “best quality”. Having the deadline set to best + quality causes the encoder to be absurdly slow, most real-life users + will prefer good-enough quality with better performance instead. + +- wpesrc: + + - implement audio support: a new sometimes source pad will be + created for each audio stream created by the web engine. + - move wpesrc to wpevideosrc and add a wrapper bin wpesrc to also + support audio + - also handles web:// URIs now (same as cefsrc) + - post messages with the estimated load progress on the bus + +- x265enc: add negative DTS support, which means timestamps are now + offset by 1h same as with x264enc + +RTP Payloaders and Depayloaders + +- rtpisacpay, rtpisacdepay: new RTP payloader and depayloader for iSAC + audio codec + +- rtph264depay: + + - new "request-keyframe" property to make the depayloader + automatically request a new keyframe from the sender on packet + loss, consistent with the new property on rtpvp8depay. + - new "wait-for-keyframe" property to make depayloader wait for a + new keyframe at the beginning and after packet loss (only + effective if the depayloader outputs AUs), consistent with the + existing property on rtpvp8depay. + +- rtpopuspay, rtpopusdepay: support libwebrtc-compatible multichannel + audio in addition to the previously supported multichannel audio + modes + +- rtpopuspay: add DTX (Discontinuous Transmission) support + +- rtpvp8depay: new "request-keyframe" property to make the depayloader + automatically request a new keyframe from the sender on packet loss. + +- rtpvp8pay: temporal scaling support + +- rtpvp9depay: Improved SVC handling (aggregate all layers) + +RTP Infrastructure + +- rtpst2022-1-fecdec, rtpst2022-1-fecenc: new elements providing SMPTE + 2022-1 2-D Forward Error Correction. More details in Mathieu’s blog + post. + +- rtpreddec: BUNDLE support + +- rtpredenc, rtpulpfecenc: add support for Transport-wide Congestion + Control (TWCC) + +- rtpsession: new "twcc-feedback-interval" property to allow RTCP TWCC + reports to be scheduled on a timer instead of per marker-bit. + +Plugin and library moves + +- There were no plugin moves or library moves in this cycle. + +Plugin removals + +The following elements or plugins have been removed: + +- The ofa audio fingerprinting plugin has been removed. The MusicIP + database has been defunct for years so this plugin is likely neither + useful nor used by anyone. + +- The mms plugin containing mmssrc has been removed. It seems unlikely + anyone still needs this or that there are even any streams left out + there. The MMS protocol was deprecated in 2003 (in favour of RTSP) + and support for it was dropped with Microsoft Media Services 2008, + and Windows Media Player apparently also does not support it any + more. + +Miscellaneous API additions + +Core + +- gst_buffer_new_memdup() is a convenience function for the + widely-used gst_buffer_new_wrapped(g_memdup(data,size),size) + pattern. + +- gst_caps_features_new_single() creates a new single GstCapsFeatures, + avoiding the need to use the vararg function with NULL terminator + for simple cases. + +- gst_element_type_set_skip_documentation() can be used by plugins to + signal that certain elements should not be included in the GStreamer + plugin documentation. This is useful for plugins where elements are + registered dynamically based on hardware capabilities and/or where + the available plugins and properties vary from system to system. + This is used in the d3d11 plugin for example to ensure that only the + list of default elements is advertised in the documentation. + +- gst_type_find_suggest_empty_simple() is a new convenience function + for typefinders for cases where there’s only a media type and no + other fields. + +- New API to create elements and set properties at construction time, + which is not only convenient, but also allows GStreamer elements to + have construct-only properties: gst_element_factory_make_full(), + gst_element_factory_make_valist(), + gst_element_factory_make_with_properties(), + gst_element_factory_create_full(), + gst_element_factory_create_valist(), + gst_element_factory_create_with_properties(). + +- GstSharedTaskPool: new “shared” task pool subclass with slightly + different default behaviour than the existing GstTaskPool which + would create unlimited number of threads for new tasks. The shared + task pool creates up to N threads (default: 1) and then distributes + pending tasks to those threads round-robin style, and blocks if no + thread is available. It is possible to join tasks. This can be used + by plugins to implement simple multi-threaded processing and is used + for the new multi-threaded video conversion and compositing done in + GstVideoAggregator, videoconverter and compositor. + +Plugins Base Utils library + +- GstDiscoverer: + + - gst_discoverer_container_info_get_tags() was added to retrieve + global/container tags (vs. per-stream tags). Per-Stream tags can + be retrieved via the existing + gst_discoverer_stream_info_get_tags(). + gst_discoverer_info_get_tags(), which for many files returns a + confusing mix of stream and container tags, has been deprecated + in favour of the container/stream-specific functions. + - gst_discoverer_stream_info_get_stream_number() returns a unique + integer identifier for a given stream within the given + GstDiscoverer context. (If this matches the stream number inside + the container bitstream that’s by coincidence and not by + design.) + +- gst_pb_utils_get_caps_description_flags() can be used to query + whether certain caps represent a container, audio, video, image, + subtitles, tags, or something else. This only works for formats + known to GStreamer. + +- gst_pb_utils_get_file_extension_from_caps() returns a possible file + extension for given caps. + +- gst_codec_utils_h264_get_profile_flags_level(): Parses profile, + flags, and level from H.264 AvcC codec_data. The format of H.264 + AVCC extradata/sequence_header is documented in the ITU-T H.264 + specification section 7.3.2.1.1 as well as in ISO/IEC 14496-15 + section 5.3.3.1.2. + +- gst_codec_utils_caps_get_mime_codec() to convert caps to a RFC 6381 + compatible MIME codec string codec. Useful for providing the codecs + field inside the Content-Type HTTP header for container formats, + such as mp4 or Matroska. + +GStreamer OpenGL integration library and plugins + +- glcolorconvert: added support for converting the video formats A420, + AV12, BGR, BGRA, RGBP and BGRP. + +- Added support to GstGLBuffer for persistent buffer mappings where a + Pixel Buffer Object (PBO) can be mapped by both the CPU and the GPU. + This removes a memcpy() when uploading textures or vertices + particularly when software decoders (e.g. libav) are direct + rendering into our memory. Improves transfer performance + significantly. Requires OpenGL 4.4, GL_ARB_buffer_storage or + GL_EXT_buffer_storage + +- Added various helper functions for handling 4x4 matrices of affine + transformations as used by GstVideoAffineTransformationMeta. + +- Add support to GstGLContext for allowing the application to control + the config (EGLConfig, GLXConfig, etc) used when creating the OpenGL + context. This allows the ability to choose between RGB16 or RGB10A2 + or RGBA8 back/front buffer configurations that were previously + hardcoded. GstGLContext also supports retrieving the configuration + it was created with or from an externally provide OpenGL context + handle. This infrastructure is also used to create a compatible + config from an application/externally provided OpenGL context in + order to improve compatibility with other OpenGL frameworks and GUI + toolkits. A new environment variable GST_GL_CONFIG was also added to + be able to request a specific configuration from the command line. + Note: different platforms will have different functionality + available. + +- Add support for choosing between EGL and WGL at runtime when running + on Windows. Previously this was a build-time switch. Allows use in + e.g. Gtk applications on Windows that target EGL/ANGLE without + recompiling GStreamer. gst_gl_display_new_with_type() can be used by + applications to choose a specific display type to use. + +- Build fixes to explicitly check for Broadcom-specific libraries on + older versions of the Raspberry Pi platform. The Broadcom OpenGL ES + and EGL libraries have different filenames. Using the vc4 Mesa + driver on the Raspberry Pi is not affected. + +- Added support to glupload and gldownload for transferring RGBA + buffers using the memory:NVMM available on the Nvidia Tegra family + of embedded devices. + +- Added support for choosing libOpenGL and libGLX as used in a GLVND + environment on unix-based platforms. This allows using desktop + OpenGL and EGL without pulling in any GLX symbols as would be + required with libGL. + +Video library + +- New raw video formats: + + - AV12 (NV12 with alpha plane) + - RGBP and BGRP (planar RGB formats) + - ARGB64 variants with specified endianness instead of host + endianness: + - ARGB64_LE, ARGB64_BE + - RGBA64_BE, RGBA64_LE + - BGRA64_BE, BGRA64_LE + - ABGR64_BE, ABGR64_LE + +- gst_video_orientation_from_tag() is new convenience API to parse the + image orientation from a GstTagList. + +- GstVideoDecoder subframe support (see below) + +- GstVideoCodecState now also carries some HDR metadata + +- Ancillary video data: implement transform functions for AFD/Bar + metas, so they will be forwarded in more cases + +MPEG-TS library + +This library only handles section parsing and such, see above for +changes to the actual mpegtsmux and mpegtsdemux elements. + +- many additions and improvements to SCTE-35 section parsing +- new API for fetching extended descriptors: + gst_mpegts_find_descriptor_with_extension() +- add support for SIT sections (Selection Information Tables) +- expose event-from-section constructor gst_event_new_mpegts_section() +- parse Audio Preselection Descriptor needed for Dolby AC-4 + +GstWebRTC library + webrtcbin + +- Change the way in which sink pads and transceivers are matched + together to support easier usage. If a pad is created without a + specific index (i.e. using sink_%u as the pad template), then an + available compatible transceiver will be searched for. If a specific + index is requested (i.e. sink_1) then if a transceiver for that + m-line already exists, that transceiver must match the new sink pad + request. If there is no transceiver available in either scenario, a + new transceiver is created. If a mixture of both sink_1 and sink_%u + requests result in an impossible situation, an error will be + produced at pad request time or from create offer/answer. + +- webrtcbin now uses regular ICE nomination instead of libnice’s + default of aggressive ICE nomination. Regular ICE nomination is the + default recommended by various relevant standards and improves + connectivity in specific network scenarios. + +- Add support for limiting the port range used for RTP with the + addition of the min-rtp-port and max-rtp-port properties on the ICE + object. + +- Expose the SCTP transport as a property on webrtcbin to more closely + match the WebRTC specification. + +- Added support for taking into account the data channel transport + state when determining the value of the "connection-state" property. + Previous versions of the WebRTC spec did not include the data + channel state when computing this value. + +- Add configuration for choosing the size of the underlying sockets + used for transporting media data + +- Always advertise support for the transport-cc RTCP feedback protocol + as rtpbin supports it. For full support, the configured caps (input + or through codec-preferences) need to include the relevant RTP + header extension. + +- Numerous fixes to caps and media handling to fail-fast when an + incompatible situation is detected. + +- Improved support for attaching the required media after a remote + offer has been set. + +- Add support for dynamically changing the amount of FEC used for a + particular stream. + +- webrtcbin now stops further SDP processing at the first error it + encounters. + +- Completed support for either local or the remote closing a data + channel. + +- Various fixes when performing BUNDLEing of the media streams in + relation to RTX and FEC usage. + +- Add support for writing out QoS DSCP marking on outgoing packets to + improve reliability in some network scenarios. + +- Improvements to the statistics returned by the get-stats signal + including the addition of the raw statistics from the internal + RTPSource, the TWCC stats when available. + +- The webrtc library does not expose any objects anymore with public + fields. Instead properties have been added to replace that + functionality. If you are accessing such fields in your application, + switch to the corresponding properties. + +GstCodecs and Video Parsers + +- Support for render delays to improve throughput across all CODECs + (used with NVDEC and V4L2). +- lots of improvements to parsers and the codec parsing decoder base + classes (H.264, H.265, VP8, VP9, AV1, MPEG-2) used for various + hardware-accelerated decoder APIs. + +Bindings support + +- gst_allocation_params_new() allocates a GstAllocationParams struct + on the heap. This should only be used by bindings (and freed via + gst_allocation_params_free() afterwards). In C code you would + allocate this on the stack and only init it in place. + +- gst_debug_log_literal() can be used to log a string to the debug log + without going through any printf format expansion and associated + overhead. This is mostly useful for bindings such as the Rust + bindings which may have done their own formatting already . + +- Provide non-inlined versions of refcounting APIs for various + GStreamer mini objects, so that they can be consumed by bindings + (e.g. gstreamer-sharp): gst_buffer_ref, gst_buffer_unref, + gst_clear_buffer, gst_buffer_copy, gst_buffer_replace, + gst_buffer_list_ref, gst_buffer_list_unref, gst_clear_buffer_list, + gst_buffer_list_copy, gst_buffer_list_replace, gst_buffer_list_take, + gst_caps_ref, gst_caps_unref, gst_clear_caps, gst_caps_replace, + gst_caps_take, gst_context_ref, gst_context_unref, gst_context_copy, + gst_context_replace, gst_event_replace, gst_event_steal, + gst_event_take, gst_event_ref, gst_event_unref, gst_clear_event, + gst_event_copy, gst_memory_ref, gst_memory_unref, gst_message_ref, + gst_message_unref, gst_clear_message, gst_message_copy, + gst_message_replace, gst_message_take, gst_promise_ref, + gst_promise_unref, gst_query_ref, gst_query_unref, gst_clear_query, + gst_query_copy, gst_query_replace, gst_query_take, gst_sample_ref, + gst_sample_unref, gst_sample_copy, gst_tag_list_ref, + gst_tag_list_unref, gst_clear_tag_list, gst_tag_list_replace, + gst_tag_list_take, gst_uri_copy, gst_uri_ref, gst_uri_unref, + gst_clear_uri. + +- expose a GType for GstMiniObject + +- gst_device_provider_probe() now returns non-floating device object + +API Deprecations + +- gst_element_get_request_pad() has been deprecated in favour of the + newly-added gst_element_request_pad_simple() which does the exact + same thing but has a less confusing name that hopefully makes clear + that the function request a new pad rather than just retrieves an + already-existing request pad. + +- gst_discoverer_info_get_tags(), which for many files returns a + confusing mix of stream and container tags, has been deprecated in + favour of the container-specific and stream-specific functions, + gst_discoverer_container_info_get_tags() and + gst_discoverer_stream_info_get_tags(). + +- gst_video_sink_center_rect() was deprecated in favour of the more + generic newly-added gst_video_center_rect(). + +- The GST_MEMORY_FLAG_NO_SHARE flag has been deprecated, as it tends + to cause problems and prevents sub-buffering. If pooling or lifetime + tracking is required, memories should be allocated through a custom + GstAllocator instead of relying on the lifetime of the buffers the + memories were originally attached to, which is fragile anyway. + +- The GstPlayer high-level playback library is being replaced with the + new GstPlay library (see above). GstPlayer should be considered + deprecated at this point and will be marked as such in the next + development cycle. Applications should be ported to GstPlay. + +- Gstreamer Editing Services: ges_video_transition_set_border(), + ges_video_transition_get_border() + ges_video_transition_set_inverted() + ges_video_transition_is_inverted() have been deprecated, use + ges_timeline_element_set_children_properties() instead. + +Miscellaneous performance, latency and memory optimisations + +More video conversion fast paths + +- v210 ↔ I420, YV12, Y42B, UYVY and YUY2 +- A420 → RGB + +Less jitter when waiting on the system clock + +- Better system clock wait accuracy, less jitter: where available, + clock_nanosleep is used for higher accuracy for waits below 500 + usecs, and waits below 2ms will first use the regular waiting system + and then clock_nanosleep for the remainder. The various wait + implementation have a latency ranging from 50 to 500+ microseconds. + While this is not a major issue when dealing with a low number of + waits per second (for ex: video), it does introduce a non-negligible + jitter for synchronisation of higher packet rate systems. + +Video decoder subframe support + +- The GstVideoDecoder base class gained API to process input at the + sub-frame level. That way video decoders can start decoding slices + before they have received the full input frame in its entirety (to + the extent this is supported by the codec, of course). This helps + with CPU utilisation and reduces latency. + +- This functionality is now being used in the OpenJPEG JPEG 2000 + decoder, the FFmpeg H.264 decoder (in case of NAL-aligned input) and + the OpenMAX H.264/H.265 decoders (in case of NAL-aligned input). + +Miscellaneous other changes and enhancements + +- GstDeviceMonitor no longer fails to start just because one of the + device providers failed to start. That could happen for example on + systems where the pulseaudio device provider is installed, but + pulseaudio isn’t actually running but ALSA is used for audio + instead. In the same vein the device monitor now keeps track of + which providers have been started (via the new + gst_device_provider_is_started()) and only stops actually running + device providers when stopping the device monitor. + +- On embedded systems it can be useful to create a registry that can + be shared and read by multiple processes running as different users. + It is now possible to set the new GST_REGISTRY_MODE environment + variable to specify the file mode for the registry file, which by + default is set to be only user readable/writable. + +- GstNetClientClock will signal lost sync in case the remote time + resets (e.g. because device power cycles), by emitting the “synced” + signal with synced=FALSE parameter, so applications can take action. + +- gst_value_deserialize_with_pspec() allows deserialisation with a + hint for what the target GType should be. This allows for example + passing arrays of flags through the command line or + gst_util_set_object_arg(), eg: foo="". + +- It’s now possible to create an empty GstVideoOverlayComposition + without any rectangles by passing a NULL rectangle to + gst_video_overlay_composition_new(). This is useful for bindings and + simplifies application code in some places. + +Tracing framework, debugging and testing improvements + +- New factories tracer to list loaded elements (and other plugin + features). This can be useful to collect a list of elements needed + for an application, which in turn can be used to create a tailored + minimal GStreamer build that contains just the elements needed and + nothing else. +- New plugin-feature-loaded tracing hook for use by tracers like the + new factories tracer + +- GstHarness: Add gst_harness_set_live() so that harnesses can be set + to non-live and return is-live=false in latency queries if needed. + Default behaviour is to always return is-live=true in latency + queries. + +- navseek: new "hold-eos" property. When enabled, the element will + hold back an EOS event until the next keystroke (via navigation + events). This can be used to keep a video sink showing the last + frame of a video pipeline until a key is pressed instead of tearing + it down immediately on EOS. + +- New fakeaudiosink element: mimics an audio sink and can be used for + testing and CI pipelines on systems where no audio system is + installed or running. It differs from fakesink in that it only + support audio caps and syncs to the clock by default like a normal + audio sink. It also implements the GstStreamVolume interface like + most audio sinks do. + +- New videocodectestsink element for video codec conformance testing: + Calculates MD5 checksums for video frames and skips any padding + whilst doing so. Can optionally also write back the video data with + padding removed into a file for easy byte-by-byte comparison with + reference data. + +Tools + +gst-inspect-1.0 + +- Can sort the list of plugins by passing --sort=name as command line + option + +gst-launch-1.0 + +- will now error out on top-level properties that don’t exist and + which were silently ignored before +- On Windows the high-resolution clock is enabled now, which provides + better clock and timer performance on Windows (see Windows section + below for more details). + +gst-play-1.0 + +- New --start-position command line argument to start playback from + the specified position +- Audio can be muted/unmuted in interactive mode by pressing the m + key. +- On Windows the high-resolution clock is enabled now (see Windows + section below for more details) + +gst-device-monitor-1.0 + +- New --include-hidden command line argument to also show “hidden” + device providers + +ges-launch-1.0 + +- New interactive mode that allows seeking and such. Can be disabled + by passing the --no-interactive argument on the command line. +- Option to forward tags +- Allow using an existing clip to determine the rendering format (both + topology and profile) via new --profile-from command line argument. + +GStreamer RTSP server + +- GstRTSPMediaFactory gained API to disable RTCP + (gst_rtsp_media_factory_set_enable_rtcp(), "enable-rtcp" property). + Previously RTCP was always allowed for all RTSP medias. With this + change it is possible to disable RTCP completely, irrespective of + whether the client wants to do RTCP or not. + +- Make a mount point of / work correctly. While not allowed by the + RTSP 2 spec, the RTSP 1 spec is silent on this and it is used in the + wild. It is now possible to use / as a mount path in + gst-rtsp-server, e.g. rtsp://example.com/ would work with this now. + Note that query/fragment parts of the URI are not necessarily + correctly handled, and behaviour will differ between various + client/server implementations; so use it if you must but don’t bug + us if it doesn’t work with third party clients as you’d hoped. + +- multithreading fixes (races, refcounting issues, deadlocks) + +- ONVIF audio backchannel fixes + +- ONVIF trick mode optimisations + +- rtspclientsink: new "update-sdp" signal that allows updating the SDP + before sending it to the server via ANNOUNCE. This can be used to + add additional metadata to the SDP, for example. The order and + number of medias must not be changed, however. + +GStreamer VAAPI + +- new AV1 decoder element (vaapiav1dec) + +- H.264 decoder: handle stereoscopic 3D video with frame packing + arrangement SEI messages + +- H.265 encoder: added Screen Content Coding extensions support + +- H.265 decoder: gained MAIN_444_12 profile support (decoded to + Y412_LE), and 4:2:2 12-bits support (decoded to Y212_LE) + +- vaapipostproc: gained BT2020 color standard support + +- vaapidecode: now generates caps templates dynamically at runtime in + order to advertise actually supported caps instead of all + theoretically supported caps. + +- GST_VAAPI_DRM_DEVICE environment variable to force a specified DRM + device when a DRM display is used. It is ignored when other types of + displays are used. By default /dev/dri/renderD128 is used for DRM + display. + +GStreamer OMX + +- subframe support in H.264/H.265 decoders + +GStreamer Editing Services and NLE + +- framepositioner: new "operator" property to access blending modes in + the compositor +- timeline: Implement snapping to markers +- smart-mixer: Add support for d3d11compositor and glvideomixer +- titleclip: add "draw-shadow" child property +- ges:// URI support to define a timeline from a description. +- command-line-formatter + - Add track management to timeline description + - Add keyframe support +- ges-launch-1.0: + - Add an interactive mode where we can seek etc… + - Add option to forward tags + - Allow using an existing clip to determine the rendering format + (both topology and profile) via new --profile-from command line + argument. +- Fix static build + +GStreamer validate + +- report: Add a way to force backtraces on reports even if not a + critical issue (GST_VALIDATE_ISSUE_FLAGS_FORCE_BACKTRACE) +- Add a flag to gst_validate_replace_variables_in_string() allow + defining how to resolve variables in structs +- Add gst_validate_bin_monitor_get_scenario() to get the bin monitor + scenario, which is useful for applications that use Validate + directly. +- Add an expected-values parameter to wait, message-type=XX allowing + more precise filtering of the message we are waiting for. +- Add config file support: each test can now use a config file for the + given media file used to test. +- Add support to check properties of object properties +- scenario: Add an "action-done" signal to signal when an action is + done +- scenario: Add a "run-command" action type +- scenario: Allow forcing running action on idle from scenario file +- scenario: Allow iterating over arrays in foreach +- scenario: Rename ‘interlaced’ action to ‘non-blocking’ +- scenario: Add a non-blocking flag to the wait signal + +GStreamer Python Bindings + +- Fixes for Python 3.10 +- Various build fixes +- at least one known breaking change caused by g-i annotation changes + (see below) + +GStreamer C# Bindings + +- Fix GstDebugGraphDetails enum +- Updated to latest GtkSharp +- Updated to include GStreamer 1.20 API + +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 (v1_20 + feature). + +- gst-plugins-rs, the module containing GStreamer plugins written in + Rust, has also seen lots of activity with many new elements and + plugins. See the New Elements section above for a list of new Rust + elements. + +Build and Dependencies + +- Meson 0.59 or newer is now required to build GStreamer. + +- The GLib requirement has been bumped to GLib 2.56 or newer (from + March 2018). + +- The wpe plugin now requires wpe >= 2.28 and wpebackend-fdo >= 1.8 + +- The souphttpsrc plugin is no longer linked against libsoup but + instead tries to pick up either libsoup2 or libsoup3 dynamically at + runtime. Distro packagers please ensure to add a dependency on one + of the libsoup runtimes to the gst-plugins-good package so that + there is actually a libsoup for the plugin to find! + +Explicit opt-in required for build of certain plugins with (A)GPL dependencies + +Some plugins have GPL- or AGPL-licensed dependencies and those plugins +will no longer be built by default unless you have explicitly opted in +to allow (A)GPL-licensed dependencies by passing -Dgpl=enabled to Meson, +even if the required dependencies are available. + +See Building plugins with (A)GPL-licensed dependencies for more details +and a non-exhaustive list of plugins affected. + +gst-build: replaced by mono repository + +See mono repository section above and the GStreamer mono repository FAQ. + +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 Cerbero improvements + +- Plugin removed: libvisual +- New plugins: rtpmanagerbad and rist + +macOS / iOS specific Cerbero improvements + +- XCode 12 support +- macOS OS release support is now future-proof, similar to iOS +- macOS Apple Silicon (ARM64) cross-compile support has been added, + including Universal binaries. There is a known bug regarding this on + ARM64. +- Running Cerbero itself on macOS Apple Silicon (ARM64) is currently + experimental and is known to have bugs + +Windows specific Cerbero improvements + +- Visual Studio 2022 support has been added +- bootstrap is faster since it requires building fewer build-tools + recipes on Windows +- package is faster due to better scheduling of recipe stages and + elimination of unnecessary autotools regeneration +- The following plugins are no longer built on Windows: + - a52dec (another decoder is still available in libav) + - dvdread + - resindvd + +Windows MSI installer + +- no major changes + +Linux specific Cerbero improvements + +- Fedora, Debian OS release support is now more future-proof +- Amazon Linux 2 support has been added + +Android specific Cerbero improvements + +- no major changes + +Platform-specific changes and improvements + +Android + +- No major changes + +macOS and iOS + +- applemedia: add ProRes support to vtenc and vtdec + +- The GStreamer.framework location is now relocatable and is not + required to be /Library/Frameworks/ + +- Cerbero now supports cross-compiling to macOS running on Apple + Silicon (ARM64), and Universal binaries are now available that can + be used on both X86_64 and ARM64 macOS. + +Windows + +- On Windows the high-resolution clock is enabled now in the + gst-launch-1.0 and gst-play-1.0 command line tools, which provides + better clock and timer performance on Windows, at the cost of higher + power consumption. By default, without the high-resolution clock + enabled, the timer precision on Windows is system-dependent and may + be as bad as 15ms which is not good enough for many multimedia + applications. Developers may want to do the same in their Windows + applications if they think it’s a good idea for their application + use case, and depending on the Windows version they target. This is + not done automatically by GStreamer because on older Windows + versions (pre-Windows 10) this affects a global Windows setting and + also there’s a power consumption vs. performance trade-off that may + differ from application to application. + +- dxgiscreencapsrc now supports resolution changes + +- The wasapi2 audio plugin was rewritten and now has a higher rank + than the old wasapi plugin since it has a number of additional + features such as automatic stream routing, and no + known-but-hard-to-fix issues. The plugin is always built if the + Windows 10 SDK is available now. + +- The wasapi device providers now detect and notify dynamic device + additions/removals + +- d3d11screencapturesrc: new desktop capture element, including + GstDeviceProvider implementation to enumerate/select target monitors + for capture. + +- Direct3D11/DXVA decoder now supports AV1 and MPEG-2 codecs + (d3d11av1dec, d3d11mpeg2dec) + +- VP9 decoding got more reliable and stable thanks to a newly written + codec parser + +- Support for decoding interlaced H.264/AVC streams + +- Hardware-accelerated video deinterlacing (d3d11deinterlace) and + video mixing (d3d11compositor) + +- Video mixing with the Direct3D11 API (d3d11compositor) + +- MediaFoundation API based hardware encoders gained the ability to + receive Direct3D11 textures as an input + +- Seungha’s blog post “GStreamer ❤ Windows: A primer on the cool stuff + you’ll find in the 1.20 release” describes many of the + Windows-related improvements in more detail + +Linux + +- bluez: LDAC Bluetooth audio codec support in a2dpsink and avdtpsink, + as well as an LDAC RTP payloader (rtpldacpay) and an LDAC audio + encoder (ldacenc) + +- kmssink: gained support for NV24, NV61, RGB16/BGR16 formats; + auto-detect NVIDIA Tegra driver + +Documentation improvements + +- hardware-accelerated GPU plugins will now no longer always list all + the element variants for all available GPUs, since those are + system-dependent and it’s confusing for users to see those in the + documentation just because the GStreamer developer who generated the + docs had multiple GPUs to play with at the time. Instead just show + the default elements. + +Possibly Breaking and Other Noteworthy Behavioural Changes + +- gst_parse_launch(), gst_parse_bin_from_description() and friends + will now error out when setting properties that don’t exist on + top-level bins. They were silently ignored before. + +- The GstWebRTC library does not expose any objects anymore with + public fields. Instead properties have been added to replace that + functionality. If you are accessing such fields in your application, + switch to the corresponding properties. + +- playbin and uridecodebin now emit the source-setup signal before the + element is added to the bin and linked so that the source element is + already configured before any scheduling query comes in, which is + useful for elements such as appsrc or giostreamsrc. + +- The source element inside urisourcebin (used inside uridecodebin3 + which is used inside playbin3) is no longer called "source". This + shouldn’t affect anyone hopefully, because there’s a "setup-source" + signal to configure the source element and no one should rely on + names of internal elements anyway. + +- The vp8enc element now expects bps (bits per second) for the + "temporal-scalability-target-bitrate” property, which is consistent + with the "target-bitrate" property. Since additional configuration + is required with modern libvpx to make temporal scaling work anyway, + chances are that very few people will have been using this property + +- vp8enc and vp9enc now default to “good quality” for the "deadline" + property rather then “best quality”. Having the deadline set to best + quality causes the encoder to be absurdly slow, most real-life users + will want the good quality tradeoff instead. + +- The experimental GstTranscoder library API in gst-plugins-bad was + changed from a GObject signal-based notification mechanism to a + GstBus/message-based mechanism akin to GstPlayer/GstPlay. + +- MPEG-TS SCTE-35 API: semantic change for SCTE-35 splice commands: + timestamps passed by the application should be in running time now, + since users of the API can’t really be expected to predict the local + PTS of the muxer. + +- The GstContext used by souphttpsrc to share the session between + multiple element instances has changed. Previously it provided + direct access to the internal SoupSession object, now it only + provides access to an opaque, internal type. This change is + necessary because SoupSession is not thread-safe at all and can’t be + shared safely between arbitrary external code and souphttpsrc. + +- Python bindings: GObject-introspection related Annotation fixes have + led to a case of a GstVideo.VideoInfo-related function signature + changing in the Python bindings (possibly one or two other cases + too). This is for a function that should never have been exposed in + the first place though, so the bindings are being updated to throw + an exception in that case, and the correct replacement API has been + added in form of an override. + +Known Issues + +- nothing in particular at this point (but also see possibly breaking + changes section above) + +Contributors + +Aaron Boxer, Adam Leppky, Adam Williamson, Alba Mendez, Alejandro +González, Aleksandr Slobodeniuk, Alexander Vandenbulcke, Alex Ashley, +Alicia Boya García, Andika Triwidada, Andoni Morales Alastruey, Andrew +Wesie, Andrey Moiseev, Antonio Ospite, Antonio Rojas, Arthur Crippa +Búrigo, Arun Raghavan, Ashley Brighthope, Axel Kellermann, Baek, Bastien +Nocera, Bastien Reboulet, Benjamin Gaignard, Bing Song, Binh Truong, +Biswapriyo Nath, Brad Hards, Brad Smith, Brady J. Garvin, Branko +Subasic, Camilo Celis Guzman, Chris Bass, ChrisDuncanAnyvision, Chris +White, Corentin Damman, Daniel Almeida, Daniel Knobe, Daniel Stone, +david, David Fernandez, David Keijser, David Phung, Devarsh Thakkar, +Dinesh Manajipet, Dmitry Samoylov, Dmitry Shusharin, Dominique Martinet, +Doug Nazar, Ederson de Souza, Edward Hervey, Emmanuel Gil Peyrot, +Enrique Ocaña González, Ezequiel Garcia, Fabian Orccon, Fabrice +Fontaine, Fernando Jimenez Moreno, Florian Karydes, Francisco Javier +Velázquez-García, François Laignel, Frederich Munch, Fredrik Pålsson, +George Kiagiadakis, Georg Lippitsch, Göran Jönsson, Guido Günther, +Guillaume Desmottes, Guiqin Zou, Haakon Sporsheim, Haelwenn (lanodan) +Monnier, Haihao Xiang, Haihua Hu, Havard Graff, He Junyan, Helmut +Januschka, Henry Wilkes, Hosang Lee, Hou Qi, Ignacio Casal Quinteiro, +Igor Kovalenko, Ilya Kreymer, Imanol Fernandez, Jacek Tomaszewski, Jade +Macho, Jakub Adam, Jakub Janků, Jan Alexander Steffens (heftig), Jan +Schmidt, Jason Carrete, Jason Pereira, Jay Douglass, Jeongki Kim, Jérôme +Laheurte, Jimmi Holst Christensen, Johan Sternerup, John Hassell, John +Lindgren, John-Mark Bell, Jonathan Matthew, Jordan Petridis, Jose +Quaresma, Julian Bouzas, Julien, Kai Uwe Broulik, Kasper Steensig +Jensen, Kellermann Axel, Kevin Song, Khem Raj, Knut Inge Hvidsten, Knut +Saastad, Kristofer Björkström, Lars Lundqvist, Lawrence Troup, Lim Siew +Hoon, Lucas Stach, Ludvig Rappe, Luis Paulo Fernandes de Barros, Luke +Yelavich, Mads Buvik Sandvei, Marc Leeman, Marco Felsch, Marek Vasut, +Marian Cichy, Marijn Suijten, Marius Vlad, Markus Ebner, Mart Raudsepp, +Matej Knopp, Mathieu Duponchelle, Matthew Waters, Matthieu De Beule, +Mengkejiergeli Ba, Michael de Gans, Michael Olbrich, Michael Tretter, +Michal Dzik, Miguel Paris, Mikhail Fludkov, mkba, Nazar Mokrynskyi, +Nicholas Jackson, Nicola Murino, Nicolas Dufresne, Niklas Hambüchen, +Nikolay Sivov, Nirbheek Chauhan, Olivier Blin, Olivier Crete, Olivier +Crête, Paul Goulpié, Per Förlin, Peter Boba, P H, Philippe Normand, +Philipp Zabel, Pieter Willem Jordaan, Piotrek Brzeziński, Rafał +Dzięgiel, Rafostar, raghavendra, Raghavendra, Raju Babannavar, Raleigh +Littles III, Randy Li, Randy Li (ayaka), Ratchanan Srirattanamet, Raul +Tambre, reed.lawrence, Ricky Tang, Robert Rosengren, Robert Swain, Robin +Burchell, Roman Sivriver, R S Nikhil Krishna, Ruben Gonzalez, Ruslan +Khamidullin, Sanchayan Maity, Scott Moreau, Sebastian Dröge, Sergei +Kovalev, Seungha Yang, Sid Sethupathi, sohwan.park, Sonny Piers, Staz M, +Stefan Brüns, Stéphane Cerveau, Stephan Hesse, Stian Selnes, Stirling +Westrup, Théo MAILLART, Thibault Saunier, Tim, Timo Wischer, Tim-Philipp +Müller, Tim Schneider, Tobias Ronge, Tom Schoonjans, Tulio Beloqui, +tyler-aicradle, U. Artie Eoff, Ung, Val Doroshchuk, VaL Doroshchuk, +Víctor Manuel Jáquez Leal, Vivek R, Vivia Nikolaidou, Vivienne +Watermeier, Vladimir Menshakov, Will Miller, Wim Taymans, Xabier +Rodriguez Calvar, Xavier Claessens, Xℹ Ruoyao, Yacine Bandou, Yinhang +Liu, youngh.lee, youngsoo.lee, yychao, Zebediah Figura, Zhang yuankun, +Zhang Yuankun, Zhao, Zhao Zhili, , Aleksandar Topic, Antonio Ospite, +Bastien Nocera, Benjamin Gaignard, Brad Hards, Carlos Falgueras García, +Célestin Marot, Corentin Damman, Corentin Noël, Daniel Almeida, Daniel +Knobe, Danny Smith, Dave Piché, Dmitry Osipenko, Fabrice Fontaine, +fjmax, Florian Zwoch, Guillaume Desmottes, Haihua Hu, Heinrich Kruger, +He Junyan, Jakub Adam, James Cowgill, Jan Alexander Steffens (heftig), +Jean Felder, Jeongki Kim, Jiri Uncovsky, Joe Todd, Jordan Petridis, +Krystian Wojtas, Marc-André Lureau, Marcin Kolny, Marc Leeman, Mark +Nauwelaerts, Martin Reboredo, Mathieu Duponchelle, Matthew Waters, +Mengkejiergeli Ba, Michael Gruner, Nicolas Dufresne, Nirbheek Chauhan, +Olivier Crête, Philippe Normand, Rafał Dzięgiel, Ralf Sippl, Robert +Mader, Sanchayan Maity, Sangchul Lee, Sebastian Dröge, Seungha Yang, +Stéphane Cerveau, Teh Yule Kim, Thibault Saunier, Thomas Klausner, Timo +Wischer, Tim-Philipp Müller, Tobias Reineke, Tomasz Andrzejak, Trung Do, +Tyler Compton, Ung, Víctor Manuel Jáquez Leal, Vivia Nikolaidou, Wim +Taymans, wngecn, Wonchul Lee, wuchang li, Xavier Claessens, Xi Ruoyao, +Yoshiharu Hirose, Zhao, + +… 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 was released on 3 February 2022. + +1.20.1 + +The first 1.20 bug-fix release (1.20.1) was released on 14 March 2022. + +This release only contains bugfixes and it should be safe to update from +1.20.0. + +Highlighted bugfixes in 1.20.1 + +- deinterlace: various bug fixes for yadif and greedy methods +- gtk video sink: Fix rotation not being applied when paused +- gst-play-1.0: Fix trick-mode handling in keyboard shortcut +- jpegdec: fix RGB conversion handling +- matroskademux: improved ProRes video handling +- matroskamux: Handle multiview-mode/flags/pixel-aspect-ratio caps + fields correctly when checking caps equality on input caps changes +- videoaggregator fixes (negative rate handling, current position + rounding) +- soup http plugin: Lookup libsoup dylib files on Apple platforms & + fix Cerbero static build on Android and iOS +- Support build against libfreeaptx in openaptx plugin +- Fix linking issues on Illumos distros +- GstPlay: Fix new error + warning parsing API (was unusuable before) +- mpegtsmux: VBR muxing fixes +- nvdecoder: Various fixes for 4:4:4 and high-bitdepth decoding +- Support build against libfreeaptx in openaptx plugin +- webrtc: Various fixes to the webrtc-sendrecv python example +- macOS: support a relocatable GStreamer.framework on macOS (see below + for details) +- macOS: fix applemedia plugin failing to load on ARM64 macOS +- windows: ship wavpack library +- gst-python: Fix build with Python 3.11 +- various bug fixes, memory leak fixes, and other stability and + reliability improvements + +gstreamer + +- plugin loader: show the reason when spawning of gst-plugin-scanner + fails +- registry, plugin loading: fix dynamic relocation if + GST_PLUGIN_SUBDIR (libdir) is not a single subdirectory; improve + GST_PLUGIN_SUBDIR handling +- context: fix transfer annotation on gst_context_writable_structure() + for bindings +- baseparse: Don’t truncate the duration to milliseconds in + gst_base_parse_convert_default() +- bufferpool: Deactivate pool and get rid of references to other + objects from dispose instead of finalize + +gst-plugins-base + +- typefindfunctions: Fix WebVTT format detection for very short files +- gldisplay: Reorder GST_GL_WINDOW check for egl-device +- rtpbasepayload: Copy all buffer metadata instead of just GstMetas + for the input meta buffer +- codec-utils: Avoid out-of-bounds error +- navigation: Fix Since markers for mouse scroll events +- videoaggregator: Fix for unhandled negative rate +- videoaggregator: Use floor() to calculate current position +- video-color: Fix for missing clipping in PQ EOTF function +- gst-play-1.0: Fix trick-mode handling in keyboard shortcut +- audiovisualizer: shader: Fix out of bound write + +gst-plugins-good + +- deinterlace: various bug fixes for yadif method +- deinterlace: Refactor greedyh and fix planar formats +- deinterlace: Prevent race between method configuration and latency + query +- gtk video sink: Fix rotation not being applied when paused +- jpegdec: fix RGB conversion handling +- matroskademux: improved ProRes video handling +- matroskamux: Handle multiview-mode/flags/pixel-aspect-ratio caps + fields correctly when checking caps equality on input caps changes +- rtprtx: don’t access type-system per buffer (performance + optimisation); code cleanups +- rtpulpfecenc: fix unmatched g_slice_free() +- rtpvp8depay: fix crash when making GstRTPPacketLost custom event +- qtmux: Don’t post an error message if pushing a sample failed with + FLUSHING (e.g. on pipeline shutdown) +- soup: Lookup libsoup dylib files on Apple platforms & fix Cerbero + static build on Android and iOS +- souphttpsrc: element not present on iOS after 1.20.0 update +- v4l2tuner: return NULL if no norm set +- v4l2bufferpool: Fix race condition between qbuf and pool streamoff +- meson: Don’t build lame plugin with -Dlame=disabled + +gst-plugins-bad + +- GstPlay: Fix new error + warning parsing API (was unusuable before) +- av1parse: let the parser continue on verbose OBUs +- d3d11converter: Fix RGB to GRAY conversion, broken debug messages, + and add missing GRAY conversion +- gs: look for google_cloud_cpp_storage.pc +- ipcpipeline: fix crash and error on windows with SOCKET or _pipe() +- ivfparse: Don’t set zero resolution on caps +- mpegtsdemux: Handle PES headers bigger than a mpeg-ts packet; fix + locking in error code path; handle more program updates +- mpegtsmux: Start last_ts with GST_CLOCK_TIME_NONE to fix VBR muxing + behaviour +- mpegtsmux: Thread safety fixes: lock mux->tsmux, the programs hash + table, and pad streams +- mpegtsmux: Skip empty buffers +- osxaudiodeviceprovider: Add initial support for duplex devices on + OSX +- rtpldacpay: Fix missing payload information +- sdpdemux: add media attributes to caps, fixes ptp clock handling +- mfaudioenc: Handle empty IMFMediaBuffer +- nvdecoder: Various fixes for 4:4:4 and high-bitdepth decoding +- nvenc: Fix deadlock because of too strict buffer pool size +- va: fix library build issues, caps leaks in the vpp transform + function, and add vaav1dec to documentation +- v4l2codecs: vp9: Minor fixes +- v4l2codecs: h264: Correct scaling matrix ABI check +- dtlstransport: Notify ICE transport property changes +- webrtc: Various fixes to the webrtc-sendrecv python example +- webrtc-ice: Fix memory leaks in gst_webrtc_ice_add_candidate() +- Support build against libfreeaptx in openaptx plugin +- Fix linking issues on Illumos distros + +gst-plugins-ugly + +- x264enc: fix plugin long-name and description + +gst-libav + +- No changes + +gst-rtsp-server + +- Fix race in rtsp-client when tunneling over HTTP + +gstreamer-vaapi + +- No changes + +gstreamer-sharp + +- No changes + +gst-omx + +- No changes + +gst-python + +- Fix build with Python 3.11 + +gst-editing-services + +- Update validate test scenarios for videoaggregator rounding + behaviour change + +gst-integration-testsuites + +- Update validate test scenarios for videoaggregator rounding + behaviour change + +Development build environment + +- gst-env: various clean-ups and documentation improvements + +Cerbero build tool and packaging changes in 1.20.1 + +- Fix nasm version check +- Disable certificate checking on RHEL/CentOS 7 +- packages: Ship wavpack.dll for Windows +- osx/universal: make the library name relocatable +- macOS: In order to support a relocatable GStreamer.framework on + macOS, an application may now need to add an rpath entry to the + location of the GStreamer.framework (which could be bundled with the + application itself). Some build systems will do this for you by + default. +- Disable MoltenVK on macOS arm64 to fix applemedia plugin loading +- Fix applemedia plugin failing to load on ARM64 macOS + +Contributors to 1.20.1 + +Bastien Nocera, Branko Subasic, David Svensson Fors, Dmitry Osipenko, +Edward Hervey, Guillaume Desmottes, Havard Graff, Heiko Becker, He +Junyan, Igor V. Kovalenko, Jan Alexander Steffens (heftig), Jan Schmidt, +jinsl00000, Joseph Donofry, Jose Quaresma, Marek Vasut, Matthew Waters, +Mengkejiergeli Ba, Nicolas Dufresne, Nirbheek Chauhan, Philippe Normand, +Qi Hou, Rouven Czerwinski, Ruben Gonzalez, Sanchayan Maity, Sangchul +Lee, Sebastian Dröge, Sebastian Fricke, Sebastian Groß, Sebastian +Mueller, Sebastian Wick, Seungha Yang, Stéphane Cerveau, Thibault +Saunier, Tim Mooney, Tim-Philipp Müller, Víctor Manuel Jáquez Leal, +Vivia Nikolaidou, Zebediah Figura, + +… and many others who have contributed bug reports, translations, sent +suggestions or helped testing. Thank you all! + +List of merge requests and issues fixed in 1.20.1 + +- List of Merge Requests applied in 1.20.1 +- List of Issues fixed in 1.20.1 + +1.20.2 + +The second 1.20 bug-fix release (1.20.2) was released on 2 May 2022. + +This release only contains bugfixes and it should be safe to update from +1.20.x. + +Highlighted bugfixes in 1.20.2 + +- avviddec: Remove vc1/wmv3 override and fix crashes on WMV files with + FFMPEG 5.0+ +- macOS: fix plugin discovery for GStreamer installed via brew and fix + loading of Rust plugins +- rtpbasepayload: various header extension handling fixes +- rtpopusdepay: fix regression in stereo input handling if + sprop-stereo is not advertised +- rtspclientsink: fix possible shutdown deadlock +- mpegts: gracefully handle “empty” program maps and fix AC-4 + detection +- mxfdemux: Handle empty VANC packets and fix EOS handling +- playbin3: various playbin3, uridecodebin3, and playsink fixes +- ptpclock: fix initial sync-up with certain devices +- gltransformation: let graphene alloc its structures memory aligned +- webrtcbin fixes and webrtc sendrecv example improvements +- video4linux2: various fixes including some fixes for Raspberry Pi + users +- videorate segment handling fixes and other fixes +- nvh264dec, nvh265dec: Fix broken key-unit trick modes and reverse + playback +- wpe: Reintroduce persistent WebContext +- cerbero: Make it easier to consume 1.20.1 macOS GStreamer .pkgs +- build fixes and gobject annotation fixes +- bug fixes, security fixes, memory leak fixes, and other stability + and reliability improvements + +gstreamer + +- devicemonitor: clean up signal handlers and hidden providers list +- Leaks tracer: fix pthread_atfork return value check leading to bogus + warning in log +- Rust plugins: Not picked up by the plugin loader on macOS +- Failed to use plugins of latest GStreamer version 1.20.x installed + by brew on macOS +- ptpclock: Allow at least 100ms delay between Sync/Follow_Up and + Delay_Req/Delay_Resp messages. Fixes problems acquiring initial sync + with certain devices +- meson: Add -Wl,-rpath,${libdir} on macOS +- registry: skip Rust dep builddirs when searching for plugins + recursively + +gst-plugins-base + +- appsrc: Clarify buffer ref semantics in signals documentation +- appsrc: fix annotations for bindings +- typefind: Skip extension parsing for data:// URIs, fixing regression + with mp4 files serialised to data uris +- playbin3: various fixes +- playbin3: fix missing lock when unknown stream type in pad-removed + cb +- decodebin3: fix collection leaks +- decodebin3: Don’t duplicate stream selections +- discoverer: chain up to parent finalize methods in all our types to + fix memory leaks +- glmixerbin: slightly better pad/element creation +- gltransformation: let graphene alloc its structures memory aligned +- ogg: fix possible buffer overrun +- rtpbasepayload: Don’t write header extensions if there’s no + corresponding… +- rtpbasepayload: always store input buffer meta before negotiation +- rtpbasepayload: fix transfer annotation for push and push_list +- subparse: don’t try to index string with -1 +- riff-media: fix memory leak after usage for g_strjoin() +- playbin/playbin3: Allow setting a NULL URI +- playsink: Complete reconfiguration on pad release. +- parsebin: Expose streams of unknown type +- pbutils: Fix wmv screen description detection +- subparse: don’t deref a potentially NULL variable +- rawvideoparse: set format from caps in + gst_raw_video_parse_set_config_from_caps +- videodecoder: release stream lock after handling gap events +- videorate: fix assertion when pushing last and only buffer without + duration +- videorate: Revert “don’t reset on segment update” to fix segment + handling regressions +- gst-play-1.0, gst-launch-1.0: Enable win32 high-resolution timer + also for MinGW build + +gst-plugins-good + +- deinterlace: silence unused-but-set werror from imported code +- qtdemux: fix leak of channel_mapping +- rtpopusdepay: missing sprop-stereo should not assume mono +- rtpjitterbuffer: Fix invalid memory access in + rtp_jitter_buffer_pop() +- rtpptdemux: fix leak of caps when ignoring a pt +- rtpredenc: quieten warning about ignoring header extensions +- soup: Fix pre-processor macros in souploader for libsoup-3.0 +- twcc: Note that twcc-stats packet loss counts reordering as loss + + add some logging +- video4linux2: Manual backports for RPi users +- wavparse: handle URI query in any parse state, fixing audio track + selection issue in GES +- wavparse: Unset DISCONT buffer flag for divided into multiple + buffers in push mode + +gst-plugins-bad + +- av1parse: Fix several issues about the colorimetry. +- av1parse: fix up various possible logic errors +- dashsink: fix missing mutex unlock in error code path when failing + to get content +- d3d11videosink: Fix for unhandled mouse double click events +- interlace: Also handle a missing “interlace-mode” field as + progressive +- msdk: fix build with MSVC +- mxfdemux: Fix issues at EOS +- mxfdemux: Handle empty VANC packets +- nvh264dec, nvh265dec: Fix broken key-unit trick and reverse playback +- nvvp9sldec: Increase DPB size to cover render delay +- rvsg: fix cairo include +- tsdemux: Fix AC-4 detection in MPEG-TS +- tsdemux: Handle “empty” PMT gracefully +- va: pool: don’t advertise the GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT + option any more +- v4l2codecs: Fix memory leak +- v4l2videodec: set frame duration according to framerate +- webrtcbin: Update documentation of ‘get-stats’ action signal +- webrtcbin: Check data channel transport for notifying + ‘ice-gathering-state’ +- webrtcbin: Avoid access of freed memory +- wpe: Reintroduce persistent WebContext +- Build: use CMake to find some openssl and exr deps +- Fix multiple “unused-but-set variable” compiler warnings + +gst-plugins-ugly + +- x264enc: Don’t try to fixate ANY allowed caps + +gst-libav + +- video decoders: fix frame leak on negotiation error +- Fix build on systems without C++ compiler +- avviddec: Remove vc1/wmv3 override (fixing crash with FFmpeg 5 +- Segfaults on ASF/WMV files with FFMPEG 5.0+ + +gst-rtsp-server + +- rtspclientsink: fix possible shutdown deadlock in collect_streams() +- Minor spelling fixes + +gstreamer-vaapi + +- No changes + +gstreamer-sharp + +- No changes + +gst-omx + +- No changes + +gst-python + +- Fix build on systems without C++ compiler + +gst-editing-services + +- License clarification: GES is released under the LGPL2+ license + +gst-examples: + +- Fix build on macOS with gtk+-quartz-3.0 +- player android: add missing dummy.cpp +- player android: update for android changes +- webrtc_sendrecv.py: Link pads instead of elements +- webrtc_sendrecv.py: Implement all negotiation modes + bugfixes + +Development build environment + gst-full build + +- meson: provide gobject-cast-checks, glib-checks and glib-asserts + options at top level as well + +Cerbero build tool and packaging changes in 1.20.2 + +- macOS: Make it easier to consume 1.20.1 GStreamer .pkgs +- Android: fix text relocation regression on Android (x86/ x86_64 + platforms) + +Bindings + +- appsrc: fix annotations for bindings +- bindings: The out args for gst_rtp_buffer_get_extension_data*() are + optional +- rtpbasepayload: fix transfer annotation for push and push_list + +Contributors to 1.20.2 + +Bastian Krause, Benjamin Gaignard, Camilo Celis Guzman, Chun-wei Fan, +Corentin Damman, Daniel Stone, Dongil Park, Edward Hervey, Fabrice +Fontaine, Guillaume Desmottes, Havard Graff, He Junyan, Hoonhee Lee, Hou +Qi, Jan Schmidt, Marc Leeman, Mathieu Duponchelle, Matthew Waters, +Nicolas Dufresne, Nirbheek Chauhan, Philippe Normand, Pierre Bourré, +Sangchul Lee, Sebastian Dröge, Seungha Yang, Stéphane Cerveau, Thibault +Saunier, Tim-Philipp Müller, Tong Wu, Tristan Matthews, Tulio Beloqui, +Wonchul Lee, Zhao Zhili, + +… and many others who have contributed bug reports, translations, sent +suggestions or helped testing. Thank you all! + +List of merge requests and issues fixed in 1.20.2 + +- List of Merge Requests applied in 1.20.2 +- List of Issues fixed in 1.20.2 + +1.20.3 + +The third 1.20 bug-fix release (1.20.3) was released on 15 June 2022. + +This release only contains bugfixes and it should be safe to upgrade +from 1.20.x. + +Highlighted bugfixes in 1.20.3 + +- Security fixes in Matroska, MP4 and AVI demuxers +- Fix scrambled video playback with hardware-accelerated VA-API + decoders on certain Intel hardware +- playbin3/decodebin3 regression fix for unhandled streams +- Fragmented MP4 playback fixes +- Android H.265 encoder mapping +- Playback of MXF files produced by FFmpeg before March 2022 +- Fix rtmp2sink crashes on 32-bit platforms +- WebRTC improvements +- D3D11 video decoder and screen recorder fixes +- Performance improvements +- Support for building against OpenCV 4.6 and other build fixes +- Miscellaneous bug fixes, memory leak fixes, and other stability and + reliability improvements + +gstreamer + +- clock: Avoid creating a weakref with every entry (performance + improvement) +- plugin: add Apache 2 license to list of known licenses to avoid + warning +- gst_plugin_load_file: force plugin reload if filename differs +- Add support for LoongArch + +Base Libraries + +- aggregator: Only send events up to CAPS event from + gst_aggregator_set_src_caps(), don’t send multiple caps events with + the same caps and fix negotiation in muxers +- basetransform: handle gst_base_transform_query_caps() returning NULL +- basetransform: fix critical if transform_caps() returned NULL +- queuearray: Fix potential heap overflow when expanding GstQueueArray + +Core Elements + +- multiqueue: fix potential crash on shutdown +- multiqueue: fix warning: ‘is_query’ may be used uninitialized in + this function +- multiqueue: SegFault during flushing with gcc11 + +gst-plugins-base + +- audioconvert: If no channel-mask can be fixated then use a NONE + channel layout +- playbin3: Configure combiner on pad-added if needed +- parsebin: Fix assertions/regression when dealing with un-handled + streams (fixes regression in 1.20.2) +- appsink: Fix race condition on caps handling +- oggdemux: Protect against invalid framerates +- rtcpbuffer: Allow padding on first reduced size packets +- gl: check for xlib-xcb.h header to fix build of tests on macOS with + homebrew +- videoaggregator: unref temporary caps +- v4l2videoenc: Setup crop rectangle if needed + +Tools + +- gst-play-1.0: Print position even if duration is unknown +- gst-device-monitor-1.0: Print string property as-is without + additional escaping + +gst-plugins-good + +- aacparse: Avoid mismatch between src_caps and output_header_type +- avidemux: Fix integer overflow resulting in heap corruption in DIB + buffer inversion code (Security fix) +- deinterlace: Clean up error handling code +- flvdemux: Actually make use of the debug category +- gtkglsink: Fix double-free when OpenGL can’t be initialised +- jack: Add support for detecting libjack on Windows +- matroskademux: Avoid integer-overflow resulting in heap corruption + in WavPack header handling code (Security fix) +- matroskademux, qtdemux: Fix integer overflows in zlib/bz2/etc + decompression code (Security fix) +- qtdemux: Don’t use tfdt for parsing subsequent trun boxes +- rtpbin: Avoid holding GST_RTP_BIN_LOCK when emitting pad-added + signal (to avoid deadlocks) +- rtpptdemux: Don’t GST_FLOW_ERROR when ignoring invalid packets +- smpte: Fix integer overflow with possible heap corruption in GstMask + creation. (Security fix) +- smpte: integer overflow with possible heap corruption in GstMask + creation (Security fix) +- soup: fix soup debug category initialisation +- soup: Fix plugin/element init +- v4l2: Reset transfer in gst_v4l2_object_acquire_format() +- vpxenc: fix crash if encoder produces unmatching timestamp +- wavparse: ensure that any pending segment is sent before an EOS + event is sent + +gst-plugins-bad + +- androidmedia: Add H.265 encoder mapping +- avfvideosrc: fix wrong framerate selected for caps +- d3d11decoder: Fix for alternate interlacing signalling +- d3d11decoder: Do not preallocate texture using downstream d3d11 + buffer pool +- d3d11decoder: Copy HDR10 related caps field manually +- d3d11decoder: Work around Intel DXVA driver crash +- d3d11screencapture: Set viewport when drawing mouse cursor +- d3d11screencapture: Fix missing/outdated cursor shape +- d3d11screencapturesrc: Fix crash when d3d11 device is different from + owned one +- h264decoder: Fix for unhandled low-delay decoding case +- matroskademux, qtdemux: Fix integer overflows in zlib/bz2/etc + decompression code (Security fix) +- mpegtsmux: Make sure to set srcpad caps under all conditions before + outputting the first buffer +- mpegtsmux: sends segment before caps +- mxfdemux: Handle files produced by legacy FFmpeg +- nvh264dec,nvh265dec: Don’t realloc bitstream buffer per slice +- nvcodec: cuda-converter: fix nvrtc compilation on non-English locale + systems +- opencv: Allow building against 4.6.x +- pcapparse: Set timestamp in DTS, not PTS +- rtmp2: fix allocation of GstRtmpMeta which caused crashes on 32-bit + platforms +- rtmp2sink crash on Android arm 32 - cerbero 1.20.2.0 +- sdpdemux: Release request pads from rtpbin when freeing a stream +- va: Add O_CLOEXEC flag at opening drm device (so subprocesses won’t + have access to it) +- webrtcbin: Reject answers that don’t contain the same number of + m-line as offer +- webrtc: datachannel: Notify low buffered amount according to spec + +gst-plugins-ugly + +- No changes + +gst-libav + +- No changes + +gst-rtsp-server + +- No changes + +gstreamer-vaapi + +- vaapi: Do not disable the whole vpp when some va operations not + available +- vaapidecode, vaapipostproc: Disable DMAbuf from caps negotiation +- scrambled video with some Intel graphics cards + +gstreamer-sharp + +- No changes + +gst-omx + +- No changes + +gst-python + +- No changes + +gst-editing-services + +- ges/videourisource: handle non-1/1 PAR source videos + +gst-examples: + +- No changes + +Development build environment + gst-full build + +- Update libnice subproject wrap to 0.1.19 +- meson: use better zlib dependency fallback +- meson: Fix deprecation warnings + +Cerbero build tool and packaging changes in 1.20.3 + +- Set GSTREAMER_1_0_ROOT_[MSVC_]X86_64 root environment variable in + System section (not User section) +- bootstrap: Add perl-FindBin dep needed by openssl (which is not + installed by default on RedHat systems) +- Also add build-tools/local/bin to PATH on Linux +- Add a variant to control building of the JACK plugin +- libnice: update to 0.1.19 (fixes some WebRTC issues) +- zlib: update to 1.2.12 + +Bindings + +- No changes + +Contributors to 1.20.3 + +Adam Doupe, Alicia Boya García, Bastien Nocera, Corentin Damman, Damian +Hobson-Garcia, Diogo Goncalves, Edward Hervey, Eli Schwartz, Erwann +Gouesbet, Guillaume Desmottes, He Junyan, Hou Qi, Jakub Adam, James +Hilliard, Jan Alexander Steffens (heftig), Jan Schmidt, Matthew Waters, +Nicolas Dufresne, Nirbheek Chauhan, Olivier Crête, Philippe Normand, +Rabindra Harlalka, Ruben Gonzalez, Sebastian Dröge, Seungha Yang, +Stéphane Cerveau, Thibault Saunier, Tim-Philipp Müller, Tom Schuring, U. +Artie Eoff, Víctor Manuel Jáquez Leal, WANG Xuerui, Xavier Claessens, + +… and many others who have contributed bug reports, translations, sent +suggestions or helped testing. Thank you all! + +List of merge requests and issues fixed in 1.20.3 + +- List of Merge Requests applied in 1.20.3 +- List of Issues fixed in 1.20.3 + +1.20.4 + +The fourth 1.20 bug-fix release (1.20.4) was released on 12 October +2022. + +This release only contains bugfixes and it should be safe to upgrade +from 1.20.x. + +Highlighted bugfixes in 1.20.4 + +- avaudiodec: fix playback issue with WMA files, would throw an error + at EOS with FFmpeg 5.x +- Fix deadlock when loading gst-editing-services plugin +- Fix input buffering capacity in live mode for aggregator, + video/audio aggregator subclasses, muxers +- glimagesink: fix crash on Android +- subtitle handling and subtitle overlay fixes +- matroska-mux: allow width + height changes for avc3|hev1|vp8|vp9 +- rtspsrc: fix control url handling for spec compliant servers and add + fallback for incompliant servers +- WebRTC fixes +- RTP retransmission fixes +- video: fixes for formats with 4x subsampling and horizontal co-sited + chroma (Y41B, YUV9, YVU9 and IYU9) +- macOS build and packaging fixes, in particular fix finding of gio + modules on macOS for https/TLS support +- Performance improvements +- Miscellaneous bug fixes, memory leak fixes, and other stability and + reliability improvements + +gstreamer + +- buffer: drop parent meta in deep copy/foreach_metadata +- devicemonitor: Use a sync bus handler for the provider to avoid + accumulating all messages until the provider is stopped +- element: Fix requesting of pads with string templates +- gst: Protect initialization state with a recursive mutex +- gst: add missing define guard for build without gstreamer debug + logging support +- gst_init: Initialize static plugins just before dynamic plugins +- info: Parse “NONE” as a valid level name +- meta: Set the parent refcount of the GstStructure correctly +- pluginloader: Don’t hang on short reads/writes +- tracers: leaks: fix potentially invalid memory access when trying to + detect object type +- tracers: leaks: fix object-refings.class flags +- uri: When setting the same string again do nothing +- value: Don’t loop forever when serializing invalid flag + +Base Libraries + +- aggregator: fix input buffering in live mode (was too low before in + many cases) +- aggregator: fix reversed active/flushing arguments in debug log + output +- aggregator: Reset EOS flag after receiving a stream-start event + +Core Elements + +- queue2: Hold the lock when modifying sinkresult +- queue2: Fix deadlock when deactivate is called in pull mode + +gst-plugins-base + +- decodebin3: fix mutex leaks +- decodebin3: Fix memory issues with active selection list +- decodebin3, uridecodebin3, urisourcebin: Event handling fixes +- decodebin3: fix EOS event sequence +- parsebin: Avoid crash with unknown streams +- parsebin: SIGSEGV during HLS stream using souphttpsrc +- glimagesink: only allow setting the GL display/context if it is a + valid value +- glimagesink: segfault on android devices +- gstgl: Fix several memory leaks in macOS +- opusenc: improve inband-fec property documentation +- playsink: Hold a reference to the soft volume element +- pbutils: descriptions: fix gst_pb_utils_get_caps_description_flags() +- rtspurl: Use gst_uri_join_strings() in + gst_rtsp_url_get_request_uri_with_control() instead of a + hand-crafted, wrong version +- rtspconnection: protect cancellable by a mutex +- sdpmessage: Don’t set SDP medias from caps without + media/payload/clock-rate fields +- samiparse: fix handling of self-closing tags +- ssaparse: include required system headers for isspace() and sscanf() + functions +- subparse: fix crash when parsing invalid timestamps in mpl2 +- subparse fixes +- textoverlay: Don’t miscalculate text running times +- videoaggregator: always convert when user provides converter-config +- video: Fix scaling in 4x horizontal co-sited chroma (Y41B, YUV9, + YVU9 and IYU9) +- xmptag: register musicbrainz tags during init to fix critical in + jpegparse +- xvimagesink: fix image leaks in error code path +- tests: skip unit tests for dependency-less elements that have been + disabled + +Tools + +- No changes + +gst-plugins-good + +- alpha: fix stride issue when out buffer has padding on right +- isoff: Fix earliest pts field parse issue +- matroska-mux: allow width + height changes for avc3|hev1|vp8|vp9 +- qt: Fix another instance of Qt/GStreamer both defining GLsync + differently +- qtdemux: Avoid crash on reconfiguring. +- qtdemux: guard against timestamp calculation overflow in gap event + loop +- qtdemux: Don’t use invalid values from failed trex parsing +- qtdemux: possible endless loop +- rtpjitterbuffer: Only unschedule timers for late packets if they’re + not RTX packets and only once +- rtpjitterbuffer: remove lost timer for out of order packets +- rtspsrc: SETUP generates 400 Bad Request +- rtspsrc: Retry SETUP with non-compliant URL resolution on “Bad + Request” and “Not found” +- rtpst2022-1-fecenc: Drain column packets on EOS +- rtpvp8depay: If configured to wait for keyframes after packet loss, + also do that if incomplete frames are detected +- splitmuxsink: Don’t crash on EOS without buffer +- splitmuxsrc: Stop pad task before cleanup +- splitmuxsrc: don’t consider unlinked pads when deactivating part +- soup: libsoup3 makes audio streaming stop +- v4l2: fix critical when unreferencign buffer with no data +- v4l2bufferpool: Fix debug trace +- v4l2object: Add support for Apple’s full-range bt709 colorspace + variant 1:3:5:1 +- v4l2videocodec: workaround for failure to fully drain frames + preceding MIDSTREAM renegotiation +- v4l2allocator: Fix invalid imported dmabuf fd +- videoflip: Fix caps negotiation when method is selected +- build failure trying to build jack examples +- examples: don’t try and build jack examples if jack was disabled +- tests: skip unit tests for dependency-less elements that have been + disabled + +gst-plugins-bad + +- amcvideodec: fix GstAmcSurfaceTexture segfault +- audiobuffersplit: Fix drift that was introduced by wrong + calculations in gapless mode +- avfvideosrc: Fix wrong default framerate value +- audiovisualizer: fix buffer mapping to not increase refcount +- d3d11decoder: Check 16K resolution support +- d3d11videosink: Fix for force-aspect-ratio setting when rendering on + shared texture +- mxfdemux: Always calculate BlockAlign of raw audio to work around + files with broken BlockAlign field in the headers +- nvdec: Fix for HEVC decoding when coded resolution is larger than + display resolution +- openh264: Register debug categories earlier +- openh264enc: Fix constrained-high encoding +- openmpt: update from now deprecated api +- GstPlay: missing cleanup for g_autoptr +- player/play: Fix object construction and various leaks +- player: Plug a memory leak +- proxysink: Make sure stream-start and caps events are forwarded, and + fix memory leak +- tsdemux: Don’t trigger a program change when falling back to + ignore-pcr behaviour +- va: allocator: Fix translation of VADRMPRIMESurfaceDescriptor +- va: h265dec: Fix a crash because of missing reference frame. +- vah265dec: Decoder segfaults on seek +- wasapi: Implement default audio channel mask +- wasapi2: Fix initial mute/volume setting +- webrtcbin: Limit sink query to sink pads +- webrtcbin: Fix pointer dereference before null check +- webrtc: Make sure to return NULL when validating TURN server fails +- tests: skip unit tests for dependency-less elements that have been + disabled + +gst-plugins-ugly + +- tests: skip unit tests for dependency-less elements that have been + disabled + +gst-libav + +- avauddec: fix regression with WMA files, would throw an error at EOS +- avauddec: fix unnecessary reconfiguration if the audio layout isn’t + specified +- libav: Fix for APNG encoder property registration +- Failure to decode end of WMA file + +gst-rtsp-server + +- gst-rtsp-server: Fix pushing backlog to client +- rtsp-server: stream: Don’t loop forever if binding to the multicast + address fails + +gstreamer-vaapi + +- vaapi: Handle when no encoders/decoders available. +- vaapi: Crash in gst_vaapidecode_class_init() when no + decoders/encoders available + +gstreamer-sharp + +- No changes + +gst-omx + +- No changes + +gst-python + +- python: Do not call gst_init when it is already is_initialized + +gst-editing-services + +- Deadlock in ges because of recursive gst_init() call +- ges/gstframepositioner: don’t create one compositor per frame meta +- nle: clear seek event properly + +gst-examples: + +- examples/webrtc/signalling: Fix compatibility with Python 3.10 + +Development build environment + gst-full build + +- build: Fix some compiler warnings by upgrading wraps +- dv, opusparse: fix duplicate symbols in static build +- Fix fedora 36 warnings - OpenSSL 3.0 deprecations + GLib 2.72 + tls-validation deprecations +- Various macOS build fixes +- meson: Improve certifi documentation on macOS + +Cerbero build tool and packaging changes in 1.20.4 + +- Add Ubuntu 22.04 Jammy Jellyfish +- Add gst-rtsp-server library to the macOS framework +- cerbero: Quick fix for gen-cache breakage +- macos: Fix the install_name for the GStreamer framework +- Download using powershell on Windows and rework download func +- macos: Add arm64 to the metadata for the installer +- cerbero: Allow building on Linux ARM64 +- pkg-config.recipe: Add to core platform files list +- git: Fix issue with last security patch +- distros: Fix CentOS allowance +- cerbero: Print working directory for commands that are run +- cerbero: Fix license property usage example +- Fix issue getting distro_version in Debian Bookworm +- glib: Fix gio modules loading on macOS +- cmake: Fix macOS ARM64 -> x86_64 cross-compilation +- Fix logo display in macOS installer +- openssl.recipe: Fix segfault on latest macOS +- msvc: Fix for broken CRT linking at application project because of + MSVCRT linking +- cerbero: Do not add rpaths that already exist on macOS +- android: fix build with android gradle plugin 7.2 +- macOS framework is unusable starting from 1.18.0 + +Contributors to 1.20.4 + +Adrian Fiergolski, Aleksandr Slobodeniuk, Andoni Morales Alastruey, +Andrew Pritchard, Bruce Liang, Corentin Damman, Daniel Morin, Edward +Hervey, Elliot Chen, Fabian Orccon, fduncanh, Guillaume Desmottes, +Haihua Hu, He Junyan, Ignazio Pillai, James Cowgill, James Hilliard, Jan +Alexander Steffens (heftig), Jan Schmidt, Jianhui Dai, Jonas Danielsson, +Jordan Petridis, Khem Raj, Krystian Wojtas, Martin Dørum, Mart Raudsepp, +Mathieu Duponchelle, Matthew Waters, Matthias Clasen, Nicolas Dufresne, +Nirbheek Chauhan, Olivier Crête, Paweł Stawicki, Philippe Normand, +Philipp Zabel, Piotr Brzeziński, Rafael Caricio, Rafael Sobral, Raul +Tambre, Ruben Gonzalez, Sangchul Lee, Sebastian Dröge, Seungha Yang, +Stéphane Cerveau, Thibault Saunier, Tim-Philipp Müller, Tristan +Matthews, Víctor Manuel Jáquez Leal, Xavier Claessens, Zhiyuan Liu, + +… and many others who have contributed bug reports, translations, sent +suggestions or helped testing. Thank you all! + +List of merge requests and issues fixed in 1.20.4 + +- List of Merge Requests applied in 1.20.4 +- List of Issues fixed in 1.20.4 + +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 now confirmed, and we aim for +a 1.22.0 release in December 2022. + +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 Matthew Waters, Nicolas Dufresne, Nirbheek Chauhan, +Sebastian Dröge and Seungha Yang. + +License: CC BY-SA 4.0 diff --git a/gst-omx/README b/gst-omx/README new file mode 100644 index 0000000000..6e94c384c2 --- /dev/null +++ b/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/gst-omx/RELEASE b/gst-omx/RELEASE new file mode 100644 index 0000000000..666e1d4aeb --- /dev/null +++ b/gst-omx/RELEASE @@ -0,0 +1,100 @@ +This is GStreamer gst-omx 1.20.4. + +The GStreamer team is thrilled to announce a new major feature release +of your favourite cross-platform multimedia framework! + +As always, this release is again packed with new features, bug fixes and +other improvements. + +The 1.20 release series adds new features on top of the 1.18 series and is +part of the API and ABI-stable 1.x release series. + +Full release notes can 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/gstreamer/ + +==== Homepage ==== + +The project's website is https://gstreamer.freedesktop.org/ + +==== Support and Bugs ==== + +We track bugs and feature requests in GitLab: + + https://gitlab.freedesktop.org/gstreamer/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 OFTC IRC network. + +Please do not submit support requests in GitLab, we only use it +for bug tracking and merge requests review. + +==== Developers ==== + +The GStreamer source code repository can be found on GitLab on freedesktop.org: + + https://gitlab.freedesktop.org/gstreamer/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/gst-omx/config/bellagio/gstomx.conf b/gst-omx/config/bellagio/gstomx.conf new file mode 100644 index 0000000000..0e856bea86 --- /dev/null +++ b/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/gst-omx/config/bellagio/meson.build b/gst-omx/config/bellagio/meson.build new file mode 100644 index 0000000000..dc99c08bc1 --- /dev/null +++ b/gst-omx/config/bellagio/meson.build @@ -0,0 +1 @@ +install_data (['gstomx.conf'], install_dir : omx_conf_dir) diff --git a/gst-omx/config/meson.build b/gst-omx/config/meson.build new file mode 100644 index 0000000000..1068c6d9c6 --- /dev/null +++ b/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/gst-omx/config/rpi/gstomx.conf b/gst-omx/config/rpi/gstomx.conf new file mode 100644 index 0000000000..d3ea56a883 --- /dev/null +++ b/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/gst-omx/config/rpi/meson.build b/gst-omx/config/rpi/meson.build new file mode 100644 index 0000000000..dc99c08bc1 --- /dev/null +++ b/gst-omx/config/rpi/meson.build @@ -0,0 +1 @@ +install_data (['gstomx.conf'], install_dir : omx_conf_dir) diff --git a/gst-omx/config/tizonia/gstomx.conf.in b/gst-omx/config/tizonia/gstomx.conf.in new file mode 100644 index 0000000000..4f7fb2b74e --- /dev/null +++ b/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/gst-omx/config/tizonia/meson.build b/gst-omx/config/tizonia/meson.build new file mode 100644 index 0000000000..86b191db79 --- /dev/null +++ b/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/gst-omx/config/zynqultrascaleplus/gstomx.conf b/gst-omx/config/zynqultrascaleplus/gstomx.conf new file mode 100644 index 0000000000..ca6f4412f0 --- /dev/null +++ b/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/gst-omx/config/zynqultrascaleplus/meson.build b/gst-omx/config/zynqultrascaleplus/meson.build new file mode 100644 index 0000000000..dc99c08bc1 --- /dev/null +++ b/gst-omx/config/zynqultrascaleplus/meson.build @@ -0,0 +1 @@ +install_data (['gstomx.conf'], install_dir : omx_conf_dir) diff --git a/gst-omx/debian/README.Debian b/gst-omx/debian/README.Debian new file mode 100644 index 0000000000..9fffbe2b68 --- /dev/null +++ b/gst-omx/debian/README.Debian @@ -0,0 +1,19 @@ +gst-omx for Debian +----------------- + +For users who are interested in gst-omx please note that just install +gstreamer1.0-omx-generic* won't give you openmax acceleration. +To make gst-omx work usually you need a gstreamer1.0-omx--config and/or +gstreamer1.0-omx- with openmax IL provided by vendor. + +For developers who want to integrate openmax IL as a gstreamer plugin +for Debian please make a new package and use update-alternatives +to /etc/xdg/gstomx.conf and/or +/usr/lib/@DEB_HOST_MULTIARCH@/gstreamer-1.0/libgstomx.so with the priority at +least 50. It depends on if the openmax IL of the vendor compatible with generic +build or not. Please refer the postinst/prerm scripts in package +gstreamer1.0-omx-bellagio-config if generic build works. Otherwise you also +need to package the custom build of gstomx and update-alternative the +libgstomx.so. Please refer gstreamer1.0-omx-generic's postinst/prerm. + + -- Ying-Chun Liu (PaulLiu) Fri, 17 Mar 2017 18:43:28 +0800 diff --git a/gst-omx/debian/changelog b/gst-omx/debian/changelog new file mode 100644 index 0000000000..698998327c --- /dev/null +++ b/gst-omx/debian/changelog @@ -0,0 +1,151 @@ +gst-omx (1.20.4-1.1) UNRELEASED; urgency=medium + + * Add sf target to gst-omx. + + -- Leo Lu Thu, 23 Mar 2023 08:57:18 +0000 + +gst-omx (1.20.4-1) unstable; urgency=low + + * New upstream release. + + -- Ying-Chun Liu (PaulLiu) Wed, 23 Nov 2022 12:54:38 +0800 + +gst-omx (1.20.3-1) unstable; urgency=low + + * New upstream release. + + -- Ying-Chun Liu (PaulLiu) Sat, 25 Jun 2022 09:42:25 +0800 + +gst-omx (1.20.2-1) unstable; urgency=low + + * New upstream release. + + -- Ying-Chun Liu (PaulLiu) Sat, 07 May 2022 00:34:21 +0800 + +gst-omx (1.20.1-1) unstable; urgency=low + + * New upstream release. + + -- Ying-Chun Liu (PaulLiu) Wed, 23 Mar 2022 22:25:03 +0800 + +gst-omx (1.18.5-1) unstable; urgency=low + + * New upstream release. + + -- Ying-Chun Liu (PaulLiu) Mon, 17 Jan 2022 15:19:59 +0800 + +gst-omx (1.18.3-1) unstable; urgency=low + + * New upstream release. + + -- Ying-Chun Liu (PaulLiu) Sat, 23 Jan 2021 03:23:43 +0800 + +gst-omx (1.18.2-1) unstable; urgency=low + + * New upstream release. + + -- Ying-Chun Liu (PaulLiu) Fri, 11 Dec 2020 00:35:56 +0800 + +gst-omx (1.18.1-1) unstable; urgency=low + + * New upstream release. + + -- Ying-Chun Liu (PaulLiu) Thu, 12 Nov 2020 08:15:58 +0800 + +gst-omx (1.18.0-2) unstable; urgency=low + + * debian/gst-omx-listcomponents.install and debian/rules: + Use ${DEB_HOST_GNU_TYPE} instead of ${DEB_HOST_MULTIARCH} to fix FTBFS + on i386. + + -- Ying-Chun Liu (PaulLiu) Wed, 23 Sep 2020 14:03:37 +0800 + +gst-omx (1.18.0-1) unstable; urgency=low + + [ Iain Lane ] + * New upstream release compatible with 1.18. (Closes: #970716) + * Convert to meson, following upstream.. + * debian/patches/0002-remove-distclean-local-orc-target.patch: Drop, this + was a patch for autotools and is not required any more. + * Use compat 13, so we can use substvars in .install files, so that ... + * debian/gst-omx-listcomponents.install: Install from the new build + directory under ${DEB_HOST_MULTIARCH}. Use dh-exec to be able to rename + the file from listcomponents (upstream's name) to gst-omx-listcomponents. + * debian/rules: Explicitly stop installing libgstomx-bellagio.so while we're + not building gstreamer1.0-omx-bellagio, so that dh_missing --fail-missing + passes. + + [ Ying-Chun Liu (PaulLiu) ] + * Bump Standards-Version to 4.5.0: nothing needs to be changed. + * Thanks for Iain's work. + + -- Ying-Chun Liu (PaulLiu) Wed, 23 Sep 2020 03:39:54 +0800 + +gst-omx (1.16.2-4) unstable; urgency=low + + * autopkgtest: Add version depends on latest libomxil-bellagio + + -- Ying-Chun Liu (PaulLiu) Tue, 01 Sep 2020 06:03:34 +0800 + +gst-omx (1.16.2-3) unstable; urgency=low + + * Fix autopkgtest: also test on old lib path + + -- Ying-Chun Liu (PaulLiu) Mon, 31 Aug 2020 06:23:34 +0800 + +gst-omx (1.16.2-2) unstable; urgency=low + + * Fix autopkgtest: libomxil-bellagio changed to Multi-Arch + * Support Multi-Arch in /etc/xdg/gstomx-bellagio.conf + + -- Ying-Chun Liu (PaulLiu) Wed, 12 Aug 2020 14:13:50 +0800 + +gst-omx (1.16.2-1) unstable; urgency=low + + * New upstream release + * Bump debhelper version to 11 + + -- Ying-Chun Liu (PaulLiu) Wed, 11 Dec 2019 04:16:19 +0800 + +gst-omx (1.16.1-1) unstable; urgency=low + + * New upstream release + + -- Ying-Chun Liu (PaulLiu) Sun, 10 Nov 2019 02:24:26 +0800 + +gst-omx (1.14.4-1) unstable; urgency=low + + * New upstream release + * Bump debhelper version to 10 + - start using dh_autoreconf + * Bump Standards-Version to 4.2.1: nothing needs to be changed. + + -- Ying-Chun Liu (PaulLiu) Thu, 08 Nov 2018 08:13:35 +0800 + +gst-omx (1.12.4-1) unstable; urgency=low + + * New upstream release + * debian/rules: fix debhelper-tools-from-autotools-dev-are-deprecated + * Bump Standards-Version to 4.1.2: nothing needs to be changed. + + -- Ying-Chun Liu (PaulLiu) Thu, 14 Dec 2017 01:07:38 +0800 + +gst-omx (1.12.3-2) unstable; urgency=low + + * Fix autopkgtest dependencies + + -- Ying-Chun Liu (PaulLiu) Fri, 03 Nov 2017 17:40:44 +0800 + +gst-omx (1.12.3-1) unstable; urgency=low + + * New upstream release + * listcomponents-bellagio: remove Priority: extra + * Bump Standards-Version to 4.1.1: nothing needs to be changed. + + -- Ying-Chun Liu (PaulLiu) Tue, 31 Oct 2017 18:37:09 +0800 + +gst-omx (1.10.4-1) unstable; urgency=low + + * Initial release (Closes: #858015) + + -- Ying-Chun Liu (PaulLiu) Fri, 17 Mar 2017 18:43:28 +0800 diff --git a/gst-omx/debian/clean b/gst-omx/debian/clean new file mode 100644 index 0000000000..151b55a51e --- /dev/null +++ b/gst-omx/debian/clean @@ -0,0 +1,15 @@ +config.log +tools/gst-omx-listcomponents +gst-omx-listcomponents.1 +examples/egl/testegl +examples/egl/*.o +Makefile +_stdint.h +config.h +config.status +examples/Makefile +examples/egl/Makefile +libtool +stamp-h1 +tests/Makefile +tests/check/Makefile diff --git a/gst-omx/debian/control b/gst-omx/debian/control new file mode 100644 index 0000000000..88afec4e6b --- /dev/null +++ b/gst-omx/debian/control @@ -0,0 +1,69 @@ +Source: gst-omx +Priority: optional +Maintainer: Ying-Chun Liu (PaulLiu) +Build-Depends: debhelper-compat (= 13), + dh-exec, + docbook-xml, + docbook-xsl, + libglib2.0-dev (>= 2.44.0), + libgstreamer-plugins-base1.0-dev (>= 1.18), + libgstreamer1.0-dev (>= 1.18), + meson (>= 0.47), + rename, + xsltproc +Standards-Version: 4.5.0 +Section: libs +Homepage: https://gstreamer.freedesktop.org/modules/gst-omx.html + +Package: gstreamer1.0-omx-generic +Architecture: amd64 arm64 armel armhf i386 mips64el mipsel ppc64el s390x +Depends: ${misc:Depends}, ${shlibs:Depends} +Description: OpenMax plugins for GStreamer + This plugin wraps available OpenMAX IL components and makes them available as + standard GStreamer elements. + +Package: gst-omx-listcomponents +Architecture: amd64 arm64 armel armhf i386 mips64el mipsel ppc64el s390x +Section: utils +Depends: ${misc:Depends}, ${shlibs:Depends} +Description: OpenMax plugins for GStreamer + This package contains listcomponents for listing components in openmax IL. + listcomponents is a debugging tool and should be only used for developers. + +Package: gstreamer1.0-omx-generic-config +Architecture: amd64 arm64 armel armhf i386 mips64el mipsel ppc64el s390x +Section: misc +Depends: gstreamer1.0-omx-generic, ${misc:Depends}, ${shlibs:Depends} +Description: OpenMax plugins for GStreamer + This plugin wraps available OpenMAX IL components and makes them available as + standard GStreamer elements. + . + This package contains the config for gstreamer1.0-omx-generic. + +Package: gstreamer1.0-omx-bellagio-config +Architecture: amd64 arm64 armel armhf i386 mips64el mipsel ppc64el s390x +Section: misc +Depends: gstreamer1.0-omx-generic, ${misc:Depends}, ${shlibs:Depends} +Description: OpenMax plugins for GStreamer + This plugin wraps available OpenMAX IL components and makes them available as + standard GStreamer elements. + . + This package is specific for using Bellagio OpenMAX IL. This package contains + the config for gstreamer1.0-omx-generic. + +Package: gstreamer1.0-omx-sf +Architecture: riscv64 +Depends: ${misc:Depends}, ${shlibs:Depends} +Description: OpenMax plugins for GStreamer + This plugin wraps available OpenMAX IL components and makes them available as + standard GStreamer elements. + +Package: gstreamer1.0-omx-sf-config +Architecture: riscv64 +Section: misc +Depends: gstreamer1.0-omx-sf, ${misc:Depends}, ${shlibs:Depends} +Description: OpenMax plugins for GStreamer + This plugin wraps available OpenMAX IL components and makes them available as + standard GStreamer elements. + This package contains the config for gstreamer1.0-omx-sf. + diff --git a/gst-omx/debian/copyright b/gst-omx/debian/copyright new file mode 100644 index 0000000000..14e8e398de --- /dev/null +++ b/gst-omx/debian/copyright @@ -0,0 +1,153 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: gst-omx +Source: https://gstreamer.freedesktop.org/src/gst-omx/ + +Files: * +Copyright: 2014 Sebastian Dröge +License: LGPL-2.1 + +Files: omx/gstomxamrdec.c +Copyright: 2014 Sebastian Dröge + 2014 LG Electronics, Inc. +License: LGPL-2.1 + +Files: omx/gstomxaudioenc.* omx/gstomxh263dec.* omx/gstomxvideoenc.* omx/gstomxmjpegdec.h omx/gstomxh264dec.* omx/gstomxh264enc.* omx/gstomxh263enc.* omx/gstomxmpeg4videodec.* omx/gstomxmpeg2videodec.* omx/gstomxaacenc.* omx/gstomxmpeg4videoenc.* omx/gstomxwmvdec.* omx/gstomxvideodec.h +Copyright: 2011 Hewlett-Packard Development Company, L.P. +License: LGPL-2.1 + +Files: omx/gstomxvideo.c +Copyright: 2011 Hewlett-Packard Development Company, L.P. + 2013 Collabora Ltd. + 2014 Advanced Micro Devices, Inc. +License: LGPL-2.1 + +Files: omx/gstomxaudiodec.c +Copyright: 2011 Hewlett-Packard Development Company, L.P. + 2013 Collabora Ltd. + 2014 Sebastian Dröge +License: LGPL-2.1 + +Files: omx/gstomxbufferpool.c omx/gstomxvideodec.c omx/gstomx.* +Copyright: 2011 Hewlett-Packard Development Company, L.P. + 2013 Collabora Ltd. +License: LGPL-2.1 + +Files: omx/gstomxvideo.h omx/gstomxbufferpool.h +Copyright: 2014 Advanced Micro Devices, Inc. +License: LGPL-2.1 + +Files: omx/gstomxaudiosink.* omx/gstomxhdmiaudiosink.* omx/gstomxanalogaudiosink.* +Copyright: 2014 Fluendo, S.A. + 2014 Metrological Media Innovations B.V. +License: LGPL-2.1 + +Files: omx/gstomxtheoradec.c omx/gstomxvp8dec.* omx/gstomxtheoradec.h omx/gstomxmjpegdec.c tools/listcomponents.c +Copyright: 2013 Collabora Ltd. +License: LGPL-2.1 + +Files: commons/m4/*.m4 +Copyright: 2004 Scott James Remnant + 2007 Guido U. Draheim + 2008 Steven G. Johnson + 2009 Johan Dahlin + 2011 Daniel Richard G. +License: GPL-2+ with autoconf exception + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + . + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + . + As a special exception to the GNU General Public License, if you + distribute this file as part of a program that contains a + configuration script generated by Autoconf, you may include it under + the same distribution terms that you use for the rest of that program. + . + On Debian systems, the complete text of the GNU General Public License + version 2 can be found in "/usr/share/common-licenses/GPL-2". + +Files: omx/openmax/* +Copyright: 2008-2010 The Khronos Group Inc. +License: MIT + +Files: examples/egl/*.c examples/egl/*.h +Copyright: 2012 Broadcom Europe Ltd + 2012 OtherCrashOverride + 2013 Fluendo S.A. + 2013 Video Experts Group LLC. + 2014 Julien Isorce +License: BSD-3-clause + +Files: debian/* +Copyright: 2017 Ying-Chun Liu (PaulLiu) +License: LGPL-2.1 + +License: LGPL-2.1 + 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 + . + On Debian systems, the complete text of the GNU Lesser General + Public License version 2.1 can be found in + "/usr/share/common-licenses/LGPL-2.1". + +License: MIT + 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. + +License: BSD-3-clause + 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. diff --git a/gst-omx/debian/gst-omx-listcomponents.1.xml b/gst-omx/debian/gst-omx-listcomponents.1.xml new file mode 100644 index 0000000000..375dae54b3 --- /dev/null +++ b/gst-omx/debian/gst-omx-listcomponents.1.xml @@ -0,0 +1,129 @@ + +.
will be generated. You may view the +manual page with: nroff -man .
| less'. A typical entry +in a Makefile or Makefile.am is: + +DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/docbook-xsl/manpages/docbook.xsl +XP = xsltproc -''-nonet -''-param man.charmap.use.subset "0" + +manpage.1: manpage.xml + $(XP) $(DB2MAN) $< + +The xsltproc binary is found in the xsltproc package. The XSL files are in +docbook-xsl. A description of the parameters you can use can be found in the +docbook-xsl-doc-* packages. Please remember that if you create the nroff +version in one of the debian/rules file targets (such as build), you will need +to include xsltproc and docbook-xsl in your Build-Depends control field. +Alternatively use the xmlto command/package. That will also automatically +pull in xsltproc and docbook-xsl. + +Notes for using docbook2x: docbook2x-man does not automatically create the +AUTHOR(S) and COPYRIGHT sections. In this case, please add them manually as + ... . + +To disable the automatic creation of the AUTHOR(S) and COPYRIGHT sections +read /usr/share/doc/docbook-xsl/doc/manpages/authors.html. This file can be +found in the docbook-xsl-doc-html package. + +Validation can be done using: `xmllint -''-noout -''-valid manpage.xml` + +General documentation about man-pages and man-page-formatting: +man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/ + +--> + + + + + + + + + + + + + +]> + + + + &dhtitle; + &dhpackage; + + + &dhfirstname; + &dhsurname; + Wrote this manpage for the Debian system. +
+ &dhemail; +
+
+
+ + 2017 + &dhusername; + + + This manual page was written for the Debian system + (and may be used by others). + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Lesser General Public License, + Version 2.1 or (at your option) any later version published by + the Free Software Foundation. + On Debian systems, the complete text of the GNU Lesser General Public + License can be found in + /usr/share/common-licenses/LGPL-2.1. + +
+ + &dhucpackage; + &dhsection; + + + &dhpackage; + program to list the name of components in openmax IL + + + + &dhpackage; + + + + + + DESCRIPTION + This manual page documents briefly the + &dhpackage; + command. + This manual page was written for the Debian distribution + because the original program does not have a manual page. + + &dhpackage; is a program that can list the name + of components in libopenmax.so. It helps you to write the /etc/xdg/gstomx.conf + + + OPTIONS + + The program doesn't have any options yet. + + + + +
+ diff --git a/gst-omx/debian/gst-omx-listcomponents.install b/gst-omx/debian/gst-omx-listcomponents.install new file mode 100644 index 0000000000..42acc4a54f --- /dev/null +++ b/gst-omx/debian/gst-omx-listcomponents.install @@ -0,0 +1,2 @@ +#!/usr/bin/dh-exec +obj-${DEB_HOST_GNU_TYPE}/tools/listcomponents => usr/bin/gst-omx-listcomponents diff --git a/gst-omx/debian/gst-omx-listcomponents.manpages b/gst-omx/debian/gst-omx-listcomponents.manpages new file mode 100644 index 0000000000..3138cfa744 --- /dev/null +++ b/gst-omx/debian/gst-omx-listcomponents.manpages @@ -0,0 +1 @@ +gst-omx-listcomponents.1 diff --git a/gst-omx/debian/gstomx-generic.conf b/gst-omx/debian/gstomx-generic.conf new file mode 100644 index 0000000000..c5596af516 --- /dev/null +++ b/gst-omx/debian/gstomx-generic.conf @@ -0,0 +1,4 @@ +# This file is empty which means the generic gstomx needs to be configured +# according to the hardware. You can edit this file for testing purpose +# but for production please provide a package and use update-alternaties +# to replace it. Please read README.Debian diff --git a/gst-omx/debian/gstreamer1.0-omx-bellagio-config.install b/gst-omx/debian/gstreamer1.0-omx-bellagio-config.install new file mode 100644 index 0000000000..6cea1226ec --- /dev/null +++ b/gst-omx/debian/gstreamer1.0-omx-bellagio-config.install @@ -0,0 +1 @@ +etc/xdg/*-bellagio.conf diff --git a/gst-omx/debian/gstreamer1.0-omx-bellagio-config.postinst b/gst-omx/debian/gstreamer1.0-omx-bellagio-config.postinst new file mode 100644 index 0000000000..e265139b82 --- /dev/null +++ b/gst-omx/debian/gstreamer1.0-omx-bellagio-config.postinst @@ -0,0 +1,44 @@ +#!/bin/sh +# postinst script for gst-omx +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + update-alternatives --install \ + /etc/xdg/gstomx.conf \ + gstomx.conf \ + /etc/xdg/gstomx-bellagio.conf \ + 30 + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/gst-omx/debian/gstreamer1.0-omx-bellagio-config.prerm b/gst-omx/debian/gstreamer1.0-omx-bellagio-config.prerm new file mode 100644 index 0000000000..fd3547f123 --- /dev/null +++ b/gst-omx/debian/gstreamer1.0-omx-bellagio-config.prerm @@ -0,0 +1,41 @@ +#!/bin/sh +# prerm script for gst-omx +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `upgrade' +# * `failed-upgrade' +# * `remove' `in-favour' +# * `deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + remove|upgrade|deconfigure) + update-alternatives --remove \ + gstomx.conf \ + /etc/xdg/gstomx-bellagio.conf + ;; + + failed-upgrade) + ;; + + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/gst-omx/debian/gstreamer1.0-omx-bellagio.install b/gst-omx/debian/gstreamer1.0-omx-bellagio.install new file mode 100644 index 0000000000..4d029c36b5 --- /dev/null +++ b/gst-omx/debian/gstreamer1.0-omx-bellagio.install @@ -0,0 +1 @@ +usr/lib/*/gstreamer*/lib*-bellagio.so diff --git a/gst-omx/debian/gstreamer1.0-omx-bellagio.postinst.in b/gst-omx/debian/gstreamer1.0-omx-bellagio.postinst.in new file mode 100644 index 0000000000..4e6396737b --- /dev/null +++ b/gst-omx/debian/gstreamer1.0-omx-bellagio.postinst.in @@ -0,0 +1,44 @@ +#!/bin/sh +# postinst script for gst-omx +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + update-alternatives --install \ + /usr/lib/@DEB_HOST_MULTIARCH@/gstreamer-1.0/libgstomx.so \ + libgstomx-@DEB_HOST_MULTIARCH@.so \ + /usr/lib/@DEB_HOST_MULTIARCH@/gstreamer-1.0/libgstomx-bellagio.so \ + 30 + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/gst-omx/debian/gstreamer1.0-omx-bellagio.prerm.in b/gst-omx/debian/gstreamer1.0-omx-bellagio.prerm.in new file mode 100644 index 0000000000..c41e9c4e63 --- /dev/null +++ b/gst-omx/debian/gstreamer1.0-omx-bellagio.prerm.in @@ -0,0 +1,41 @@ +#!/bin/sh +# prerm script for gst-omx +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `upgrade' +# * `failed-upgrade' +# * `remove' `in-favour' +# * `deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + remove|upgrade|deconfigure) + update-alternatives --remove \ + libgstomx-@DEB_HOST_MULTIARCH@.so \ + /usr/lib/@DEB_HOST_MULTIARCH@/gstreamer-1.0/libgstomx-bellagio.so + ;; + + failed-upgrade) + ;; + + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/gst-omx/debian/gstreamer1.0-omx-generic-config.dirs b/gst-omx/debian/gstreamer1.0-omx-generic-config.dirs new file mode 100644 index 0000000000..e7c764f897 --- /dev/null +++ b/gst-omx/debian/gstreamer1.0-omx-generic-config.dirs @@ -0,0 +1 @@ +etc/xdg diff --git a/gst-omx/debian/gstreamer1.0-omx-generic-config.docs b/gst-omx/debian/gstreamer1.0-omx-generic-config.docs new file mode 100644 index 0000000000..e174728f54 --- /dev/null +++ b/gst-omx/debian/gstreamer1.0-omx-generic-config.docs @@ -0,0 +1 @@ +debian/README.Debian diff --git a/gst-omx/debian/gstreamer1.0-omx-generic-config.install b/gst-omx/debian/gstreamer1.0-omx-generic-config.install new file mode 100644 index 0000000000..0111bb1e1d --- /dev/null +++ b/gst-omx/debian/gstreamer1.0-omx-generic-config.install @@ -0,0 +1 @@ +debian/gstomx-generic.conf etc/xdg/ diff --git a/gst-omx/debian/gstreamer1.0-omx-generic-config.postinst b/gst-omx/debian/gstreamer1.0-omx-generic-config.postinst new file mode 100644 index 0000000000..18fc7cb7a5 --- /dev/null +++ b/gst-omx/debian/gstreamer1.0-omx-generic-config.postinst @@ -0,0 +1,44 @@ +#!/bin/sh +# postinst script for gst-omx +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + update-alternatives --install \ + /etc/xdg/gstomx.conf \ + gstomx.conf \ + /etc/xdg/gstomx-generic.conf \ + 10 + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/gst-omx/debian/gstreamer1.0-omx-generic-config.prerm b/gst-omx/debian/gstreamer1.0-omx-generic-config.prerm new file mode 100644 index 0000000000..4a3fc41c35 --- /dev/null +++ b/gst-omx/debian/gstreamer1.0-omx-generic-config.prerm @@ -0,0 +1,41 @@ +#!/bin/sh +# prerm script for gst-omx +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `upgrade' +# * `failed-upgrade' +# * `remove' `in-favour' +# * `deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + remove|upgrade|deconfigure) + update-alternatives --remove \ + gstomx.conf \ + /etc/xdg/gstomx-generic.conf + ;; + + failed-upgrade) + ;; + + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/gst-omx/debian/gstreamer1.0-omx-generic.docs b/gst-omx/debian/gstreamer1.0-omx-generic.docs new file mode 100644 index 0000000000..e174728f54 --- /dev/null +++ b/gst-omx/debian/gstreamer1.0-omx-generic.docs @@ -0,0 +1 @@ +debian/README.Debian diff --git a/gst-omx/debian/gstreamer1.0-omx-generic.install b/gst-omx/debian/gstreamer1.0-omx-generic.install new file mode 100644 index 0000000000..3813206155 --- /dev/null +++ b/gst-omx/debian/gstreamer1.0-omx-generic.install @@ -0,0 +1 @@ +usr/lib/*/gstreamer*/lib*-generic.so diff --git a/gst-omx/debian/gstreamer1.0-omx-generic.postinst.in b/gst-omx/debian/gstreamer1.0-omx-generic.postinst.in new file mode 100644 index 0000000000..0def278354 --- /dev/null +++ b/gst-omx/debian/gstreamer1.0-omx-generic.postinst.in @@ -0,0 +1,44 @@ +#!/bin/sh +# postinst script for gst-omx +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + update-alternatives --install \ + /usr/lib/@DEB_HOST_MULTIARCH@/gstreamer-1.0/libgstomx.so \ + libgstomx-@DEB_HOST_MULTIARCH@.so \ + /usr/lib/@DEB_HOST_MULTIARCH@/gstreamer-1.0/libgstomx-generic.so \ + 10 + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/gst-omx/debian/gstreamer1.0-omx-generic.prerm.in b/gst-omx/debian/gstreamer1.0-omx-generic.prerm.in new file mode 100644 index 0000000000..f7bcc227cb --- /dev/null +++ b/gst-omx/debian/gstreamer1.0-omx-generic.prerm.in @@ -0,0 +1,41 @@ +#!/bin/sh +# prerm script for gst-omx +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `upgrade' +# * `failed-upgrade' +# * `remove' `in-favour' +# * `deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + remove|upgrade|deconfigure) + update-alternatives --remove \ + libgstomx-@DEB_HOST_MULTIARCH@.so \ + /usr/lib/@DEB_HOST_MULTIARCH@/gstreamer-1.0/libgstomx-generic.so + ;; + + failed-upgrade) + ;; + + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/gst-omx/debian/gstreamer1.0-omx-sf-config.install b/gst-omx/debian/gstreamer1.0-omx-sf-config.install new file mode 100644 index 0000000000..719505b72d --- /dev/null +++ b/gst-omx/debian/gstreamer1.0-omx-sf-config.install @@ -0,0 +1 @@ +etc/xdg/ diff --git a/gst-omx/debian/gstreamer1.0-omx-sf.install b/gst-omx/debian/gstreamer1.0-omx-sf.install new file mode 100644 index 0000000000..cd5386e73d --- /dev/null +++ b/gst-omx/debian/gstreamer1.0-omx-sf.install @@ -0,0 +1 @@ +usr/lib/${DEB_HOST_GNU_TYPE}/ diff --git a/gst-omx/debian/patches/0001-add-starfive-support.patch b/gst-omx/debian/patches/0001-add-starfive-support.patch new file mode 100644 index 0000000000..9cfc90765e --- /dev/null +++ b/gst-omx/debian/patches/0001-add-starfive-support.patch @@ -0,0 +1,515 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +--- gst-omx-1.22.0.orig/config/meson.build ++++ gst-omx-1.22.0/config/meson.build +@@ -6,6 +6,8 @@ elif omx_target == 'zynqultrascaleplus' + sub = 'zynqultrascaleplus' + elif omx_target == 'tizonia' + sub = 'tizonia' ++ elif omx_target == 'sf' ++ sub = 'sf' + else + # No config file defined for the 'generic' target + sub = '' +--- /dev/null ++++ gst-omx-1.22.0/config/sf/gstomx.conf +@@ -0,0 +1,17 @@ ++[omxh265dec] ++type-name=GstOMXH265Dec ++core-name=/usr/lib/libsf-omx-il.so ++component-name=sf.dec.decoder.h265 ++in-port-index=0 ++out-port-index=1 ++rank=0 ++hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual ++ ++[omxh264dec] ++type-name=GstOMXH264Dec ++core-name=/usr/lib/libsf-omx-il.so ++component-name=sf.dec.decoder.h264 ++in-port-index=0 ++out-port-index=1 ++rank=1 ++hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual +--- /dev/null ++++ gst-omx-1.22.0/config/sf/meson.build +@@ -0,0 +1 @@ ++install_data (['gstomx.conf'], install_dir : omx_conf_dir) +--- gst-omx-1.22.0.orig/meson.build ++++ gst-omx-1.22.0/meson.build +@@ -227,6 +227,8 @@ elif omx_target == 'tizonia' + tizil_includedir = tizil_dep.get_variable('includedir') + gst_omx_args += ['-I' + tizil_includedir + '/tizonia'] + omx_inc = [] ++elif omx_target == 'sf' ++ warning('sf selected') + else + error ('Unsupported omx target specified. Use the -Dtarget option') + endif +--- /dev/null ++++ gst-omx-1.22.0/meson.build.orig +@@ -0,0 +1,429 @@ ++project('gst-omx', 'c', ++ version : '1.22.0', ++ meson_version : '>= 0.62', ++ 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.62.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 ++ ++# glib doesn't support unloading, which means that unloading and reloading ++# any library that registers static types will fail ++if cc.has_link_argument('-Wl,-z,nodelete') ++ add_project_link_arguments('-Wl,-z,nodelete', language: 'c') ++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) ++gmodule_dep = dependency('gmodule-no-export-2.0', version: glib_req) ++ ++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_variable('gl_winsys').split(' ') ++ gl_platforms = gstgl_dep.get_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_variable('libdir')) ++ tizil_includedir = tizil_dep.get_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 ''' ++ 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', ++ '-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'), check: true) ++ release_date = run_result.stdout().strip() ++ cdata.set_quoted('GST_PACKAGE_RELEASE_DATETIME', release_date) ++ message('Package release date: ' + release_date) ++endif ++ ++configure_file(output: 'config.h', configuration: cdata) ++ ++meson.add_dist_script('scripts/gen-changelog.py', meson.project_name(), '1.20.0', meson.project_version()) +--- gst-omx-1.22.0.orig/meson_options.txt ++++ gst-omx-1.22.0/meson_options.txt +@@ -1,7 +1,7 @@ + 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', ++ choices : ['none', 'generic', 'rpi', 'bellagio', 'tizonia', 'zynqultrascaleplus', 'sf'], value : 'none', + description : 'The OMX platform to target') + option('struct_packing', type : 'combo', + choices : ['0', '1', '2', '4', '8'], value : '0', diff --git a/gst-omx/debian/patches/0002-Fix-gst-omx-Enable-the-gst-omx-VPU-decoding-and-enco.patch b/gst-omx/debian/patches/0002-Fix-gst-omx-Enable-the-gst-omx-VPU-decoding-and-enco.patch new file mode 100644 index 0000000000..05fee6b3ef --- /dev/null +++ b/gst-omx/debian/patches/0002-Fix-gst-omx-Enable-the-gst-omx-VPU-decoding-and-enco.patch @@ -0,0 +1,90 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +--- gst-omx-1.22.0.orig/meson.build ++++ gst-omx-1.22.0/meson.build +@@ -228,6 +228,7 @@ elif omx_target == 'tizonia' + gst_omx_args += ['-I' + tizil_includedir + '/tizonia'] + omx_inc = [] + elif omx_target == 'sf' ++ cdata.set('USE_OMX_TARGET_STARFIVE', 1) + warning('sf selected') + else + error ('Unsupported omx target specified. Use the -Dtarget option') +--- gst-omx-1.22.0.orig/meson.build.orig ++++ gst-omx-1.22.0/meson.build.orig +@@ -227,6 +227,8 @@ elif omx_target == 'tizonia' + tizil_includedir = tizil_dep.get_variable('includedir') + gst_omx_args += ['-I' + tizil_includedir + '/tizonia'] + omx_inc = [] ++elif omx_target == 'sf' ++ warning('sf selected') + else + error ('Unsupported omx target specified. Use the -Dtarget option') + endif +--- gst-omx-1.22.0.orig/omx/gstomxh264enc.c ++++ gst-omx-1.22.0/omx/gstomxh264enc.c +@@ -824,6 +824,11 @@ gst_omx_h264_enc_get_caps (GstOMXVideoEn + case OMX_VIDEO_AVCLevel51: + level = "5.1"; + break; ++#ifdef USE_OMX_TARGET_STARFIVE ++ case OMX_VIDEO_AVCLevel52: ++ level = "5.2"; ++ break; ++#else + #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS + case OMX_ALG_VIDEO_AVCLevel52: + level = "5.2"; +@@ -838,6 +843,7 @@ gst_omx_h264_enc_get_caps (GstOMXVideoEn + level = "6.2"; + break; + #endif ++#endif + default: + g_assert_not_reached (); + gst_caps_unref (caps); +--- gst-omx-1.22.0.orig/omx/gstomxh264utils.c ++++ gst-omx-1.22.0/omx/gstomxh264utils.c +@@ -115,6 +115,10 @@ gst_omx_h264_utils_get_level_from_str (c + return OMX_VIDEO_AVCLevel5; + } else if (g_str_equal (level, "5.1")) { + return OMX_VIDEO_AVCLevel51; ++#ifdef USE_OMX_TARGET_STARFIVE ++ } else if (g_str_equal (level, "5.2")) { ++ return OMX_VIDEO_AVCLevel52; ++#else + #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS + } else if (g_str_equal (level, "5.2")) { + return (OMX_VIDEO_AVCLEVELTYPE) OMX_ALG_VIDEO_AVCLevel52; +@@ -125,6 +129,7 @@ gst_omx_h264_utils_get_level_from_str (c + } else if (g_str_equal (level, "6.2")) { + return (OMX_VIDEO_AVCLEVELTYPE) OMX_ALG_VIDEO_AVCLevel62; + #endif ++#endif + } + + return OMX_VIDEO_AVCLevelMax; diff --git a/gst-omx/debian/patches/0003-add-video-scale-support.patch b/gst-omx/debian/patches/0003-add-video-scale-support.patch new file mode 100644 index 0000000000..584f2f583a --- /dev/null +++ b/gst-omx/debian/patches/0003-add-video-scale-support.patch @@ -0,0 +1,76 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +--- gst-omx-1.22.0.orig/omx/gstomxvideodec.c ++++ gst-omx-1.22.0/omx/gstomxvideodec.c +@@ -2185,6 +2185,7 @@ static gboolean + gst_omx_video_dec_negotiate (GstOMXVideoDec * self) + { + OMX_VIDEO_PARAM_PORTFORMATTYPE param; ++ OMX_PARAM_PORTDEFINITIONTYPE port_def; + OMX_ERRORTYPE err; + GstCaps *comp_supported_caps; + GList *negotiation_map = NULL, *l; +@@ -2192,6 +2193,7 @@ gst_omx_video_dec_negotiate (GstOMXVideo + GstVideoFormat format; + GstStructure *s; + const gchar *format_str; ++ gint width, height; + + GST_DEBUG_OBJECT (self, "Trying to negotiate a video format with downstream"); + +@@ -2281,6 +2283,31 @@ gst_omx_video_dec_negotiate (GstOMXVideo + gst_omx_error_to_string (err), err); + } + ++ if (gst_structure_get_int(s, "width", &width) && gst_structure_get_int(s, "height", &height)) ++ { ++ GST_OMX_INIT_STRUCT (&port_def); ++ port_def.nPortIndex = self->dec_out_port->index; ++ err = gst_omx_component_get_parameter (self->dec, ++ OMX_IndexParamPortDefinition, &port_def); ++ if (err != OMX_ErrorNone) { ++ GST_ERROR_OBJECT (self, "Failed to get video port definition: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ return FALSE; ++ } ++ ++ port_def.format.video.nFrameHeight = height; ++ port_def.format.video.nFrameWidth = width; ++ ++ err = ++ gst_omx_component_set_parameter (self->dec, ++ OMX_IndexParamPortDefinition, &port_def); ++ if (err != OMX_ErrorNone) { ++ GST_ERROR_OBJECT (self, "Failed to set video port definition: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ return FALSE; ++ } ++ } ++ + gst_caps_unref (intersection); + return (err == OMX_ErrorNone); + } diff --git a/gst-omx/debian/patches/0004-add-encoder-support.patch b/gst-omx/debian/patches/0004-add-encoder-support.patch new file mode 100644 index 0000000000..952751bd9c --- /dev/null +++ b/gst-omx/debian/patches/0004-add-encoder-support.patch @@ -0,0 +1,50 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +--- gst-omx-1.22.0.orig/config/sf/gstomx.conf ++++ gst-omx-1.22.0/config/sf/gstomx.conf +@@ -15,3 +15,21 @@ in-port-index=0 + out-port-index=1 + rank=1 + hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual ++ ++[omxh265enc] ++type-name=GstOMXH265Enc ++core-name=/usr/lib/libsf-omx-il.so ++component-name=sf.enc.encoder.h265 ++in-port-index=0 ++out-port-index=1 ++rank=1 ++hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual;video-framerate-integer ++ ++[omxh264enc] ++type-name=GstOMXH264Enc ++core-name=/usr/lib/libsf-omx-il.so ++component-name=sf.enc.encoder.h264 ++in-port-index=0 ++out-port-index=1 ++rank=1 ++hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual;video-framerate-integer diff --git a/gst-omx/debian/patches/0005-rank-257-for-sf-codecs.patch b/gst-omx/debian/patches/0005-rank-257-for-sf-codecs.patch new file mode 100644 index 0000000000..6188f9d3ff --- /dev/null +++ b/gst-omx/debian/patches/0005-rank-257-for-sf-codecs.patch @@ -0,0 +1,48 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +Index: gst-omx-1.22.0/config/sf/gstomx.conf +=================================================================== +--- gst-omx-1.22.0.orig/config/sf/gstomx.conf 2023-03-02 08:43:33.398733747 +0000 ++++ gst-omx-1.22.0/config/sf/gstomx.conf 2023-03-02 08:49:43.000000000 +0000 +@@ -4,7 +4,7 @@ + component-name=sf.dec.decoder.h265 + in-port-index=0 + out-port-index=1 +-rank=0 ++rank=257 + hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual + + [omxh264dec] +@@ -13,7 +13,7 @@ + component-name=sf.dec.decoder.h264 + in-port-index=0 + out-port-index=1 +-rank=1 ++rank=257 + hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual + + [omxh265enc] diff --git a/gst-omx/debian/patches/0006-dont-invoke-USE_BUFFER-if-no-dmabuffer.patch b/gst-omx/debian/patches/0006-dont-invoke-USE_BUFFER-if-no-dmabuffer.patch new file mode 100644 index 0000000000..35181be194 --- /dev/null +++ b/gst-omx/debian/patches/0006-dont-invoke-USE_BUFFER-if-no-dmabuffer.patch @@ -0,0 +1,44 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +--- gst-omx-1.22.0.orig/omx/gstomxvideodec.c ++++ gst-omx-1.22.0/omx/gstomxvideodec.c +@@ -718,6 +718,15 @@ gst_omx_try_importing_buffer (GstOMXVide + goto out; + } + ++#ifdef USE_OMX_TARGET_STARFIVE ++ if ( !gst_is_dmabuf_memory (mem)) { ++ GST_INFO_OBJECT (self, ++ " %d-th buffer doesn't contain dmabuf, go to out. port->port_def.nBufferSize: %lu", ++ i, port->port_def.nBufferSize); ++ goto out; ++ } ++#endif ++ + *frame = g_slice_new0 (GstVideoFrame); + + is_mapped = gst_video_frame_map (*frame, v_info, buffer, flags); diff --git a/gst-omx/debian/patches/0007-add-omxmjpegdec-support.patch b/gst-omx/debian/patches/0007-add-omxmjpegdec-support.patch new file mode 100644 index 0000000000..ddd94a7bb7 --- /dev/null +++ b/gst-omx/debian/patches/0007-add-omxmjpegdec-support.patch @@ -0,0 +1,41 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +--- gst-omx-1.22.0.orig/config/sf/gstomx.conf ++++ gst-omx-1.22.0/config/sf/gstomx.conf +@@ -33,3 +33,12 @@ in-port-index=0 + out-port-index=1 + rank=1 + hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual;video-framerate-integer ++ ++[omxmjpegdec] ++type-name=GstOMXMJPEGDec ++core-name=/usr/lib/libsf-omx-il.so ++component-name=sf.dec.decoder.mjpeg ++in-port-index=0 ++out-port-index=1 ++rank=1 ++hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual diff --git a/gst-omx/debian/patches/0008-support-nv21-i422-y444-for-omxmjpegdec.patch b/gst-omx/debian/patches/0008-support-nv21-i422-y444-for-omxmjpegdec.patch new file mode 100644 index 0000000000..c56d69e57c --- /dev/null +++ b/gst-omx/debian/patches/0008-support-nv21-i422-y444-for-omxmjpegdec.patch @@ -0,0 +1,126 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +--- gst-omx-1.22.0.orig/config/sf/gstomx.conf ++++ gst-omx-1.22.0/config/sf/gstomx.conf +@@ -42,3 +42,4 @@ in-port-index=0 + out-port-index=1 + rank=1 + hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual ++src-template-caps=video/x-raw, format = (string) { NV16_10LE32, NV12_10LE32, NV16, YUY2, YVYU, UYVY, NV12, NV21, I420, RGB16, BGR16, ABGR, ARGB, GRAY8, Y42B, Y444 }, width = (int) [ 1, max ], height = (int) [ 1, max ], framerate = (fraction) [ 0, max ] +--- gst-omx-1.22.0.orig/omx/gstomxbufferpool.c ++++ gst-omx-1.22.0/omx/gstomxbufferpool.c +@@ -370,9 +370,29 @@ gst_omx_buffer_pool_alloc_buffer (GstBuf + case GST_VIDEO_FORMAT_NV12_10LE32: + case GST_VIDEO_FORMAT_NV16: + case GST_VIDEO_FORMAT_NV16_10LE32: ++#ifdef USE_OMX_TARGET_STARFIVE ++ case GST_VIDEO_FORMAT_NV21: ++#endif + stride[1] = nstride; + offset[1] = offset[0] + stride[0] * nslice; + break; ++#ifdef USE_OMX_TARGET_STARFIVE ++ case GST_VIDEO_FORMAT_Y42B: ++ stride[0] = GST_ROUND_UP_4 (nstride); ++ stride[1] = GST_ROUND_UP_8 (nstride) / 2; ++ stride[2] = stride[1]; ++ ++ offset[1] = stride[0] * nslice; ++ offset[2] = offset[1] + stride[1] * nslice; ++ break; ++ ++ case GST_VIDEO_FORMAT_Y444: ++ stride[1] = nstride; ++ stride[2] = nstride; ++ offset[1] = offset[0] + stride[0] * nslice; ++ offset[2] = offset[1] + stride[1] * nslice; ++ break; ++#endif + default: + g_assert_not_reached (); + break; +--- gst-omx-1.22.0.orig/omx/gstomxvideo.c ++++ gst-omx-1.22.0/omx/gstomxvideo.c +@@ -94,6 +94,17 @@ gst_omx_video_get_format_from_omx (OMX_C + break; + #pragma GCC diagnostic pop + #endif ++#ifdef USE_OMX_TARGET_STARFIVE ++ case OMX_COLOR_FormatYUV422Planar: ++ format = GST_VIDEO_FORMAT_Y42B; ++ break; ++ case OMX_COLOR_FormatYUV444Interleaved: ++ format = GST_VIDEO_FORMAT_Y444; ++ break; ++ case OMX_COLOR_FormatYVU420SemiPlanar: ++ format = GST_VIDEO_FORMAT_NV21; ++ break; ++#endif + default: + format = GST_VIDEO_FORMAT_UNKNOWN; + break; +--- gst-omx-1.22.0.orig/omx/gstomxvideodec.c ++++ gst-omx-1.22.0/omx/gstomxvideodec.c +@@ -592,6 +592,9 @@ gst_omx_video_dec_fill_buffer (GstOMXVid + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_YVYU: ++#ifdef USE_OMX_TARGET_STARFIVE ++ case GST_VIDEO_FORMAT_Y42B: ++#endif + dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo) * 2; + break; + case GST_VIDEO_FORMAT_GRAY8: +@@ -609,6 +612,9 @@ gst_omx_video_dec_fill_buffer (GstOMXVid + dst_height[2] = GST_VIDEO_INFO_FIELD_HEIGHT (vinfo) / 2; + break; + case GST_VIDEO_FORMAT_NV12: ++#ifdef USE_OMX_TARGET_STARFIVE ++ case GST_VIDEO_FORMAT_NV21: ++#endif + dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo); + src_stride[1] = nstride; + src_size[1] = src_stride[1] * nslice / 2; +@@ -638,6 +644,18 @@ gst_omx_video_dec_fill_buffer (GstOMXVid + src_size[1] = src_stride[1] * nslice; + dst_height[1] = GST_VIDEO_INFO_FIELD_HEIGHT (vinfo); + break; ++#ifdef USE_OMX_TARGET_STARFIVE ++ case GST_VIDEO_FORMAT_Y444: ++ dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo); ++ dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo); ++ dst_width[2] = GST_VIDEO_INFO_WIDTH (vinfo); ++ src_size[1] = src_size[0]; ++ src_size[2] = src_size[0]; ++ src_stride[1] = nstride; ++ dst_height[1] = dst_height[0]; ++ dst_height[2] = dst_height[0]; ++ break; ++#endif + default: + g_assert_not_reached (); + break; diff --git a/gst-omx/debian/patches/0009-suport-usebuffer-mode-for-encoding.patch b/gst-omx/debian/patches/0009-suport-usebuffer-mode-for-encoding.patch new file mode 100644 index 0000000000..9b1a661d16 --- /dev/null +++ b/gst-omx/debian/patches/0009-suport-usebuffer-mode-for-encoding.patch @@ -0,0 +1,271 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +--- gst-omx-1.22.0.orig/omx/gstomx.h ++++ gst-omx-1.22.0/omx/gstomx.h +@@ -332,6 +332,7 @@ struct _GstOMXPort { + */ + gint settings_cookie; + gint configured_settings_cookie; ++ GstBuffer * c_buf; + }; + + struct _GstOMXComponent { +--- gst-omx-1.22.0.orig/omx/gstomxvideoenc.c ++++ gst-omx-1.22.0/omx/gstomxvideoenc.c +@@ -2102,6 +2102,143 @@ gst_omx_video_enc_ensure_nb_in_buffers ( + return TRUE; + } + ++#ifdef USE_OMX_TARGET_STARFIVE ++static GstBuffer * ++gst_omx_try_importing_buffer (GstOMXVideoEnc * 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, ¶ms) != 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 ( !gst_is_dmabuf_memory (mem)) { ++ GST_INFO_OBJECT (self, ++ " %d-th buffer doesn't contain dmabuf, go to out. port->port_def.nBufferSize: %lu", ++ i, port->port_def.nBufferSize); ++ goto out; ++ } ++ ++ *frame = g_slice_new0 (GstVideoFrame); ++ ++ is_mapped = gst_video_frame_map (*frame, v_info, buffer, flags); ++ GST_INFO_OBJECT (self, " *frame = %p, mem: %p", *frame, mem); ++ ++ 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; ++} ++#endif ++ ++#ifdef USE_OMX_TARGET_STARFIVE ++static gboolean ++gst_omx_video_enc_use_buffers (GstOMXVideoEnc * self) ++{ ++ GstOMXPort * port = self->enc_in_port; ++ GstBufferPool *pool = port->c_buf->pool; ++ GstVideoCodecState *input_state = self->input_state; ++ GstVideoInfo v_info = input_state->info; ++ guint n = port->port_def.nBufferCountActual; ++ GList *images = NULL; ++ GList *buffers = NULL; ++ GList *frames = NULL; ++ OMX_ERRORTYPE err = OMX_ErrorNone; ++ gboolean is_mapped = FALSE ; ++ GST_DEBUG(" nBufferCountActual=%d, nBufferCountMin= %lu", n, port->port_def.nBufferCountMin); ++ ++ if ( pool != NULL ) { ++ guint i; ++ for (i = 0; i < n; i++) { ++ GstBuffer * buf = NULL; ++ GstVideoFrame *frame = NULL; ++ buf = gst_omx_try_importing_buffer (self, pool, port, &v_info, i, &frame); ++ if (!buf) { ++ 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); ++ break; ++ } else { ++ buffers = g_list_append (buffers, buf); ++ frames = g_list_append (frames, frame); ++ images = g_list_append (images, GST_VIDEO_FRAME_PLANE_DATA (frame, 0)); ++ GST_DEBUG_OBJECT (self, " pBuffer: %p", GST_VIDEO_FRAME_PLANE_DATA (frame, 0)); ++ } ++ } ++ } ++ ++ if (images) { ++ is_mapped = TRUE; ++ ++ 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", n); ++ } 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); ++ return FALSE; ++ } ++ } ++ ++ if ( !is_mapped ) { ++ GST_WARNING_OBJECT (self, " failed to call UseBuffer, trying to use allocation"); ++ self->input_dmabuf = FALSE; ++ self->input_allocation = GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER; ++ if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone){ ++ return FALSE; ++ } ++ } ++ ++ return TRUE; ++} ++#endif ++ + static gboolean + gst_omx_video_enc_allocate_in_buffers (GstOMXVideoEnc * self) + { +@@ -2115,6 +2252,9 @@ gst_omx_video_enc_allocate_in_buffers (G + return FALSE; + break; + case GST_OMX_BUFFER_ALLOCATION_USE_BUFFER: ++#ifdef USE_OMX_TARGET_STARFIVE ++ return gst_omx_video_enc_use_buffers(self); ++#endif + default: + /* Not supported */ + g_return_val_if_reached (FALSE); +@@ -2179,8 +2319,18 @@ static GstOMXBufferAllocation + gst_omx_video_enc_pick_input_allocation_mode (GstOMXVideoEnc * self, + GstBuffer * inbuf) + { ++#ifdef USE_OMX_TARGET_STARFIVE ++ if (!gst_omx_is_dynamic_allocation_supported ()){ ++ if (gst_is_dmabuf_memory (gst_buffer_peek_memory (inbuf, 0))){ ++ GST_DEBUG_OBJECT (self, "select GST_OMX_BUFFER_ALLOCATION_USE_BUFFER"); ++ return GST_OMX_BUFFER_ALLOCATION_USE_BUFFER; ++ } ++ return GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER; ++ } ++#else + if (!gst_omx_is_dynamic_allocation_supported ()) + return GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER; ++#endif + + if (can_use_dynamic_buffer_mode (self, inbuf)) { + GST_DEBUG_OBJECT (self, +@@ -2272,6 +2422,15 @@ gst_omx_video_enc_enable (GstOMXVideoEnc + input); + self->input_dmabuf = FALSE; + ++#ifdef USE_OMX_TARGET_STARFIVE ++ if (self->input_allocation == ++ GST_OMX_BUFFER_ALLOCATION_USE_BUFFER) { ++ self->input_dmabuf = TRUE; ++ self->enc_in_port->c_buf = input; ++ GST_DEBUG_OBJECT (self, "input_dmabuf is true"); ++ } ++#endif ++ + #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS + if (gst_is_dmabuf_memory (gst_buffer_peek_memory (input, 0))) { + if (self->input_allocation == +@@ -2786,7 +2945,11 @@ gst_omx_video_enc_fill_buffer (GstOMXVid + } + + if (self->enc_in_port->allocation == +- GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC) { ++ GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC ++#ifdef USE_OMX_TARGET_STARFIVE ++ || self->enc_in_port->allocation == GST_OMX_BUFFER_ALLOCATION_USE_BUFFER ++#endif ++ ) { + 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")); +@@ -2812,12 +2975,29 @@ gst_omx_video_enc_fill_buffer (GstOMXVid + gst_buffer_get_size (inbuf)); + } else { + /* dmabuf input */ ++#ifdef USE_OMX_TARGET_STARFIVE ++ if (self->enc_in_port->allocation == GST_OMX_BUFFER_ALLOCATION_USE_BUFFER) { ++ GstMemory *mem = gst_buffer_peek_memory (inbuf, 0); ++ GST_LOG_OBJECT (self, " mem: %p, inbuf: %p, outbuf: %p", mem, inbuf, outbuf); ++ if (!gst_omx_buffer_map_memory (outbuf, mem)) { ++ GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL),("failed to import")); ++ GST_ERROR_OBJECT (self, "failed to import dmabuf %p, inbuf: %p",mem, inbuf); ++ return FALSE; ++ } ++ } else { ++ if (!gst_omx_buffer_import_fd (outbuf, inbuf)) { ++ GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL), ++ ("failed to import dmabuf")); ++ return FALSE; ++ } ++ } ++#else + if (!gst_omx_buffer_import_fd (outbuf, inbuf)) { + GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL), + ("failed to import dmabuf")); + return FALSE; + } +- ++#endif + GST_LOG_OBJECT (self, "Import dmabuf of %" G_GSIZE_FORMAT " bytes", + gst_buffer_get_size (inbuf)); + } diff --git a/gst-omx/debian/patches/0010-add-property-framerate.patch b/gst-omx/debian/patches/0010-add-property-framerate.patch new file mode 100644 index 0000000000..b218cfd232 --- /dev/null +++ b/gst-omx/debian/patches/0010-add-property-framerate.patch @@ -0,0 +1,170 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +--- gst-omx-1.22.0.orig/omx/gstomxmjpegdec.c ++++ gst-omx-1.22.0/omx/gstomxmjpegdec.c +@@ -28,16 +28,28 @@ + + GST_DEBUG_CATEGORY_STATIC (gst_omx_mjpeg_dec_debug_category); + #define GST_CAT_DEFAULT gst_omx_mjpeg_dec_debug_category +- ++#ifdef USE_OMX_TARGET_STARFIVE ++#define DEFAULT_FRAMERATE 0 ++#endif + /* 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); +- ++#ifdef USE_OMX_TARGET_STARFIVE ++static void gst_omx_mjpeg_dec_set_property (GObject * object, guint prop_id, ++ const GValue * value, GParamSpec * pspec); ++static void gst_omx_mjpeg_dec_get_property (GObject * object, guint prop_id, ++ GValue * value, GParamSpec * pspec); ++#endif + enum + { ++#ifdef USE_OMX_TARGET_STARFIVE ++ PROP_0, ++ PROP_FRAMERATE ++#else + PROP_0 ++#endif + }; + + /* class initialization */ +@@ -54,11 +66,16 @@ gst_omx_mjpeg_dec_class_init (GstOMXMJPE + { + GstOMXVideoDecClass *videodec_class = GST_OMX_VIDEO_DEC_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); +- ++#ifdef USE_OMX_TARGET_STARFIVE ++ GObjectClass *gobject_class = G_OBJECT_CLASS (videodec_class); ++#endif + 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); +- ++#ifdef USE_OMX_TARGET_STARFIVE ++ gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_omx_mjpeg_dec_set_property); ++ gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_omx_mjpeg_dec_get_property); ++#endif + videodec_class->cdata.default_sink_template_caps = "image/jpeg, " + "width=(int) [1,MAX], " "height=(int) [1,MAX]"; + +@@ -67,7 +84,16 @@ gst_omx_mjpeg_dec_class_init (GstOMXMJPE + "Codec/Decoder/Video/Hardware", + "Decode MJPEG video streams", + "Sebastian Dröge "); +- ++#ifdef USE_OMX_TARGET_STARFIVE ++ g_object_class_install_property (gobject_class, PROP_FRAMERATE, ++ g_param_spec_int ("framerate", ++ "Framerate", ++ "Frames per second in raw stream.\n \ ++ Only workable for the container not exposing fps.\n\ ++ '0' means disabled.", ++ 0, G_MAXINT, ++ DEFAULT_FRAMERATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); ++#endif + gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.mjpeg"); + } + +@@ -89,10 +115,53 @@ gst_omx_mjpeg_dec_set_format (GstOMXVide + { + gboolean ret; + OMX_PARAM_PORTDEFINITIONTYPE port_def; +- ++#ifdef USE_OMX_TARGET_STARFIVE ++ GstVideoInfo *info = &state->info; ++ GstOMXMJPEGDec * mjpeg_dec = GST_OMX_MJPEG_DEC (dec); ++ ++ if (mjpeg_dec->framerate != DEFAULT_FRAMERATE) { ++ GST_DEBUG_OBJECT (dec, " change fps from %d/%d to %d/1" GST_PTR_FORMAT, info->fps_n, info->fps_d, mjpeg_dec->framerate); ++ info->fps_n = mjpeg_dec->framerate; ++ info->fps_d = 1; ++ if (state->caps) { ++ gst_caps_set_simple (state->caps, "framerate", GST_TYPE_FRACTION, info->fps_n, info->fps_d, NULL); ++ } ++ } ++#endif + 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; + } ++#ifdef USE_OMX_TARGET_STARFIVE ++static void ++gst_omx_mjpeg_dec_set_property (GObject * object, guint prop_id, ++ const GValue * value, GParamSpec * pspec) ++{ ++ GstOMXMJPEGDec * mjpeg_dec = GST_OMX_MJPEG_DEC (object); ++ switch (prop_id) { ++ case PROP_FRAMERATE: ++ mjpeg_dec->framerate = g_value_get_int (value); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++static void ++gst_omx_mjpeg_dec_get_property (GObject * object, guint prop_id, GValue * value, ++ GParamSpec * pspec) ++{ ++ GstOMXMJPEGDec * mjpeg_dec = GST_OMX_MJPEG_DEC (object); ++ switch (prop_id) { ++ case PROP_FRAMERATE: ++ g_value_set_int (value, mjpeg_dec->framerate); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++#endif +--- gst-omx-1.22.0.orig/omx/gstomxmjpegdec.h ++++ gst-omx-1.22.0/omx/gstomxmjpegdec.h +@@ -45,6 +45,16 @@ typedef struct _GstOMXMJPEGDecClass GstO + struct _GstOMXMJPEGDec + { + GstOMXVideoDec parent; ++#ifdef USE_OMX_TARGET_STARFIVE ++ //If container shows fps as public api, it won't work ++ //as GstBuffer containing pts/dts/duration and it will calculate fps in upstream. ++ //i.e. ++ //not works: ++ // gst-launch-1.0 -v filesrc location=xxx.mp4 ! qtdemux name=demux demux.video_0 ! jpegparse ! omxmjpegdec framerate=xxx ! kmssink driver-name=starfive force-modesetting=1 ++ //works: ++ // gst-launch-1.0 -v filesrc location=xxx.mjpeg ! jpegparse ! omxmjpegdec framerate=xxx ! kmssink driver-name=starfive force-modesetting=1 ++ gint framerate; ++#endif + }; + + struct _GstOMXMJPEGDecClass diff --git a/gst-omx/debian/patches/0011-hanle-some-extra-profile-for-avc.patch b/gst-omx/debian/patches/0011-hanle-some-extra-profile-for-avc.patch new file mode 100644 index 0000000000..5480ece610 --- /dev/null +++ b/gst-omx/debian/patches/0011-hanle-some-extra-profile-for-avc.patch @@ -0,0 +1,64 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +--- gst-omx-1.22.0.orig/omx/gstomxh264utils.c ++++ gst-omx-1.22.0/omx/gstomxh264utils.c +@@ -54,6 +54,19 @@ static const H264ProfileMapping h264_pro + #endif + }; + ++#ifdef USE_OMX_TARGET_STARFIVE ++static const H264ProfileMapping h264_ext_profiles[] = { ++ {"progressive-high", ++ (OMX_VIDEO_AVCPROFILETYPE) OMX_VIDEO_AVCProfileHigh}, ++ {"constrained-high", ++ (OMX_VIDEO_AVCPROFILETYPE) OMX_VIDEO_AVCProfileHigh}, ++ {"high-10-intra", ++ (OMX_VIDEO_AVCPROFILETYPE) OMX_VIDEO_AVCProfileHigh10}, ++ {"high-4:2:2-intra", ++ (OMX_VIDEO_AVCPROFILETYPE) OMX_VIDEO_AVCProfileHigh422}, ++}; ++#endif ++ + OMX_VIDEO_AVCPROFILETYPE + gst_omx_h264_utils_get_profile_from_str (const gchar * profile) + { +@@ -64,6 +77,15 @@ gst_omx_h264_utils_get_profile_from_str + return h264_profiles[i].e; + } + ++#ifdef USE_OMX_TARGET_STARFIVE ++ for (i = 0; i < G_N_ELEMENTS (h264_ext_profiles); i++) { ++ if (g_str_equal (profile, h264_ext_profiles[i].profile)) { ++ GST_INFO("extra profile: %s ==> avc profie type: %d", profile, h264_ext_profiles[i].e); ++ return h264_ext_profiles[i].e; ++ } ++ } ++#endif ++ + return OMX_VIDEO_AVCProfileMax; + } + diff --git a/gst-omx/debian/patches/0012-combine-sps-pps-header-to-idr.patch b/gst-omx/debian/patches/0012-combine-sps-pps-header-to-idr.patch new file mode 100644 index 0000000000..74d2f60280 --- /dev/null +++ b/gst-omx/debian/patches/0012-combine-sps-pps-header-to-idr.patch @@ -0,0 +1,527 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +Index: gst-omx-1.22.0/meson.build +=================================================================== +--- gst-omx-1.22.0.orig/meson.build 2023-03-02 08:43:33.398733747 +0000 ++++ gst-omx-1.22.0/meson.build 2023-03-02 08:43:33.406733682 +0000 +@@ -229,6 +229,7 @@ + omx_inc = [] + elif omx_target == 'sf' + cdata.set('USE_OMX_TARGET_STARFIVE', 1) ++ gst_omx_args += ['-DCOMBINE_SPS_PPS_HEADERS'] + warning('sf selected') + else + error ('Unsupported omx target specified. Use the -Dtarget option') +Index: gst-omx-1.22.0/meson.build.orig +=================================================================== +--- gst-omx-1.22.0.orig/meson.build.orig 2023-03-02 08:43:33.398733747 +0000 ++++ /dev/null 1970-01-01 00:00:00.000000000 +0000 +@@ -1,431 +0,0 @@ +-project('gst-omx', 'c', +- version : '1.22.0', +- meson_version : '>= 0.62', +- 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.62.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 +- +-# glib doesn't support unloading, which means that unloading and reloading +-# any library that registers static types will fail +-if cc.has_link_argument('-Wl,-z,nodelete') +- add_project_link_arguments('-Wl,-z,nodelete', language: 'c') +-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) +-gmodule_dep = dependency('gmodule-no-export-2.0', version: glib_req) +- +-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_variable('gl_winsys').split(' ') +- gl_platforms = gstgl_dep.get_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_variable('libdir')) +- tizil_includedir = tizil_dep.get_variable('includedir') +- gst_omx_args += ['-I' + tizil_includedir + '/tizonia'] +- omx_inc = [] +-elif omx_target == 'sf' +- warning('sf selected') +-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 ''' +- 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', +- '-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'), check: true) +- release_date = run_result.stdout().strip() +- cdata.set_quoted('GST_PACKAGE_RELEASE_DATETIME', release_date) +- message('Package release date: ' + release_date) +-endif +- +-configure_file(output: 'config.h', configuration: cdata) +- +-meson.add_dist_script('scripts/gen-changelog.py', meson.project_name(), '1.20.0', meson.project_version()) +Index: gst-omx-1.22.0/omx/gstomx.c +=================================================================== +--- gst-omx-1.22.0.orig/omx/gstomx.c 2023-03-02 08:43:33.398733747 +0000 ++++ gst-omx-1.22.0/omx/gstomx.c 2023-03-02 08:43:33.394733779 +0000 +@@ -70,6 +70,11 @@ + G_LOCK_DEFINE_STATIC (buffer_flags_str); + static GHashTable *buffer_flags_str; + ++#ifdef COMBINE_SPS_PPS_HEADERS ++static OMX_U8 *sps_pps_header = NULL; ++static OMX_U32 sps_pps_header_size = 0; ++#endif ++ + GstOMXCore * + gst_omx_core_acquire (const gchar * filename) + { +@@ -903,6 +908,36 @@ + + g_assert (buf->omx_buf == pBuffer); + ++#ifdef COMBINE_SPS_PPS_HEADERS ++ if (pBuffer->nFlags == 0x80) { ++ g_assert (sps_pps_header == NULL); ++ if (sps_pps_header) ++ g_free (sps_pps_header); ++ ++ sps_pps_header = g_new (OMX_U8, pBuffer->nFilledLen); ++ if (sps_pps_header) { ++ sps_pps_header_size = pBuffer->nFilledLen; ++ memcpy(sps_pps_header, pBuffer->pBuffer + pBuffer->nOffset, pBuffer->nFilledLen); ++ } ++ return OMX_ErrorNone; ++ } ++ ++ if (sps_pps_header) { ++ g_assert (sps_pps_header_size + pBuffer->nFilledLen <= pBuffer->nAllocLen); ++ if (sps_pps_header_size + pBuffer->nFilledLen <= pBuffer->nAllocLen) { ++ OMX_U8 *buf; ++ buf = pBuffer->pBuffer + pBuffer->nOffset; ++ memmove (buf + sps_pps_header_size, buf, pBuffer->nFilledLen); ++ memcpy (buf, sps_pps_header, sps_pps_header_size); ++ pBuffer->nFilledLen += sps_pps_header_size; ++ ++ g_free (sps_pps_header); ++ sps_pps_header = NULL; ++ sps_pps_header_size = 0; ++ } ++ } ++#endif /* COMBINE_SPS_PPS_HEADERS */ ++ + if (buf->port->tunneled) { + GST_ERROR ("FillBufferDone on tunneled port"); + return OMX_ErrorBadParameter; diff --git a/gst-omx/debian/patches/0013-Modify-sf-component-name-to-in-std-format.patch b/gst-omx/debian/patches/0013-Modify-sf-component-name-to-in-std-format.patch new file mode 100644 index 0000000000..83ffe933db --- /dev/null +++ b/gst-omx/debian/patches/0013-Modify-sf-component-name-to-in-std-format.patch @@ -0,0 +1,73 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +--- gst-omx-1.22.0.orig/config/sf/gstomx.conf ++++ gst-omx-1.22.0/config/sf/gstomx.conf +@@ -1,7 +1,7 @@ + [omxh265dec] + type-name=GstOMXH265Dec + core-name=/usr/lib/libsf-omx-il.so +-component-name=sf.dec.decoder.h265 ++component-name=OMX.sf.video_decoder.hevc.internal + in-port-index=0 + out-port-index=1 + rank=257 +@@ -10,7 +10,7 @@ hacks=pass-profile-to-decoder;pass-color + [omxh264dec] + type-name=GstOMXH264Dec + core-name=/usr/lib/libsf-omx-il.so +-component-name=sf.dec.decoder.h264 ++component-name=OMX.sf.video_decoder.avc.internal + in-port-index=0 + out-port-index=1 + rank=257 +@@ -19,7 +19,7 @@ hacks=pass-profile-to-decoder;pass-color + [omxh265enc] + type-name=GstOMXH265Enc + core-name=/usr/lib/libsf-omx-il.so +-component-name=sf.enc.encoder.h265 ++component-name=OMX.sf.video_encoder.hevc + in-port-index=0 + out-port-index=1 + rank=1 +@@ -28,7 +28,7 @@ hacks=pass-profile-to-decoder;pass-color + [omxh264enc] + type-name=GstOMXH264Enc + core-name=/usr/lib/libsf-omx-il.so +-component-name=sf.enc.encoder.h264 ++component-name=OMX.sf.video_encoder.avc + in-port-index=0 + out-port-index=1 + rank=1 +@@ -37,7 +37,7 @@ hacks=pass-profile-to-decoder;pass-color + [omxmjpegdec] + type-name=GstOMXMJPEGDec + core-name=/usr/lib/libsf-omx-il.so +-component-name=sf.dec.decoder.mjpeg ++component-name=OMX.sf.video_decoder.mjpeg.internal + in-port-index=0 + out-port-index=1 + rank=1 diff --git a/gst-omx/debian/patches/0014-support-nv21-for-omxh264_5dec.patch b/gst-omx/debian/patches/0014-support-nv21-for-omxh264_5dec.patch new file mode 100644 index 0000000000..b9877261a4 --- /dev/null +++ b/gst-omx/debian/patches/0014-support-nv21-for-omxh264_5dec.patch @@ -0,0 +1,37 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +--- gst-omx-1.22.0.orig/omx/gstomxvideo.h ++++ gst-omx-1.22.0/omx/gstomxvideo.h +@@ -36,7 +36,7 @@ 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 }" ++ "NV16, YUY2, YVYU, UYVY, NV12, NV21, I420, RGB16, BGR16, ABGR, ARGB, GRAY8 }" + + #define GST_OMX_VIDEO_ENC_SUPPORTED_FORMATS "{ NV16_10LE32, NV12_10LE32, " \ + "NV16, NV12, I420, GRAY8 }" diff --git a/gst-omx/debian/patches/0015_Add_NV21_for_gstomxvideoenc_class.patch b/gst-omx/debian/patches/0015_Add_NV21_for_gstomxvideoenc_class.patch new file mode 100644 index 0000000000..57cad7406d --- /dev/null +++ b/gst-omx/debian/patches/0015_Add_NV21_for_gstomxvideoenc_class.patch @@ -0,0 +1,91 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +--- gst-omx-1.22.0.orig/omx/gstomxvideo.h ++++ gst-omx-1.22.0/omx/gstomxvideo.h +@@ -39,7 +39,7 @@ G_BEGIN_DECLS + "NV16, YUY2, YVYU, UYVY, NV12, NV21, I420, RGB16, BGR16, ABGR, ARGB, GRAY8 }" + + #define GST_OMX_VIDEO_ENC_SUPPORTED_FORMATS "{ NV16_10LE32, NV12_10LE32, " \ +- "NV16, NV12, I420, GRAY8 }" ++ "NV16, NV12, NV21, I420, GRAY8 }" + + typedef struct + { +--- gst-omx-1.22.0.orig/omx/gstomxvideoenc.c ++++ gst-omx-1.22.0/omx/gstomxvideoenc.c +@@ -1391,6 +1391,7 @@ get_chroma_info_from_input (GstOMXVideoE + break; + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_NV12: ++ case GST_VIDEO_FORMAT_NV21: + *chroma_format = "4:2:0"; + *bit_depth_luma = *bit_depth_chroma = 8; + break; +@@ -2045,6 +2046,7 @@ gst_omx_video_enc_configure_input_buffer + + case OMX_COLOR_FormatYUV420PackedSemiPlanar: + case OMX_COLOR_FormatYUV420SemiPlanar: ++ case OMX_COLOR_FormatYVU420SemiPlanar: + port_def.nBufferSize = + (port_def.format.video.nStride * port_def.format.video.nFrameHeight) + + (port_def.format.video.nStride * +@@ -2693,6 +2695,9 @@ gst_omx_video_enc_set_format (GstVideoEn + case GST_VIDEO_FORMAT_ARGB: + port_def.format.video.eColorFormat = OMX_COLOR_Format32bitBGRA8888; + break; ++ case GST_VIDEO_FORMAT_NV21: ++ port_def.format.video.eColorFormat = OMX_COLOR_FormatYVU420SemiPlanar; ++ break; + default: + GST_ERROR_OBJECT (self, "Unsupported format %s", + gst_video_format_to_string (info->finfo->format)); +@@ -3094,6 +3099,7 @@ gst_omx_video_enc_fill_buffer (GstOMXVid + break; + } + case GST_VIDEO_FORMAT_NV12: ++ case GST_VIDEO_FORMAT_NV21: + case GST_VIDEO_FORMAT_NV16: + case GST_VIDEO_FORMAT_NV12_10LE32: + case GST_VIDEO_FORMAT_NV16_10LE32: +@@ -3728,6 +3734,7 @@ filter_supported_formats (GList * negoti + case GST_VIDEO_FORMAT_NV16: + case GST_VIDEO_FORMAT_NV16_10LE32: + case GST_VIDEO_FORMAT_GRAY8: ++ case GST_VIDEO_FORMAT_NV21: + cur = g_list_next (cur); + continue; + default: +--- gst-omx-1.22.0.orig/omx/openmax/OMX_IVCommon.h ++++ gst-omx-1.22.0/omx/openmax/OMX_IVCommon.h +@@ -130,6 +130,7 @@ typedef enum OMX_COLOR_FORMATTYPE { + OMX_COLOR_Format18BitBGR666, + OMX_COLOR_Format24BitARGB6666, + OMX_COLOR_Format24BitABGR6666, ++ OMX_COLOR_FormatYVU420SemiPlanar, /* NV21 */ + 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 diff --git a/gst-omx/debian/patches/0016-Modify-gstomxmjpegdec-format.patch b/gst-omx/debian/patches/0016-Modify-gstomxmjpegdec-format.patch new file mode 100644 index 0000000000..47dfaccf81 --- /dev/null +++ b/gst-omx/debian/patches/0016-Modify-gstomxmjpegdec-format.patch @@ -0,0 +1,103 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +--- gst-omx-1.22.0.orig/config/sf/gstomx.conf ++++ gst-omx-1.22.0/config/sf/gstomx.conf +@@ -42,4 +42,4 @@ in-port-index=0 + out-port-index=1 + rank=1 + hacks=pass-profile-to-decoder;pass-color-format-to-decoder;ensure-buffer-count-actual +-src-template-caps=video/x-raw, format = (string) { NV16_10LE32, NV12_10LE32, NV16, YUY2, YVYU, UYVY, NV12, NV21, I420, RGB16, BGR16, ABGR, ARGB, GRAY8, Y42B, Y444 }, width = (int) [ 1, max ], height = (int) [ 1, max ], framerate = (fraction) [ 0, max ] ++src-template-caps=video/x-raw, format = (string) { NV16_10LE32, NV12_10LE32, NV16, NV61, YUY2, YVYU, UYVY, NV12, NV21, I420, RGB16, BGR16, ABGR, ARGB, GRAY8, Y42B, Y444, VYUY, v308 }, width = (int) [ 1, max ], height = (int) [ 1, max ], framerate = (fraction) [ 0, max ] +--- gst-omx-1.22.0.orig/omx/gstomxbufferpool.c ++++ gst-omx-1.22.0/omx/gstomxbufferpool.c +@@ -355,10 +355,13 @@ gst_omx_buffer_pool_alloc_buffer (GstBuf + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: ++ case GST_VIDEO_FORMAT_GRAY8: ++ break; + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_YVYU: +- case GST_VIDEO_FORMAT_GRAY8: ++ case GST_VIDEO_FORMAT_VYUY: ++ stride[0] = GST_ROUND_UP_4(nstride * 2); + break; + case GST_VIDEO_FORMAT_I420: + stride[1] = nstride / 2; +@@ -370,6 +373,7 @@ gst_omx_buffer_pool_alloc_buffer (GstBuf + case GST_VIDEO_FORMAT_NV12_10LE32: + case GST_VIDEO_FORMAT_NV16: + case GST_VIDEO_FORMAT_NV16_10LE32: ++ case GST_VIDEO_FORMAT_NV61: + #ifdef USE_OMX_TARGET_STARFIVE + case GST_VIDEO_FORMAT_NV21: + #endif +@@ -392,6 +396,9 @@ gst_omx_buffer_pool_alloc_buffer (GstBuf + offset[1] = offset[0] + stride[0] * nslice; + offset[2] = offset[1] + stride[1] * nslice; + break; ++ case GST_VIDEO_FORMAT_v308: ++ stride[0] = GST_ROUND_UP_4(nstride * 3); ++ break; + #endif + default: + g_assert_not_reached (); +--- gst-omx-1.22.0.orig/omx/gstomxvideo.c ++++ gst-omx-1.22.0/omx/gstomxvideo.c +@@ -99,11 +99,20 @@ gst_omx_video_get_format_from_omx (OMX_C + format = GST_VIDEO_FORMAT_Y42B; + break; + case OMX_COLOR_FormatYUV444Interleaved: +- format = GST_VIDEO_FORMAT_Y444; ++ format = GST_VIDEO_FORMAT_v308; + break; + case OMX_COLOR_FormatYVU420SemiPlanar: + format = GST_VIDEO_FORMAT_NV21; + break; ++ case OMX_COLOR_FormatCrYCbY: ++ format = GST_VIDEO_FORMAT_VYUY; ++ break; ++ case OMX_COLOR_FormatYUV444Planar: ++ format = GST_VIDEO_FORMAT_Y444; ++ break; ++ case OMX_COLOR_FormatYVU422SemiPlanar: ++ format = GST_VIDEO_FORMAT_NV61; ++ break; + #endif + default: + format = GST_VIDEO_FORMAT_UNKNOWN; +--- gst-omx-1.22.0.orig/omx/gstomxvideodec.c ++++ gst-omx-1.22.0/omx/gstomxvideodec.c +@@ -646,6 +646,7 @@ gst_omx_video_dec_fill_buffer (GstOMXVid + break; + #ifdef USE_OMX_TARGET_STARFIVE + case GST_VIDEO_FORMAT_Y444: ++ case GST_VIDEO_FORMAT_v308: + dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo); + dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo); + dst_width[2] = GST_VIDEO_INFO_WIDTH (vinfo); diff --git a/gst-omx/debian/patches/0017-support-mirror-rotation-scale-for-gstomxmjpegdec.patch b/gst-omx/debian/patches/0017-support-mirror-rotation-scale-for-gstomxmjpegdec.patch new file mode 100644 index 0000000000..8f6644f650 --- /dev/null +++ b/gst-omx/debian/patches/0017-support-mirror-rotation-scale-for-gstomxmjpegdec.patch @@ -0,0 +1,408 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +--- gst-omx-1.22.0.orig/omx/gstomxmjpegdec.c ++++ gst-omx-1.22.0/omx/gstomxmjpegdec.c +@@ -30,8 +30,19 @@ GST_DEBUG_CATEGORY_STATIC (gst_omx_mjpeg + #define GST_CAT_DEFAULT gst_omx_mjpeg_dec_debug_category + #ifdef USE_OMX_TARGET_STARFIVE + #define DEFAULT_FRAMERATE 0 ++#define DEFAULT_MIRROR 0 ++#define DEFAULT_ROTATION 0 ++#define DEFAULT_SCALEH 0 ++#define DEFAULT_SCALEV 0 + #endif + /* prototypes */ ++ ++static gboolean ++gst_omx_jpegdec_set_scale (GstOMXVideoDec * self); ++static gboolean ++gst_omx_jpegdec_set_rotation (GstOMXVideoDec * self); ++static gboolean ++gst_omx_jpegdec_set_mirror (GstOMXVideoDec * self); + 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, +@@ -46,10 +57,14 @@ enum + { + #ifdef USE_OMX_TARGET_STARFIVE + PROP_0, +- PROP_FRAMERATE ++ PROP_FRAMERATE, + #else +- PROP_0 ++ PROP_0, + #endif ++ PROP_MIRROR, ++ PROP_SCALEH, ++ PROP_SCALEV, ++ PROP_ROTATION, + }; + + /* class initialization */ +@@ -61,6 +76,67 @@ enum + G_DEFINE_TYPE_WITH_CODE (GstOMXMJPEGDec, gst_omx_mjpeg_dec, + GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT); + ++#define GST_OMX_MJPEG_DEC_MIRROR_MODE (gst_omx_mjpeg_dec_mirror_mode_get_type ()) ++ ++static GType ++gst_omx_mjpeg_dec_mirror_mode_get_type (void) ++{ ++ static GType qtype = 0; ++ if (qtype == 0) { ++ static const GEnumValue values[] = { ++ { OMX_MirrorNone, "None", "none"}, ++ { OMX_MirrorVertical, "Mirror Vertical", "V"}, ++ { OMX_MirrorHorizontal, "Mirror Horizontal", "H"}, ++ { OMX_MirrorBoth, "Mirror Both", "VH"}, ++ { 0, NULL, NULL} ++ }; ++ ++ qtype = g_enum_register_static("GstOMXMJPEGDecMirrorMode",values); ++ } ++ return qtype; ++} ++ ++#define GST_OMX_MJPEG_DEC_ROTATION_MODE (gst_omx_mjpeg_dec_rotation_mode_get_type ()) ++ ++static GType ++gst_omx_mjpeg_dec_rotation_mode_get_type (void) ++{ ++ static GType qtype = 0; ++ if (qtype == 0) { ++ static const GEnumValue values[] = { ++ { ROTATION_0, "None", "none"}, ++ { ROTATION_90, "Rotate 90", "M1"}, ++ { ROTATION_180, "Rotate 180", "M2"}, ++ { ROTATION_270, "Rotate 270", "M3"}, ++ { 0, NULL, NULL} ++ }; ++ ++ qtype = g_enum_register_static ("GstOMXMJPEGDecRotationMode", values); ++ } ++ return qtype; ++} ++ ++#define GST_OMX_MJPEG_DEC_SCALE_MODE (gst_omx_mjpeg_dec_scale_mode_get_type ()) ++ ++static GType ++gst_omx_mjpeg_dec_scale_mode_get_type (void) ++{ ++ static GType qtype = 0; ++ if (qtype == 0) { ++ static const GEnumValue values[] = { ++ { SCALEMODE_0, "None", "none"}, ++ { SCALEMODE1_2, "Scale half", "1/2"}, ++ { SCALEMODE1_4, "Scale quarter", "1/4"}, ++ { SCALEMODE1_8, "Scale eighth", "1/8"}, ++ { 0, NULL, NULL} ++ }; ++ ++ qtype = g_enum_register_static ("GstOMXMJPEGDecScaleMode", values); ++ } ++ return qtype; ++} ++ ++ + static void + gst_omx_mjpeg_dec_class_init (GstOMXMJPEGDecClass * klass) + { +@@ -94,12 +170,40 @@ gst_omx_mjpeg_dec_class_init (GstOMXMJPE + 0, G_MAXINT, + DEFAULT_FRAMERATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + #endif ++ g_object_class_install_property (gobject_class, PROP_MIRROR, ++ g_param_spec_enum ("mirror", "MIRROR", ++ "Mirror 0(none), 1(V), 2(H), 3(VH).", ++ GST_OMX_MJPEG_DEC_MIRROR_MODE, ++ DEFAULT_MIRROR, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); ++ ++ g_object_class_install_property (gobject_class, PROP_ROTATION, ++ g_param_spec_enum ("rotation", "ROTATION", ++ "Rotation 0(none), 1(90), 2(180), 3(270).", ++ GST_OMX_MJPEG_DEC_ROTATION_MODE, ++ DEFAULT_ROTATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); ++ ++ g_object_class_install_property (gobject_class, PROP_SCALEH, ++ g_param_spec_enum ("scaleH", "ScaleH", ++ "Horizontal downscale: 0(none), 1(1/2), 2(1/4), 3(1/8).", ++ GST_OMX_MJPEG_DEC_SCALE_MODE, DEFAULT_SCALEH, ++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); ++ ++ g_object_class_install_property (gobject_class, PROP_SCALEV, ++ g_param_spec_enum ("scaleV", "ScaleV", ++ "Vertical downscale: 0(none), 1(1/2), 2(1/4), 3(1/8).", ++ GST_OMX_MJPEG_DEC_SCALE_MODE, DEFAULT_SCALEV, ++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); ++ + gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.mjpeg"); + } + + static void + gst_omx_mjpeg_dec_init (GstOMXMJPEGDec * self) + { ++ self->mirror = DEFAULT_MIRROR; ++ self->rotation = DEFAULT_ROTATION; ++ self->scaleH = DEFAULT_SCALEH; ++ self->scaleV = DEFAULT_SCALEV; + } + + static gboolean +@@ -128,6 +232,15 @@ gst_omx_mjpeg_dec_set_format (GstOMXVide + } + } + #endif ++ if (!gst_omx_jpegdec_set_mirror (dec)) ++ return FALSE; ++ ++ if (!gst_omx_jpegdec_set_rotation (dec)) ++ return FALSE; ++ ++ if (!gst_omx_jpegdec_set_scale (dec)) ++ return FALSE; ++ + 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; +@@ -144,6 +257,18 @@ gst_omx_mjpeg_dec_set_property (GObject + case PROP_FRAMERATE: + mjpeg_dec->framerate = g_value_get_int (value); + break; ++ case PROP_MIRROR: ++ mjpeg_dec->mirror = g_value_get_enum (value); ++ break; ++ case PROP_ROTATION: ++ mjpeg_dec->rotation = g_value_get_enum (value); ++ break; ++ case PROP_SCALEH: ++ mjpeg_dec->scaleH = g_value_get_enum (value); ++ break; ++ case PROP_SCALEV: ++ mjpeg_dec->scaleV = g_value_get_enum (value); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -159,9 +284,164 @@ gst_omx_mjpeg_dec_get_property (GObject + case PROP_FRAMERATE: + g_value_set_int (value, mjpeg_dec->framerate); + break; ++ case PROP_MIRROR: ++ g_value_set_enum (value, mjpeg_dec->mirror); ++ break; ++ case PROP_ROTATION: ++ g_value_set_enum (value, mjpeg_dec->rotation); ++ break; ++ case PROP_SCALEH: ++ g_value_set_enum (value, mjpeg_dec->scaleH); ++ break; ++ case PROP_SCALEV: ++ g_value_set_enum (value, mjpeg_dec->scaleV); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + } + #endif ++ ++static gboolean ++gst_omx_jpegdec_set_rotation (GstOMXVideoDec * self) ++{ ++ OMX_ERRORTYPE err; ++ OMX_CONFIG_ROTATIONTYPE rotation_config; ++ gboolean result = TRUE; ++ GstOMXMJPEGDec * mjpeg_dec = GST_OMX_MJPEG_DEC (self); ++ ++ GST_OBJECT_LOCK (self); ++ ++ GST_OMX_INIT_STRUCT (&rotation_config); ++ rotation_config.nPortIndex = self->dec_out_port->index; ++ ++ err = ++ gst_omx_component_get_config (self->dec, ++ OMX_IndexConfigCommonRotate, &rotation_config); ++ ++ if (err == OMX_ErrorNone) { ++ if (mjpeg_dec->rotation >= 0 && mjpeg_dec->rotation <= 270) ++ rotation_config.nRotation = mjpeg_dec->rotation; ++ ++ err = ++ gst_omx_component_set_config (self->dec, ++ OMX_IndexConfigCommonRotate, &rotation_config); ++ if (err == OMX_ErrorUnsupportedIndex) { ++ GST_WARNING_OBJECT (self, ++ "Setting a rotation not supported by the component"); ++ } else if (err == OMX_ErrorUnsupportedSetting) { ++ GST_WARNING_OBJECT (self, ++ "Setting rotation settings %u not supported by the component", ++ mjpeg_dec->rotation); ++ } else if (err != OMX_ErrorNone) { ++ GST_ERROR_OBJECT (self, ++ "Failed to set rotation parameters: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ result = FALSE; ++ } ++ } else { ++ GST_ERROR_OBJECT (self, "Failed to get rotation parameters: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ } ++ ++ GST_OBJECT_UNLOCK (self); ++ return result; ++} ++ ++ ++ ++static gboolean ++gst_omx_jpegdec_set_mirror (GstOMXVideoDec * self) ++{ ++ OMX_ERRORTYPE err; ++ OMX_CONFIG_MIRRORTYPE mirror_config; ++ gboolean result = TRUE; ++ GstOMXMJPEGDec * mjpeg_dec = GST_OMX_MJPEG_DEC (self); ++ ++ GST_OBJECT_LOCK (self); ++ ++ GST_OMX_INIT_STRUCT (&mirror_config); ++ mirror_config.nPortIndex = self->dec_out_port->index; ++ ++ err = ++ gst_omx_component_get_config (self->dec, ++ OMX_IndexConfigCommonMirror, &mirror_config); ++ ++ if (err == OMX_ErrorNone) { ++ if (mjpeg_dec->mirror >= 0 && mjpeg_dec->mirror <= OMX_MirrorBoth) ++ mirror_config.eMirror = mjpeg_dec->mirror; ++ ++ err = ++ gst_omx_component_set_config (self->dec, ++ OMX_IndexConfigCommonMirror, &mirror_config); ++ if (err == OMX_ErrorUnsupportedIndex) { ++ GST_WARNING_OBJECT (self, ++ "Setting a mirror not supported by the component"); ++ } else if (err == OMX_ErrorUnsupportedSetting) { ++ GST_WARNING_OBJECT (self, ++ "Setting mirror settings %u not supported by the component", ++ mjpeg_dec->mirror); ++ } else if (err != OMX_ErrorNone) { ++ GST_ERROR_OBJECT (self, ++ "Failed to set mirror parameters: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ result = FALSE; ++ } ++ } else { ++ GST_ERROR_OBJECT (self, "Failed to get mirror parameters: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ } ++ ++ GST_OBJECT_UNLOCK (self); ++ return result; ++} ++ ++static gboolean ++gst_omx_jpegdec_set_scale (GstOMXVideoDec * self) ++{ ++ OMX_ERRORTYPE err; ++ OMX_CONFIG_SCALEFACTORTYPE scale_config; ++ gboolean result = TRUE; ++ GstOMXMJPEGDec * mjpeg_dec = GST_OMX_MJPEG_DEC (self); ++ ++ GST_OBJECT_LOCK (self); ++ ++ GST_OMX_INIT_STRUCT (&scale_config); ++ scale_config.nPortIndex = self->dec_out_port->index; ++ ++ err = ++ gst_omx_component_get_config (self->dec, ++ OMX_IndexConfigCommonScale, &scale_config); ++ ++ if (err == OMX_ErrorNone) { ++ if ((mjpeg_dec->scaleV >= 0 && mjpeg_dec->scaleV <= 3 ) || ++ (mjpeg_dec->scaleH >= 0 && mjpeg_dec->scaleH <= 3)) { ++ scale_config.xWidth = (1 << 16) >> (mjpeg_dec->scaleH & 0x3); ++ scale_config.xHeight = (1 << 16) >> (mjpeg_dec->scaleV & 0x3); ++ } ++ ++ err = ++ gst_omx_component_set_config (self->dec, ++ OMX_IndexConfigCommonScale, &scale_config); ++ if (err == OMX_ErrorUnsupportedIndex) { ++ GST_WARNING_OBJECT (self, ++ "Setting a scale not supported by the component"); ++ } else if (err == OMX_ErrorUnsupportedSetting) { ++ GST_WARNING_OBJECT (self, ++ "Setting scale settings %u %u not supported by the component", ++ mjpeg_dec->scaleV, mjpeg_dec->scaleH); ++ } else if (err != OMX_ErrorNone) { ++ GST_ERROR_OBJECT (self, ++ "Failed to set scale parameters: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ result = FALSE; ++ } ++ } else { ++ GST_ERROR_OBJECT (self, "Failed to get scale parameters: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ } ++ ++ GST_OBJECT_UNLOCK (self); ++ return result; ++} +\ No newline at end of file +--- gst-omx-1.22.0.orig/omx/gstomxmjpegdec.h ++++ gst-omx-1.22.0/omx/gstomxmjpegdec.h +@@ -55,6 +55,10 @@ struct _GstOMXMJPEGDec + // gst-launch-1.0 -v filesrc location=xxx.mjpeg ! jpegparse ! omxmjpegdec framerate=xxx ! kmssink driver-name=starfive force-modesetting=1 + gint framerate; + #endif ++ guint32 mirror; ++ guint32 scaleH; ++ guint32 scaleV; ++ guint32 rotation; + }; + + struct _GstOMXMJPEGDecClass +@@ -68,3 +72,19 @@ G_END_DECLS + + #endif /* __GST_OMX_MJPEG_DEC_H__ */ + ++typedef enum ROTATIONTYPE ++{ ++ ROTATION_0 = 0, ++ ROTATION_90 = 90, ++ ROTATION_180 = 180, ++ ROTATION_270 = 270, ++} ROTATIONTYPE; ++ ++typedef enum SCALETYPE ++{ ++ SCALEMODE_0 = 0, ++ SCALEMODE1_2, ++ SCALEMODE1_4, ++ SCALEMODE1_8, ++} SCALETYPE; ++ diff --git a/gst-omx/debian/patches/0018-support-cut-for-gstomxmjpegdec.patch- b/gst-omx/debian/patches/0018-support-cut-for-gstomxmjpegdec.patch- new file mode 100644 index 0000000000..c8eee5ab9a --- /dev/null +++ b/gst-omx/debian/patches/0018-support-cut-for-gstomxmjpegdec.patch- @@ -0,0 +1,214 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +--- gst-omx-1.22.0.orig/omx/gstomxmjpegdec.c ++++ gst-omx-1.22.0/omx/gstomxmjpegdec.c +@@ -34,6 +34,8 @@ GST_DEBUG_CATEGORY_STATIC (gst_omx_mjpeg + #define DEFAULT_ROTATION 0 + #define DEFAULT_SCALEH 0 + #define DEFAULT_SCALEV 0 ++#define DEFAULT_ROI "" ++ + #endif + /* prototypes */ + +@@ -43,6 +45,8 @@ static gboolean + gst_omx_jpegdec_set_rotation (GstOMXVideoDec * self); + static gboolean + gst_omx_jpegdec_set_mirror (GstOMXVideoDec * self); ++static gboolean ++gst_omx_jpegdec_set_roi (GstOMXVideoDec * self); + 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, +@@ -65,6 +69,7 @@ enum + PROP_SCALEH, + PROP_SCALEV, + PROP_ROTATION, ++ PROP_ROI, + }; + + /* class initialization */ +@@ -194,6 +199,17 @@ gst_omx_mjpeg_dec_class_init (GstOMXMJPE + GST_OMX_MJPEG_DEC_SCALE_MODE, DEFAULT_SCALEV, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + ++ g_object_class_install_property (gobject_class, PROP_ROI, ++ g_param_spec_string ("roi", "ROI", ++ "Cutting image roi=,,, .\n \ ++ roi coord and width/height(from left top).\n \ ++ X Coordinate of the top left corner of the rectangle.\n \ ++ Y Coordinate of the top left corner of the rectangle.\n \ ++ Width of the rectangle.\n \ ++ Height of the rectangle.\n \ ++ EX:omxmjpegdec roi=0,0,800,480", ++ DEFAULT_ROI, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); ++ + gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.mjpeg"); + } + +@@ -204,6 +220,7 @@ gst_omx_mjpeg_dec_init (GstOMXMJPEGDec * + self->rotation = DEFAULT_ROTATION; + self->scaleH = DEFAULT_SCALEH; + self->scaleV = DEFAULT_SCALEV; ++ memset (self->roi, 0, ROI_ARRAY_SIZE); + } + + static gboolean +@@ -240,6 +257,9 @@ gst_omx_mjpeg_dec_set_format (GstOMXVide + + if (!gst_omx_jpegdec_set_scale (dec)) + return FALSE; ++ ++ if (!gst_omx_jpegdec_set_roi (dec)) ++ return FALSE; + + gst_omx_port_get_port_definition (port, &port_def); + port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingMJPEG; +@@ -269,6 +289,9 @@ gst_omx_mjpeg_dec_set_property (GObject + case PROP_SCALEV: + mjpeg_dec->scaleV = g_value_get_enum (value); + break; ++ case PROP_ROI: ++ strncpy (mjpeg_dec->roi, g_value_get_string (value), ROI_ARRAY_SIZE); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -296,6 +319,9 @@ gst_omx_mjpeg_dec_get_property (GObject + case PROP_SCALEV: + g_value_set_enum (value, mjpeg_dec->scaleV); + break; ++ case PROP_ROI: ++ g_value_set_string (value, mjpeg_dec->roi); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -444,4 +470,81 @@ gst_omx_jpegdec_set_scale (GstOMXVideoDe + + GST_OBJECT_UNLOCK (self); + return result; +-} +\ No newline at end of file ++} ++ ++static gboolean ++gst_omx_jpegdec_set_roi (GstOMXVideoDec *self) ++{ ++ OMX_ERRORTYPE err; ++ OMX_CONFIG_RECTTYPE RectConfig; ++ gboolean result = TRUE; ++ GstOMXMJPEGDec * mjpeg_dec = GST_OMX_MJPEG_DEC (self); ++ gchar* val; ++ gchar roi_tmp[ROI_ARRAY_SIZE]; ++ strncpy (roi_tmp, mjpeg_dec->roi, ROI_ARRAY_SIZE); ++ ++ GST_OBJECT_LOCK (self); ++ GST_OMX_INIT_STRUCT (&RectConfig); ++ RectConfig.nPortIndex = self->dec_out_port->index; ++ ++ err = ++ gst_omx_component_get_config (self->dec, ++ OMX_IndexConfigCommonScale, &RectConfig); ++ if (err == OMX_ErrorNone) { ++ if (strlen (mjpeg_dec->roi) > 0) { ++ val = strtok (roi_tmp, ","); ++ if (val == NULL) { ++ goto ROI_PARAM_ERROR; ++ } else { ++ RectConfig.nLeft = atoi (val); ++ } ++ val = strtok (NULL, ","); ++ if (val == NULL) { ++ goto ROI_PARAM_ERROR; ++ } else { ++ RectConfig.nTop = atoi (val); ++ } ++ val = strtok (NULL, ","); ++ if (val == NULL) { ++ goto ROI_PARAM_ERROR; ++ } else { ++ RectConfig.nWidth = atoi (val); ++ } ++ val = strtok (NULL, ","); ++ if (val == NULL) { ++ goto ROI_PARAM_ERROR; ++ } else { ++ RectConfig.nHeight = atoi (val); ++ } ++ } else { ++ GST_OBJECT_UNLOCK (self); ++ return TRUE; ++ } ++ ++ err = ++ gst_omx_component_set_config (self->dec, ++ OMX_IndexConfigCommonOutputCrop, &RectConfig); ++ if (err == OMX_ErrorUnsupportedIndex) { ++ GST_WARNING_OBJECT (self, ++ "Setting a ROI not supported by the component"); ++ } else if (err == OMX_ErrorUnsupportedSetting) { ++ GST_WARNING_OBJECT (self, ++ "Setting ROI settings %s not supported by the component", mjpeg_dec->roi); ++ } else if (err != OMX_ErrorNone) { ++ GST_ERROR_OBJECT (self, ++ "Failed to set ROI parameters: %s (0x%08x)", gst_omx_error_to_string (err), err); ++ result = FALSE; ++ } ++ } else { ++ GST_ERROR_OBJECT (self, "Failed to get ROI parameters: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ } ++ ++ GST_OBJECT_UNLOCK (self); ++ return result; ++ ++ROI_PARAM_ERROR: ++ GST_ERROR_OBJECT (self, "Invalid ROI parameter: %s", mjpeg_dec->roi); ++ GST_OBJECT_UNLOCK (self); ++ return FALSE; ++} +--- gst-omx-1.22.0.orig/omx/gstomxmjpegdec.h ++++ gst-omx-1.22.0/omx/gstomxmjpegdec.h +@@ -42,6 +42,8 @@ G_BEGIN_DECLS + typedef struct _GstOMXMJPEGDec GstOMXMJPEGDec; + typedef struct _GstOMXMJPEGDecClass GstOMXMJPEGDecClass; + ++#define ROI_ARRAY_SIZE 128 ++ + struct _GstOMXMJPEGDec + { + GstOMXVideoDec parent; +@@ -59,6 +61,8 @@ struct _GstOMXMJPEGDec + guint32 scaleH; + guint32 scaleV; + guint32 rotation; ++ gchar roi[ROI_ARRAY_SIZE]; ++ + }; + + struct _GstOMXMJPEGDecClass diff --git a/gst-omx/debian/patches/0019-Add-Interlaced-mode-judgment.patch b/gst-omx/debian/patches/0019-Add-Interlaced-mode-judgment.patch new file mode 100644 index 0000000000..d799374990 --- /dev/null +++ b/gst-omx/debian/patches/0019-Add-Interlaced-mode-judgment.patch @@ -0,0 +1,85 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +--- gst-omx-1.22.0.orig/omx/gstomxvideodec.c ++++ gst-omx-1.22.0/omx/gstomxvideodec.c +@@ -740,7 +740,7 @@ gst_omx_try_importing_buffer (GstOMXVide + #ifdef USE_OMX_TARGET_STARFIVE + if ( !gst_is_dmabuf_memory (mem)) { + GST_INFO_OBJECT (self, +- " %d-th buffer doesn't contain dmabuf, go to out. port->port_def.nBufferSize: %lu", ++ " %d-th buffer doesn't contain dmabuf, go to out. port->port_def.nBufferSize: %u", + i, port->port_def.nBufferSize); + goto out; + } +@@ -2795,7 +2795,7 @@ gst_omx_video_dec_set_format (GstVideoDe + gboolean needs_disable = FALSE; + OMX_PARAM_PORTDEFINITIONTYPE port_def; + OMX_U32 framerate_q16 = gst_omx_video_calculate_framerate_q16 (info); +- ++ static gboolean interlaced_print_flag = FALSE; + self = GST_OMX_VIDEO_DEC (decoder); + klass = GST_OMX_VIDEO_DEC_GET_CLASS (decoder); + +@@ -2857,9 +2857,17 @@ gst_omx_video_dec_set_format (GstVideoDe + /*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)) ++ if (GST_VIDEO_INFO_IS_INTERLACED (info)) { + port_def.format.video.nFrameHeight = + GST_ROUND_UP_2 (port_def.format.video.nFrameHeight / 2); ++ if (!interlaced_print_flag) { ++ g_print("Current stream mode is %s, but just support PROGRESSIVE type. \n", ++ gst_video_interlace_mode_to_string (info->interlace_mode)); ++ GST_ERROR_OBJECT (self, "Just support PROGRESSIVE type "); ++ interlaced_print_flag = TRUE; ++ } ++ return FALSE; ++ } + port_def.format.video.xFramerate = framerate_q16; + + if (klass->cdata.hacks & GST_OMX_HACK_PASS_COLOR_FORMAT_TO_DECODER) { +--- gst-omx-1.22.0.orig/omx/gstomxvideoenc.c ++++ gst-omx-1.22.0/omx/gstomxvideoenc.c +@@ -2136,7 +2136,7 @@ gst_omx_try_importing_buffer (GstOMXVide + + if ( !gst_is_dmabuf_memory (mem)) { + GST_INFO_OBJECT (self, +- " %d-th buffer doesn't contain dmabuf, go to out. port->port_def.nBufferSize: %lu", ++ " %d-th buffer doesn't contain dmabuf, go to out. port->port_def.nBufferSize: %u", + i, port->port_def.nBufferSize); + goto out; + } +@@ -2187,7 +2187,7 @@ gst_omx_video_enc_use_buffers (GstOMXVid + GList *frames = NULL; + OMX_ERRORTYPE err = OMX_ErrorNone; + gboolean is_mapped = FALSE ; +- GST_DEBUG(" nBufferCountActual=%d, nBufferCountMin= %lu", n, port->port_def.nBufferCountMin); ++ GST_DEBUG(" nBufferCountActual=%d, nBufferCountMin= %u", n, port->port_def.nBufferCountMin); + + if ( pool != NULL ) { + guint i; diff --git a/gst-omx/debian/patches/0020-use-sf-omx-header-replace-orig-file.patch b/gst-omx/debian/patches/0020-use-sf-omx-header-replace-orig-file.patch new file mode 100644 index 0000000000..7a949bfe5a --- /dev/null +++ b/gst-omx/debian/patches/0020-use-sf-omx-header-replace-orig-file.patch @@ -0,0 +1,8156 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.22.0-1) unstable; urgency=low + . + * New upstream release. +Author: Ying-Chun Liu (PaulLiu) + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: +Bug-Debian: https://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: (no|not-needed|) +Applied-Upstream: , (|commit:) +Reviewed-By: +Last-Update: 2023-03-01 + +Index: gst-omx-1.22.0/omx/openmax/OMX_Audio.h +=================================================================== +--- gst-omx-1.22.0.orig/omx/openmax/OMX_Audio.h 2023-03-02 08:48:43.000000000 +0000 ++++ gst-omx-1.22.0/omx/openmax/OMX_Audio.h 2023-03-02 08:58:22.000000000 +0000 +@@ -1,23 +1,23 @@ + /* +- * Copyright (c) 2008 The Khronos Group Inc. +- * ++ * 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: ++ * to the following conditions: + * The above copyright notice and this permission notice shall be included +- * in all copies or substantial portions of the Software. +- * ++ * 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. ++ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +@@ -36,7 +36,7 @@ + + /* 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 ++ * for this header file to compile successfully + */ + + #include +@@ -44,7 +44,7 @@ + /** @defgroup midi MIDI + * @ingroup audio + */ +- ++ + /** @defgroup effects Audio effects + * @ingroup audio + */ +@@ -54,10 +54,10 @@ + * @{ + */ + +-/** 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 ++/** 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 { +@@ -89,14 +89,14 @@ + 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_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 ++/** 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. +@@ -104,11 +104,11 @@ + 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, ++ for an output device, + otherwise this field is 0 */ +- OMX_BOOL bFlagErrorConcealment; /**< Turns on error concealment if it is ++ 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 ++ OMX_AUDIO_CODINGTYPE eEncoding; /**< Type of data expected for this + port (e.g. PCM, AMR, MP3, etc) */ + } OMX_AUDIO_PORTDEFINITIONTYPE; + +@@ -125,15 +125,15 @@ + } 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 */ ++/** 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; ++ OMX_AUDIO_PCMModeMax = 0x7FFFFFFF ++} OMX_AUDIO_PCMMODETYPE; + + + typedef enum OMX_AUDIO_CHANNELTYPE { +@@ -147,45 +147,45 @@ + 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_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_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 */ ++/** 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; ++} 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. ++ * 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 ++ 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 ++ 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 ++ 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_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; +@@ -195,7 +195,7 @@ + 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_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; +@@ -225,7 +225,7 @@ + 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_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; +@@ -233,20 +233,20 @@ + + /** 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 ++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; + + +@@ -309,40 +309,40 @@ + 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). ++ 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 ++ 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_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_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_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; + + +@@ -355,14 +355,14 @@ + 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_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 { +@@ -374,34 +374,34 @@ + 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_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 */ ++/** 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; ++} 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_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; + + +@@ -424,18 +424,18 @@ + } 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; ++/** 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 */ +@@ -443,25 +443,25 @@ + 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_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 */ ++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; ++ OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ ++ OMX_BOOL bPostFilter; /**< Enable Post Filter */ ++} OMX_AUDIO_PARAM_G723TYPE; + + + /** ITU G726 (ADPCM) rate */ +@@ -471,22 +471,22 @@ + 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_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; ++/** 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 */ +@@ -495,7 +495,7 @@ + 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_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; +@@ -514,23 +514,23 @@ + } 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 */ ++/** 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; ++ OMX_AUDIO_AMRFrameFormatMax = 0x7FFFFFFF ++} OMX_AUDIO_AMRFRAMEFORMATTYPE; + + + /** AMR band mode */ +@@ -538,7 +538,7 @@ + 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_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 */ +@@ -546,36 +546,36 @@ + 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_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_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 */ ++ ++/** 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_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; +- ++ OMX_AUDIO_AMRDTXModeMax = 0x7FFFFFFF ++} OMX_AUDIO_AMRDTXMODETYPE; ++ + + /** AMR params */ + typedef struct OMX_AUDIO_PARAM_AMRTYPE { +@@ -584,7 +584,7 @@ + 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_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; +@@ -692,7 +692,7 @@ + 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_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; +@@ -764,11 +764,10 @@ + } OMX_AUDIO_PARAM_SMVTYPE; + + +-/** MIDI Format ++/** MIDI Format + * @ingroup midi + */ +-typedef enum OMX_AUDIO_MIDIFORMATTYPE +-{ ++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 */ +@@ -777,33 +776,33 @@ + 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_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 ++/** 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 ++ 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 ++ 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_MIDIFORMATTYPE eMidiFormat; /**< Version of the MIDI file */ + } OMX_AUDIO_PARAM_MIDITYPE; + + +-/** Type of the MIDI sound bank ++/** Type of the MIDI sound bank + * @ingroup midi + */ + typedef enum OMX_AUDIO_MIDISOUNDBANKTYPE { +@@ -812,27 +811,27 @@ + 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_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 ++/** 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_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 ++/** MIDI params to load/unload user soundbank + * @ingroup midi + */ + typedef struct OMX_AUDIO_PARAM_MIDILOADUSERSOUNDTYPE { +@@ -847,8 +846,8 @@ + } OMX_AUDIO_PARAM_MIDILOADUSERSOUNDTYPE; + + +-/** Structure for Live MIDI events and MIP messages. +- * (MIP = Maximum Instantaneous Polyphony; part of the SP-MIDI standard.) ++/** 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 { +@@ -857,12 +856,12 @@ + 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 ++ 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 ++/** MIDI sound bank/ program pair in a given channel + * @ingroup midi + */ + typedef struct OMX_AUDIO_CONFIG_MIDISOUNDBANKPROGRAMTYPE { +@@ -872,29 +871,29 @@ + 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 ++ OMX_U32 nUserSoundBankIndex;/**< User soundbank index, easier to access soundbanks + by index if multiple banks are present */ + } OMX_AUDIO_CONFIG_MIDISOUNDBANKPROGRAMTYPE; + + +-/** MIDI control ++/** 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 ++ 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 ++ 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 ++ 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 ++ 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 */ +@@ -906,125 +905,125 @@ + } OMX_AUDIO_CONFIG_MIDICONTROLTYPE; + + +-/** MIDI Playback States ++/** 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 ++ 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 ++ 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 ++ 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 ++ 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 ++ 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 ++ OMX_AUDIO_MIDIPlayBackStatePlayingPartially, /**< Best-effort playback due to SP-MIDI/DLS + resource constraints */ +- OMX_AUDIO_MIDIPlayBackStatePlayingSilently, /**< Due to system resource constraints and ++ 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_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 ++/** 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 ++ 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 ++ 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 ++ 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 ++ 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 ++ 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. ++ * 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 */ ++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; ++} OMX_AUDIO_CONFIG_MIDIMETAEVENTTYPE; + + +-/** MIDI Meta Event Data structure - one per Meta Event. ++/** 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; ++ */ ++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 ++ 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) ++ 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 ++ 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 ++ 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 +@@ -1037,27 +1036,27 @@ + 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 ++ 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, ++ 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 ++ 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 ++ 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). ++ 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 ++ 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 +@@ -1072,12 +1071,12 @@ + 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 ++ 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 ++ OMX_S32 nBalance; /**< balance setting for this port + (-100 to 100, where -100 indicates + all left, and no right */ + } OMX_AUDIO_CONFIG_BALANCETYPE; +@@ -1087,10 +1086,10 @@ + 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 ++ 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; +@@ -1101,20 +1100,20 @@ + 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, ++ 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 */ ++ FALSE otherwise */ + } OMX_AUDIO_CONFIG_CHANNELMUTETYPE; + + + +-/** Enable / Disable for loudness control, which boosts bass and to a ++/** 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 */ +@@ -1124,33 +1123,33 @@ + + + /** 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 ++ 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 ++ 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 ++/** 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 +@@ -1160,33 +1159,33 @@ + 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 ++ 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 ++ 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 ++/** 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_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. ++ * 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 */ +@@ -1199,10 +1198,10 @@ + + + /** 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 ++ * 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 + */ +@@ -1213,16 +1212,16 @@ + 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 ++ 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. ++/** 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 { +@@ -1230,57 +1229,57 @@ + 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 ++ 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 ++ 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 ++ 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 ++ 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 ++ 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 ++/** 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 - ++ 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 ++ OMX_AUDIO_EchoCanHFree, /**< Echo Cancellation optimized for + Hands Free operation */ +- OMX_AUDIO_EchoCanCarKit, /**< Echo Cancellation optimized for ++ 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_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 */ +@@ -1292,7 +1291,7 @@ + /** 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 */ +Index: gst-omx-1.22.0/omx/openmax/OMX_Component.h +=================================================================== +--- gst-omx-1.22.0.orig/omx/openmax/OMX_Component.h 2023-03-02 08:48:43.000000000 +0000 ++++ gst-omx-1.22.0/omx/openmax/OMX_Component.h 2023-03-02 08:58:22.000000000 +0000 +@@ -1,23 +1,23 @@ + /* +- * Copyright (c) 2008 The Khronos Group Inc. +- * ++ * 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: ++ * to the following conditions: + * The above copyright notice and this permission notice shall be included +- * in all copies or substantial portions of the Software. +- * ++ * 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. ++ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +@@ -38,7 +38,7 @@ + + /* 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 ++ * for this header file to compile successfully + */ + + #include +@@ -47,12 +47,12 @@ + #include + + /** @ingroup comp */ +-typedef enum OMX_PORTDOMAINTYPE { +- OMX_PortDomainAudio, +- OMX_PortDomainVideo, +- OMX_PortDomainImage, ++typedef enum OMX_PORTDOMAINTYPE { ++ OMX_PortDomainAudio, ++ OMX_PortDomainVideo, ++ OMX_PortDomainImage, + OMX_PortDomainOther, +- OMX_PortDomainKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ ++ OMX_PortDomainKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_PortDomainVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_PortDomainMax = 0x7ffffff + } OMX_PORTDOMAINTYPE; +@@ -71,7 +71,7 @@ + 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. ++ 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. */ +@@ -86,26 +86,26 @@ + } 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 */ ++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_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_U32 nSize; ++ OMX_VERSIONTYPE nVersion; + OMX_SUSPENSIONPOLICYTYPE ePolicy; + } OMX_PARAM_SUSPENSIONPOLICYTYPE; + +@@ -113,28 +113,27 @@ + 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_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_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_BOOL bEnabled; + } OMX_CONFIG_BOOLEANTYPE; + + /* Parameter specifying the content uri to use. */ + /** @ingroup cp */ +-typedef struct OMX_PARAM_CONTENTURITYPE +-{ ++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 */ +@@ -143,8 +142,7 @@ + + /* Parameter specifying the pipe to use. */ + /** @ingroup cp */ +-typedef struct OMX_PARAM_CONTENTPIPETYPE +-{ ++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*/ +@@ -154,9 +152,9 @@ + 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) ++ 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; + +@@ -171,7 +169,7 @@ + OMX_MetadataCharsetJavaConformantUTF8, + OMX_MetadataCharsetUTF7, + OMX_MetadataCharsetImapUTF7, +- OMX_MetadataCharsetUTF16LE, ++ OMX_MetadataCharsetUTF16LE, + OMX_MetadataCharsetUTF16BE, + OMX_MetadataCharsetGB12345, + OMX_MetadataCharsetHZGB2312, +@@ -197,36 +195,33 @@ + OMX_MetadataCharsetISO2022JP1, + OMX_MetadataCharsetISOEUCJP, + OMX_MetadataCharsetSMS7Bit, +- OMX_MetadataCharsetKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ ++ OMX_MetadataCharsetKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_MetadataCharsetVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ +- OMX_MetadataCharsetTypeMax= 0x7FFFFFFF ++ OMX_MetadataCharsetTypeMax = 0x7FFFFFFF + } OMX_METADATACHARSETTYPE; + + /** @ingroup metadata */ +-typedef enum OMX_METADATASCOPETYPE +-{ ++typedef enum OMX_METADATASCOPETYPE { + OMX_MetadataScopeAllLevels, + OMX_MetadataScopeTopLevel, + OMX_MetadataScopePortLevel, + OMX_MetadataScopeNodeLevel, +- OMX_MetadataScopeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ ++ 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 +-{ ++typedef enum OMX_METADATASEARCHMODETYPE { + OMX_MetadataSearchValueSizeByIndex, + OMX_MetadataSearchItemByIndex, + OMX_MetadataSearchNextItemByKey, +- OMX_MetadataSearchKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ ++ 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 +-{ ++typedef struct OMX_CONFIG_METADATAITEMCOUNTTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_METADATASCOPETYPE eScopeMode; +@@ -235,13 +230,12 @@ + } OMX_CONFIG_METADATAITEMCOUNTTYPE; + + /** @ingroup metadata */ +-typedef struct OMX_CONFIG_METADATAITEMTYPE +-{ ++typedef struct OMX_CONFIG_METADATAITEMTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_METADATASCOPETYPE eScopeMode; + OMX_U32 nScopeSpecifier; +- OMX_U32 nMetadataItemIndex; ++ OMX_U32 nMetadataItemIndex; + OMX_METADATASEARCHMODETYPE eSearchMode; + OMX_METADATACHARSETTYPE eKeyCharset; + OMX_U8 nKeySizeUsed; +@@ -254,8 +248,7 @@ + } OMX_CONFIG_METADATAITEMTYPE; + + /* @ingroup metadata */ +-typedef struct OMX_CONFIG_CONTAINERNODECOUNTTYPE +-{ ++typedef struct OMX_CONFIG_CONTAINERNODECOUNTTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_BOOL bAllKeys; +@@ -264,36 +257,34 @@ + } OMX_CONFIG_CONTAINERNODECOUNTTYPE; + + /** @ingroup metadata */ +-typedef struct OMX_CONFIG_CONTAINERNODEIDTYPE +-{ ++typedef struct OMX_CONFIG_CONTAINERNODEIDTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_BOOL bAllKeys; + OMX_U32 nParentNodeID; +- OMX_U32 nNodeIndex; +- OMX_U32 nNodeID; ++ 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 ++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 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. ++ 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; ++} OMX_PARAM_METADATAFILTERTYPE; + +-/** The OMX_HANDLETYPE structure defines the component handle. The component ++/** 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) +@@ -301,144 +292,143 @@ + * 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 +-{ ++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 ++ /** 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 ++ /** 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 ++ /** 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 ++ /** 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); ++ 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 ++ /** 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); ++ 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 ++ /** 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); ++ 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 ++ /** 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); ++ 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 ++ /** 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); ++ 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 ++ /** 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); ++ 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 ++ /** 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); ++ 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 ++ /** 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); ++ 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 ++ tunneling. The return codes for this method can be used to + determine if tunneling is not possible, or if tunneling is not +- supported. +- ++ supported. ++ + Base profile components (i.e. non-interop) do not support this +- method and should return OMX_ErrorNotImplemented ++ method and should return OMX_ErrorNotImplemented + +- The interop profile component MUST support tunneling to another +- interop profile component with a compatible port parameters. ++ 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. +- ++ ++ 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 ++ 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 ++ 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. +@@ -446,7 +436,7 @@ + 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 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. +@@ -469,55 +459,55 @@ + OMX_IN OMX_U32 nPort, + OMX_IN OMX_HANDLETYPE hTunneledComp, + OMX_IN OMX_U32 nTunneledPort, +- OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup); ++ OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup); + +- /** refer to OMX_UseBuffer in OMX_core.h or the OMX IL ++ /** 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); ++ 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 ++ /** 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); ++ 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 ++ /** 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); ++ 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 ++ /** 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); ++ OMX_IN OMX_HANDLETYPE hComponent, ++ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); + +- /** refer to OMX_FillThisBuffer in OMX_core.h or the OMX IL ++ /** 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); ++ 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 +@@ -526,10 +516,10 @@ + 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 ++ 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 ++ 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 +@@ -538,9 +528,9 @@ + 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); ++ 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 +@@ -554,20 +544,20 @@ + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + */ + OMX_ERRORTYPE (*ComponentDeInit)( +- OMX_IN OMX_HANDLETYPE hComponent); ++ 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_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_OUT OMX_U8 *cRole, ++ OMX_IN OMX_U32 nIndex); + + } OMX_COMPONENTTYPE; + +Index: gst-omx-1.22.0/omx/openmax/OMX_ComponentExt.h +=================================================================== +--- gst-omx-1.22.0.orig/omx/openmax/OMX_ComponentExt.h 2023-03-02 08:48:43.000000000 +0000 ++++ gst-omx-1.22.0/omx/openmax/OMX_ComponentExt.h 2023-03-02 08:58:22.000000000 +0000 +@@ -1,61 +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 +- +- +-/** 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 */ ++/* ++ * Copyright (c) 2016 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 ++ ++ ++/** 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 */ +Index: gst-omx-1.22.0/omx/openmax/OMX_ContentPipe.h +=================================================================== +--- gst-omx-1.22.0.orig/omx/openmax/OMX_ContentPipe.h 2023-03-02 08:48:43.000000000 +0000 ++++ gst-omx-1.22.0/omx/openmax/OMX_ContentPipe.h 2023-03-02 08:58:22.000000000 +0000 +@@ -1,23 +1,23 @@ + /* +- * Copyright (c) 2008 The Khronos Group Inc. +- * ++ * 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: ++ * to the following conditions: + * The above copyright notice and this permission notice shall be included +- * in all copies or substantial portions of the Software. +- * ++ * 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. ++ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +@@ -64,83 +64,81 @@ + + /** Map types from OMX standard types only here so interface is as generic as possible. */ + typedef OMX_U32 CPresult; +-typedef char * CPstring; ++typedef char * CPstring; + typedef void * CPhandle; + typedef OMX_U32 CPuint; +-typedef OMX_S32 CPint; +-typedef char CPbyte; ++typedef OMX_S32 CPint; ++typedef char CPbyte; + typedef OMX_BOOL CPbool; + +-/** enumeration of origin types used in the CP_PIPETYPE's Seek function ++/** 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_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 ++/** 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_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 ++/** 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 ++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 ++ 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 ++ 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_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. ++/** 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 */ ++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 ++/** content pipe definition + * @ingroup cp + */ +-typedef struct CP_PIPETYPE +-{ +- /** Open a content stream for reading or writing. */ ++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. */ ++ /** Close a content stream. */ + CPresult (*Close)( CPhandle hContent ); + +- /** Create a content source and open it for writing. */ ++ /** 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).*/ +@@ -154,19 +152,19 @@ + + /** 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); ++ CPresult (*Read)( CPhandle hContent, CPbyte *pData, CPuint nSize); + +- /** Retrieve a buffer allocated by the pipe that contains the requested number of bytes. ++ /** 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. ++ 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 ++ 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 ++ 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); + +@@ -175,14 +173,14 @@ + + /** 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); ++ CPresult (*Write)( CPhandle hContent, CPbyte *data, CPuint nSize); + +- /** Retrieve a buffer allocated by the pipe used to write data to the content. ++ /** 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 ++ /** 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); + +Index: gst-omx-1.22.0/omx/openmax/OMX_Core.h +=================================================================== +--- gst-omx-1.22.0.orig/omx/openmax/OMX_Core.h 2023-03-02 08:48:43.000000000 +0000 ++++ gst-omx-1.22.0/omx/openmax/OMX_Core.h 2023-03-02 08:58:22.000000000 +0000 +@@ -1,23 +1,23 @@ + /* +- * Copyright (c) 2008 The Khronos Group Inc. +- * ++ * 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: ++ * to the following conditions: + * The above copyright notice and this permission notice shall be included +- * in all copies or substantial portions of the Software. +- * ++ * 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. ++ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +@@ -36,14 +36,14 @@ + + /* 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 ++ * for this header file to compile successfully + */ + + #include + + + /** The OMX_COMMANDTYPE enumeration is used to specify the action in the +- * OMX_SendCommand macro. ++ * OMX_SendCommand macro. + * @ingroup core + */ + typedef enum OMX_COMMANDTYPE +@@ -53,7 +53,7 @@ + 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_CommandKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_CommandVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_CommandMax = 0X7FFFFFFF + } OMX_COMMANDTYPE; +@@ -76,28 +76,27 @@ + * 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 ++ * 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 ++ * 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 ++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 ++ 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 +@@ -105,17 +104,17 @@ + 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 ++ 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_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 ++/** 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. +@@ -123,147 +122,145 @@ + * with the component. No error messages are allowed that are + * not defined. + */ +-typedef enum OMX_ERRORTYPE +-{ +- OMX_ErrorNone = 0, ++typedef enum OMX_ERRORTYPE { ++ OMX_ErrorNone = 0, + +- /** There were insufficient resources to perform the requested operation */ +- OMX_ErrorInsufficientResources = (OMX_S32) 0x80001000, ++ /** 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, ++ /** 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, ++ /** 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, ++ /** 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, ++ /** 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, ++ /** One or more parameters were not valid */ ++ OMX_ErrorBadParameter = (OMX_S32) 0x80001005, + +- /** The requested function is not implemented */ +- OMX_ErrorNotImplemented = (OMX_S32) 0x80001006, ++ /** 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 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 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 hardware failed to respond as expected */ ++ OMX_ErrorHardware = (OMX_S32) 0x80001009, + +- /** The component is in the state OMX_StateInvalid */ +- OMX_ErrorInvalidState = (OMX_S32) 0x8000100A, ++ /** The component is in the state OMX_StateInvalid */ ++ OMX_ErrorInvalidState = (OMX_S32) 0x8000100A, + +- /** Stream is found to be corrupt */ +- OMX_ErrorStreamCorrupt = (OMX_S32) 0x8000100B, ++ /** Stream is found to be corrupt */ ++ OMX_ErrorStreamCorrupt = (OMX_S32) 0x8000100B, + +- /** Ports being connected are not compatible */ +- OMX_ErrorPortsNotCompatible = (OMX_S32) 0x8000100C, ++ /** 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, ++ /** 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, ++ /** No more indicies can be enumerated */ ++ OMX_ErrorNoMore = (OMX_S32) 0x8000100E, + +- /** The component detected a version mismatch */ +- OMX_ErrorVersionMismatch = (OMX_S32) 0x8000100F, ++ /** 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, ++ /** 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, ++ /** 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, ++ /** 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, ++ /** 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 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 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, ++ /** 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 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, ++ /* 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 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 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 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, ++ /** 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 temporary loss of resources */ ++ OMX_ErrorComponentSuspended = (OMX_S32) 0x8000101D, + +- /** Component suspended due to an inability to acquire dynamic resources */ +- OMX_ErrorDynamicResourcesUnavailable = (OMX_S32) 0x8000101E, ++ /** 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, ++ /** 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, ++ /** 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 open operation failed. */ ++ OMX_ErrorContentPipeOpenFailed = (OMX_S32) 0x80001021, + +- /** The content creation operation failed. */ +- OMX_ErrorContentPipeCreationFailed = (OMX_S32) 0x80001022, ++ /** The content creation operation failed. */ ++ OMX_ErrorContentPipeCreationFailed = (OMX_S32) 0x80001022, + +- /** Separate table information is being used */ +- OMX_ErrorSeperateTablesUsed = (OMX_S32) 0x80001023, ++ /** Separate table information is being used */ ++ OMX_ErrorSeperateTablesUsed = (OMX_S32) 0x80001023, + +- /** Tunneling is unsupported by the component*/ +- OMX_ErrorTunnelingUnsupported = (OMX_S32) 0x80001024, ++ /** 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_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 */ ++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 */ +@@ -271,10 +268,10 @@ + + /** @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_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'. */ +@@ -287,69 +284,69 @@ + OMX_U8 cRole[OMX_MAX_STRINGNAME_SIZE]; /**< name of standard component which defines component role */ + } OMX_PARAM_COMPONENTROLETYPE; + +-/** End of Stream Buffer Flag: ++/** 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 ++ * 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 ++#define OMX_BUFFERFLAG_EOS 0x00000001 + +-/** Start Time Buffer Flag: ++/** 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 ++ * 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 ++ * 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 ++ * 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: ++ ++/** 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 ++ * 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 ++ * 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 ++ * 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 ++/* Data Corrupt Flag: This flag is set when the IL client believes the data in the associated buffer is corrupt + * @ingroup buf + */ + +@@ -357,29 +354,29 @@ + + /* 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. ++ * 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 ++/* 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 ++ * residing in the buffer ++ * @ingroup buf + */ + #define OMX_BUFFERFLAG_EXTRADATA 0x00000040 + +-/** Codec Config Buffer Flag: ++/** 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_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 +@@ -395,72 +392,70 @@ + + + /** @ingroup buf */ +-typedef struct OMX_BUFFERHEADERTYPE +-{ ++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 ++ 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 ++ 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 */ ++ 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 ++ 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 ++ 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 ++ 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 ++ 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 ++ 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 ++ 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 ++ 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 ++/** 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 ++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_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_EXTRADATATYPE eType; /* Extra Data type */ + OMX_U32 nDataSize; /* Size of the supporting data to follow */ +@@ -473,34 +468,32 @@ + 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; ++} OMX_PORT_PARAM_TYPE; + + /** @ingroup comp */ +-typedef enum OMX_EVENTTYPE +-{ ++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_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_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 +-{ ++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 ++ 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 +@@ -510,14 +503,14 @@ + 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 ++ 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 ++ 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 ++ 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 +@@ -527,7 +520,7 @@ + Pointer to additional event-specific data (see spec for meaning). + */ + +- OMX_ERRORTYPE (*EventHandler)( ++ OMX_ERRORTYPE (*EventHandler)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_EVENTTYPE eEvent, +@@ -536,21 +529,21 @@ + 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 ++ 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. +- ++ 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 ++ 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 ++ 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 +@@ -563,23 +556,23 @@ + 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 ++ 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. ++ 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 ++ 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 ++ 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 +@@ -597,19 +590,18 @@ + preference when tunneling between two ports. + @ingroup tun buf + */ +-typedef enum OMX_BUFFERSUPPLIERTYPE +-{ ++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_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 ++/** buffer supplier parameter + * @ingroup tun + */ + typedef struct OMX_PARAM_BUFFERSUPPLIERTYPE { +@@ -620,61 +612,60 @@ + } OMX_PARAM_BUFFERSUPPLIERTYPE; + + +-/**< indicates that buffers received by an input port of a tunnel +- may not modify the data in the buffers ++/**< 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 ++#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. ++ resulting from a OMX_SetupTunnel call from the IL Client. + @ingroup tun +- */ +-typedef struct OMX_TUNNELSETUPTYPE +-{ ++ */ ++typedef struct OMX_TUNNELSETUPTYPE { + OMX_U32 nTunnelFlags; /**< bit flags for tunneling */ + OMX_BUFFERSUPPLIERTYPE eSupplier; /**< supplier preference */ +-} OMX_TUNNELSETUPTYPE; ++} OMX_TUNNELSETUPTYPE; + + /* OMX Component headers is included to enable the core to use +- macros for functions into the component for OMX release 1.0. ++ 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 */ + +-/** GetComponentVersion will return information about the component. ++/** 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. ++ 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 ++ 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 ++ 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 ++ 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 +@@ -697,46 +688,46 @@ + + /** 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. ++ 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 ++ 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 ++ ++ When the command is "OMX_CommandPortDisable" or + "OMX_CommandPortEnable", the component's port (given by the value of +- nParam) will be stopped or restarted. +- ++ 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. +- ++ 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 ++ 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 ++ 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". ++ "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. +@@ -754,21 +745,21 @@ + 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 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 ++ 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. +- ++ 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. +@@ -776,7 +767,7 @@ + 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 ++ Pointer to application allocated structure to be filled by the + component. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be +@@ -797,17 +788,17 @@ + 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 ++ 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 ++ 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. +- ++ 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. +@@ -832,18 +823,18 @@ + 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 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. +@@ -851,13 +842,13 @@ + 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 ++ 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, \ +@@ -868,18 +859,18 @@ + pComponentConfigStructure) /* Macro End */ + + +-/** The OMX_SetConfig macro will send one of the configuration ++/** 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. +- ++ 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. +@@ -904,22 +895,22 @@ + 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 ++/** 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. +- ++ 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 ++ 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. +@@ -938,18 +929,18 @@ + pIndexType) /* Macro End */ + + +-/** The OMX_GetState macro will invoke the component to get the current ++/** 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. +- ++ 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 ++ 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. +@@ -964,17 +955,17 @@ + + + /** 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 ++ 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 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 +@@ -998,25 +989,25 @@ + 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 ++/** 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 ++ 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 ++ 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. +@@ -1024,7 +1015,7 @@ + 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, \ +@@ -1040,13 +1031,13 @@ + + + /** 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. +- ++ 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. +@@ -1071,17 +1062,17 @@ + pBuffer) /* Macro End */ + + +-/** The OMX_EmptyThisBuffer macro will send a buffer full of data to an ++/** 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 ++ 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. +- ++ 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. +@@ -1101,17 +1092,17 @@ + pBuffer) /* Macro End */ + + +-/** The OMX_FillThisBuffer macro will send an empty buffer to an ++/** 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 ++ 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. +- ++ 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. +@@ -1135,14 +1126,14 @@ + /** 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 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 +@@ -1150,13 +1141,13 @@ + 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 ++ 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 ++ 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. ++ 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. +@@ -1177,8 +1168,8 @@ + + /** 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. +- ++ an interviening OMX_Deinit call. ++ + The core should return from this call within 20 msec. + + @return OMX_ERRORTYPE +@@ -1189,13 +1180,13 @@ + 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 ++/** 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. +@@ -1212,23 +1203,23 @@ + 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 ++ 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 ++ 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. ++ 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 +@@ -1236,7 +1227,7 @@ + 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 ++ 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 +@@ -1249,18 +1240,18 @@ + + /** 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 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 ++ 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 +@@ -1268,24 +1259,24 @@ + of the callback. + @param [in] pCallBacks + pointer to a OMX_CALLBACKTYPE structure that will be passed to the +- component to initialize it with. ++ 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_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 ++/** 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 ++ 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 +@@ -1304,34 +1295,34 @@ + /** 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 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 ++ 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. ++ 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 ++ 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. ++ 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 ++ 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 +@@ -1342,9 +1333,9 @@ + @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 ++ 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 +@@ -1354,50 +1345,50 @@ + 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 ++ 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 ++ * 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 ++ 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. +- ++ 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 ++ ++ 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. ++ 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_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 ++ 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 ++ * 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. +@@ -1405,20 +1396,20 @@ + @param [in] compName + This is the name of the component being queried about. + @param [inout] pNumRoles +- This is used both as input and output. +- ++ 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 ++ ++ 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 ++ 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_API OMX_ERRORTYPE OMX_GetRolesOfComponent ( ++ OMX_IN OMX_STRING compName, + OMX_INOUT OMX_U32 *pNumRoles, + OMX_OUT OMX_U8 **roles); + +Index: gst-omx-1.22.0/omx/openmax/OMX_CoreExt.h +=================================================================== +--- gst-omx-1.22.0.orig/omx/openmax/OMX_CoreExt.h 2023-03-02 08:48:43.000000000 +0000 ++++ gst-omx-1.22.0/omx/openmax/OMX_CoreExt.h 2023-03-02 08:58:22.000000000 +0000 +@@ -1,73 +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 +- +-/** 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 */ ++/* ++ * Copyright (c) 2016 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 ++ ++/** 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 */ +Index: gst-omx-1.22.0/omx/openmax/OMX_IVCommon.h +=================================================================== +--- gst-omx-1.22.0.orig/omx/openmax/OMX_IVCommon.h 2023-03-02 08:58:22.000000000 +0000 ++++ gst-omx-1.22.0/omx/openmax/OMX_IVCommon.h 2023-03-02 08:58:22.000000000 +0000 +@@ -1,27 +1,27 @@ + /** +- * Copyright (c) 2008 The Khronos Group Inc. +- * ++ * 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: ++ * to the following conditions: + * The above copyright notice and this permission notice shall be included +- * in all copies or substantial portions of the Software. +- * ++ * 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. ++ * 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. +@@ -36,7 +36,7 @@ + /** + * 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 ++ * file to compile successfully + */ + + #include +@@ -47,8 +47,8 @@ + */ + + +-/** +- * Enumeration defining possible uncompressed image/video formats. ++/** ++ * Enumeration defining possible uncompressed image/video formats. + * + * ENUMS: + * Unused : Placeholder value when format is N/A +@@ -96,7 +96,7 @@ + OMX_COLOR_Format16bitBGR565, + OMX_COLOR_Format18bitRGB666, + OMX_COLOR_Format18bitARGB1665, +- OMX_COLOR_Format19bitARGB1666, ++ OMX_COLOR_Format19bitARGB1666, + OMX_COLOR_Format24bitRGB888, + OMX_COLOR_Format24bitBGR888, + OMX_COLOR_Format24bitARGB1887, +@@ -119,54 +119,126 @@ + 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_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_FormatYVU420SemiPlanar, /* NV21 */ +- OMX_COLOR_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ ++ OMX_COLOR_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_COLOR_FormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ ++ ++ /* Starfive extensions */ ++ /* I420 */ ++ OMX_COLOR_FormatYUV420Planar_P10_16BIT_MSB, ++ OMX_COLOR_FormatYUV420Planar_P10_16BIT_LSB, ++ OMX_COLOR_FormatYUV420Planar_P12_16BIT_MSB, ++ OMX_COLOR_FormatYUV420Planar_P12_16BIT_LSB, ++ /* NV12 */ ++ OMX_COLOR_FormatYUV420SemiPlanar_P10_16BIT_MSB, ++ OMX_COLOR_FormatYUV420SemiPlanar_P10_16BIT_LSB, ++ OMX_COLOR_FormatYUV420SemiPlanar_P12_16BIT_MSB, ++ OMX_COLOR_FormatYUV420SemiPlanar_P12_16BIT_LSB, ++ /* NV21 */ ++ OMX_COLOR_FormatYVU420SemiPlanar, ++ OMX_COLOR_FormatYVU420SemiPlanar_P10_16BIT_MSB, ++ OMX_COLOR_FormatYVU420SemiPlanar_P10_16BIT_LSB, ++ OMX_COLOR_FormatYVU420SemiPlanar_P12_16BIT_MSB, ++ OMX_COLOR_FormatYVU420SemiPlanar_P12_16BIT_LSB, ++ /* I422 */ ++ OMX_COLOR_FormatYUV422Planar_P10_16BIT_MSB, ++ OMX_COLOR_FormatYUV422Planar_P10_16BIT_LSB, ++ OMX_COLOR_FormatYUV422Planar_P12_16BIT_MSB, ++ OMX_COLOR_FormatYUV422Planar_P12_16BIT_LSB, ++ /* NV16 */ ++ OMX_COLOR_FormatYUV422SemiPlanar_P10_16BIT_MSB, ++ OMX_COLOR_FormatYUV422SemiPlanar_P10_16BIT_LSB, ++ OMX_COLOR_FormatYUV422SemiPlanar_P12_16BIT_MSB, ++ OMX_COLOR_FormatYUV422SemiPlanar_P12_16BIT_LSB, ++ /* NV61 */ ++ OMX_COLOR_FormatYVU422SemiPlanar, ++ OMX_COLOR_FormatYVU422SemiPlanar_P10_16BIT_MSB, ++ OMX_COLOR_FormatYVU422SemiPlanar_P10_16BIT_LSB, ++ OMX_COLOR_FormatYVU422SemiPlanar_P12_16BIT_MSB, ++ OMX_COLOR_FormatYVU422SemiPlanar_P12_16BIT_LSB, ++ /* YUYV */ ++ OMX_COLOR_FormatYCbYCr_P10_16BIT_MSB, ++ OMX_COLOR_FormatYCbYCr_P10_16BIT_LSB, ++ OMX_COLOR_FormatYCbYCr_P12_16BIT_MSB, ++ OMX_COLOR_FormatYCbYCr_P12_16BIT_LSB, ++ /* YVYU */ ++ OMX_COLOR_FormatYCrYCb_P10_16BIT_MSB, ++ OMX_COLOR_FormatYCrYCb_P10_16BIT_LSB, ++ OMX_COLOR_FormatYCrYCb_P12_16BIT_MSB, ++ OMX_COLOR_FormatYCrYCb_P12_16BIT_LSB, ++ /* UYVY */ ++ OMX_COLOR_FormatCbYCrY_P10_16BIT_MSB, ++ OMX_COLOR_FormatCbYCrY_P10_16BIT_LSB, ++ OMX_COLOR_FormatCbYCrY_P12_16BIT_MSB, ++ OMX_COLOR_FormatCbYCrY_P12_16BIT_LSB, ++ /* VYUY */ ++ OMX_COLOR_FormatCrYCbY_P10_16BIT_MSB, ++ OMX_COLOR_FormatCrYCbY_P10_16BIT_LSB, ++ OMX_COLOR_FormatCrYCbY_P12_16BIT_MSB, ++ OMX_COLOR_FormatCrYCbY_P12_16BIT_LSB, ++ /* I444 */ ++ OMX_COLOR_FormatYUV444Planar, ++ OMX_COLOR_FormatYUV444Planar_P10_16BIT_MSB, ++ OMX_COLOR_FormatYUV444Planar_P10_16BIT_LSB, ++ OMX_COLOR_FormatYUV444Planar_P12_16BIT_MSB, ++ OMX_COLOR_FormatYUV444Planar_P12_16BIT_LSB, ++ /* YUV444PACKED */ ++ OMX_COLOR_FormatYUV444Interleaved_P10_16BIT_MSB, ++ OMX_COLOR_FormatYUV444Interleaved_P10_16BIT_LSB, ++ OMX_COLOR_FormatYUV444Interleaved_P12_16BIT_MSB, ++ OMX_COLOR_FormatYUV444Interleaved_P12_16BIT_LSB, ++ /* YUV400 */ ++ OMX_COLOR_FormatYUV400, ++ OMX_COLOR_FormatYUV400_P10_16BIT_MSB, ++ OMX_COLOR_FormatYUV400_P10_16BIT_LSB, ++ OMX_COLOR_FormatYUV400_P12_16BIT_MSB, ++ OMX_COLOR_FormatYUV400_P12_16BIT_LSB, ++ /* Starfive extensions end */ ++ + 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 ++ * 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_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; ++} OMX_CONFIG_COLORCONVERSIONTYPE; + + +-/** +- * Structure defining percent to scale each frame dimension. For example: ++/** ++ * 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_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; ++} OMX_CONFIG_SCALEFACTORTYPE; + + +-/** +- * Enumeration of possible image filter types ++/** ++ * Enumeration of possible image filter types + */ + typedef enum OMX_IMAGEFILTERTYPE { + OMX_ImageFilterNone, +@@ -177,23 +249,23 @@ + OMX_ImageFilterOilPaint, + OMX_ImageFilterHatch, + OMX_ImageFilterGpen, +- OMX_ImageFilterAntialias, +- OMX_ImageFilterDeRing, ++ OMX_ImageFilterAntialias, ++ OMX_ImageFilterDeRing, + OMX_ImageFilterSolarize, +- OMX_ImageFilterKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ ++ 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 ++/** ++ * Image filter configuration + * + * STRUCT MEMBERS: +- * nSize : Size of the structure in bytes ++ * nSize : Size of the structure in bytes + * nVersion : OMX specification version information +- * nPortIndex : Port that this structure applies to +- * eImageFilter : Image filter type enumeration ++ * nPortIndex : Port that this structure applies to ++ * eImageFilter : Image filter type enumeration + */ + typedef struct OMX_CONFIG_IMAGEFILTERTYPE { + OMX_U32 nSize; +@@ -203,22 +275,22 @@ + } OMX_CONFIG_IMAGEFILTERTYPE; + + +-/** +- * Customized U and V for color enhancement ++/** ++ * Customized U and V for color enhancement + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes +- * nVersion : OMX specification version information ++ * 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 ++ * nCustomizedU : Practical values: 16-240, range: 0-255, value set for + * U component +- * nCustomizedV : Practical values: 16-240, range: 0-255, value set for ++ * 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_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bColorEnhancement; + OMX_U8 nCustomizedU; +@@ -226,12 +298,12 @@ + } OMX_CONFIG_COLORENHANCEMENTTYPE; + + +-/** +- * Define color key and color key mask ++/** ++ * Define color key and color key mask + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes +- * nVersion : OMX specification version information ++ * 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 +@@ -245,12 +317,12 @@ + } OMX_CONFIG_COLORKEYTYPE; + + +-/** +- * List of color blend types for pre/post processing ++/** ++ * List of color blend types for pre/post processing + * + * ENUMS: + * None : No color blending present +- * AlphaConstant : Function is (alpha_constant * src) + ++ * 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 +@@ -266,21 +338,21 @@ + OMX_ColorBlendAnd, + OMX_ColorBlendOr, + OMX_ColorBlendInvert, +- OMX_ColorBlendKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ ++ 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 ++/** ++ * Color blend configuration + * + * STRUCT MEMBERS: +- * nSize : Size of the structure in bytes +- * nVersion : OMX specification version information +- * nPortIndex : Port that this structure applies to ++ * 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 ++ * eColorBlend : Color blend type enumeration + */ + typedef struct OMX_CONFIG_COLORBLENDTYPE { + OMX_U32 nSize; +@@ -291,15 +363,15 @@ + } OMX_CONFIG_COLORBLENDTYPE; + + +-/** ++/** + * Hold frame dimension + * + * STRUCT MEMBERS: +- * nSize : Size of the structure in bytes ++ * 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 ++ * nPortIndex : Port that this structure applies to ++ * nWidth : Frame width in pixels ++ * nHeight : Frame height in pixels + */ + typedef struct OMX_FRAMESIZETYPE { + OMX_U32 nSize; +@@ -311,69 +383,69 @@ + + + /** +- * Rotation configuration ++ * Rotation configuration + * + * STRUCT MEMBERS: +- * nSize : Size of the structure in bytes ++ * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to +- * nRotation : +/- integer rotation value ++ * nRotation : +/- integer rotation value + */ + typedef struct OMX_CONFIG_ROTATIONTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; +- OMX_S32 nRotation; ++ OMX_S32 nRotation; + } OMX_CONFIG_ROTATIONTYPE; + + +-/** +- * Possible mirroring directions for pre/post processing ++/** ++ * 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 ++ * 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_MirrorBoth, ++ OMX_MirrorKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_MirrorVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ +- OMX_MirrorMax = 0x7FFFFFFF ++ OMX_MirrorMax = 0x7FFFFFFF + } OMX_MIRRORTYPE; + + +-/** +- * Mirroring configuration ++/** ++ * Mirroring configuration + * + * STRUCT MEMBERS: +- * nSize : Size of the structure in bytes ++ * nSize : Size of the structure in bytes + * nVersion : OMX specification version information +- * nPortIndex : Port that this structure applies to +- * eMirror : Mirror type enumeration ++ * nPortIndex : Port that this structure applies to ++ * eMirror : Mirror type enumeration + */ + typedef struct OMX_CONFIG_MIRRORTYPE { + OMX_U32 nSize; +- OMX_VERSIONTYPE nVersion; ++ OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_MIRRORTYPE eMirror; + } OMX_CONFIG_MIRRORTYPE; + + +-/** +- * Position information only ++/** ++ * Position information only + * + * STRUCT MEMBERS: +- * nSize : Size of the structure in bytes ++ * 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 +- */ ++ * nX : X coordinate for the point ++ * nY : Y coordinate for the point ++ */ + typedef struct OMX_CONFIG_POINTTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; +@@ -383,37 +455,37 @@ + } OMX_CONFIG_POINTTYPE; + + +-/** +- * Frame size plus position ++/** ++ * 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 ++ * 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 ++ * 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_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 ++/** ++ * 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 ++ * nSize : Size of the structure in bytes ++ * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to +- * bDeblocking : Enable/disable deblocking mode ++ * bDeblocking : Enable/disable deblocking mode + */ + typedef struct OMX_PARAM_DEBLOCKINGTYPE { + OMX_U32 nSize; +@@ -423,13 +495,13 @@ + } OMX_PARAM_DEBLOCKINGTYPE; + + +-/** +- * Stabilization state ++/** ++ * Stabilization state + * + * STRUCT MEMBERS: +- * nSize : Size of the structure in bytes +- * nVersion : OMX specification version information +- * nPortIndex : Port that this structure applies to ++ * 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 { +@@ -440,8 +512,8 @@ + } OMX_CONFIG_FRAMESTABTYPE; + + +-/** +- * White Balance control type ++/** ++ * White Balance control type + * + * STRUCT MEMBERS: + * SunLight : Referenced in JSR-234 +@@ -458,20 +530,20 @@ + OMX_WhiteBalControlIncandescent, + OMX_WhiteBalControlFlash, + OMX_WhiteBalControlHorizon, +- OMX_WhiteBalControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ ++ 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 ++/** ++ * White Balance control configuration + * + * STRUCT MEMBERS: +- * nSize : Size of the structure in bytes ++ * nSize : Size of the structure in bytes + * nVersion : OMX specification version information +- * nPortIndex : Port that this structure applies to +- * eWhiteBalControl : White balance enumeration ++ * nPortIndex : Port that this structure applies to ++ * eWhiteBalControl : White balance enumeration + */ + typedef struct OMX_CONFIG_WHITEBALCONTROLTYPE { + OMX_U32 nSize; +@@ -481,8 +553,8 @@ + } OMX_CONFIG_WHITEBALCONTROLTYPE; + + +-/** +- * Exposure control type ++/** ++ * Exposure control type + */ + typedef enum OMX_EXPOSURECONTROLTYPE { + OMX_ExposureControlOff = 0, +@@ -495,20 +567,20 @@ + OMX_ExposureControlBeach, + OMX_ExposureControlLargeAperture, + OMX_ExposureControlSmallApperture, +- OMX_ExposureControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ ++ 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 ++/** ++ * White Balance control configuration + * + * STRUCT MEMBERS: +- * nSize : Size of the structure in bytes ++ * nSize : Size of the structure in bytes + * nVersion : OMX specification version information +- * nPortIndex : Port that this structure applies to +- * eExposureControl : Exposure control enumeration ++ * nPortIndex : Port that this structure applies to ++ * eExposureControl : Exposure control enumeration + */ + typedef struct OMX_CONFIG_EXPOSURECONTROLTYPE { + OMX_U32 nSize; +@@ -518,16 +590,16 @@ + } OMX_CONFIG_EXPOSURECONTROLTYPE; + + +-/** +- * Defines sensor supported mode. ++/** ++ * Defines sensor supported mode. + * + * STRUCT MEMBERS: +- * nSize : Size of the structure in bytes ++ * 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 ++ * 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 ++ * sFrameSize : Framesize + */ + typedef struct OMX_PARAM_SENSORMODETYPE { + OMX_U32 nSize; +@@ -539,13 +611,13 @@ + } OMX_PARAM_SENSORMODETYPE; + + +-/** +- * Defines contrast level ++/** ++ * Defines contrast level + * + * STRUCT MEMBERS: +- * nSize : Size of the structure in bytes +- * nVersion : OMX specification version information +- * nPortIndex : Port that this structure applies to ++ * 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 { +@@ -556,14 +628,14 @@ + } OMX_CONFIG_CONTRASTTYPE; + + +-/** +- * Defines brightness level ++/** ++ * 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% ++ * 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; +@@ -573,16 +645,16 @@ + } OMX_CONFIG_BRIGHTNESSTYPE; + + +-/** +- * Defines backlight level configuration for a video sink, e.g. LCD panel ++/** ++ * 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 ++ * 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 ++ * nTimeout : Number of milliseconds before backlight automatically turns ++ * off. A value of 0x0 disables backight timeout + */ + typedef struct OMX_CONFIG_BACKLIGHTTYPE { + OMX_U32 nSize; +@@ -593,12 +665,12 @@ + } OMX_CONFIG_BACKLIGHTTYPE; + + +-/** +- * Defines setting for Gamma ++/** ++ * Defines setting for Gamma + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes +- * nVersion : OMX specification version information ++ * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nGamma : Values allowed for gamma -100 to 100, zero means no change + */ +@@ -610,14 +682,14 @@ + } OMX_CONFIG_GAMMATYPE; + + +-/** +- * Define for setting saturation +- * ++/** ++ * 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 ++ * nSaturation : Values allowed for saturation -100 to 100, zero means + * no change + */ + typedef struct OMX_CONFIG_SATURATIONTYPE { +@@ -628,14 +700,14 @@ + } OMX_CONFIG_SATURATIONTYPE; + + +-/** +- * Define for setting Lightness ++/** ++ * 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 ++ * nLightness : Values allowed for lightness -100 to 100, zero means no + * change + */ + typedef struct OMX_CONFIG_LIGHTNESSTYPE { +@@ -646,17 +718,17 @@ + } OMX_CONFIG_LIGHTNESSTYPE; + + +-/** +- * Plane blend configuration ++/** ++ * Plane blend configuration + * + * STRUCT MEMBERS: +- * nSize : Size of the structure in bytes ++ * 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. ++ * 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. ++ * nAlpha : Transparency blending component for the entire plane. + * See blending modes for more detail. + */ + typedef struct OMX_CONFIG_PLANEBLENDTYPE { +@@ -668,17 +740,17 @@ + } OMX_CONFIG_PLANEBLENDTYPE; + + +-/** ++/** + * Define interlace type + * + * STRUCT MEMBERS: +- * nSize : Size of the structure in bytes +- * nVersion : OMX specification version information ++ * 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 ++ * bEnable : Enable control variable for this functionality + * (see below) +- * nInterleavePortIndex : Index of input or output port associated with +- * the interleaved plane. ++ * 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 { +@@ -690,8 +762,8 @@ + } OMX_PARAM_INTERLEAVETYPE; + + +-/** +- * Defines the picture effect used for an input picture ++/** ++ * Defines the picture effect used for an input picture + */ + typedef enum OMX_TRANSITIONEFFECTTYPE { + OMX_EffectNone, +@@ -701,18 +773,18 @@ + OMX_EffectDissolve, + OMX_EffectWipe, + OMX_EffectUnspecifiedMixOfTwoScenes, +- OMX_EffectKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ ++ 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 ++/** ++ * Structure used to configure current transition effect + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes +- * nVersion : OMX specification version information ++ * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eEffect : Effect to enable + */ +@@ -724,43 +796,43 @@ + } OMX_CONFIG_TRANSITIONEFFECTTYPE; + + +-/** +- * Defines possible data unit types for encoded video data. The data unit ++/** ++ * 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. ++ * 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_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. ++/** ++ * 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_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 ++/** ++ * 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_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port that this structure applies to */ + OMX_DATAUNITTYPE eUnitType; + OMX_DATAUNITENCAPSULATIONTYPE eEncapsulationType; +@@ -768,25 +840,25 @@ + + + /** +- * Defines dither types ++ * 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_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 ++/** ++ * 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_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; +@@ -795,28 +867,28 @@ + 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 ++ 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 ++ 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_MeteringModeSpot, /**< Spot (partial) metering. */ + OMX_MeteringModeMatrix, /**< Matrix or evaluative metering. */ +- +- OMX_MeteringKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ ++ ++ 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; +@@ -824,15 +896,15 @@ + 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_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_BOOL bAutoSensitivity; /**< Whether sensitivity is defined automatically */ + } OMX_CONFIG_EXPOSUREVALUETYPE; + +-/** +- * Focus region configuration ++/** ++ * Focus region configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes +@@ -863,8 +935,8 @@ + OMX_BOOL bBottomRight; + } OMX_CONFIG_FOCUSREGIONTYPE; + +-/** +- * Focus Status type ++/** ++ * Focus Status type + */ + typedef enum OMX_FOCUSSTATUSTYPE { + OMX_FocusStatusOff = 0, +@@ -872,13 +944,13 @@ + OMX_FocusStatusReached, + OMX_FocusStatusUnableToReach, + OMX_FocusStatusLost, +- OMX_FocusStatusKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ ++ 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 ++/** ++ * Focus status configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes +Index: gst-omx-1.22.0/omx/openmax/OMX_Image.h +=================================================================== +--- gst-omx-1.22.0.orig/omx/openmax/OMX_Image.h 2023-03-02 08:48:43.000000000 +0000 ++++ gst-omx-1.22.0/omx/openmax/OMX_Image.h 2023-03-02 08:58:22.000000000 +0000 +@@ -1,28 +1,28 @@ + /** +- * Copyright (c) 2008 The Khronos Group Inc. +- * ++ * 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: ++ * to the following conditions: + * The above copyright notice and this permission notice shall be included +- * in all copies or substantial portions of the Software. +- * ++ * 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. ++ * 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 ++ * The structures needed by Image components to exchange parameters and + * configuration data with the components. + */ + #ifndef OMX_Image_h +@@ -34,9 +34,9 @@ + + + /** +- * 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 ++ * 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 +@@ -47,8 +47,8 @@ + * @{ + */ + +-/** +- * Enumeration used to define the possible image compression coding. ++/** ++ * Enumeration used to define the possible image compression coding. + */ + typedef enum OMX_IMAGE_CODINGTYPE { + OMX_IMAGE_CodingUnused, /**< Value when format is N/A */ +@@ -61,59 +61,59 @@ + 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_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. +- * ++ * 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 ++ * ++ * 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 ++ * 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 ++ * 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 ++ * 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. ++ * 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 ++ * 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 ++ * 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 ++ * 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. ++ * 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 nFrameWidth; + OMX_U32 nFrameHeight; +- OMX_S32 nStride; ++ OMX_S32 nStride; + OMX_U32 nSliceHeight; + OMX_BOOL bFlagErrorConcealment; + OMX_IMAGE_CODINGTYPE eCompressionFormat; +@@ -122,18 +122,18 @@ + } OMX_IMAGE_PORTDEFINITIONTYPE; + + +-/** +- * Port format parameter. This structure is used to enumerate the various ++/** ++ * 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 ++ * 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, ++ * 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 + */ +@@ -147,8 +147,8 @@ + } OMX_IMAGE_PARAM_PORTFORMATTYPE; + + +-/** +- * Flash control type ++/** ++ * Flash control type + * + * ENUMS + * Torch : Flash forced constantly on +@@ -160,14 +160,14 @@ + OMX_IMAGE_FlashControlRedEyeReduction, + OMX_IMAGE_FlashControlFillin, + OMX_IMAGE_FlashControlTorch, +- OMX_IMAGE_FlashControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ ++ 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 ++/** ++ * Flash control configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes +@@ -183,29 +183,29 @@ + } OMX_IMAGE_PARAM_FLASHCONTROLTYPE; + + +-/** +- * Focus control type ++/** ++ * 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_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 ++ ++/** ++ * 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. ++ * 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 + */ +@@ -219,30 +219,30 @@ + } 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 ++ * 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 ++ * 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_U32 nSize; ++ OMX_VERSIONTYPE nVersion; ++ OMX_U32 nPortIndex; ++ OMX_U32 nQFactor; + } OMX_IMAGE_PARAM_QFACTORTYPE; + +-/** +- * Quantization table type ++/** ++ * Quantization table type + */ + + typedef enum OMX_IMAGE_QUANTIZATIONTABLETYPE { +@@ -250,27 +250,27 @@ + OMX_IMAGE_QuantizationTableChroma, + OMX_IMAGE_QuantizationTableChromaCb, + OMX_IMAGE_QuantizationTableChromaCr, +- OMX_IMAGE_QuantizationTableKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ ++ 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 ++ * 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 ++ * 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 ++ * 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) ++ * (i.e. the component will zig-zag the ++ * quantization table data if required internally) + */ + typedef struct OMX_IMAGE_PARAM_QUANTIZATIONTABLETYPE { + OMX_U32 nSize; +@@ -281,9 +281,9 @@ + } OMX_IMAGE_PARAM_QUANTIZATIONTABLETYPE; + + +-/** +- * Huffman table type, the same Huffman table is applied for chroma and +- * luma component ++/** ++ * Huffman table type, the same Huffman table is applied for chroma and ++ * luma component + */ + typedef enum OMX_IMAGE_HUFFMANTABLETYPE { + OMX_IMAGE_HuffmanTableAC = 0, +@@ -292,23 +292,23 @@ + OMX_IMAGE_HuffmanTableACChroma, + OMX_IMAGE_HuffmanTableDCLuma, + OMX_IMAGE_HuffmanTableDCChroma, +- OMX_IMAGE_HuffmanTableKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ ++ 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 ++/** ++ * 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 ++ * 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 ++ * 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; +@@ -317,7 +317,7 @@ + OMX_IMAGE_HUFFMANTABLETYPE eHuffmanTable; + OMX_U8 nNumberOfHuffmanCodeOfLength[16]; + OMX_U8 nHuffmanTable[256]; +-}OMX_IMAGE_PARAM_HUFFMANTTABLETYPE; ++} OMX_IMAGE_PARAM_HUFFMANTTABLETYPE; + + /** @} */ + #ifdef __cplusplus +Index: gst-omx-1.22.0/omx/openmax/OMX_ImageExt.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gst-omx-1.22.0/omx/openmax/OMX_ImageExt.h 2023-03-02 08:58:22.000000000 +0000 +@@ -0,0 +1,55 @@ ++/* ++ * Copyright (c) 2016 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_ImageExt.h - OpenMax IL version 1.1.2 ++ * The OMX_ImageExt header file contains extensions to the ++ * definitions used by both the application and the component to ++ * access image items. ++ */ ++ ++#ifndef OMX_ImageExt_h ++#define OMX_ImageExt_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 ++ ++/** Enum for standard image codingtype extensions */ ++typedef enum OMX_IMAGE_CODINGEXTTYPE { ++ OMX_IMAGE_CodingExtUnused = OMX_IMAGE_CodingKhronosExtensions, ++ OMX_IMAGE_CodingWEBP, /**< WebP image format */ ++} OMX_IMAGE_CODINGEXTTYPE; ++ ++ ++#ifdef __cplusplus ++} ++#endif /* __cplusplus */ ++ ++#endif /* OMX_ImageExt_h */ ++/* File EOF */ +Index: gst-omx-1.22.0/omx/openmax/OMX_Index.h +=================================================================== +--- gst-omx-1.22.0.orig/omx/openmax/OMX_Index.h 2023-03-02 08:48:43.000000000 +0000 ++++ gst-omx-1.22.0/omx/openmax/OMX_Index.h 2023-03-02 08:58:22.000000000 +0000 +@@ -1,23 +1,23 @@ + /* +- * Copyright (c) 2008 The Khronos Group Inc. +- * ++ * 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: ++ * to the following conditions: + * The above copyright notice and this permission notice shall be included +- * in all copies or substantial portions of the Software. +- * ++ * 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. ++ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +@@ -37,22 +37,22 @@ + + /* 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 ++ * for this header file to compile successfully + */ + #include + + + /** 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 ++ * 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 ++ * 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. +@@ -69,11 +69,11 @@ + 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_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_IndexParamCustomContentPipe, /**< reference: OMX_PARAM_CONTENTPIPETYPE */ + OMX_IndexParamDisableResourceConcealment, /**< reference: OMX_RESOURCECONCEALMENTTYPE */ + OMX_IndexConfigMetadataItemCount, /**< reference: OMX_CONFIG_METADATAITEMCOUNTTYPE */ + OMX_IndexConfigContainerNodeCount, /**< reference: OMX_CONFIG_CONTAINERNODECOUNTTYPE */ +@@ -86,7 +86,7 @@ + + OMX_IndexPortStartUnused = 0x02000000, + OMX_IndexParamPortDefinition, /**< reference: OMX_PARAM_PORTDEFINITIONTYPE */ +- OMX_IndexParamCompBufferSupplier, /**< reference: OMX_PARAM_BUFFERSUPPLIERTYPE */ ++ OMX_IndexParamCompBufferSupplier, /**< reference: OMX_PARAM_BUFFERSUPPLIERTYPE */ + OMX_IndexReservedStartUnused = 0x03000000, + + /* Audio parameters and configurations */ +@@ -238,10 +238,12 @@ + OMX_IndexConfigTimeSeekMode, /**< reference: OMX_TIME_CONFIG_SEEKMODETYPE */ + + +- OMX_IndexKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ ++ OMX_IndexKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + /* Vendor specific area */ ++ OMX_IndexRockchipExtensions = 0x70000000, /**< Reserved region for introducing Rockchip Standard Extensions */ ++ OMX_IndexParamVideoHDRRockchipExtensions, /**< reference: OMX_EXTENSION_VIDEO_PARAM_HDR */ + OMX_IndexVendorStartUnused = 0x7F000000, +- /* Vendor specific structures should be in the range of 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. */ +Index: gst-omx-1.22.0/omx/openmax/OMX_IndexExt.h +=================================================================== +--- gst-omx-1.22.0.orig/omx/openmax/OMX_IndexExt.h 2023-03-02 08:48:43.000000000 +0000 ++++ gst-omx-1.22.0/omx/openmax/OMX_IndexExt.h 2023-03-02 08:58:22.000000000 +0000 +@@ -1,87 +1,105 @@ +-/* +- * 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 +- +- +-/** 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 */ ++/* ++ * 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 ++ ++ ++/** 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, ++ OMX_IndexParamAudioAndroidAc3, /**< reference: OMX_AUDIO_PARAM_ANDROID_AC3TYPE */ ++ OMX_IndexParamAudioAndroidOpus, /**< reference: OMX_AUDIO_PARAM_ANDROID_OPUSTYPE */ ++ OMX_IndexParamAudioAndroidAacPresentation, /**< reference: OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE */ ++ OMX_IndexParamAudioAndroidEac3, /**< reference: OMX_AUDIO_PARAM_ANDROID_EAC3TYPE */ ++ OMX_IndexParamAudioProfileQuerySupported, /**< reference: OMX_AUDIO_PARAM_ANDROID_PROFILETYPE */ ++ ++ /* 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 */ ++ OMX_IndexParamVideoVp8, /**< reference: OMX_VIDEO_PARAM_VP8TYPE */ ++ OMX_IndexConfigVideoVp8ReferenceFrame, /**< reference: OMX_VIDEO_VP8REFERENCEFRAMETYPE */ ++ OMX_IndexConfigVideoVp8ReferenceFrameType, /**< reference: OMX_VIDEO_VP8REFERENCEFRAMEINFOTYPE */ ++ OMX_IndexParamVideoAndroidVp8Encoder, /**< reference: OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE */ ++ OMX_IndexParamVideoHevc, /**< reference: OMX_VIDEO_PARAM_HEVCTYPE */ ++ OMX_IndexParamSliceSegments, /**< reference: OMX_VIDEO_SLICESEGMENTSTYPE */ ++ OMX_IndexConfigAndroidIntraRefresh, /**< reference: OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE */ ++ OMX_IndexParamAndroidVideoTemporalLayering, /**< reference: OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE */ ++ OMX_IndexConfigAndroidVideoTemporalLayering, /**< reference: OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE */ ++ ++ /* Image & Video common configurations */ ++ OMX_IndexExtCommonStartUnused = OMX_IndexKhronosExtensions + 0x00700000, ++ ++ /* Other configurations */ ++ OMX_IndexExtOtherStartUnused = OMX_IndexKhronosExtensions + 0x00800000, ++ OMX_IndexConfigAutoFramerateConversion, /**< reference: OMX_CONFIG_BOOLEANTYPE */ ++ OMX_IndexConfigPriority, /**< reference: OMX_PARAM_U32TYPE */ ++ OMX_IndexConfigOperatingRate, /**< reference: OMX_PARAM_U32TYPE in Q16 format for video and in Hz for audio */ ++ OMX_IndexParamConsumerUsageBits, /**< reference: OMX_PARAM_U32TYPE */ ++ ++ /* Time configurations */ ++ OMX_IndexExtTimeStartUnused = OMX_IndexKhronosExtensions + 0x00900000, ++ ++ OMX_IndexExtMax = 0x7FFFFFFF ++} OMX_INDEXEXTTYPE; ++ ++#ifdef __cplusplus ++} ++#endif /* __cplusplus */ ++ ++#endif /* OMX_IndexExt_h */ ++/* File EOF */ +Index: gst-omx-1.22.0/omx/openmax/OMX_Other.h +=================================================================== +--- gst-omx-1.22.0.orig/omx/openmax/OMX_Other.h 2023-03-02 08:48:43.000000000 +0000 ++++ gst-omx-1.22.0/omx/openmax/OMX_Other.h 2023-03-02 08:58:22.000000000 +0000 +@@ -1,23 +1,23 @@ + /* +- * Copyright (c) 2008 The Khronos Group Inc. +- * ++ * 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: ++ * to the following conditions: + * The above copyright notice and this permission notice shall be included +- * in all copies or substantial portions of the Software. +- * ++ * 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. ++ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +@@ -36,46 +36,46 @@ + + /* 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 ++ * for this header file to compile successfully + */ + + #include + + +-/** ++/** + * 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, ++ OMX_OTHER_FormatTime = 0, /**< Transmission of various timestamps, elapsed time, + time deltas, etc */ +- OMX_OTHER_FormatPower, /**< Perhaps used for enabling/disabling power ++ OMX_OTHER_FormatPower, /**< Perhaps used for enabling/disabling power + management, setting clocks? */ +- OMX_OTHER_FormatStats, /**< Could be things such as frame rate, frames ++ 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 ++ 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_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 ++ * 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 ++ 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_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; +@@ -87,66 +87,95 @@ + OMX_TIME_SEEKMODETYPE eType; /**< The seek mode */ + } OMX_TIME_CONFIG_SEEKMODETYPE; + +-/** Structure representing a time stamp used with the following configs ++/** ++ * colorspace ++ */ ++typedef enum OMX_ROCKCHIP_EXT_COLORSPACE { ++ OMX_RK_EXT_ColorspaceBT709 = 1, ++ OMX_RK_EXT_ColorspaceBT2020, ++ OMX_RK_EXT_ColorspaceMax = 0x7FFFFFFF ++} OMX_RK_EXT_COLORSPACE; ++ ++/** ++ * dynamic range ++ */ ++typedef enum OMX_ROCKCHIP_EXT_DYNCRANGE { ++ OMX_RK_EXT_DyncrangeSDR = 0, ++ OMX_RK_EXT_DyncrangeHDR10, ++ OMX_RK_EXT_DyncrangeHDRHLG, ++ OMX_RK_EXT_DyncrangeHDRDOLBY, ++ OMX_RK_EXT_DyncrangeMax = 0x7FFFFFFF ++} OMX_RK_EXT_DYNCRANGE; ++ ++ ++/* Structure Rockchip extension HDR param of the component */ ++ typedef struct OMX_EXTENSION_VIDEO_PARAM_HDR { ++ OMX_U32 nSize; /**< size of the structure in bytes */ ++ OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ ++ OMX_RK_EXT_COLORSPACE eColorSpace; /**< Color space */ ++ OMX_RK_EXT_DYNCRANGE eDyncRange; /**< dynamic range */ ++} OMX_EXTENSION_VIDEO_PARAM_HDR; ++ ++/** Structure representing a time stamp used with the following configs + * on the Clock Component (CC): +- * +- * OMX_IndexConfigTimeCurrentWallTime: query of the CC�s current wall ++ * ++ * 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 ++ * 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 ++ * 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. ++ * 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 ++ * 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; ++ 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_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_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 ++ 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_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. +@@ -154,18 +183,18 @@ + * 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 ++ * 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. ++ * 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 ++ * 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 +@@ -176,52 +205,52 @@ + 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 ++ 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 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. ++/**< 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 ++ * 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. ++ * 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. ++ * 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 ++ * 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 ++ * 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. ++ * 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. ++ 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 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 */ + +@@ -232,21 +261,21 @@ + * 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; ++ /**< State of the media time. */ ++} OMX_TIME_MEDIATIMETYPE; + +-/** Structure representing the current media time scale factor. Applicable only to clock ++/** 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. +- */ ++ * 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 +@@ -257,38 +286,38 @@ + #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 ++/** 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. +- * ++ * 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. */ ++ * 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 ++ 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 ++ OMX_TICKS nOffset; /**< Time to offset the media time by + * (e.g. preroll). Media time will be +- * reported to be nOffset ticks earlier. ++ * 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 ++ * 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_REFCLOCKTYPE eClock; /**< Reference clock used to compute media time */ + } OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE; + + /** Descriptor for setting specifics of power type. +@@ -310,8 +339,8 @@ + + + /** +- * The PortDefinition structure is used to define all of the parameters +- * necessary for the compliant component to setup an input or an output other ++ * 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 { +@@ -327,7 +356,7 @@ + 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; ++} OMX_OTHER_PARAM_PORTFORMATTYPE; + + #ifdef __cplusplus + } +Index: gst-omx-1.22.0/omx/openmax/OMX_Types.h +=================================================================== +--- gst-omx-1.22.0.orig/omx/openmax/OMX_Types.h 2023-03-02 08:48:43.000000000 +0000 ++++ gst-omx-1.22.0/omx/openmax/OMX_Types.h 2023-03-02 08:58:22.000000000 +0000 +@@ -1,36 +1,38 @@ + /* +- * Copyright (c) 2008 The Khronos Group Inc. +- * ++ * Copyright (c) 2016 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: ++ * to the following conditions: + * The above copyright notice and this permission notice shall be included +- * in all copies or substantial portions of the Software. +- * ++ * 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. ++ * 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 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, ++ * 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 + ++#include ++ + #ifdef __cplusplus + extern "C" { + #endif /* __cplusplus */ +@@ -38,12 +40,12 @@ + /** 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 __SYMBIAN32__ + # ifdef __OMX_EXPORTS + # define OMX_API __declspec(dllexport) + # else + # ifdef _WIN32 +-# define OMX_API __declspec(dllexport) ++# define OMX_API __declspec(dllexport) + # else + # define OMX_API __declspec(dllimport) + # endif +@@ -65,18 +67,18 @@ + #endif + + #ifndef OMX_APIENTRY +-#define OMX_APIENTRY +-#endif ++#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 ++/** 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 ++/** 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 +@@ -84,8 +86,8 @@ + + + /** 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 ++ 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 +@@ -103,53 +105,53 @@ + /** @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 ++ ++/** @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; ++typedef uint8_t OMX_U8; + + /** OMX_S8 is an 8 bit signed quantity that is byte aligned */ +-typedef signed char OMX_S8; ++typedef int8_t OMX_S8; + + /** OMX_U16 is a 16 bit unsigned quantity that is 16 bit word aligned */ +-typedef unsigned short OMX_U16; ++typedef uint16_t OMX_U16; + + /** OMX_S16 is a 16 bit signed quantity that is 16 bit word aligned */ +-typedef signed short OMX_S16; ++typedef int16_t OMX_S16; + + /** OMX_U32 is a 32 bit unsigned quantity that is 32 bit word aligned */ +-typedef unsigned long OMX_U32; ++typedef uint32_t OMX_U32; + + /** OMX_S32 is a 32 bit signed quantity that is 32 bit word aligned */ +-typedef signed long OMX_S32; ++typedef int32_t 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 ++ 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. +@@ -164,7 +166,7 @@ + + #elif defined(WIN32) + +-/** OMX_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */ ++/** 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 */ +@@ -173,16 +175,16 @@ + #else /* WIN32 */ + + /** OMX_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */ +-typedef unsigned long long OMX_U64; ++typedef uint64_t OMX_U64; + + /** OMX_S64 is a 64 bit signed quantity that is 64 bit word aligned */ +-typedef signed long long OMX_S64; ++typedef int64_t OMX_S64; + + #endif /* WIN32 */ + #endif + + +-/** The OMX_BOOL type is intended to be used to represent a true or a false ++/** 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. + */ +@@ -190,8 +192,8 @@ + OMX_FALSE = 0, + OMX_TRUE = !OMX_FALSE, + OMX_BOOL_MAX = 0x7FFFFFFF +-} OMX_BOOL; +- ++} 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. +@@ -199,14 +201,14 @@ + 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. ++ 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 ++ 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. + */ +@@ -219,7 +221,7 @@ + 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. ++ an output port. This enumeration is common across all component types. + */ + typedef enum OMX_DIRTYPE + { +@@ -228,8 +230,8 @@ + 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). ++/** 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 + { +@@ -239,7 +241,7 @@ + } OMX_ENDIANTYPE; + + +-/** The OMX_NUMERICALDATATYPE enumeration is used to indicate if data ++/** The OMX_NUMERICALDATATYPE enumeration is used to indicate if data + is signed or unsigned + */ + typedef enum OMX_NUMERICALDATATYPE +@@ -267,16 +269,16 @@ + + + /** 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 ++ * 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 ++ * 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. ++ * 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; +@@ -296,17 +298,17 @@ + + typedef struct OMX_MARKTYPE + { +- OMX_HANDLETYPE hMarkTargetComponent; /**< The component that will +- generate a mark event upon ++ 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 ++ 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 ++ * 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; + +@@ -329,7 +331,7 @@ + /** 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 ++ 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 +Index: gst-omx-1.22.0/omx/openmax/OMX_Video.h +=================================================================== +--- gst-omx-1.22.0.orig/omx/openmax/OMX_Video.h 2023-03-02 08:48:43.000000000 +0000 ++++ gst-omx-1.22.0/omx/openmax/OMX_Video.h 2023-03-02 08:58:22.000000000 +0000 +@@ -1,29 +1,29 @@ + /** +- * Copyright (c) 2008 The Khronos Group Inc. +- * ++ * 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: ++ * to the following conditions: + * The above copyright notice and this permission notice shall be included +- * in all copies or substantial portions of the Software. +- * ++ * 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. ++ * 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 ++ * The structures is needed by Video components to exchange parameters + * and configuration data with OMX components. + */ + #ifndef OMX_Video_h +@@ -43,19 +43,19 @@ + /** + * 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 ++ * for this header file to compile successfully + */ + + #include + + + /** +- * 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 ++ * 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 { +@@ -68,58 +68,61 @@ + 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_CodingVP8, /**< Google VP8, formerly known as On2 VP8 */ ++ OMX_VIDEO_CodingVP9, /**< Google VP9 */ ++ OMX_VIDEO_CodingHEVC, /**< ITU H.265/HEVC */ ++ 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. +- * ++ * 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 ++ * ++ * 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 ++ * 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 ++ * 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 ++ * 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 ++ * 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, ++ * 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 ++ * 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 ++ * 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 ++ * 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. ++ * 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; +@@ -136,19 +139,19 @@ + OMX_NATIVE_WINDOWTYPE pNativeWindow; + } OMX_VIDEO_PORTDEFINITIONTYPE; + +-/** +- * Port format parameter. This structure is used to enumerate the various ++/** ++ * 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 ++ * 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 ++ * 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 + */ +@@ -157,14 +160,14 @@ + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nIndex; +- OMX_VIDEO_CODINGTYPE eCompressionFormat; ++ OMX_VIDEO_CODINGTYPE eCompressionFormat; + OMX_COLOR_FORMATTYPE eColorFormat; + OMX_U32 xFramerate; + } OMX_VIDEO_PARAM_PORTFORMATTYPE; + + + /** +- * This is a structure for configuring video compression quantization ++ * This is a structure for configuring video compression quantization + * parameter values. Codecs may support different QP values for different + * frame types. + * +@@ -174,10 +177,10 @@ + * 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 ++ * nQpB : QP values to use for bidirectional frames + */ + typedef struct OMX_VIDEO_PARAM_QUANTIZATIONTYPE { +- OMX_U32 nSize; ++ OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nQpI; +@@ -186,32 +189,32 @@ + } OMX_VIDEO_PARAM_QUANTIZATIONTYPE; + + +-/** +- * Structure for configuration of video fast update parameters. +- * ++/** ++ * Structure for configuration of video fast update parameters. ++ * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes +- * nVersion : OMX specification version info ++ * 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 ++ * 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_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 ++/** ++ * Enumeration of possible bitrate control types + */ + typedef enum OMX_VIDEO_CONTROLRATETYPE { + OMX_Video_ControlRateDisable, +@@ -219,14 +222,14 @@ + OMX_Video_ControlRateConstant, + OMX_Video_ControlRateVariableSkipFrames, + OMX_Video_ControlRateConstantSkipFrames, +- OMX_Video_ControlRateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ ++ 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. ++/** ++ * Structure for configuring bitrate mode of a codec. + * + * STRUCT MEMBERS: + * nSize : Size of the struct in bytes +@@ -236,23 +239,23 @@ + * 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_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 ++/** ++ * 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_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; +@@ -261,7 +264,7 @@ + /** + * 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 +@@ -284,32 +287,32 @@ + } OMX_VIDEO_PARAM_MOTIONVECTORTYPE; + + +-/** +- * Enumeration of possible methods to use for Intra Refresh ++/** ++ * 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_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 +- * ++ * 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 ++ * 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 ++ * nAirRef : Number of times a motion marked macroblock has to be + * intra coded +- * nCirMBs : Number of consecutive macroblocks to be coded as "intra" ++ * nCirMBs : Number of consecutive macroblocks to be coded as "intra" + * when CIR is enabled + */ + typedef struct OMX_VIDEO_PARAM_INTRAREFRESHTYPE { +@@ -324,19 +327,19 @@ + + + /** +- * Structure for enabling various error correction methods for video ++ * 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 ++ * 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 ++ * 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 { +@@ -351,12 +354,12 @@ + } OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE; + + +-/** +- * Configuration of variable block-size motion compensation (VBSMC) +- * ++/** ++ * Configuration of variable block-size motion compensation (VBSMC) ++ * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes +- * nVersion : OMX specification version information ++ * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * b16x16 : Enable inter block search 16x16 + * b16x8 : Enable inter block search 16x8 +@@ -367,11 +370,11 @@ + * 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_U32 nSize; ++ OMX_VERSIONTYPE nVersion; ++ OMX_U32 nPortIndex; ++ OMX_BOOL b16x16; ++ OMX_BOOL b16x8; + OMX_BOOL b8x16; + OMX_BOOL b8x8; + OMX_BOOL b8x4; +@@ -380,67 +383,67 @@ + } OMX_VIDEO_PARAM_VBSMCTYPE; + + +-/** +- * H.263 profile types, each profile indicates support for various ++/** ++ * 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 ++ * 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 ++ * 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_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_H263ProfileMax = 0x7FFFFFFF + } OMX_VIDEO_H263PROFILETYPE; + + +-/** +- * H.263 level types, each level indicates support for various frame sizes, ++/** ++ * 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_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_H263LevelMax = 0x7FFFFFFF + } OMX_VIDEO_H263LEVELTYPE; + + +-/** +- * Specifies the picture type. These values should be OR'd to signal all ++/** ++ * Specifies the picture type. These values should be OR'd to signal all + * pictures types which are allowed. + * + * ENUMS: +@@ -458,36 +461,36 @@ + 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_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 ++/** ++ * H.263 Params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes +- * nVersion : OMX specification version information ++ * 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 ++ * 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 ++ * 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 ++ * nPictureHeaderRepetition : Specifies the frequency of picture header + * repetition +- * nGOBHeaderInterval : Specifies the interval of non-empty GOB ++ * nGOBHeaderInterval : Specifies the interval of non-empty GOB + * headers in units of GOBs + */ + typedef struct OMX_VIDEO_PARAM_H263TYPE { +@@ -497,7 +500,7 @@ + OMX_U32 nPFrames; + OMX_U32 nBFrames; + OMX_VIDEO_H263PROFILETYPE eProfile; +- OMX_VIDEO_H263LEVELTYPE eLevel; ++ OMX_VIDEO_H263LEVELTYPE eLevel; + OMX_BOOL bPLUSPTYPEAllowed; + OMX_U32 nAllowedPictureTypes; + OMX_BOOL bForceRoundingTypeToZero; +@@ -506,8 +509,8 @@ + } OMX_VIDEO_PARAM_H263TYPE; + + +-/** +- * MPEG-2 profile types, each profile indicates support for various ++/** ++ * MPEG-2 profile types, each profile indicates support for various + * performance bounds and different annexes. + */ + typedef enum OMX_VIDEO_MPEG2PROFILETYPE { +@@ -517,29 +520,29 @@ + 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_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_MPEG2ProfileMax = 0x7FFFFFFF + } OMX_VIDEO_MPEG2PROFILETYPE; + + +-/** +- * MPEG-2 level types, each level indicates support for various frame +- * sizes, bit rates, decoder frame rates. No need ++/** ++ * 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_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_MPEG2LevelMax = 0x7FFFFFFF + } OMX_VIDEO_MPEG2LEVELTYPE; + + +-/** +- * MPEG-2 params ++/** ++ * MPEG-2 params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes +@@ -551,20 +554,20 @@ + * eLevel : MPEG-2 levels(s) to use + */ + typedef struct OMX_VIDEO_PARAM_MPEG2TYPE { +- OMX_U32 nSize; ++ OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; +- OMX_U32 nPortIndex; +- OMX_U32 nPFrames; +- OMX_U32 nBFrames; ++ OMX_U32 nPortIndex; ++ OMX_U32 nPFrames; ++ OMX_U32 nBFrames; + OMX_VIDEO_MPEG2PROFILETYPE eProfile; +- OMX_VIDEO_MPEG2LEVELTYPE eLevel; ++ OMX_VIDEO_MPEG2LEVELTYPE eLevel; + } OMX_VIDEO_PARAM_MPEG2TYPE; + + +-/** +- * MPEG-4 profile types, each profile indicates support for various ++/** ++ * 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 +@@ -583,48 +586,48 @@ + * - 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_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_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_MPEG4ProfileMax = 0x7FFFFFFF + } OMX_VIDEO_MPEG4PROFILETYPE; + + +-/** +- * MPEG-4 level types, each level indicates support for various frame +- * sizes, bit rates, decoder frame rates. No need ++/** ++ * 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_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_MPEG4LevelMax = 0x7FFFFFFF + } OMX_VIDEO_MPEG4LEVELTYPE; + + +-/** ++/** + * MPEG-4 configuration. This structure handles configuration options + * which are specific to MPEG4 algorithms + * +@@ -632,24 +635,24 @@ + * 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+ ++ * 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 ++ * 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. ++ * 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 ++ * bReversibleVLC : Specifies whether reversible variable length coding + * is in use + */ + typedef struct OMX_VIDEO_PARAM_MPEG4TYPE { +@@ -673,22 +676,22 @@ + } OMX_VIDEO_PARAM_MPEG4TYPE; + + +-/** +- * WMV Versions ++/** ++ * 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_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 ++/** ++ * WMV Params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes +@@ -697,33 +700,33 @@ + * eFormat : Version of WMV stream / data + */ + typedef struct OMX_VIDEO_PARAM_WMVTYPE { +- OMX_U32 nSize; ++ OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_WMVFORMATTYPE eFormat; + } OMX_VIDEO_PARAM_WMVTYPE; + + +-/** +- * Real Video Version ++/** ++ * 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_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 ++/** ++ * Real Video Params + * + * STUCT MEMBERS: + * nSize : Size of the structure in bytes +- * nVersion : OMX specification version information ++ * 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 +@@ -735,11 +738,11 @@ + * 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 ++ * 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; +@@ -759,8 +762,8 @@ + } OMX_VIDEO_PARAM_RVTYPE; + + +-/** +- * AVC profile types, each profile indicates support for various ++/** ++ * AVC profile types, each profile indicates support for various + * performance bounds and different annexes. + */ + typedef enum OMX_VIDEO_AVCPROFILETYPE { +@@ -771,15 +774,15 @@ + 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_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_AVCProfileMax = 0x7FFFFFFF + } OMX_VIDEO_AVCPROFILETYPE; + + +-/** +- * AVC level types, each level indicates support for various frame sizes, +- * bit rates, decoder frame rates. No need ++/** ++ * 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 */ +@@ -798,14 +801,15 @@ + 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_AVCLevel52 = 0x10000, /**< Level 5.2 */ ++ 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_AVCLevelMax = 0x7FFFFFFF + } OMX_VIDEO_AVCLEVELTYPE; + + +-/** +- * AVC loop filter modes ++/** ++ * AVC loop filter modes + * + * OMX_VIDEO_AVCLoopFilterEnable : Enable + * OMX_VIDEO_AVCLoopFilterDisable : Disable +@@ -815,20 +819,20 @@ + OMX_VIDEO_AVCLoopFilterEnable = 0, + OMX_VIDEO_AVCLoopFilterDisable, + OMX_VIDEO_AVCLoopFilterDisableSliceBoundary, +- OMX_VIDEO_AVCLoopFilterKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ ++ 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 ++/** ++ * 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 ++ * 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 +@@ -841,85 +845,85 @@ + * 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 ++ * 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 ++ * nAllowedPictureTypes : Specifies the picture types allowed in the + * bitstream +- * bFrameMBsOnly : specifies that every coded picture of the +- * coded video sequence is a coded frame ++ * 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 ++ * 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 ++ * 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 ++ * bWeightedPPrediction : Enable/disable weighted prediction shall not + * be applied to P and SP slices +- * nWeightedBipredicitonMode : Default weighted prediction is applied to B +- * 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 ++ * 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 ++ * 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_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_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_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_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, ++ 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, ++ 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_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. ++/** ++ * Structure for dynamically configuring bitrate mode of a codec. + * + * STRUCT MEMBERS: + * nSize : Size of the struct in bytes +@@ -928,18 +932,18 @@ + * 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_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 ++ * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * xEncodeFramerate : Encoding framerate represented in Q16 format + */ +@@ -979,8 +983,85 @@ + OMX_U32 nMacroblocks; + } OMX_PARAM_MACROBLOCKSTYPE; + +-/** +- * AVC Slice Mode modes ++ ++#ifdef AVS80 ++/** ++ * Aspects of color. ++ */ ++ ++// NOTE: this structure is expected to grow in the future if new color aspects are ++// added to codec bitstreams. OMX component should not require a specific nSize ++// though could verify that nSize is at least the size of the structure at the ++// time of implementation. All new fields will be added at the end of the structure ++// ensuring backward compatibility. ++ ++typedef enum OMX_RANGE { ++ RangeUnspecified, ++ RangeFull, ++ RangeLimited, ++ RangeOther = 0xff, ++} OMX_RANGE; ++ ++typedef enum OMX_PRIMARIES { ++ PrimariesUnspecified, ++ PrimariesBT709_5, // Rec.ITU-R BT.709-5 or equivalent ++ PrimariesBT470_6M, // Rec.ITU-R BT.470-6 System M or equivalent ++ PrimariesBT601_6_625, // Rec.ITU-R BT.601-6 625 or equivalent ++ PrimariesBT601_6_525, // Rec.ITU-R BT.601-6 525 or equivalent ++ PrimariesGenericFilm, // Generic Film ++ PrimariesBT2020, // Rec.ITU-R BT.2020 or equivalent ++ PrimariesOther = 0xff, ++} OMX_PRIMARIES; ++ ++typedef enum OMX_TRANSFER { ++ TransferUnspecified, ++ TransferLinear, // Linear transfer characteristics ++ TransferSRGB, // sRGB or equivalent ++ TransferSMPTE170M, // SMPTE 170M or equivalent (e.g. BT.601/709/2020) ++ TransferGamma22, // Assumed display gamma 2.2 ++ TransferGamma28, // Assumed display gamma 2.8 ++ TransferST2084, // SMPTE ST 2084 for 10/12/14/16 bit systems ++ TransferHLG, // ARIB STD-B67 hybrid-log-gamma ++ // transfers unlikely to be required by Android ++ TransferSMPTE240M = 0x40, // SMPTE 240M ++ TransferXvYCC, // IEC 61966-2-4 ++ TransferBT1361, // Rec.ITU-R BT.1361 extended gamut ++ TransferST428, // SMPTE ST 428-1 ++ TransferOther = 0xff, ++} OMX_TRANSFER; ++ ++typedef enum OMX_MATRIXCOEFFS { ++ MatrixUnspecified, ++ MatrixBT709_5, // Rec.ITU-R BT.709-5 or equivalent ++ MatrixBT470_6M, // KR=0.30, KB=0.11 or equivalent ++ MatrixBT601_6, // Rec.ITU-R BT.601-6 625 or equivalent ++ MatrixSMPTE240M, // SMPTE 240M or equivalent ++ MatrixBT2020, // Rec.ITU-R BT.2020 non-constant luminance ++ MatrixBT2020Constant, // Rec.ITU-R BT.2020 constant luminance ++ MatrixOther = 0xff, ++} OMX_MATRIXCOEFFS; ++ ++typedef struct OMX_COLORASPECTS { ++ OMX_RANGE mRange; // IN/OUT ++ OMX_PRIMARIES mPrimaries; // IN/OUT ++ OMX_TRANSFER mTransfer; // IN/OUT ++ OMX_MATRIXCOEFFS mMatrixCoeffs; // IN/OUT ++} OMX_COLORASPECTS; ++ ++typedef struct OMX_CONFIG_DESCRIBECOLORASPECTSPARAMS { ++ OMX_U32 nSize; // IN ++ OMX_VERSIONTYPE nVersion; // IN ++ OMX_U32 nPortIndex; // IN ++ OMX_BOOL bRequestingDataSpace; // IN ++ OMX_BOOL bDataSpaceChanged; // IN ++ OMX_U32 nPixelFormat; // IN ++ OMX_U32 nDataSpace; // OUT ++ OMX_COLORASPECTS sAspects; // IN/OUT ++} OMX_CONFIG_DESCRIBECOLORASPECTSPARAMS; ++#endif ++ ++/** ++ * 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 +@@ -990,13 +1071,13 @@ + 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_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 ++/** ++ * AVC FMO Slice Mode Params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes +@@ -1007,7 +1088,7 @@ + * eSliceMode : Specifies the type of slice + */ + typedef struct OMX_VIDEO_PARAM_AVCSLICEFMO { +- OMX_U32 nSize; ++ OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U8 nNumSliceGroups; +@@ -1015,7 +1096,7 @@ + OMX_VIDEO_AVCSLICEMODETYPE eSliceMode; + } OMX_VIDEO_PARAM_AVCSLICEFMO; + +-/** ++/** + * AVC IDR Period Configs + * + * STRUCT MEMBERS: +@@ -1026,14 +1107,14 @@ + * nPFrames : Specifies internal of coding Intra frames + */ + typedef struct OMX_VIDEO_CONFIG_AVCINTRAPERIOD { +- OMX_U32 nSize; ++ 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: +@@ -1043,7 +1124,7 @@ + * nNaluBytes : Specifies the NAL unit size + */ + typedef struct OMX_VIDEO_CONFIG_NALSIZE { +- OMX_U32 nSize; ++ OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nNaluBytes; +Index: gst-omx-1.22.0/omx/openmax/OMX_VideoExt.h +=================================================================== +--- gst-omx-1.22.0.orig/omx/openmax/OMX_VideoExt.h 2023-03-02 08:48:43.000000000 +0000 ++++ gst-omx-1.22.0/omx/openmax/OMX_VideoExt.h 2023-03-02 08:58:22.000000000 +0000 +@@ -1,69 +1,401 @@ +-/* +- * 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 +- +-/** 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 */ ++/* ++ * 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 ++ ++/** 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; ++ ++/** VP8 profiles */ ++typedef enum OMX_VIDEO_VP8PROFILETYPE { ++ OMX_VIDEO_VP8ProfileMain = 0x01, ++ OMX_VIDEO_VP8ProfileUnknown = 0x6EFFFFFF, ++ OMX_VIDEO_VP8ProfileMax = 0x7FFFFFFF ++} OMX_VIDEO_VP8PROFILETYPE; ++ ++/** VP8 levels */ ++typedef enum OMX_VIDEO_VP8LEVELTYPE { ++ OMX_VIDEO_VP8Level_Version0 = 0x01, ++ OMX_VIDEO_VP8Level_Version1 = 0x02, ++ OMX_VIDEO_VP8Level_Version2 = 0x04, ++ OMX_VIDEO_VP8Level_Version3 = 0x08, ++ OMX_VIDEO_VP8LevelUnknown = 0x6EFFFFFF, ++ OMX_VIDEO_VP8LevelMax = 0x7FFFFFFF ++} OMX_VIDEO_VP8LEVELTYPE; ++ ++/** VP9 profiles */ ++typedef enum OMX_VIDEO_VP9PROFILETYPE { ++ OMX_VIDEO_VP9Profile0 = 0x1, ++ OMX_VIDEO_VP9Profile1 = 0x2, ++ OMX_VIDEO_VP9Profile2 = 0x4, ++ OMX_VIDEO_VP9Profile3 = 0x8, ++ // HDR profiles also support passing HDR metadata ++ OMX_VIDEO_VP9Profile2HDR = 0x1000, ++ OMX_VIDEO_VP9Profile3HDR = 0x2000, ++ OMX_VIDEO_VP9ProfileUnknown = 0x6EFFFFFF, ++ OMX_VIDEO_VP9ProfileMax = 0x7FFFFFFF ++} OMX_VIDEO_VP9PROFILETYPE; ++ ++/** VP9 levels */ ++typedef enum OMX_VIDEO_VP9LEVELTYPE { ++ OMX_VIDEO_VP9Level1 = 0x1, ++ OMX_VIDEO_VP9Level11 = 0x2, ++ OMX_VIDEO_VP9Level2 = 0x4, ++ OMX_VIDEO_VP9Level21 = 0x8, ++ OMX_VIDEO_VP9Level3 = 0x10, ++ OMX_VIDEO_VP9Level31 = 0x20, ++ OMX_VIDEO_VP9Level4 = 0x40, ++ OMX_VIDEO_VP9Level41 = 0x80, ++ OMX_VIDEO_VP9Level5 = 0x100, ++ OMX_VIDEO_VP9Level51 = 0x200, ++ OMX_VIDEO_VP9Level52 = 0x400, ++ OMX_VIDEO_VP9Level6 = 0x800, ++ OMX_VIDEO_VP9Level61 = 0x1000, ++ OMX_VIDEO_VP9Level62 = 0x2000, ++ OMX_VIDEO_VP9LevelUnknown = 0x6EFFFFFF, ++ OMX_VIDEO_VP9LevelMax = 0x7FFFFFFF ++} OMX_VIDEO_VP9LEVELTYPE; ++ ++/** VP8 Param */ ++typedef struct OMX_VIDEO_PARAM_VP8TYPE { ++ OMX_U32 nSize; ++ OMX_VERSIONTYPE nVersion; ++ OMX_U32 nPortIndex; ++ OMX_VIDEO_VP8PROFILETYPE eProfile; ++ OMX_VIDEO_VP8LEVELTYPE eLevel; ++ OMX_U32 nDCTPartitions; ++ OMX_BOOL bErrorResilientMode; ++} OMX_VIDEO_PARAM_VP8TYPE; ++ ++/** Structure for configuring VP8 reference frames */ ++typedef struct OMX_VIDEO_VP8REFERENCEFRAMETYPE { ++ OMX_U32 nSize; ++ OMX_VERSIONTYPE nVersion; ++ OMX_U32 nPortIndex; ++ OMX_BOOL bPreviousFrameRefresh; ++ OMX_BOOL bGoldenFrameRefresh; ++ OMX_BOOL bAlternateFrameRefresh; ++ OMX_BOOL bUsePreviousFrame; ++ OMX_BOOL bUseGoldenFrame; ++ OMX_BOOL bUseAlternateFrame; ++} OMX_VIDEO_VP8REFERENCEFRAMETYPE; ++ ++/** Structure for querying VP8 reference frame type */ ++typedef struct OMX_VIDEO_VP8REFERENCEFRAMEINFOTYPE { ++ OMX_U32 nSize; ++ OMX_VERSIONTYPE nVersion; ++ OMX_U32 nPortIndex; ++ OMX_BOOL bIsIntraFrame; ++ OMX_BOOL bIsGoldenOrAlternateFrame; ++} OMX_VIDEO_VP8REFERENCEFRAMEINFOTYPE; ++ ++/** Maximum number of VP8 temporal layers */ ++#define OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS 3 ++ ++/** VP8 temporal layer patterns */ ++typedef enum OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE { ++ OMX_VIDEO_VPXTemporalLayerPatternNone = 0, ++ OMX_VIDEO_VPXTemporalLayerPatternWebRTC = 1, ++ OMX_VIDEO_VPXTemporalLayerPatternMax = 0x7FFFFFFF ++} OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE; ++ ++/** ++ * Android specific VP8 encoder params ++ * ++ * STRUCT MEMBERS: ++ * nSize : Size of the structure in bytes ++ * nVersion : OMX specification version information ++ * nPortIndex : Port that this structure applies to ++ * nKeyFrameInterval : Key frame interval in frames ++ * eTemporalPattern : Type of temporal layer pattern ++ * nTemporalLayerCount : Number of temporal coding layers ++ * nTemporalLayerBitrateRatio : Bitrate ratio allocation between temporal ++ * streams in percentage ++ * nMinQuantizer : Minimum (best quality) quantizer ++ * nMaxQuantizer : Maximum (worst quality) quantizer ++ */ ++typedef struct OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE { ++ OMX_U32 nSize; ++ OMX_VERSIONTYPE nVersion; ++ OMX_U32 nPortIndex; ++ OMX_U32 nKeyFrameInterval; // distance between consecutive key_frames (including one ++ // of the key_frames). 0 means interval is unspecified and ++ // can be freely chosen by the codec. 1 means a stream of ++ // only key_frames. ++ ++ OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE eTemporalPattern; ++ OMX_U32 nTemporalLayerCount; ++ OMX_U32 nTemporalLayerBitrateRatio[OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]; ++ OMX_U32 nMinQuantizer; ++ OMX_U32 nMaxQuantizer; ++} OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE; ++ ++/** HEVC Profile enum type */ ++typedef enum OMX_VIDEO_HEVCPROFILETYPE { ++ OMX_VIDEO_HEVCProfileUnknown = 0x0, ++ OMX_VIDEO_HEVCProfileMain = 0x1, ++ OMX_VIDEO_HEVCProfileMain10 = 0x2, ++ // Main10 profile with HDR SEI support. ++ OMX_VIDEO_HEVCProfileMain10HDR10 = 0x1000, ++ OMX_VIDEO_HEVCProfileMax = 0x7FFFFFFF ++} OMX_VIDEO_HEVCPROFILETYPE; ++ ++/** HEVC Level enum type */ ++typedef enum OMX_VIDEO_HEVCLEVELTYPE { ++ OMX_VIDEO_HEVCLevelUnknown = 0x0, ++ OMX_VIDEO_HEVCMainTierLevel1 = 0x1, ++ OMX_VIDEO_HEVCHighTierLevel1 = 0x2, ++ OMX_VIDEO_HEVCMainTierLevel2 = 0x4, ++ OMX_VIDEO_HEVCHighTierLevel2 = 0x8, ++ OMX_VIDEO_HEVCMainTierLevel21 = 0x10, ++ OMX_VIDEO_HEVCHighTierLevel21 = 0x20, ++ OMX_VIDEO_HEVCMainTierLevel3 = 0x40, ++ OMX_VIDEO_HEVCHighTierLevel3 = 0x80, ++ OMX_VIDEO_HEVCMainTierLevel31 = 0x100, ++ OMX_VIDEO_HEVCHighTierLevel31 = 0x200, ++ OMX_VIDEO_HEVCMainTierLevel4 = 0x400, ++ OMX_VIDEO_HEVCHighTierLevel4 = 0x800, ++ OMX_VIDEO_HEVCMainTierLevel41 = 0x1000, ++ OMX_VIDEO_HEVCHighTierLevel41 = 0x2000, ++ OMX_VIDEO_HEVCMainTierLevel5 = 0x4000, ++ OMX_VIDEO_HEVCHighTierLevel5 = 0x8000, ++ OMX_VIDEO_HEVCMainTierLevel51 = 0x10000, ++ OMX_VIDEO_HEVCHighTierLevel51 = 0x20000, ++ OMX_VIDEO_HEVCMainTierLevel52 = 0x40000, ++ OMX_VIDEO_HEVCHighTierLevel52 = 0x80000, ++ OMX_VIDEO_HEVCMainTierLevel6 = 0x100000, ++ OMX_VIDEO_HEVCHighTierLevel6 = 0x200000, ++ OMX_VIDEO_HEVCMainTierLevel61 = 0x400000, ++ OMX_VIDEO_HEVCHighTierLevel61 = 0x800000, ++ OMX_VIDEO_HEVCMainTierLevel62 = 0x1000000, ++ OMX_VIDEO_HEVCHighTierLevel62 = 0x2000000, ++ OMX_VIDEO_HEVCHighTiermax = 0x7FFFFFFF ++} OMX_VIDEO_HEVCLEVELTYPE; ++ ++/** Structure for controlling HEVC video encoding */ ++typedef struct OMX_VIDEO_PARAM_HEVCTYPE { ++ OMX_U32 nSize; ++ OMX_VERSIONTYPE nVersion; ++ OMX_U32 nPortIndex; ++ OMX_VIDEO_HEVCPROFILETYPE eProfile; ++ OMX_VIDEO_HEVCLEVELTYPE eLevel; ++ OMX_U32 nKeyFrameInterval; // distance between consecutive I-frames (including one ++ // of the I frames). 0 means interval is unspecified and ++ // can be freely chosen by the codec. 1 means a stream of ++ // only I frames. ++} OMX_VIDEO_PARAM_HEVCTYPE; ++ ++/** Structure to define if dependent slice segments should be used */ ++typedef struct OMX_VIDEO_SLICESEGMENTSTYPE { ++ OMX_U32 nSize; ++ OMX_VERSIONTYPE nVersion; ++ OMX_U32 nPortIndex; ++ OMX_BOOL bDepedentSegments; ++ OMX_BOOL bEnableLoopFilterAcrossSlices; ++} OMX_VIDEO_SLICESEGMENTSTYPE; ++ ++/** Structure to return timestamps of rendered output frames as well as EOS ++ * for tunneled components. ++ */ ++typedef struct OMX_VIDEO_RENDEREVENTTYPE { ++ OMX_S64 nMediaTimeUs; // timestamp of rendered video frame ++ OMX_S64 nSystemTimeNs; // system monotonic time at the time frame was rendered ++ // Use INT64_MAX for nMediaTimeUs to signal that the EOS ++ // has been reached. In this case, nSystemTimeNs MUST be ++ // the system time when the last frame was rendered. ++ // This MUST be done in addition to returning (and ++ // following) the render information for the last frame. ++} OMX_VIDEO_RENDEREVENTTYPE; ++ ++/** Dolby Vision Profile enum type */ ++typedef enum OMX_VIDEO_DOLBYVISIONPROFILETYPE { ++ OMX_VIDEO_DolbyVisionProfileUnknown = 0x0, ++ OMX_VIDEO_DolbyVisionProfileDvavPer = 0x1, ++ OMX_VIDEO_DolbyVisionProfileDvavPen = 0x2, ++ OMX_VIDEO_DolbyVisionProfileDvheDer = 0x4, ++ OMX_VIDEO_DolbyVisionProfileDvheDen = 0x8, ++ OMX_VIDEO_DolbyVisionProfileDvheDtr = 0x10, ++ OMX_VIDEO_DolbyVisionProfileDvheStn = 0x20, ++ OMX_VIDEO_DolbyVisionProfileDvheDth = 0x40, ++ OMX_VIDEO_DolbyVisionProfileDvheDtb = 0x80, ++ OMX_VIDEO_DolbyVisionProfileMax = 0x7FFFFFFF ++} OMX_VIDEO_DOLBYVISIONPROFILETYPE; ++ ++/** Dolby Vision Level enum type */ ++typedef enum OMX_VIDEO_DOLBYVISIONLEVELTYPE { ++ OMX_VIDEO_DolbyVisionLevelUnknown = 0x0, ++ OMX_VIDEO_DolbyVisionLevelHd24 = 0x1, ++ OMX_VIDEO_DolbyVisionLevelHd30 = 0x2, ++ OMX_VIDEO_DolbyVisionLevelFhd24 = 0x4, ++ OMX_VIDEO_DolbyVisionLevelFhd30 = 0x8, ++ OMX_VIDEO_DolbyVisionLevelFhd60 = 0x10, ++ OMX_VIDEO_DolbyVisionLevelUhd24 = 0x20, ++ OMX_VIDEO_DolbyVisionLevelUhd30 = 0x40, ++ OMX_VIDEO_DolbyVisionLevelUhd48 = 0x80, ++ OMX_VIDEO_DolbyVisionLevelUhd60 = 0x100, ++ OMX_VIDEO_DolbyVisionLevelmax = 0x7FFFFFFF ++} OMX_VIDEO_DOLBYVISIONLEVELTYPE; ++ ++/** ++ * Structure for configuring video compression intra refresh period ++ * ++ * STRUCT MEMBERS: ++ * nSize : Size of the structure in bytes ++ * nVersion : OMX specification version information ++ * nPortIndex : Port that this structure applies to ++ * nRefreshPeriod : Intra refreh period in frames. Value 0 means disable intra refresh ++ */ ++typedef struct OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE { ++ OMX_U32 nSize; ++ OMX_VERSIONTYPE nVersion; ++ OMX_U32 nPortIndex; ++ OMX_U32 nRefreshPeriod; ++} OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE; ++ ++/** Maximum number of temporal layers supported by AVC/HEVC */ ++#define OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS 8 ++ ++/** temporal layer patterns */ ++typedef enum OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE { ++ OMX_VIDEO_AndroidTemporalLayeringPatternNone = 0, ++ // pattern as defined by WebRTC ++ OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC = 1 << 0, ++ // pattern where frames in any layer other than the base layer only depend on at most the very ++ // last frame from each preceding layer (other than the base layer.) ++ OMX_VIDEO_AndroidTemporalLayeringPatternAndroid = 1 << 1, ++} OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE; ++ ++/** ++ * Android specific param for configuration of temporal layering. ++ * Android only supports temporal layering where successive layers each double the ++ * previous layer's framerate. ++ * NOTE: Reading this parameter at run-time SHALL return actual run-time values. ++ * ++ * nSize : Size of the structure in bytes ++ * nVersion : OMX specification version information ++ * nPortIndex : Port that this structure applies to (output port for encoders) ++ * eSupportedPatterns : A bitmask of supported layering patterns ++ * nLayerCountMax : Max number of temporal coding layers supported ++ * by the encoder (must be at least 1, 1 meaning temporal layering ++ * is NOT supported) ++ * nBLayerCountMax : Max number of layers that can contain B frames ++ * (0) to (nLayerCountMax - 1) ++ * ePattern : Layering pattern. ++ * nPLayerCountActual : Number of temporal layers to be coded with non-B frames, ++ * starting from and including the base-layer. ++ * (1 to nLayerCountMax - nBLayerCountActual) ++ * If nPLayerCountActual is 1 and nBLayerCountActual is 0, temporal ++ * layering is disabled. Otherwise, it is enabled. ++ * nBLayerCountActual : Number of temporal layers to be coded with B frames, ++ * starting after non-B layers. ++ * (0 to nBLayerCountMax) ++ * bBitrateRatiosSpecified : Flag to indicate if layer-wise bitrate ++ * distribution is specified. ++ * nBitrateRatios : Bitrate ratio (100 based) per layer (index 0 is base layer). ++ * Honored if bBitrateRatiosSpecified is set. ++ * i.e for 4 layers with desired distribution (25% 25% 25% 25%), ++ * nBitrateRatio = {25, 50, 75, 100, ... } ++ * Values in indices not less than 'the actual number of layers ++ * minus 1' MAY be ignored and assumed to be 100. ++ */ ++typedef struct OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE { ++ OMX_U32 nSize; ++ OMX_VERSIONTYPE nVersion; ++ OMX_U32 nPortIndex; ++ OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE eSupportedPatterns; ++ OMX_U32 nLayerCountMax; ++ OMX_U32 nBLayerCountMax; ++ OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE ePattern; ++ OMX_U32 nPLayerCountActual; ++ OMX_U32 nBLayerCountActual; ++ OMX_BOOL bBitrateRatiosSpecified; ++ OMX_U32 nBitrateRatios[OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS]; ++} OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE; ++ ++/** ++ * Android specific config for changing the temporal-layer count or ++ * bitrate-distribution at run-time. ++ * ++ * nSize : Size of the structure in bytes ++ * nVersion : OMX specification version information ++ * nPortIndex : Port that this structure applies to (output port for encoders) ++ * ePattern : Layering pattern. ++ * nPLayerCountActual : Number of temporal layers to be coded with non-B frames. ++ * (same OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE limits apply.) ++ * nBLayerCountActual : Number of temporal layers to be coded with B frames. ++ * (same OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE limits apply.) ++ * bBitrateRatiosSpecified : Flag to indicate if layer-wise bitrate ++ * distribution is specified. ++ * nBitrateRatios : Bitrate ratio (100 based, Q16 values) per layer (0 is base layer). ++ * Honored if bBitrateRatiosSpecified is set. ++ * (same OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE limits apply.) ++ */ ++typedef struct OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE { ++ OMX_U32 nSize; ++ OMX_VERSIONTYPE nVersion; ++ OMX_U32 nPortIndex; ++ OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE ePattern; ++ OMX_U32 nPLayerCountActual; ++ OMX_U32 nBLayerCountActual; ++ OMX_BOOL bBitrateRatiosSpecified; ++ OMX_U32 nBitrateRatios[OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS]; ++} OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE; ++ ++#ifdef __cplusplus ++} ++#endif /* __cplusplus */ ++ ++#endif /* OMX_VideoExt_h */ ++/* File EOF */ diff --git a/gst-omx/debian/patches/0021-setting-default-framerate-for-omxmjpegdec.patch b/gst-omx/debian/patches/0021-setting-default-framerate-for-omxmjpegdec.patch new file mode 100644 index 0000000000..f02d1e72c9 --- /dev/null +++ b/gst-omx/debian/patches/0021-setting-default-framerate-for-omxmjpegdec.patch @@ -0,0 +1,35 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + gst-omx (1.20.4-1.1) UNRELEASED; urgency=medium + . + * Add sf target to gst-omx. +Author: Leo Lu + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: (upstream|backport|vendor|other), (|commit:) +Bug: #4488 +omxmjpegdec plugins : modify default framerate. +Last-Update: 2023-07-31 +Signed-off-by: Leo Lu + + +--- gst-omx-1.20.4.orig/omx/gstomxmjpegdec.c ++++ gst-omx-1.20.4/omx/gstomxmjpegdec.c +@@ -29,7 +29,7 @@ + GST_DEBUG_CATEGORY_STATIC (gst_omx_mjpeg_dec_debug_category); + #define GST_CAT_DEFAULT gst_omx_mjpeg_dec_debug_category + #ifdef USE_OMX_TARGET_STARFIVE +-#define DEFAULT_FRAMERATE 0 ++#define DEFAULT_FRAMERATE 25 + #define DEFAULT_MIRROR 0 + #define DEFAULT_ROTATION 0 + #define DEFAULT_SCALEH 0 diff --git a/gst-omx/debian/patches/series b/gst-omx/debian/patches/series new file mode 100644 index 0000000000..0acac1c503 --- /dev/null +++ b/gst-omx/debian/patches/series @@ -0,0 +1,21 @@ +0001-add-starfive-support.patch +0002-Fix-gst-omx-Enable-the-gst-omx-VPU-decoding-and-enco.patch +0003-add-video-scale-support.patch +0004-add-encoder-support.patch +0005-rank-257-for-sf-codecs.patch +0006-dont-invoke-USE_BUFFER-if-no-dmabuffer.patch +0007-add-omxmjpegdec-support.patch +0008-support-nv21-i422-y444-for-omxmjpegdec.patch +0009-suport-usebuffer-mode-for-encoding.patch +0010-add-property-framerate.patch +0011-hanle-some-extra-profile-for-avc.patch +0012-combine-sps-pps-header-to-idr.patch +0013-Modify-sf-component-name-to-in-std-format.patch +0014-support-nv21-for-omxh264_5dec.patch +0015_Add_NV21_for_gstomxvideoenc_class.patch +0016-Modify-gstomxmjpegdec-format.patch +0017-support-mirror-rotation-scale-for-gstomxmjpegdec.patch +0018-support-cut-for-gstomxmjpegdec.patch- +0019-Add-Interlaced-mode-judgment.patch +0020-use-sf-omx-header-replace-orig-file.patch +0021-setting-default-framerate-for-omxmjpegdec.patch diff --git a/gst-omx/debian/rules b/gst-omx/debian/rules new file mode 100644 index 0000000000..142c07317b --- /dev/null +++ b/gst-omx/debian/rules @@ -0,0 +1,108 @@ +#!/usr/bin/make -f +# See debhelper(7) (uncomment to enable) +# output every command that modifies files on the build system. +#export DH_VERBOSE = 1 + +DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) + +%: + dh $@ + +override_dh_auto_configure: +ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH),riscv64)) + dh_auto_configure -- -Dtarget=sf +else + dh_auto_configure -- -Dtarget=generic +endif + +override_dh_auto_build: +ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH),riscv64)) + dh_auto_build +else + gst-omx-listcomponents.1 + dh_auto_configure --builddir=obj-$(DEB_HOST_GNU_TYPE)-bellagio -- -Dtarget=bellagio + dh_auto_build --builddir=obj-$(DEB_HOST_GNU_TYPE)-bellagio + dh_auto_test --builddir=obj-$(DEB_HOST_GNU_TYPE)-bellagio + fakeroot dh_auto_install --builddir=obj-$(DEB_HOST_GNU_TYPE)-bellagio --destdir=$(CURDIR)/debian/tmp-bellagio + find $(CURDIR)/debian/tmp-bellagio/usr/lib -name '*.so' -exec rename s/\\.so$$/-bellagio\\.so/ {} \; + find $(CURDIR)/debian/tmp-bellagio/usr/lib -name '*.la' -exec rename s/\\.la$$/-bellagio\\.la/ {} \; + find $(CURDIR)/debian/tmp-bellagio/etc/xdg -name '*.conf' -exec rename s/\\.conf$$/-bellagio\\.conf/ {} \; + sed -i 's#/usr.*/lib/libomxil-bellagio[.]so[.]0#/usr/lib/$(DEB_HOST_MULTIARCH)/libomxil-bellagio.so.0#g' $(CURDIR)/debian/tmp-bellagio/etc/xdg/gstomx-bellagio.conf + dh_auto_clean --builddir=obj-$(DEB_HOST_GNU_TYPE)-bellagio + dh_auto_clean + + #dh_auto_configure --builddir=obj-$(DEB_HOST_GNU_TYPE)-rpi -- -Dtarget=rpi + #dh_auto_build --builddir=obj-$(DEB_HOST_GNU_TYPE)-rpi + #dh_auto_install --builddir=obj-$(DEB_HOST_GNU_TYPE)-rpi --destdir=$(CURDIR)/debian/tmp-rpi + #dh_auto_clean --builddir=obj-$(DEB_HOST_GNU_TYPE)-rpi + #dh_auto_clean + + #dh_auto_configure --builddir=obj-$(DEB_HOST_GNU_TYPE)-tizonia -- -Dtarget=tizonia + #dh_auto_build --builddir=obj-$(DEB_HOST_GNU_TYPE)-tizonia + #dh_auto_install --builddir=obj-$(DEB_HOST_GNU_TYPE)-tizonia --destdir=$(CURDIR)/debian/tmp-tizonia + #dh_auto_clean --builddir=obj-$(DEB_HOST_GNU_TYPE)-tizonia + #dh_auto_clean + + #dh_auto_configure --builddir=obj-$(DEB_HOST_GNU_TYPE)-zynqultrascaleplus -- -Dtarget=zynqultrascaleplus + #dh_auto_build --builddir=obj-$(DEB_HOST_GNU_TYPE)-zynqultrascaleplus + #dh_auto_install --builddir=obj-$(DEB_HOST_GNU_TYPE)-zynqultrascaleplus --destdir=$(CURDIR)/debian/tmp-zynqultrascaleplus + #dh_auto_clean --builddir=obj-$(DEB_HOST_GNU_TYPE)-zynqultrascaleplus + #dh_auto_clean + + dh_auto_configure -- -Dtarget=generic + dh_auto_build +endif + +override_dh_auto_install: +ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH),riscv64)) + dh_auto_install + sed -i 's/\/usr\/lib/\/usr\/lib\/$(DEB_HOST_GNU_TYPE)/' debian/tmp/etc/xdg/gstomx.conf +else + dh_auto_install + find $(CURDIR)/debian/tmp/usr/lib -name '*.so' -exec rename s/\\.so$$/-generic\\.so/ {} \; + find $(CURDIR)/debian/tmp/usr/lib -name '*.la' -exec rename s/\\.la$$/-generic\\.la/ {} \; + mkdir -p $(CURDIR)/debian/tmp/etc/xdg + cp -n -R $(CURDIR)/debian/tmp-bellagio/* $(CURDIR)/debian/tmp + # While we don't build gstreamer1.0-omx-bellagio + rm $(CURDIR)/debian/tmp/usr/lib/$(DEB_HOST_MULTIARCH)/gstreamer-1.0/libgstomx-bellagio.so +endif + +override_dh_auto_clean: +ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH),riscv64)) + rm -rf $(CURDIR)/debian/tmp + dh_auto_clean --builddir=obj-$(DEB_HOST_GNU_TYPE) +else + rm -rf $(CURDIR)/debian/tmp-bellagio + rm -rf $(CURDIR)/debian/tmp-rpi + rm -rf $(CURDIR)/debian/tmp-tizonia + rm -rf $(CURDIR)/debian/tmp-zynqultrascaleplus + dh_auto_clean --builddir=obj-$(DEB_HOST_GNU_TYPE)-bellagio + dh_auto_clean --builddir=obj-$(DEB_HOST_GNU_TYPE)-rpi + dh_auto_clean --builddir=obj-$(DEB_HOST_GNU_TYPE)-tizonia + dh_auto_clean --builddir=obj-$(DEB_HOST_GNU_TYPE)-zynqultrascaleplus + dh_auto_clean + rm -f $(MULTIARCH_INSTALL) +endif + +ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH),riscv64)) +override_dh_install: + dh_install +else +MULTIARCH_INSTALL = debian/gstreamer1.0-omx-generic.postinst \ + debian/gstreamer1.0-omx-generic.prerm \ + debian/gstreamer1.0-omx-bellagio.postinst \ + debian/gstreamer1.0-omx-bellagio.prerm + +$(MULTIARCH_INSTALL): % : %.in + sed 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' $< > $@ + +override_dh_install: $(MULTIARCH_INSTALL) + dh_install + +DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/docbook-xsl/manpages/docbook.xsl +XP = xsltproc -''-nonet -''-param man.charmap.use.subset "0" + +gst-omx-listcomponents.1: debian/gst-omx-listcomponents.1.xml + $(XP) $(DB2MAN) $< +endif diff --git a/gst-omx/debian/source/format b/gst-omx/debian/source/format new file mode 100644 index 0000000000..163aaf8d82 --- /dev/null +++ b/gst-omx/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/gst-omx/debian/tests/control b/gst-omx/debian/tests/control new file mode 100644 index 0000000000..1f82e51db0 --- /dev/null +++ b/gst-omx/debian/tests/control @@ -0,0 +1,12 @@ +Tests: gstinspect +Depends: gstreamer1.0-omx-bellagio-config, + gstreamer1.0-omx-generic, + gstreamer1.0-omx-generic-config, + gstreamer1.0-tools, + libomxil-bellagio0-components-base (>= 0.9.3-6) + +Tests: listcomponents-bellagio +Depends: gst-omx-listcomponents, + gstreamer1.0-omx-bellagio-config, + gstreamer1.0-omx-generic, + libomxil-bellagio0-components-base diff --git a/gst-omx/debian/tests/gstinspect b/gst-omx/debian/tests/gstinspect new file mode 100644 index 0000000000..f6a7cecc78 --- /dev/null +++ b/gst-omx/debian/tests/gstinspect @@ -0,0 +1,7 @@ +#!/bin/sh + +set -e + +gst-inspect-1.0 omx +gst-inspect-1.0 omx omxmpeg4videodec +gst-inspect-1.0 omx omxh264dec diff --git a/gst-omx/debian/tests/listcomponents-bellagio b/gst-omx/debian/tests/listcomponents-bellagio new file mode 100644 index 0000000000..747dbb3c5f --- /dev/null +++ b/gst-omx/debian/tests/listcomponents-bellagio @@ -0,0 +1,21 @@ +#!/bin/sh + +set -e + +DEB_BUILD_MULTIARCH=`dpkg-architecture -qDEB_BUILD_MULTIARCH` + +if [ -e /usr/lib/"$DEB_BUILD_MULTIARCH"/libomxil-bellagio.so.0 ]; then + echo "Test for multi-arch" + gst-omx-listcomponents \ + /usr/lib/"$DEB_BUILD_MULTIARCH"/libomxil-bellagio.so.0 +elif [ -e /usr/lib/libomxil-bellagio.so.0 ]; then + echo "Test for non-multiarch" + gst-omx-listcomponents \ + /usr/lib/libomxil-bellagio.so.0 +else + echo "Did not found libomxil-bellagio.so.0" + exit 1 +fi + + + diff --git a/gst-omx/debian/watch b/gst-omx/debian/watch new file mode 100644 index 0000000000..911e25b891 --- /dev/null +++ b/gst-omx/debian/watch @@ -0,0 +1,6 @@ +# Compulsory line, this is a version 4 file +version=4 + +# HTTP site (basic) +https://gstreamer.freedesktop.org/src/gst-omx/ \ + gst-omx-([\d\.]+)\.tar\.xz debian uupdate diff --git a/gst-omx/docs/gst_plugins_cache.json b/gst-omx/docs/gst_plugins_cache.json new file mode 100644 index 0000000000..2fa2156c4c --- /dev/null +++ b/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/gst-omx/docs/index.md b/gst-omx/docs/index.md new file mode 100644 index 0000000000..b5d574b93f --- /dev/null +++ b/gst-omx/docs/index.md @@ -0,0 +1,3 @@ +--- +short-description: GStreamer plugins from OpenMax +... \ No newline at end of file diff --git a/gst-omx/docs/meson.build b/gst-omx/docs/meson.build new file mode 100644 index 0000000000..811929d90d --- /dev/null +++ b/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_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/gst-omx/docs/sitemap.txt b/gst-omx/docs/sitemap.txt new file mode 100644 index 0000000000..058a2713a4 --- /dev/null +++ b/gst-omx/docs/sitemap.txt @@ -0,0 +1 @@ +gst-index diff --git a/gst-omx/examples/egl/cube_texture_and_coords.h b/gst-omx/examples/egl/cube_texture_and_coords.h new file mode 100644 index 0000000000..1832df3e9f --- /dev/null +++ b/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/gst-omx/examples/egl/meson.build b/gst-omx/examples/egl/meson.build new file mode 100644 index 0000000000..5ba6fc43ea --- /dev/null +++ b/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/gst-omx/examples/egl/testegl.c b/gst-omx/examples/egl/testegl.c new file mode 100644 index 0000000000..b7e77450e8 --- /dev/null +++ b/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 +Copyright (C) 2013, Video Experts Group LLC. + @author: Ilya Smelykh +Copyright (C) 2014 Julien Isorce +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 +#include + +#include +#include +#include +#include +#include +#include + +#include + +#define GST_USE_UNSTABLE_API +#include +#include + +#if defined (USE_OMX_TARGET_RPI) +#include +#include +#elif defined(HAVE_X11) +#include +#include +#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 or \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/gst-omx/examples/meson.build b/gst-omx/examples/meson.build new file mode 100644 index 0000000000..5173880576 --- /dev/null +++ b/gst-omx/examples/meson.build @@ -0,0 +1,3 @@ +if gstgl_dep.found() + subdir('egl') +endif diff --git a/gst-omx/gst-omx.doap b/gst-omx/gst-omx.doap new file mode 100644 index 0000000000..f5f13e336e --- /dev/null +++ b/gst-omx/gst-omx.doap @@ -0,0 +1,402 @@ + + + GStreamer OpenMAX IL wrapper plugin + gst-omx + + 2005-06-17 + +a basic collection of elements + + + This plugin wraps available OpenMAX IL components and makes + them available as standard GStreamer elements. + + + + + + C + + + + + + + + + + + + + 1.20.4 + 1.20 + + 2022-10-12 + + + + + + + 1.20.3 + 1.20 + + 2022-06-15 + + + + + + + 1.20.2 + 1.20 + + 2022-05-02 + + + + + + + 1.20.1 + 1.20 + + 2022-03-14 + + + + + + + 1.20.0 + main + + 2022-02-03 + + + + + + + 1.19.90 + main + + 2022-01-28 + + + + + + + 1.19.3 + main + + 2021-11-03 + + + + + + + 1.19.2 + master + + 2021-09-23 + + + + + + + 1.19.1 + master + + 2021-06-01 + + + + + + + 1.18.0 + master + + 2020-09-08 + + + + + + + 1.17.90 + master + + 2020-08-20 + + + + + + + 1.17.2 + master + + 2020-07-03 + + + + + + + 1.17.1 + master + + 2020-06-19 + + + + + + + 1.16.0 + master + + 2019-04-19 + + + + + + + 1.15.90 + master + + 2019-04-11 + + + + + + + 1.15.2 + master + + 2019-02-26 + + + + + + + 1.15.1 + master + + 2019-01-17 + + + + + + + 1.14.0 + master + + 2018-03-19 + + + + + + + 1.13.91 + master + + 2018-03-13 + + + + + + + 1.13.90 + master + + 2018-03-03 + + + + + + + 1.13.1 + master + + 2018-02-15 + + + + + + + + 1.12.4 + 1.12 + + 2017-12-07 + + + + + + + 1.12.3 + 1.12 + + 2017-09-18 + + + + + + + 1.12.2 + 1.12 + + 2017-07-14 + + + + + + + 1.12.1 + 1.12 + + 2017-06-20 + + + + + + + 1.12.0 + master + + 2017-05-04 + + + + + + + 1.11.91 + master + + 2017-04-27 + + + + + + + 1.11.90 + master + + 2017-04-07 + + + + + + + 1.11.2 + master + + 2017-02-24 + + + + + + + 1.11.1 + master + + 2017-01-12 + + + + + + + 1.10.0 + master + + 2016-11-01 + + + + + + + 1.9.90 + master + + 2016-09-30 + + + + + + + 1.9.2 + master + + 2016-09-01 + + + + + + + 1.9.1 + master + + 2016-06-06 + + + + + + + 1.2.0 + 1.2 + + 2014-07-23 + + + + + + + 1.0.0 + 1.0 + + 2013-03-22 + + + + + + + Sebastian Dröge + 7c1069ea873ef7751e4eca5f1a42744b0e9a3a0a + + + + diff --git a/gst-omx/meson.build b/gst-omx/meson.build new file mode 100644 index 0000000000..75c61bcb34 --- /dev/null +++ b/gst-omx/meson.build @@ -0,0 +1,423 @@ +project('gst-omx', 'c', + version : '1.20.4', + meson_version : '>= 0.59', + 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_variable('gl_winsys').split(' ') + gl_platforms = gstgl_dep.get_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_variable('libdir')) + tizil_includedir = tizil_dep.get_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 ''' + 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', + '-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'), check: true) + release_date = run_result.stdout().strip() + cdata.set_quoted('GST_PACKAGE_RELEASE_DATETIME', release_date) + message('Package release date: ' + release_date) +endif + +configure_file(output: 'config.h', configuration: cdata) diff --git a/gst-omx/meson_options.txt b/gst-omx/meson_options.txt new file mode 100644 index 0000000000..e18beb25d8 --- /dev/null +++ b/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/gst-omx/omx/gstomx.c b/gst-omx/omx/gstomx.c new file mode 100644 index 0000000000..8aeb99b755 --- /dev/null +++ b/gst-omx/omx/gstomx.c @@ -0,0 +1,4179 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , Collabora Ltd. + * Copyright (C) 2013, Collabora Ltd. + * Author: Sebastian Dröge + * + * 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 +#include +#include + +#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 (¶m); + + g_strlcpy ((gchar *) param.cRole, component_role, sizeof (param.cRole)); + err = + gst_omx_component_set_parameter (comp, + OMX_IndexParamStandardComponentRole, ¶m); + + 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 ""; + + 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/gst-omx/omx/gstomx.h b/gst-omx/omx/gstomx.h new file mode 100644 index 0000000000..68624632df --- /dev/null +++ b/gst-omx/omx/gstomx.h @@ -0,0 +1,493 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , Collabora Ltd. + * Copyright (C) 2013, Collabora Ltd. + * Author: Sebastian Dröge + * + * 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 +#include +#include +#include + +#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 +#include + +#ifdef USE_OMX_TARGET_RPI +#include +#endif + +#ifdef HAVE_VIDEO_EXT +#include +#endif + +#ifdef HAVE_INDEX_EXT +#include +#endif + +#ifdef HAVE_COMPONENT_EXT +#include +#endif + +#ifdef HAVE_CORE_EXT +#include +#endif + +#ifdef HAVE_AUDIO_EXT +#include +#endif + +#ifdef HAVE_IV_COMMON_EXT +#include +#endif + +#ifdef HAVE_IMAGE_EXT +#include +#endif + +#ifdef HAVE_OTHER_EXT +#include +#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/gst-omx/omx/gstomxaacdec.c b/gst-omx/omx/gstomxaacdec.c new file mode 100644 index 0000000000..9606b7fd33 --- /dev/null +++ b/gst-omx/omx/gstomxaacdec.c @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2014, Sebastian Dröge + * + * 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 + +#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 "); + + 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/gst-omx/omx/gstomxaacdec.h b/gst-omx/omx/gstomxaacdec.h new file mode 100644 index 0000000000..891589b01e --- /dev/null +++ b/gst-omx/omx/gstomxaacdec.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2014, Sebastian Dröge + * + * 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 +#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/gst-omx/omx/gstomxaacenc.c b/gst-omx/omx/gstomxaacenc.c new file mode 100644 index 0000000000..c568ddd184 --- /dev/null +++ b/gst-omx/omx/gstomxaacenc.c @@ -0,0 +1,511 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 + +#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 "); + + 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/gst-omx/omx/gstomxaacenc.h b/gst-omx/omx/gstomxaacenc.h new file mode 100644 index 0000000000..b6c3daa9b7 --- /dev/null +++ b/gst-omx/omx/gstomxaacenc.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 +#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/gst-omx/omx/gstomxallocator.c b/gst-omx/omx/gstomxallocator.c new file mode 100644 index 0000000000..a180669791 --- /dev/null +++ b/gst-omx/omx/gstomxallocator.c @@ -0,0 +1,554 @@ +/* + * Copyright (C) 2019, Collabora Ltd. + * Author: George Kiagiadakis + * + * 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_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/gst-omx/omx/gstomxallocator.h b/gst-omx/omx/gstomxallocator.h new file mode 100644 index 0000000000..5c94584ec2 --- /dev/null +++ b/gst-omx/omx/gstomxallocator.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2019, Collabora Ltd. + * Author: George Kiagiadakis + * + * 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 + +#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/gst-omx/omx/gstomxamrdec.c b/gst-omx/omx/gstomxamrdec.c new file mode 100644 index 0000000000..d7e468fbbf --- /dev/null +++ b/gst-omx/omx/gstomxamrdec.c @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2014, Sebastian Dröge + * Copyright (C) 2014, LG Electronics, Inc. + * + * 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 + +#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 "); + + 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/gst-omx/omx/gstomxamrdec.h b/gst-omx/omx/gstomxamrdec.h new file mode 100644 index 0000000000..7a2df33050 --- /dev/null +++ b/gst-omx/omx/gstomxamrdec.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2014, Sebastian Dröge + * + * 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 +#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/gst-omx/omx/gstomxanalogaudiosink.c b/gst-omx/omx/gstomxanalogaudiosink.c new file mode 100644 index 0000000000..7c8c885273 --- /dev/null +++ b/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 + * + * 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 + +#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 "); + + gst_omx_set_default_role (&audiosink_class->cdata, "audio_render.local"); +} + +static void +gst_omx_analog_audio_sink_init (GstOMXAnalogAudioSink * self) +{ +} diff --git a/gst-omx/omx/gstomxanalogaudiosink.h b/gst-omx/omx/gstomxanalogaudiosink.h new file mode 100644 index 0000000000..7f5704812f --- /dev/null +++ b/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 + * + * 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 +#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/gst-omx/omx/gstomxaudiodec.c b/gst-omx/omx/gstomxaudiodec.c new file mode 100644 index 0000000000..8275b7204f --- /dev/null +++ b/gst-omx/omx/gstomxaudiodec.c @@ -0,0 +1,1404 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , Collabora Ltd. + * Copyright (C) 2013, Collabora Ltd. + * Author: Sebastian Dröge + * Copyright (C) 2014, Sebastian Dröge + * + * 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 + +#include + +#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 (¶m); + + err = + gst_omx_component_get_parameter (self->dec, OMX_IndexParamAudioInit, + ¶m); + 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/gst-omx/omx/gstomxaudiodec.h b/gst-omx/omx/gstomxaudiodec.h new file mode 100644 index 0000000000..0f4adc693e --- /dev/null +++ b/gst-omx/omx/gstomxaudiodec.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2014, Sebastian Dröge + * + * 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 +#include +#include + +#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/gst-omx/omx/gstomxaudioenc.c b/gst-omx/omx/gstomxaudioenc.c new file mode 100644 index 0000000000..c5c1d6fffd --- /dev/null +++ b/gst-omx/omx/gstomxaudioenc.c @@ -0,0 +1,1181 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 +#include + +#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 (¶m); + + err = + gst_omx_component_get_parameter (self->enc, OMX_IndexParamAudioInit, + ¶m); + 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/gst-omx/omx/gstomxaudioenc.h b/gst-omx/omx/gstomxaudioenc.h new file mode 100644 index 0000000000..8fe5369cdf --- /dev/null +++ b/gst-omx/omx/gstomxaudioenc.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 +#include +#include + +#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/gst-omx/omx/gstomxaudiosink.c b/gst-omx/omx/gstomxaudiosink.c new file mode 100644 index 0000000000..d4e684f3b5 --- /dev/null +++ b/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 + * + * 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 +#include + +#include + +#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 (¶m); + param.nPortIndex = self->in_port->index; + param.bMute = (mute ? OMX_TRUE : OMX_FALSE); + err = gst_omx_component_set_config (self->comp, + OMX_IndexConfigAudioMute, ¶m); + 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 (¶m); + 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, ¶m); + 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 (¶m); + + err = + gst_omx_component_get_parameter (self->comp, OMX_IndexParamAudioInit, + ¶m); + 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 (¶m); + + err = + gst_omx_component_get_parameter (self->comp, OMX_IndexParamAudioInit, + ¶m); + 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 (¶m); + 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, ¶m.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, + ¶m); + 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 (¶m); + strcpy ((char *) param.sName, klass->destination); + err = gst_omx_component_set_config (self->comp, + OMX_IndexConfigBrcmAudioDestination, ¶m); + 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 (¶m); + param.nPortIndex = self->in_port->index; + param.nU32 = 0; + err = gst_omx_component_get_config (self->comp, + OMX_IndexConfigAudioRenderingLatency, ¶m); + 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/gst-omx/omx/gstomxaudiosink.h b/gst-omx/omx/gstomxaudiosink.h new file mode 100644 index 0000000000..481b18a513 --- /dev/null +++ b/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 + * + * 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 +#include + +#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/gst-omx/omx/gstomxbufferpool.c b/gst-omx/omx/gstomxbufferpool.c new file mode 100644 index 0000000000..b88568524c --- /dev/null +++ b/gst-omx/omx/gstomxbufferpool.c @@ -0,0 +1,674 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , Collabora Ltd. + * Copyright (C) 2013-2019, Collabora Ltd. + * Author: Sebastian Dröge + * George Kiagiadakis + * + * 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_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/gst-omx/omx/gstomxbufferpool.h b/gst-omx/omx/gstomxbufferpool.h new file mode 100644 index 0000000000..bc5ac60588 --- /dev/null +++ b/gst-omx/omx/gstomxbufferpool.h @@ -0,0 +1,101 @@ +/* + * Copyright 2014 Advanced Micro Devices, Inc. + * Author: Christian König + * + * 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 +#include +#include + +#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/gst-omx/omx/gstomxh263dec.c b/gst-omx/omx/gstomxh263dec.c new file mode 100644 index 0000000000..d76f1b9a57 --- /dev/null +++ b/gst-omx/omx/gstomxh263dec.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 + +#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 "); + + 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/gst-omx/omx/gstomxh263dec.h b/gst-omx/omx/gstomxh263dec.h new file mode 100644 index 0000000000..aa24c2f7f8 --- /dev/null +++ b/gst-omx/omx/gstomxh263dec.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 +#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/gst-omx/omx/gstomxh263enc.c b/gst-omx/omx/gstomxh263enc.c new file mode 100644 index 0000000000..9e80bfbb19 --- /dev/null +++ b/gst-omx/omx/gstomxh263enc.c @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 + +#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 "); + + 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 (¶m); + 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, ¶m); + 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, ¶m); + 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 (¶m); + 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, ¶m); + 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/gst-omx/omx/gstomxh263enc.h b/gst-omx/omx/gstomxh263enc.h new file mode 100644 index 0000000000..0dbd0deb23 --- /dev/null +++ b/gst-omx/omx/gstomxh263enc.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 +#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/gst-omx/omx/gstomxh264dec.c b/gst-omx/omx/gstomxh264dec.c new file mode 100644 index 0000000000..32b575742c --- /dev/null +++ b/gst-omx/omx/gstomxh264dec.c @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 + +#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 "); + + 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 (¶m); + 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, ¶m); + 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/gst-omx/omx/gstomxh264dec.h b/gst-omx/omx/gstomxh264dec.h new file mode 100644 index 0000000000..4c0ea1f37b --- /dev/null +++ b/gst-omx/omx/gstomxh264dec.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 +#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/gst-omx/omx/gstomxh264enc.c b/gst-omx/omx/gstomxh264enc.c new file mode 100644 index 0000000000..51d84a805a --- /dev/null +++ b/gst-omx/omx/gstomxh264enc.c @@ -0,0 +1,894 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 + +#include "gstomxh264enc.h" +#include "gstomxh264utils.h" + +#ifdef USE_OMX_TARGET_RPI +#include +#include +#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 "); + + 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 (¶m); + 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, ¶m); + 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, ¶m); + 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 (¶m); + 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, ¶m); + 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, ¶m); + 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 (¶m); + 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, ¶m); + 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/gst-omx/omx/gstomxh264enc.h b/gst-omx/omx/gstomxh264enc.h new file mode 100644 index 0000000000..4d67c86b02 --- /dev/null +++ b/gst-omx/omx/gstomxh264enc.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 +#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/gst-omx/omx/gstomxh264utils.c b/gst-omx/omx/gstomxh264utils.c new file mode 100644 index 0000000000..ba292115af --- /dev/null +++ b/gst-omx/omx/gstomxh264utils.c @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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/gst-omx/omx/gstomxh264utils.h b/gst-omx/omx/gstomxh264utils.h new file mode 100644 index 0000000000..e5c35e4f24 --- /dev/null +++ b/gst-omx/omx/gstomxh264utils.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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/gst-omx/omx/gstomxh265dec.c b/gst-omx/omx/gstomxh265dec.c new file mode 100644 index 0000000000..f8abf419f7 --- /dev/null +++ b/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 , 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 + +#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 "); + + 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 (¶m); + 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, ¶m); + 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/gst-omx/omx/gstomxh265dec.h b/gst-omx/omx/gstomxh265dec.h new file mode 100644 index 0000000000..f0f1016ae1 --- /dev/null +++ b/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 , 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 +#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/gst-omx/omx/gstomxh265enc.c b/gst-omx/omx/gstomxh265enc.c new file mode 100644 index 0000000000..8b31c42414 --- /dev/null +++ b/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 , 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 + +#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 "); + + 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 (¶m); + 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, ¶m); + 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, ¶m); + 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 (¶m); + 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, ¶m); +#else + err = + gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc, + (OMX_INDEXTYPE) OMX_IndexParamVideoHevc, ¶m); +#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, ¶m); + + 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 (¶m); + 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, ¶m); + 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/gst-omx/omx/gstomxh265enc.h b/gst-omx/omx/gstomxh265enc.h new file mode 100644 index 0000000000..b67fa1f0fb --- /dev/null +++ b/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 , 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 +#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/gst-omx/omx/gstomxh265utils.c b/gst-omx/omx/gstomxh265utils.c new file mode 100644 index 0000000000..8bf81da06d --- /dev/null +++ b/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 , 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/gst-omx/omx/gstomxh265utils.h b/gst-omx/omx/gstomxh265utils.h new file mode 100644 index 0000000000..1987a326aa --- /dev/null +++ b/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 , 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/gst-omx/omx/gstomxhdmiaudiosink.c b/gst-omx/omx/gstomxhdmiaudiosink.c new file mode 100644 index 0000000000..211b719343 --- /dev/null +++ b/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 + * + * 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 + +#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 "); + + gst_omx_set_default_role (&audiosink_class->cdata, "audio_render.hdmi"); +} + +static void +gst_omx_hdmi_audio_sink_init (GstOMXHdmiAudioSink * self) +{ +} diff --git a/gst-omx/omx/gstomxhdmiaudiosink.h b/gst-omx/omx/gstomxhdmiaudiosink.h new file mode 100644 index 0000000000..e45e56b3ce --- /dev/null +++ b/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 + * + * 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 +#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/gst-omx/omx/gstomxmjpegdec.c b/gst-omx/omx/gstomxmjpegdec.c new file mode 100644 index 0000000000..6ca34f2d56 --- /dev/null +++ b/gst-omx/omx/gstomxmjpegdec.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2013, Collabora Ltd. + * Author: Sebastian Dröge + * + * 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 + +#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 "); + + 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/gst-omx/omx/gstomxmjpegdec.h b/gst-omx/omx/gstomxmjpegdec.h new file mode 100644 index 0000000000..8802c8d7ea --- /dev/null +++ b/gst-omx/omx/gstomxmjpegdec.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 +#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/gst-omx/omx/gstomxmp3dec.c b/gst-omx/omx/gstomxmp3dec.c new file mode 100644 index 0000000000..aa22e80fb0 --- /dev/null +++ b/gst-omx/omx/gstomxmp3dec.c @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2014, Sebastian Dröge + * + * 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 + +#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 "); + + 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/gst-omx/omx/gstomxmp3dec.h b/gst-omx/omx/gstomxmp3dec.h new file mode 100644 index 0000000000..4f07659783 --- /dev/null +++ b/gst-omx/omx/gstomxmp3dec.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2014, Sebastian Dröge + * + * 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 +#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/gst-omx/omx/gstomxmp3enc.c b/gst-omx/omx/gstomxmp3enc.c new file mode 100644 index 0000000000..1296564f31 --- /dev/null +++ b/gst-omx/omx/gstomxmp3enc.c @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2017 + * Author: Julien Isorce + * + * 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 + +#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 "); + + 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/gst-omx/omx/gstomxmp3enc.h b/gst-omx/omx/gstomxmp3enc.h new file mode 100644 index 0000000000..74e115e6c6 --- /dev/null +++ b/gst-omx/omx/gstomxmp3enc.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2017 + * Author: Julien Isorce + * + * 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 +#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/gst-omx/omx/gstomxmpeg2videodec.c b/gst-omx/omx/gstomxmpeg2videodec.c new file mode 100644 index 0000000000..144845060d --- /dev/null +++ b/gst-omx/omx/gstomxmpeg2videodec.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 + +#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 "); + + 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/gst-omx/omx/gstomxmpeg2videodec.h b/gst-omx/omx/gstomxmpeg2videodec.h new file mode 100644 index 0000000000..ff86bcdee5 --- /dev/null +++ b/gst-omx/omx/gstomxmpeg2videodec.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 +#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/gst-omx/omx/gstomxmpeg4videodec.c b/gst-omx/omx/gstomxmpeg4videodec.c new file mode 100644 index 0000000000..8cebef82d6 --- /dev/null +++ b/gst-omx/omx/gstomxmpeg4videodec.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 + +#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 "); + + 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/gst-omx/omx/gstomxmpeg4videodec.h b/gst-omx/omx/gstomxmpeg4videodec.h new file mode 100644 index 0000000000..73a68d5d70 --- /dev/null +++ b/gst-omx/omx/gstomxmpeg4videodec.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 +#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/gst-omx/omx/gstomxmpeg4videoenc.c b/gst-omx/omx/gstomxmpeg4videoenc.c new file mode 100644 index 0000000000..c928171c33 --- /dev/null +++ b/gst-omx/omx/gstomxmpeg4videoenc.c @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 + +#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 "); + + 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 (¶m); + 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, ¶m); + 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, ¶m); + 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 (¶m); + 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, ¶m); + 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/gst-omx/omx/gstomxmpeg4videoenc.h b/gst-omx/omx/gstomxmpeg4videoenc.h new file mode 100644 index 0000000000..01d6698c87 --- /dev/null +++ b/gst-omx/omx/gstomxmpeg4videoenc.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 +#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/gst-omx/omx/gstomxtheoradec.c b/gst-omx/omx/gstomxtheoradec.c new file mode 100644 index 0000000000..b17419e41f --- /dev/null +++ b/gst-omx/omx/gstomxtheoradec.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2013, Collabora Ltd. + * Author: Sebastian Dröge + * + * 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 + +#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 "); + + 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/gst-omx/omx/gstomxtheoradec.h b/gst-omx/omx/gstomxtheoradec.h new file mode 100644 index 0000000000..4b5a2fa2fa --- /dev/null +++ b/gst-omx/omx/gstomxtheoradec.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2013, Collabora Ltd. + * Author: Sebastian Dröge + * + * 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 +#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/gst-omx/omx/gstomxvideo.c b/gst-omx/omx/gstomxvideo.c new file mode 100644 index 0000000000..e08ff4ceaa --- /dev/null +++ b/gst-omx/omx/gstomxvideo.c @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , Collabora Ltd. + * Copyright (C) 2013, Collabora Ltd. + * Author: Sebastian Dröge * + * Copyright 2014 Advanced Micro Devices, Inc. + * Author: Christian König + * + * 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 + +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 (¶m); + 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, ¶m); + + /* 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/gst-omx/omx/gstomxvideo.h b/gst-omx/omx/gstomxvideo.h new file mode 100644 index 0000000000..8664345f21 --- /dev/null +++ b/gst-omx/omx/gstomxvideo.h @@ -0,0 +1,74 @@ +/* + * Copyright 2014 Advanced Micro Devices, Inc. + * Author: Christian König + * + * 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 +#include +#include +#include + +#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/gst-omx/omx/gstomxvideodec.c b/gst-omx/omx/gstomxvideodec.c new file mode 100644 index 0000000000..917ce8a315 --- /dev/null +++ b/gst-omx/omx/gstomxvideodec.c @@ -0,0 +1,3524 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , Collabora Ltd. + * Copyright (C) 2013, Collabora Ltd. + * Author: Sebastian Dröge + * + * 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 +#include + +#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 +#endif + +#if defined (USE_OMX_TARGET_RPI) && defined(__GNUC__) +#pragma GCC reset_options +#pragma GCC diagnostic pop +#endif + +#include + +#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 (¶m); + + err = + gst_omx_component_get_parameter (self->dec, OMX_IndexParamVideoInit, + ¶m); + 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 (¶m); + + err = + gst_omx_component_get_parameter (self->egl_render, + OMX_IndexParamVideoInit, ¶m); + 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, ¶ms) != 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, ¶ms) != 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, + ¶ms); + 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, ¶ms); + 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 (¶m); + param.nPortIndex = self->dec_out_port->index; + + err = gst_omx_component_get_parameter (self->dec, + OMX_IndexParamVideoPortFormat, ¶m); + 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, ¶m); + 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 (¶m); + err = + gst_omx_component_get_parameter (self->dec, + (OMX_INDEXTYPE) OMX_ALG_IndexParamReportedLatency, ¶m); + + 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, ¶ms); + if (allocator) { + if (GST_IS_GL_MEMORY_EGL_ALLOCATOR (allocator)) { + found = TRUE; + gst_query_set_nth_allocation_param (query, 0, allocator, ¶ms); + 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/gst-omx/omx/gstomxvideodec.h b/gst-omx/omx/gstomxvideodec.h new file mode 100644 index 0000000000..df441d9d08 --- /dev/null +++ b/gst-omx/omx/gstomxvideodec.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 +#include +#include + +#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/gst-omx/omx/gstomxvideoenc.c b/gst-omx/omx/gstomxvideoenc.c new file mode 100644 index 0000000000..6dbfb411ca --- /dev/null +++ b/gst-omx/omx/gstomxvideoenc.c @@ -0,0 +1,3732 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 +#include +#include + +#include + +#include "gstomxbufferpool.h" +#include "gstomxvideo.h" +#include "gstomxvideoenc.h" + +#ifdef USE_OMX_TARGET_RPI +#include +#include +#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 (¶m); + + err = + gst_omx_component_get_parameter (self->enc, OMX_IndexParamVideoInit, + ¶m); + 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 (¶m); + err = + gst_omx_component_get_parameter (self->enc, + (OMX_INDEXTYPE) OMX_ALG_IndexParamReportedLatency, ¶m); + + 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/gst-omx/omx/gstomxvideoenc.h b/gst-omx/omx/gstomxvideoenc.h new file mode 100644 index 0000000000..51e2baf4f8 --- /dev/null +++ b/gst-omx/omx/gstomxvideoenc.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 +#include +#include + +#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/gst-omx/omx/gstomxvp8dec.c b/gst-omx/omx/gstomxvp8dec.c new file mode 100644 index 0000000000..fd2e5acddf --- /dev/null +++ b/gst-omx/omx/gstomxvp8dec.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2013, Collabora Ltd. + * Author: Sebastian Dröge + * + * 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 + +#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 "); + + 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/gst-omx/omx/gstomxvp8dec.h b/gst-omx/omx/gstomxvp8dec.h new file mode 100644 index 0000000000..f99f4cebcb --- /dev/null +++ b/gst-omx/omx/gstomxvp8dec.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2013, Collabora Ltd. + * Author: Sebastian Dröge + * + * 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 +#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/gst-omx/omx/gstomxwmvdec.c b/gst-omx/omx/gstomxwmvdec.c new file mode 100644 index 0000000000..14758275f4 --- /dev/null +++ b/gst-omx/omx/gstomxwmvdec.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 + +#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 "); + + 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/gst-omx/omx/gstomxwmvdec.h b/gst-omx/omx/gstomxwmvdec.h new file mode 100644 index 0000000000..9375dc5dfa --- /dev/null +++ b/gst-omx/omx/gstomxwmvdec.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge , 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 +#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/gst-omx/omx/meson.build b/gst-omx/omx/meson.build new file mode 100644 index 0000000000..becb72ff5b --- /dev/null +++ b/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/gst-omx/omx/openmax/OMX_Audio.h b/gst-omx/omx/openmax/OMX_Audio.h new file mode 100644 index 0000000000..04f1a9997b --- /dev/null +++ b/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 + +/** @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/gst-omx/omx/openmax/OMX_Component.h b/gst-omx/omx/openmax/OMX_Component.h new file mode 100644 index 0000000000..d5956405e2 --- /dev/null +++ b/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 +#include +#include +#include + +/** @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/gst-omx/omx/openmax/OMX_ComponentExt.h b/gst-omx/omx/openmax/OMX_ComponentExt.h new file mode 100644 index 0000000000..e5aa74871c --- /dev/null +++ b/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 + + +/** 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/gst-omx/omx/openmax/OMX_ContentPipe.h b/gst-omx/omx/openmax/OMX_ContentPipe.h new file mode 100644 index 0000000000..5f6310c28a --- /dev/null +++ b/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/gst-omx/omx/openmax/OMX_Core.h b/gst-omx/omx/openmax/OMX_Core.h new file mode 100644 index 0000000000..a076f2f479 --- /dev/null +++ b/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 + + +/** 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 */ + +/** 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/gst-omx/omx/openmax/OMX_CoreExt.h b/gst-omx/omx/openmax/OMX_CoreExt.h new file mode 100644 index 0000000000..b7a5b62334 --- /dev/null +++ b/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 + +/** 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/gst-omx/omx/openmax/OMX_IVCommon.h b/gst-omx/omx/openmax/OMX_IVCommon.h new file mode 100644 index 0000000000..4c4995ce04 --- /dev/null +++ b/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 + +/** @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/gst-omx/omx/openmax/OMX_Image.h b/gst-omx/omx/openmax/OMX_Image.h new file mode 100644 index 0000000000..a6d4666c03 --- /dev/null +++ b/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 + +/** @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/gst-omx/omx/openmax/OMX_Index.h b/gst-omx/omx/openmax/OMX_Index.h new file mode 100644 index 0000000000..44d4ea76d2 --- /dev/null +++ b/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 + + +/** 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, /** + + +/** 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/gst-omx/omx/openmax/OMX_Other.h b/gst-omx/omx/openmax/OMX_Other.h new file mode 100644 index 0000000000..caf7f38448 --- /dev/null +++ b/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 + + +/** + * 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/gst-omx/omx/openmax/OMX_Types.h b/gst-omx/omx/openmax/OMX_Types.h new file mode 100644 index 0000000000..8698358786 --- /dev/null +++ b/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/gst-omx/omx/openmax/OMX_Video.h b/gst-omx/omx/openmax/OMX_Video.h new file mode 100644 index 0000000000..163e45081f --- /dev/null +++ b/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 + + +/** + * 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/gst-omx/omx/openmax/OMX_VideoExt.h b/gst-omx/omx/openmax/OMX_VideoExt.h new file mode 100644 index 0000000000..a9b5d458b9 --- /dev/null +++ b/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 + +/** 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/gst-omx/scripts/extract-release-date-from-doap-file.py b/gst-omx/scripts/extract-release-date-from-doap-file.py new file mode 100644 index 0000000000..f09b60e9d0 --- /dev/null +++ b/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 +# +# 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/gst-omx/tests/check/generic/states.c b/gst-omx/tests/check/generic/states.c new file mode 100644 index 0000000000..415ac543c2 --- /dev/null +++ b/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 + * + * 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 + +#include + +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/gst-omx/tests/check/meson.build b/gst-omx/tests/check/meson.build new file mode 100644 index 0000000000..4bb7de6976 --- /dev/null +++ b/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_variable('pluginsdir'), + pbase.get_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.project_build_root(), separator: ':') + env.set('GST_PLUGIN_PATH_1_0', [meson.global_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/gst-omx/tests/meson.build b/gst-omx/tests/meson.build new file mode 100644 index 0000000000..76b079162c --- /dev/null +++ b/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/gst-omx/tools/listcomponents.c b/gst-omx/tools/listcomponents.c new file mode 100644 index 0000000000..3933564b26 --- /dev/null +++ b/gst-omx/tools/listcomponents.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2012 Collabora Ltd. + * Author: Sebastian Dröge + * + * 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 +#include + +#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 +#include + +#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/gst-omx/tools/meson.build b/gst-omx/tools/meson.build new file mode 100644 index 0000000000..7f6a6704b6 --- /dev/null +++ b/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, +)