Tizen 2.1 base
authorJinkun Jang <jinkun.jang@samsung.com>
Tue, 12 Mar 2013 16:49:46 +0000 (01:49 +0900)
committerJinkun Jang <jinkun.jang@samsung.com>
Tue, 12 Mar 2013 16:49:46 +0000 (01:49 +0900)
204 files changed:
AUTHORS
COPYING.LIB [new file with mode: 0644]
Makefile.am
NEWS
README
autogen.sh
configure.ac
debian.upstream/Makefile.am [new file with mode: 0644]
debian.upstream/changelog.in [new file with mode: 0644]
debian.upstream/compat [new file with mode: 0644]
debian.upstream/control.in [new file with mode: 0644]
debian.upstream/copyright [new file with mode: 0644]
debian.upstream/gstreamer-vaapi-doc.install.in [new file with mode: 0644]
debian.upstream/gstreamer-vaapi.install.in [new file with mode: 0644]
debian.upstream/libgstvaapi-dev.install.in [new file with mode: 0644]
debian.upstream/libgstvaapi-drm.install.in [new file with mode: 0644]
debian.upstream/libgstvaapi-glx.install.in [new file with mode: 0644]
debian.upstream/libgstvaapi-wayland.install.in [new file with mode: 0644]
debian.upstream/libgstvaapi-x11.install.in [new file with mode: 0644]
debian.upstream/libgstvaapi.install.in [new file with mode: 0644]
debian.upstream/rules [new file with mode: 0755]
docs/Makefile.am [new file with mode: 0644]
docs/reference/Makefile.am [new file with mode: 0644]
docs/reference/libs/Makefile.am [new file with mode: 0644]
docs/reference/libs/libs-docs.xml.in [new file with mode: 0644]
docs/reference/libs/libs-overrides.txt [new file with mode: 0644]
docs/reference/libs/libs-sections.txt [new file with mode: 0644]
docs/reference/libs/libs.core.types [new file with mode: 0644]
docs/reference/libs/libs.glx.types [new file with mode: 0644]
docs/reference/libs/libs.x11.types [new file with mode: 0644]
docs/reference/plugins/Makefile.am [new file with mode: 0644]
docs/reference/plugins/plugins-docs.xml.in [new file with mode: 0644]
docs/reference/plugins/plugins-overrides.txt [new file with mode: 0644]
docs/reference/plugins/plugins-sections.txt [new file with mode: 0644]
docs/reference/plugins/plugins.types [new file with mode: 0644]
gst-libs/gst/Makefile.am
gst-libs/gst/codecparsers/Makefile.am [new file with mode: 0644]
gst-libs/gst/codecparsers/gstjpegparser.c [new file with mode: 0644]
gst-libs/gst/codecparsers/gstjpegparser.h [new file with mode: 0644]
gst-libs/gst/vaapi/Makefile.am
gst-libs/gst/vaapi/glibcompat.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapi_priv.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapibaseencoder.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapibaseencoder.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapicodec_objects.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapicodec_objects.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapicompat.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapicontext.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapicontext.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidebug.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder_dpb.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder_dpb.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder_h264.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder_h264.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder_jpeg.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder_jpeg.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder_mpeg2.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder_mpeg2.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder_mpeg4.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder_mpeg4.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder_objects.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder_objects.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder_priv.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder_vc1.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidecoder_vc1.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplay.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplay.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplay_drm.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplay_drm.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplay_drm_priv.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplay_glx.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplay_glx.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplay_glx_priv.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplay_priv.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplay_wayland.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplay_wayland.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplay_wayland_priv.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplay_x11.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplay_x11.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplay_x11_priv.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplaycache.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplaycache.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiencoder.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiencoder.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiencoder_h263.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiencoder_h263.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiencoder_h264.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiencoder_h264.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiencoder_mpeg4.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiencoder_mpeg4.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiimage.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiimage.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiimageformat.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiimageformat.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiimagepool.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiimagepool.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiobject.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiobject.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiobject_priv.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiparamspecs.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiparamspecs.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiprofile.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiprofile.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapisubpicture.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapisubpicture.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapisurface.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapisurface.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapisurface_priv.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapisurface_userptr.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapisurface_userptr.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapisurfacepool.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapisurfacepool.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapisurfaceproxy.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapisurfaceproxy.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapitexture.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapitexture.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapitypes.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiutils.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiutils.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiutils_glx.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiutils_glx.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiutils_x11.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiutils_x11.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapivalue.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapivalue.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapivideobuffer.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapivideobuffer.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapivideobuffer_glx.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapivideobuffer_glx.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapivideobuffer_priv.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapivideoconverter_glx.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapivideoconverter_glx.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapivideopool.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapivideopool.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiwindow.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiwindow.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiwindow_drm.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiwindow_drm.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiwindow_glx.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiwindow_glx.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiwindow_wayland.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiwindow_wayland.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiwindow_x11.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiwindow_x11.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiworkarounds.h [new file with mode: 0644]
gst-libs/gst/vaapi/sysdeps.h [new file with mode: 0644]
gst/Makefile.am [new file with mode: 0644]
gst/vaapi/Makefile.am [new file with mode: 0644]
gst/vaapi/gstvaapi.c [new file with mode: 0644]
gst/vaapi/gstvaapidecode.c [new file with mode: 0644]
gst/vaapi/gstvaapidecode.h [new file with mode: 0644]
gst/vaapi/gstvaapidownload.c [new file with mode: 0644]
gst/vaapi/gstvaapidownload.h [new file with mode: 0644]
gst/vaapi/gstvaapiencode.c [new file with mode: 0644]
gst/vaapi/gstvaapiencode.h [new file with mode: 0644]
gst/vaapi/gstvaapiencode_h263.c [new file with mode: 0644]
gst/vaapi/gstvaapiencode_h263.h [new file with mode: 0644]
gst/vaapi/gstvaapiencode_h264.c [new file with mode: 0644]
gst/vaapi/gstvaapiencode_h264.h [new file with mode: 0644]
gst/vaapi/gstvaapiencode_mpeg4.c [new file with mode: 0644]
gst/vaapi/gstvaapiencode_mpeg4.h [new file with mode: 0644]
gst/vaapi/gstvaapipluginbuffer.c [new file with mode: 0644]
gst/vaapi/gstvaapipluginbuffer.h [new file with mode: 0644]
gst/vaapi/gstvaapipluginutil.c [new file with mode: 0644]
gst/vaapi/gstvaapipluginutil.h [new file with mode: 0644]
gst/vaapi/gstvaapipostproc.c [new file with mode: 0644]
gst/vaapi/gstvaapipostproc.h [new file with mode: 0644]
gst/vaapi/gstvaapisink.c [new file with mode: 0644]
gst/vaapi/gstvaapisink.h [new file with mode: 0644]
gst/vaapi/gstvaapiupload.c [new file with mode: 0644]
gst/vaapi/gstvaapiupload.h [new file with mode: 0644]
packaging/gstreamer-vaapi.changes [new file with mode: 0644]
packaging/gstreamer-vaapi.manifest [new file with mode: 0644]
packaging/gstreamer-vaapi.spec [new file with mode: 0644]
pkgconfig/Makefile.am [new file with mode: 0644]
pkgconfig/gstreamer-vaapi-drm.pc.in [new file with mode: 0644]
pkgconfig/gstreamer-vaapi-glx.pc.in [new file with mode: 0644]
pkgconfig/gstreamer-vaapi-wayland.pc.in [new file with mode: 0644]
pkgconfig/gstreamer-vaapi-x11.pc.in [new file with mode: 0644]
pkgconfig/gstreamer-vaapi.pc.in [new file with mode: 0644]
tests/Makefile.am [new file with mode: 0644]
tests/image.c [new file with mode: 0644]
tests/image.h [new file with mode: 0644]
tests/output.c [new file with mode: 0644]
tests/output.h [new file with mode: 0644]
tests/test-decode.c [new file with mode: 0644]
tests/test-decode.h [new file with mode: 0644]
tests/test-display.c [new file with mode: 0644]
tests/test-h264.c [new file with mode: 0644]
tests/test-h264.h [new file with mode: 0644]
tests/test-jpeg.c [new file with mode: 0644]
tests/test-jpeg.h [new file with mode: 0644]
tests/test-mpeg2.c [new file with mode: 0644]
tests/test-mpeg2.h [new file with mode: 0644]
tests/test-subpicture-data.c [new file with mode: 0644]
tests/test-subpicture-data.h [new file with mode: 0644]
tests/test-subpicture.c [new file with mode: 0644]
tests/test-surfaces.c [new file with mode: 0644]
tests/test-textures.c [new file with mode: 0644]
tests/test-vc1.c [new file with mode: 0644]
tests/test-vc1.h [new file with mode: 0644]
tests/test-windows.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
index 4558581..96d5fc7 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1 +1,14 @@
-Gwenole Beauchesne <gbeauchesne@splitted-desktop.com>  - Primary author
+Maintainers:
+
+Gwenole Beauchesne      - Lead developer
+Halley Zhao             - MPEG-4:2 decoder
+
+This project is maintained by Intel Corporation.
+
+Contributors (sorted by first name):
+
+Feng Yuan
+Holger Kaelberer
+Nicolas Dufresne
+Sreerenj Balachandran
+Thibault Saunier
diff --git a/COPYING.LIB b/COPYING.LIB
new file mode 100644 (file)
index 0000000..4362b49
--- /dev/null
@@ -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.
+\f
+  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.
+\f
+                  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.
+\f
+  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.
+\f
+  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.
+\f
+  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.
+\f
+  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.
+\f
+  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.
+\f
+  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
+\f
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
index d931a82..a204514 100644 (file)
@@ -1,9 +1,25 @@
+ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
+
 AUTOMAKE_OPTIONS = foreign
 
-SUBDIRS = gst-libs sys
+SUBDIRS = debian.upstream gst-libs gst pkgconfig tests docs
 
 # Extra clean files so that maintainer-clean removes *everything*
 MAINTAINERCLEANFILES = \
        aclocal.m4 compile config.guess config.sub \
        configure depcomp install-sh ltmain.sh     \
-       Makefile.in missing config.h.in
+       Makefile.in missing config.h.in gtk-doc.make
+
+DEB_BUILDDIR = debian.build
+
+deb:
+       dpkg-buildpackage -rfakeroot -uc -us
+
+deb.upstream: dist
+       -mkdir -p $(DEB_BUILDDIR)
+       cd $(DEB_BUILDDIR)                              && \
+       rm -rf $(PACKAGE)-$(VERSION)                    && \
+       tar zxvf ../$(PACKAGE)-$(VERSION).tar.gz        && \
+       cd $(PACKAGE)-$(VERSION)                        && \
+       $(LN_S) debian.upstream debian                  && \
+       $(MAKE) deb -f Makefile.am
diff --git a/NEWS b/NEWS
index 297704a..2ad1dbe 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,131 @@
-gst-vaapi NEWS -- summary of changes.  2010-01-DD
-Copyright (C) 2010 Splitted-Desktop Systems
+gst-vaapi NEWS -- summary of changes.  2012-08-DD
+Copyright (C) 2010-2011 Splitted-Desktop Systems
+Copyright (C) 2011-2012 Intel Corporation
+Copyright (C) 2011 Collabora
 
-Version 0.1.0 - DD.Jan.2010
+Version 0.4.0 - DD.Aug.2012
+* Add support for Wayland
+* Add support for headless pipelines (VA/DRM API)
+* Drop FFmpeg-based decoders
+
+Version 0.3.7 - 26.Jun.2012
+* Fix vaapidecode to report unsupported codec profiles
+* Fix MPEG-2 decoding of streams with extra slice() information
+* Map MPEG-2 compatible High profile streams to Main profile
+* Map MPEG-4 Simple Scalable profile streams to Advanced Simple (Feng Yuan)
+* Fix various MPEG-4 decoding bugs (timestamps, reference frames) (Feng Yuan)
+* Don't forcibly resize user provided X windows (Holger Kaelberer)
+* Recalculate render rect only if caps are negotiated (Holger Kaelberer)
+
+Version 0.3.6 - 02.Apr.2012
+* Add support for decoding MPEG-2 interlaced streams
+* Add support for interlaced streams with FFmpeg decoders (Holger Kaelberer)
+* Add vaapipostproc element for video postprocessing (e.g. deinterlacing)
+* Skip all H.264 Filler Data NALs
+* Fix crashes in MPEG-4 decoder (Feng Yuan)
+* Fix fallback from MPEG-2 Simple to Main profile
+* Improve decoding of misformed MPEG-2 streams (+Feng Yuan)
+* Avoid a hang in playbin2 for some MPEG-2 TS streams (Feng Yuan)
+
+Version 0.3.5 - 02.Mar.2012
+* Fix H.264 decoding when emulation prevention bytes are detected
+* Skip all H.264 Access Unit (AU) NALs (Feng Yuan)
+* Fix modification process of H.264 reference picture lists (Feng Yuan)
+* Fix MPEG-2 stream size calculation (Sreerenj Balachandran)
+* Fix MPEG-2 decoding on Intel Gen with multiple slices per MB line
+* Fix crash when downloading/uploading VA images on PowerVR (Cedar Trail)
+* Fix double buffer free issues with some VA drivers
+* Fix crash when there is no free surface available for decoding
+* Skip profiles which have no entrypoints (Halley Zhao)
+* Fix minor memory leaks in plug-in elements
+
+Version 0.3.4 - 01.Feb.2012
+* Add H.264 decoder (based on codecparsers)
+* Add workaround for qtdemux not exposing H.263 profiles (Halley Zhao)
+* Alias H.263 Baseline profile to MPEG-4:2 Simple profile (Halley Zhao)
+* Use optimized path to submit slice data buffers
+* Fix possible memory leak in MPEG-2 decoder
+* Fix vaapisink to cap window size to the maximum display size
+* Fix MPEG-2, MPEG-4 and VC-1 decoders to refcount reference surfaces properly
+
+Version 0.3.3 - 16.Jan.2012
+* Add MPEG-2, MPEG-4 and VC-1 decoders (based on codecparsers)
+* Add support for GstXOverlay::set_render_rectangle() in vaapisink
+* Fix memory leak of GL texture (Nicolas Dufresne)
+* Fix vaapisink to automatically fit video to window
+* Fix vaapiupload to only set caps on newly created buffers (Nicolas Dufresne)
+* Fix gst_vaapi_ensure_display() to honour DISPLAY environment variable
+
+Version 0.3.2 - 06.Jan.2012
+* Rename vaapiconvert element to vaapiupload
+* Fix vaapiupload from NV12 buffers
+* Fix possible leaks of VA surfaces in FFmpeg decoder
+* Fix memory leak in vaapiupload initialization function
+* Fix possible crash in vaapidecode deinitialization code
+* Add vaapidownload element to convert from VA surfaces to YUV pixels
+
+Version 0.3.1 - 16.Dec.2011
+* Fix check for supported VA images
+* Add support for partial VA image updates
+* Add support for new subtitle/overlay infrastructure (Thibault Saunier)
+* Add missing video context queries in vaapisink/vaapiconvert (Nicolas Dufresne)
+
+Version 0.3.0 - 09.Dec.2011
+* Group all plugins into the same bundle
+* Use new XOverlay API (Sreerenj Balachandran)
+* Use new GstVideoContext and GstSurfaceBuffer API (Nicolas Dufresne)
+* Fix vaapidecode sink caps if decoder is in NULL state (Sreerenj Balachandran)
+* Fix auto-plugging and downstream buffer allocation (Nicolas Dufresne)
+* Fix crash in VA display init if no VA configs were found (Nicolas Dufresne)
+
+Version 0.2.7 - 07.Dec.2011
+* Relicense plugins and tests to LGPL v2.1 (SDS)
+* Fix MPEG-2 decoding from TS & PS streams
+* Fix build with newer versions of FFmpeg
+* Fix vaapiconvert direct-rendering modes
+* Fix use of invalid data at the end-of-stream
+
+Version 0.2.6 - 14.Jun.2011
+* Fix licensing terms (LGPL v2.1)
+
+Version 0.2.5 - 20.Jul.2010
+* Fix build with older VA-API 0.29-sds
+* Fix decoding of some H.264 streams. e.g. Ice Age 2 trailer
+* Fix VA/GLX support with texture-from-pixmap and GLX version < 1.3
+
+Version 0.2.4 - 18.May.2010
+* Fix video rendering rect within an embedder window (Totem)
+* Disable GLX rendering when vaapisink uses a foreign X window
+
+Version 0.2.3 - 16.May.2010
+* Fix memory leak of encoded buffers
+* Fix decoder caps to report codec aliases
+* Fix VC-1 decoding through the playbin2 pipeline
+
+Version 0.2.2 - 14.May.2010
+* Fix packaging dependencies
+* Fix a crash in the FFmpeg decoder on close
+* Fix OpenGL texture internal format (Clutter)
+* Fix foreign window size for embedding (Totem)
+
+Version 0.2.1 - 12.May.2010
+* Fix integration within the playbin2 pipeline
+* Fix vaapidecode to expose the HW supported caps only
+* Add GstXOverlay interface to vaapisink (Totem media player)
+
+Version 0.2.0 - 05.May.2010
+* Relicense gst-libs/ code to LGPL v2.1+
+* Add FFmpeg/VAAPI decoder for the new `vaapidecode' element
+
+Version 0.1.2 - 30.Mar.2010
+* Add AYUV image format
+* Add compatibility with the original VA-API 0.29
+* Add OpenGL support through VA/GLX extensions or TFP+FBO fallback
+
+Version 0.1.1 - 23.Mar.2010
+* Document public API for libgstvaapi-*.so.*
+* Optimize `vaapiconvert' pipeline (direct-rendering)
+* Allow `vaapisink` to render videos in fullscreen mode
+
+Version 0.1.0 - 16.Mar.2010
 * Initial release
diff --git a/README b/README
index 3dcad3f..3c1e078 100644 (file)
--- a/README
+++ b/README
@@ -1,26 +1,88 @@
 
-  gst-vaapi
-  VA API support to GStreamer
+  gstreamer-vaapi
+  VA-API support to GStreamer
 
-  Copyright (C) 2010 Splitted-Desktop Systems
+  Copyright (C) 2010-2011 Splitted-Desktop Systems
+  Copyright (C) 2011-2012 Intel Corporation
+  Copyright (C) 2011 Collabora Ltd.
 
 
 License
 -------
 
-gst-vaapi is available under the terms of the GNU General Public
-License.
-
+gstreamer-vaapi helper libraries and plugin elements are available
+under the terms of the GNU Lesser General Public License v2.1+
 
 Overview
 --------
 
-gst-vaapi consists in a VA API based videosink for GStreamer and
-helper libraries.
+gstreamer-vaapi consists in a collection of VA-API based plugins for
+GStreamer and helper libraries.
+
+  * `vaapidecode' is used to decode MPEG-2, MPEG-4, H.264, VC-1, WMV3
+    videos to video/x-vaapi-surfaces surfaces, depending on the
+    underlying HW capabilities.
+
+  * `vaapiupload' is used to convert from video/x-raw-yuv pixels to
+    video/x-vaapi-surface surfaces.
+
+  * `vaapidownload' is used to convert from video/x-vaapi-surface
+    surfaces to video/x-raw-yuv pixels.
+
+  * `vaapipostproc' is used to postprocess video/x-vaapi-surface
+    surfaces, for e.g. deinterlacing.
+
+  * `vaapisink' is used to display video/x-vaapi-surface surfaces to
+    screen.
+
+
+Features
+--------
+
+  * VA-API support from 0.29 to 0.32
+  * MPEG-2, MPEG-4, H.264 and VC-1 ad-hoc decoders
+  * OpenGL rendering through VA/GLX or GLX texture-from-pixmap + FBO
+  * Support for major HW video decoding solutions on Linux (AMD, Intel, NVIDIA)
 
 
 Requirements
 ------------
 
-gstreamer-0.10 >= 0.10.0
-gstreamer-plugins-base-0.10 >= 0.10.0
+Software requirements
+
+  * libva-dev >= 1.0.3 (VA/GLX)
+  * libgstreamer0.10-dev >= 0.10.35.1
+      or with GstBaseSink::query()
+  * libgstreamer-plugins-base0.10-dev >= 0.10.35
+  * libgstreamer-plugins-bad0.10-dev >= 0.10.22.1
+      or with GstVideoContext, GstSurfaceBuffer, codecparsers
+
+  If codecparsers-based decoders are not used:
+
+  * libavcodec-dev >= 0.6
+      or with <libavcodec/vaapi.h>
+
+Hardware requirements
+
+  * AMD platforms with UVD2 (XvBA supported)
+  * Intel Eaglelake (G45)
+  * Intel Ironlake, Sandy Bridge and Ivy Bridge (HD Graphics)
+  * Intel Poulsbo (US15W)
+  * Intel Medfield or Cedar Trail
+  * NVIDIA platforms with PureVideo (VDPAU supported)
+
+
+Usage
+-----
+
+  VA elements are automatically plugged into GStreamer pipelines. So,
+  using playbin2 should work as is. However, here are a few alternate
+  pipelines constructed manually.
+
+  * Play an H.264 video with an MP4 container in fullscreen mode
+  $ gst-launch-0.10 -v filesrc location=/path/to/video.mp4 ! \
+      qtdemux ! vaapidecode ! vaapisink fullscreen=true
+
+  * Play a raw MPEG-2 interlaced stream
+  $ gst-launch-0.10 -v filesrc location=/path/to/mpeg2.bits ! \
+      mpegvideoparse ! vaapidecode ! vaapipostproc ! vaapisink
index 9c2f4f6..920e77e 100755 (executable)
@@ -1,3 +1,38 @@
-#! /bin/sh
-autoreconf -v --install
-./configure "$@"
+#!/bin/sh
+
+PROJECT="gstreamer-vaapi"
+
+test -n "$srcdir" || srcdir="`dirname \"$0\"`"
+test -n "$srcdir" || srcdir=.
+
+if ! test -f "$srcdir/configure.ac"; then
+    echo "Failed to find the top-level $PROJECT directory"
+    exit 1
+fi
+
+olddir="`pwd`"
+cd "$srcdir"
+
+mkdir -p m4
+
+GTKDOCIZE=`which gtkdocize`
+if test -z $GTKDOCIZE; then
+    echo "*** No gtk-doc support ***"
+    echo "EXTRA_DIST =" > gtk-doc.make
+else
+    gtkdocize || exit $?
+fi
+
+AUTORECONF=`which autoreconf`
+if test -z $AUTORECONF; then
+    echo "*** No autoreconf found ***"
+    exit 1
+else
+    autoreconf -v --install || exit $?
+fi
+
+cd "$olddir"
+
+if test -z "$NO_CONFIGURE"; then
+    $srcdir/configure "$@" && echo "Now type 'make' to compile $PROJECT."
+fi
index 08c64a5..8ced37f 100644 (file)
@@ -1,7 +1,27 @@
+# gstreamer-vaapi package version number
+m4_define([gst_vaapi_major_version], [0])
+m4_define([gst_vaapi_minor_version], [4])
+m4_define([gst_vaapi_micro_version], [0])
+m4_define([gst_vaapi_pre_version],   [1])
+m4_define([gst_vaapi_version],
+          [gst_vaapi_major_version.gst_vaapi_minor_version.gst_vaapi_micro_version])
+m4_if(gst_vaapi_pre_version, [0], [], [
+m4_append([gst_vaapi_version], gst_vaapi_pre_version, [.pre])
+])
+
+# glib version number
+m4_define([glib_major_version], [2])
+m4_define([glib_minor_version], [28])
+m4_define([glib_micro_version], [0])
+m4_define([glib_major_minor_version],
+          [glib_major_version.glib_minor_version])
+m4_define([glib_version],
+          [glib_major_version.glib_minor_version.glib_micro_version])
+
 # gst version number
 m4_define([gst_major_version], [0])
 m4_define([gst_minor_version], [10])
-m4_define([gst_micro_version], [0])
+m4_define([gst_micro_version], [14])
 m4_define([gst_major_minor_version],
           [gst_major_version.gst_minor_version])
 m4_define([gst_version],
@@ -10,49 +30,252 @@ m4_define([gst_version],
 # gst plugins-base version number
 m4_define([gst_plugins_base_major_version], [0])
 m4_define([gst_plugins_base_minor_version], [10])
-m4_define([gst_plugins_base_micro_version], [0])
+m4_define([gst_plugins_base_micro_version], [31])
 m4_define([gst_plugins_base_version],
           [gst_plugins_base_major_version.gst_plugins_base_minor_version.gst_plugins_base_micro_version])
 
-# gst_vaapi package version number
-m4_define([gst_vaapi_major_version], [0])
-m4_define([gst_vaapi_minor_version], [1])
-m4_define([gst_vaapi_micro_version], [0])
-m4_define([gst_vaapi_version],
-          [gst_vaapi_major_version.gst_vaapi_minor_version.gst_vaapi_micro_version])
+# gst plugins-bad version number
+m4_define([gst_plugins_bad_major_version], [0])
+m4_define([gst_plugins_bad_minor_version], [10])
+m4_define([gst_plugins_bad_micro_version], [22])
+m4_define([gst_plugins_bad_version],
+          [gst_plugins_bad_major_version.gst_plugins_bad_minor_version.gst_plugins_bad_micro_version])
+
+# VA-API minimum version number
+m4_define([va_api_version],     [0.30.4])
+m4_define([va_api_drm_version], [0.34.0])
+m4_define([va_api_x11_version], [0.31.0])
+m4_define([va_api_glx_version], [0.32.0])
+m4_define([va_api_wld_version], [0.34.0])
+m4_define([va_api_tpi_version], [0.33.0])
+
+# libva package version number
+m4_define([libva_drm_package_version], [1.2.0])
+m4_define([libva_x11_package_version], [1.0.3])
+m4_define([libva_glx_package_version], [1.0.9])
+m4_define([libva_wld_package_version], [1.2.0])
 
-AC_PREREQ([2.57])
+# gtk-doc version number
+# XXX: introspection annotations require gtk-doc >= 1.12
+m4_define([gtkdoc_major_version], [1])
+m4_define([gtkdoc_minor_version], [9])
+m4_define([gtkdoc_version], [gtkdoc_major_version.gtkdoc_minor_version])
+
+AC_PREREQ([2.58])
 AC_INIT([gst_vaapi], [gst_vaapi_version],
-    [gbeauchesne@splitted-desktop.com],
+    [gwenole.beauchesne@intel.com],
     [gstreamer-vaapi])
+
+AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_SRCDIR([Makefile.am])
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_AUX_DIR([build-aux])
+
 AC_CANONICAL_TARGET
+
 AM_INIT_AUTOMAKE
-AM_CONFIG_HEADER([config.h])
+
+TODAY="`LC_ALL=C date +'%a, %d %b %Y %X %z'`"
+AC_SUBST(TODAY)
+
+GST_VAAPI_MAJOR_VERSION=gst_vaapi_major_version
+AC_SUBST(GST_VAAPI_MAJOR_VERSION)
+
+LIBVA_PACKAGE_VERSION=libva_x11_package_version
+AC_SUBST(LIBVA_PACKAGE_VERSION)
 
 dnl Versions for GStreamer and plugins-base
 GST_MAJORMINOR=gst_major_minor_version
 GST_VERSION_REQUIRED=gst_version
 GST_PLUGINS_BASE_VERSION_REQUIRED=gst_plugins_base_version
+GST_PLUGINS_BAD_VERSION_REQUIRED=gst_plugins_bad_version
 AC_SUBST(GST_MAJORMINOR)
+AC_SUBST(GST_VERSION_REQUIRED)
+AC_SUBST(GST_PLUGINS_BASE_VERSION_REQUIRED)
+AC_SUBST(GST_PLUGINS_BAD_VERSION_REQUIRED)
+
+dnl Use pretty build output with automake >= 1.11
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])], [
+  AM_DEFAULT_VERBOSITY=1
+  AC_SUBST(AM_DEFAULT_VERBOSITY)
+])
 
 dnl Check for tools
 AC_PROG_CC
-AC_PROG_LIBTOOL
+AM_PROG_CC_C_O
+
+dnl Initialize libtool
+LT_PREREQ([2.2])
+LT_INIT
+
+AC_ARG_ENABLE(drm,
+    AS_HELP_STRING([--enable-drm],
+                   [enable DRM backend @<:@default=yes@:>@]),
+    [], [enable_drm="yes"])
+
+AC_ARG_ENABLE(x11,
+    AS_HELP_STRING([--enable-x11],
+                   [enable X11 output @<:@default=yes@:>@]),
+    [], [enable_x11="yes"])
+
+AC_ARG_ENABLE(glx,
+    AS_HELP_STRING([--enable-glx],
+                   [enable OpenGL/X11 output @<:@default=yes@:>@]),
+    [], [enable_glx="yes"])
 
-dnl Check for GStreamer
-PKG_CHECK_MODULES([GST],
-    [gstreamer-$GST_MAJORMINOR >= $GST_VERSION_REQUIRED]
-)
-AC_SUBST(GST_CFLAGS)
-AC_SUBST(GST_LIBS)
+AC_ARG_ENABLE(wayland,
+    AC_HELP_STRING([--enable-wayland],
+                   [enable Wayland output @<:@default=yes@:>@]),
+    [], [enable_wayland="yes"])
 
-dnl Check for GStreamer plugins-base
+AC_ARG_ENABLE(encoders,
+    AC_HELP_STRING([--enable-encoders],
+                   [enable encoders @<:@default=no@:>@]),
+    [], [enable_encoders="no"])
+
+dnl Check for basic libraries
+AC_CHECK_LIB(m, tan)
+
+dnl Check for Gtk doc
+GTKDOC_VERSION=gtkdoc_version
+# gtkdocize greps for '^GTK_DOC_CHECK', so it needs to be on its own line
+m4_ifdef([GTK_DOC_CHECK], [
+GTK_DOC_CHECK([$GTKDOC_VERSION], [--flavour no-tmpl])], [
+AM_CONDITIONAL([ENABLE_GTK_DOC], [false])])
+AC_SUBST(GTKDOC_VERSION)
+
+dnl Check for GLib
+GLIB_VERSION_REQUIRED=glib_version
+PKG_CHECK_MODULES([GLIB], [glib-2.0 >= $GLIB_VERSION_REQUIRED])
+AC_SUBST(GLIB_VERSION_REQUIRED)
+
+dnl ---------------------------------------------------------------------------
+dnl -- GStreamer                                                             --
+dnl ---------------------------------------------------------------------------
+
+dnl GStreamer Core
+PKG_CHECK_MODULES([GST],      [gstreamer-$GST_MAJORMINOR >= gst_version])
+PKG_CHECK_MODULES([GST_BASE], [gstreamer-base-$GST_MAJORMINOR >= gst_version])
+
+AC_CACHE_CHECK([for GstBaseSink::query hook], ac_cv_have_gst_base_sink_query, [
+    saved_CFLAGS="$CFLAGS"
+    CFLAGS="$CFLAGS $GST_BASE_CFLAGS"
+    saved_LIBS="$LIBS"
+    LIBS="$LIBS $GST_BASE_LIBS"
+    AC_COMPILE_IFELSE(
+        [AC_LANG_PROGRAM(
+            [[#include <gst/base/gstbasesink.h>]],
+            [[GstBaseSinkClass klass; klass.query = NULL;]])],
+        [ac_cv_have_gst_base_sink_query="yes"],
+        [ac_cv_have_gst_base_sink_query="no"]
+    )
+    CFLAGS="$saved_CFLAGS"
+    LIBS="$saved_LIBS"
+])
+if test "$ac_cv_have_gst_base_sink_query" != "yes"; then
+    AC_MSG_ERROR([GstBaseSink does not contain the 'query' vfunc])
+fi
+
+dnl GStreamer -base plugins
 PKG_CHECK_MODULES([GST_PLUGINS_BASE],
-    [gstreamer-plugins-base-$GST_MAJORMINOR >= $GST_PLUGINS_BASE_VERSION_REQUIRED]
-)
-AC_SUBST(GST_PLUGINS_BASE_CFLAGS)
-AC_SUBST(GST_PLUGINS_BASE_LIBS)
+    [gstreamer-plugins-base-$GST_MAJORMINOR >= gst_plugins_base_version])
+PKG_CHECK_MODULES([GST_INTERFACES],
+    [gstreamer-interfaces-$GST_MAJORMINOR >= gst_plugins_base_version])
+
+dnl ... GstVideoOverlayComposition (gstreamer-video)
+PKG_CHECK_MODULES([GST_VIDEO],
+    [gstreamer-video-$GST_MAJORMINOR >= gst_plugins_base_version])
+
+AC_CACHE_CHECK([for GstVideoOverlayComposition],
+    ac_cv_have_gst_video_overlay_composition, [
+    saved_CFLAGS="$CFLAGS"
+    CFLAGS="$CFLAGS $GST_CFLAGS"
+    saved_LIBS="$LIBS"
+    LIBS="$LIBS $GST_LIBS"
+    AC_COMPILE_IFELSE(
+        [AC_LANG_PROGRAM(
+            [[#include <gst/video/video-overlay-composition.h>]],
+            [[GstVideoOverlayComposition *c = gst_video_overlay_composition_new(0);]])],
+        [ac_cv_have_gst_video_overlay_composition="yes"],
+        [ac_cv_have_gst_video_overlay_composition="no"]
+    )
+    CFLAGS="$saved_CFLAGS"
+    LIBS="$saved_LIBS"
+])
+if test "$ac_cv_have_gst_video_overlay_composition" != "yes"; then
+    AC_MSG_ERROR([GstVideoOverlayComposition is not available])
+fi
+
+dnl GStreamer -bad plugins
+PKG_CHECK_MODULES([GST_BASEVIDEO],
+    [gstreamer-basevideo-$GST_MAJORMINOR >= gst_plugins_bad_version])
+
+dnl ... bitstream parsers
+USE_CODEC_PARSERS=1
+USE_LOCAL_CODEC_PARSERS=0
+
+PKG_CHECK_MODULES([GST_CODEC_PARSERS],
+    [gstreamer-codecparsers-$GST_MAJORMINOR >= gst_plugins_bad_version])
+
+dnl ... 0.10.23 addition, could be implemented otherwise
+AC_CACHE_CHECK([for GstH264SliceHdr::n_emulation_prevention_bytes],
+    ac_cv_have_gst_h264_slice_hdr_epb_count, [
+    saved_CFLAGS="$CFLAGS"
+    CFLAGS="$CFLAGS $GST_CFLAGS $GST_CODEC_PARSERS_CFLAGS"
+    saved_LIBS="$LIBS"
+    LIBS="$LIBS $GST_LIBS $GST_CODEC_PARSERS_LIBS"
+    AC_COMPILE_IFELSE(
+        [AC_LANG_PROGRAM(
+            [[#include <gst/codecparsers/gsth264parser.h>]],
+            [[GstH264SliceHdr slice_hdr;
+              slice_hdr.n_emulation_prevention_bytes = 0;]])],
+        [ac_cv_have_gst_h264_slice_hdr_epb_count="yes"],
+        [ac_cv_have_gst_h264_slice_hdr_epb_count="no"]
+    )
+    CFLAGS="$saved_CFLAGS"
+    LIBS="$saved_LIBS"
+])
+
+if test "$ac_cv_have_gst_h264_slice_hdr_epb_count" = "yes"; then
+    AC_DEFINE_UNQUOTED(HAVE_GST_H264_SLICE_HDR_EPB_COUNT, 1,
+        [Defined to 1 if GstH264SliceHdr::n_emulation_prevention_bytes exists.])
+fi
+
+dnl ... JPEG parser, not upstream yet
+AC_CACHE_CHECK([for JPEG parser],
+    ac_cv_have_gst_jpeg_parser, [
+    saved_CFLAGS="$CFLAGS"
+    CFLAGS="$CFLAGS $GST_CFLAGS $GST_CODEC_PARSERS_CFLAGS"
+    saved_LIBS="$LIBS"
+    LIBS="$LIBS $GST_LIBS $GST_CODEC_PARSERS_LIBS"
+    AC_COMPILE_IFELSE(
+        [AC_LANG_PROGRAM(
+            [[#include <gst/codecparsers/gstjpegparser.h>]],
+            [[GstJpegImage jpeg_image;]])],
+        [ac_cv_have_gst_jpeg_parser="yes"],
+        [ac_cv_have_gst_jpeg_parser="no" USE_LOCAL_CODEC_PARSERS=1]
+    )
+    CFLAGS="$saved_CFLAGS"
+    LIBS="$saved_LIBS"
+])
+
+if test "$ac_cv_have_gst_jpeg_parser" = "yes"; then
+    AC_DEFINE_UNQUOTED(HAVE_GST_JPEG_PARSER, 1,
+        [Defined to 1 if JPEG parser exists.])
+fi
+AM_CONDITIONAL(USE_LOCAL_CODEC_PARSERS, test $USE_LOCAL_CODEC_PARSERS -eq 1)
+
+dnl GST_ALL_LDFLAGS:
+dnl LDFLAGS really should only contain flags, not libs - they get added before
+dnl whatevertarget_LIBS and -L flags here affect the rest of the linking
+GST_ALL_LDFLAGS="-no-undefined"
+AC_SUBST(GST_ALL_LDFLAGS)
+
+dnl GST_PLUGIN_LDFLAGS:
+dnl this really should only contain flags, not libs - they get added before
+dnl whatevertarget_LIBS and -L flags here affect the rest of the linking
+GST_PLUGIN_LDFLAGS="-module -avoid-version -export-symbols-regex '^([_]*gst_plugin_desc|gst_.*_get_type)\$\$' $GST_ALL_LDFLAGS"
+AC_SUBST(GST_PLUGIN_LDFLAGS)
 
 dnl Check for the GStreamer plugins directory
 AC_MSG_CHECKING([for GStreamer plugins directory])
@@ -65,48 +288,314 @@ AC_MSG_RESULT([$GST_PLUGINS_DIR])
 plugindir="$GST_PLUGINS_DIR"
 AC_SUBST(plugindir)
 
-dnl Check for VA API
-PKG_CHECK_MODULES(LIBVA_DEPS, [libva])
-PKG_CHECK_MODULES(LIBVA_X11_DEPS, [libva-x11])
-
-dnl Check for SDS extensions to VA API
-AC_CACHE_CHECK([for VA API],
-  ac_cv_libva_sds_extensions, [
-  saved_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS $LIBVA_DEPS_CFLAGS"
-  AC_TRY_COMPILE([
-    #include <va/va_version.h>
-    #if VA_MAJOR_VERSION == 0 && VA_MINOR_VERSION == 29
-    # if !defined(VA_SDS_VERSION) || (VA_SDS_VERSION < $LIBVA_SDS_VERSION_0_29)
-    #  error "VA API version >= 0.29.0-sds$LIBVA_SDS_VERSION_0_29 is required"
-    # endif
-    #elif VA_MAJOR_VERSION == 0 && VA_MINOR_VERSION == 30
-    # if !defined(VA_SDS_VERSION) || (VA_SDS_VERSION < $LIBVA_SDS_VERSION_0_30)
-    #  error "VA API version >= 0.30.0-sds$LIBVA_SDS_VERSION_0_30 is required"
-    # endif
-    #elif !VA_CHECK_VERSION(0,31,0)
-    # error "VA API version >= 0.31 is required"
-    #endif
-  ], [],
-  [ac_cv_libva_sds_extensions="yes"],
-  [ac_cv_libva_sds_extensions="no"])
-  CFLAGS="$saved_CFLAGS"
-])
+dnl ---------------------------------------------------------------------------
+dnl -- Renderers                                                             --
+dnl ---------------------------------------------------------------------------
+
+dnl Check for DRM/libudev
+USE_DRM=0
+if test "$enable_drm" = "yes"; then
+    PKG_CHECK_MODULES(DRM, [libdrm], [USE_DRM=1], [USE_DRM=0])
+    PKG_CHECK_MODULES(UDEV, [libudev], [:], [USE_DRM=0])
+
+    if test $USE_DRM -eq 1; then
+        saved_CPPFLAGS="$CPPFLAGS"
+        CPPFLAGS="$CPPFLAGS $DRM_CFLAGS"
+        AC_CHECK_HEADERS([drm_fourcc.h], [:], [USE_DRM=0])
+        CPPFLAGS="$saved_CPPFLAGS"
+    fi
+fi
+
+dnl Check for X11
+USE_X11=0
+if test "$enable_x11" = "yes"; then
+    PKG_CHECK_MODULES(X11, [x11], [USE_X11=1], [USE_X11=0])
+    if test $USE_X11 -eq 1; then
+        saved_CPPFLAGS="$CPPFLAGS"
+        CPPFLAGS="$CPPFLAGS $X11_CFLAGS"
+        AC_CHECK_HEADERS([X11/Xlib.h X11/Xutil.h X11/Xatom.h], [:], [USE_X11=0])
+        CPPFLAGS="$saved_CPPFLAGS"
+    fi
+fi
+
+dnl Check for XRandR
+HAVE_XRANDR=0
+if test $USE_X11 -eq 1; then
+    HAVE_XRANDR=1
+    PKG_CHECK_MODULES([XRANDR], [xrandr], [:], [HAVE_XRANDR=0])
+    if test $HAVE_XRANDR -eq 1; then
+        saved_CPPFLAGS="$CPPFLAGS"
+        CPPFLAGS="$CPPFLAGS $XRANDR_CFLAGS"
+        AC_CHECK_HEADERS([X11/extensions/Xrandr.h], [:], [HAVE_XRANDR=0])
+        CPPFLAGS="$saved_CPPFLAGS"
+    fi
+fi
+if test $HAVE_XRANDR -eq 1; then
+    AC_DEFINE_UNQUOTED(HAVE_XRANDR, 1,
+        [Defined to 1 if the XRandR extension exists.])
+fi
+
+dnl OpenGL
+enable_opengl="no"
+if test "$enable_glx" = "yes"; then
+    enable_opengl="yes"
+fi
+
+HAVE_GL=0
+if test "$enable_opengl" = "yes"; then
+    HAVE_GL=1
+    PKG_CHECK_MODULES([GL], [gl], [:], [HAVE_GL=0])
+    saved_CPPFLAGS="$CPPFLAGS"
+    CPPFLAGS="$CPPFLAGS $GL_CFLAGS"
+    AC_CHECK_HEADERS([GL/gl.h GL/glext.h], [:], [HAVE_GL=0], [
+#ifdef HAVE_GL_GL_H
+# include <GL/gl.h>
+#endif
+    ])
+    CPPFLAGS="$saved_CPPFLAGS"
+fi
+
+dnl Check for encoders
+USE_ENCODERS=0
+if test "$enable_encoders" = "yes"; then
+    USE_ENCODERS=1
+fi
+
+AC_DEFINE_UNQUOTED(USE_ENCODERS, $USE_ENCODERS,
+    [Defined to 1 if GStreamer Vaapi Encoder are used])
+AM_CONDITIONAL(USE_ENCODERS, test $USE_ENCODERS -eq 1)
+
+dnl ... GLX
+USE_GLX=0
+if test "$enable_glx" = "yes" -a $HAVE_GL -eq 1 -a $USE_X11 -eq 1; then
+    USE_GLX=1
+    saved_CPPFLAGS="$CPPFLAGS"
+    saved_LIBS="$LIBS"
+    CPPFLAGS="$CPPFLAGS $GL_CFLAGS"
+    LIBS="$LIBS $GL_LIBS"
+    AC_CHECK_HEADERS([GL/glx.h], [:], [USE_GLX=0], [
+#ifdef HAVE_GL_GL_H
+# include <GL/gl.h>
+#endif
+    ])
+    AC_CHECK_LIB([GL], [glXCreateContext], [:], [USE_GLX=0])
+    CPPFLAGS="$saved_CPPFLAGS"
+    LIBS="$saved_LIBS"
+fi
+
+dnl Check for Wayland
+USE_WAYLAND=0
+if test "$enable_wayland" = "yes"; then
+    PKG_CHECK_MODULES(WAYLAND, [wayland-client],
+        [USE_WAYLAND=1], [USE_WAYLAND=0])
+
+    if test $USE_WAYLAND -eq 1; then
+        saved_CPPFLAGS="$CPPFLAGS"
+        CPPFLAGS="$CPPFLAGS $WAYLAND_CFLAGS"
+        AC_CHECK_HEADERS([wayland-client.h], [:], [USE_WAYLAND=0])
+        CPPFLAGS="$saved_CPPFLAGS"
+    fi
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl -- VA-API                                                                --
+dnl ---------------------------------------------------------------------------
+
+dnl Core API
+LIBVA_PKGNAME="libva"
+PKG_CHECK_MODULES(LIBVA, [$LIBVA_PKGNAME >= va_api_version])
+AC_SUBST(LIBVA_PKGNAME)
+
+LIBVA_TPI_PKGNAME="libva-tpi"
+PKG_CHECK_MODULES(LIBVA_TPI, [$LIBVA_TPI_PKGNAME >= va_api_tpi_version])
+AC_SUBST(LIBVA_TPI_PKGNAME)
+
 VA_VERSION=`$PKG_CONFIG --modversion libva`
 VA_MAJOR_VERSION=`echo "$VA_VERSION" | cut -d'.' -f1`
 VA_MINOR_VERSION=`echo "$VA_VERSION" | cut -d'.' -f2`
-VA_DRIVER_INIT_FUNC="__vaDriverInit_${VA_MAJOR_VERSION}_${VA_MINOR_VERSION}_sds"
-if test "$ac_cv_libva_sds_extensions" = "yes"; then
-    AC_DEFINE_UNQUOTED([VA_DRIVER_INIT_FUNC], [$VA_DRIVER_INIT_FUNC], [Define driver entry-point])
-else
-    AC_MSG_ERROR([Your VA API SDK does not include SDS extensions])
+VA_MICRO_VERSION=`echo "$VA_VERSION" | cut -d'.' -f3`
+VA_VERSION_STR="$VA_VERSION"
+
+dnl VA/DRM API
+if test "$enable_drm" = "yes"; then
+    PKG_CHECK_MODULES([LIBVA_DRM], [libva-drm >= va_api_drm_version],
+        [:], [USE_DRM=0])
+fi
+
+dnl VA/X11 API
+HAVE_VA_X11=0
+LIBVA_X11_PKGNAME="libva-x11"
+if test $USE_X11 -eq 1; then
+    PKG_CHECK_MODULES(LIBVA_X11, [$LIBVA_X11_PKGNAME >= va_api_x11_version],
+        [HAVE_VA_X11=1], [USE_X11=0])
+fi
+AC_SUBST(LIBVA_X11_PKGNAME)
+
+dnl VA/GLX API
+HAVE_VA_GLX=0
+LIBVA_GLX_PKGNAME="libva-glx"
+if test $USE_GLX -eq 1; then
+    PKG_CHECK_MODULES(LIBVA_GLX, [$LIBVA_GLX_PKGNAME >= va_api_glx_version],
+        [HAVE_VA_GLX=1], [LIBVA_GLX_PKGNAME="$LIBVA_X11_PKGNAME"])
+
+    if test $HAVE_VA_GLX -eq 1; then
+        saved_CPPFLAGS="$CPPFLAGS"
+        CPPFLAGS="$LIBVA_GLX_CPPFLAGS"
+        AC_CHECK_HEADERS([va/va_glx.h], [:], [HAVE_VA_GLX=0])
+        CPPFLAGS="$saved_CPPFLAGS"
+    fi
 fi
+AC_SUBST(LIBVA_GLX_PKGNAME)
 
-AC_OUTPUT([
+dnl Check for JPEG decoding API (0.32.1+)
+USE_JPEG_DECODER=0
+AC_CACHE_CHECK([for JPEG decoding API],
+    ac_cv_have_jpeg_decoding_api, [
+    saved_CFLAGS="$CFLAGS"
+    CFLAGS="$CFLAGS $LIBVA_CFLAGS"
+    saved_LIBS="$LIBS"
+    LIBS="$CFLAGS $LIBVA_LIBS"
+    AC_COMPILE_IFELSE(
+        [AC_LANG_PROGRAM(
+            [[#include <va/va.h>]],
+            [[VAPictureParameterBufferJPEGBaseline pic_param;
+              VASliceParameterBufferJPEGBaseline slice_param;
+              VAHuffmanTableBufferJPEGBaseline huffman_table;
+              VAIQMatrixBufferJPEGBaseline iq_matrix;]])],
+        [ac_cv_have_jpeg_decoding_api="yes" USE_JPEG_DECODER=1],
+        [ac_cv_have_jpeg_decoding_api="no"]
+    )
+    CFLAGS="$saved_CFLAGS"
+    LIBS="$saved_LIBS"
+])
+
+dnl Check libva old H.264 encoder API
+HAVE_OLD_H264_ENCODER=0
+AC_CACHE_CHECK([for H264 encoder old structures],
+    ac_cv_have_old_h264_encoder, [
+       saved_CFLAGS="$CFLAGS"
+       CFLAGS="$CFLAGS $LIBVA_CFLAGS"
+       saved_LIBS="$LIBS"
+       LIBS="$CFLAGS $LIBVA_LIBS"
+    AC_COMPILE_IFELSE(
+        [AC_LANG_PROGRAM(
+            [[#include <va/va_enc_h264.h>]],
+            [[VAEncSequenceParameterBufferH264 seq;
+              seq.seq_fields.value = 0;
+                         seq.vui_fields.value = 0;]])],
+        [ac_cv_have_old_h264_encoder="no" HAVE_OLD_H264_ENCODER=0],
+        [ac_cv_have_old_h264_encoder="yes" HAVE_OLD_H264_ENCODER=1]
+    )
+    CFLAGS="$saved_CFLAGS"
+    LIBS="$saved_LIBS"
+])
+
+AC_DEFINE_UNQUOTED(HAVE_OLD_H264_ENCODER, $HAVE_OLD_H264_ENCODER,
+    [Defined to 1 if old h264 encoder API exists.])
+
+dnl VA/Wayland API
+if test "$enable_wayland" = "yes"; then
+    PKG_CHECK_MODULES([LIBVA_WAYLAND], [libva-wayland >= va_api_wld_version],
+        [:], [USE_WAYLAND=0])
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl -- Generate files and summary                                            --
+dnl ---------------------------------------------------------------------------
+
+case ":$USE_X11:$USE_GLX:$USE_WAYLAND:$USE_DRM:" in
+*:1:*)
+    ;;
+*)
+    AC_MSG_ERROR([No renderer is enabled])
+    ;;
+esac
+
+AC_DEFINE_UNQUOTED(USE_JPEG_DECODER, $USE_JPEG_DECODER,
+    [Defined to 1 if JPEG decoder is used])
+AM_CONDITIONAL(USE_JPEG_DECODER, test $USE_JPEG_DECODER -eq 1)
+
+AC_DEFINE_UNQUOTED(USE_DRM, $USE_DRM,
+    [Defined to 1 if DRM is enabled])
+AM_CONDITIONAL(USE_DRM, test $USE_DRM -eq 1)
+
+AC_DEFINE_UNQUOTED(USE_X11, $USE_X11,
+    [Defined to 1 if X11 is enabled])
+AM_CONDITIONAL(USE_X11, test $USE_X11 -eq 1)
+
+AC_DEFINE_UNQUOTED(USE_GLX, $USE_GLX,
+    [Defined to 1 if GLX is enabled])
+AM_CONDITIONAL(USE_GLX, test $USE_GLX -eq 1)
+
+AC_DEFINE_UNQUOTED(USE_WAYLAND, $USE_WAYLAND,
+    [Defined to 1 if WAYLAND is enabled])
+AM_CONDITIONAL(USE_WAYLAND, test $USE_WAYLAND -eq 1)
+
+pkgconfigdir=${libdir}/pkgconfig
+AC_SUBST(pkgconfigdir)
+
+AC_CONFIG_FILES([
     Makefile
+    debian.upstream/Makefile
+    debian.upstream/changelog
+    debian.upstream/control
+    debian.upstream/gstreamer$GST_MAJORMINOR-vaapi-doc.install:\
+debian.upstream/gstreamer-vaapi-doc.install.in
+    debian.upstream/gstreamer$GST_MAJORMINOR-vaapi.install:\
+debian.upstream/gstreamer-vaapi.install.in
+    debian.upstream/libgstvaapi$GST_VAAPI_MAJOR_VERSION.install:\
+debian.upstream/libgstvaapi.install.in
+    debian.upstream/libgstvaapi-dev.install
+    debian.upstream/libgstvaapi-drm-$GST_VAAPI_MAJOR_VERSION.install:\
+debian.upstream/libgstvaapi-drm.install.in
+    debian.upstream/libgstvaapi-glx-$GST_VAAPI_MAJOR_VERSION.install:\
+debian.upstream/libgstvaapi-glx.install.in
+    debian.upstream/libgstvaapi-wayland-$GST_VAAPI_MAJOR_VERSION.install:\
+debian.upstream/libgstvaapi-wayland.install.in
+    debian.upstream/libgstvaapi-x11-$GST_VAAPI_MAJOR_VERSION.install:\
+debian.upstream/libgstvaapi-x11.install.in
+    docs/Makefile
+    docs/reference/Makefile
+    docs/reference/libs/Makefile
+    docs/reference/libs/libs-docs.xml
+    docs/reference/plugins/Makefile
+    docs/reference/plugins/plugins-docs.xml
     gst-libs/Makefile
     gst-libs/gst/Makefile
+    gst-libs/gst/codecparsers/Makefile
     gst-libs/gst/vaapi/Makefile
-    sys/Makefile
-    sys/vaapi/Makefile
+    gst/Makefile
+    gst/vaapi/Makefile
+    pkgconfig/Makefile
+    pkgconfig/gstreamer-vaapi-$GST_MAJORMINOR.pc:\
+pkgconfig/gstreamer-vaapi.pc.in
+    pkgconfig/gstreamer-vaapi-drm-$GST_MAJORMINOR.pc:\
+pkgconfig/gstreamer-vaapi-drm.pc.in
+    pkgconfig/gstreamer-vaapi-glx-$GST_MAJORMINOR.pc:\
+pkgconfig/gstreamer-vaapi-glx.pc.in
+    pkgconfig/gstreamer-vaapi-wayland-$GST_MAJORMINOR.pc:\
+pkgconfig/gstreamer-vaapi-wayland.pc.in
+    pkgconfig/gstreamer-vaapi-x11-$GST_MAJORMINOR.pc:\
+pkgconfig/gstreamer-vaapi-x11.pc.in
+    tests/Makefile
 ])
+AC_OUTPUT
+
+dnl Print summary
+yesno() {
+    test $1 -eq 1 && echo yes || echo no
+}
+
+VIDEO_OUTPUTS=""
+AS_IF([test $USE_DRM -eq 1], [VIDEO_OUTPUTS="$VIDEO_OUTPUTS drm"])
+AS_IF([test $USE_X11 -eq 1], [VIDEO_OUTPUTS="$VIDEO_OUTPUTS x11"])
+AS_IF([test $USE_GLX -eq 1], [VIDEO_OUTPUTS="$VIDEO_OUTPUTS glx"])
+AS_IF([test $USE_WAYLAND -eq 1], [VIDEO_OUTPUTS="$VIDEO_OUTPUTS wayland"])
+
+echo
+echo $PACKAGE configuration summary:
+echo
+echo VA-API version ................... : $VA_VERSION_STR
+echo Video outputs .................... : $VIDEO_OUTPUTS
+echo VaapiEncoder support....... ...... : $(yesno $USE_ENCODERS)
+echo
diff --git a/debian.upstream/Makefile.am b/debian.upstream/Makefile.am
new file mode 100644 (file)
index 0000000..cacc519
--- /dev/null
@@ -0,0 +1,52 @@
+DOCS = \
+       AUTHORS         \
+       COPYING         \
+       COPYING.LIB     \
+       NEWS            \
+       README          \
+       $(NULL)
+
+DEBIANFILES = \
+       changelog                                               \
+       changelog.in                                            \
+       compat                                                  \
+       control                                                 \
+       control.in                                              \
+       copyright                                               \
+       gstreamer-vaapi.install.in                              \
+       gstreamer$(GST_MAJORMINOR)-vaapi.install                \
+       gstreamer-vaapi-doc.install.in                          \
+       gstreamer$(GST_MAJORMINOR)-vaapi-doc.install            \
+       libgstvaapi.install.in                                  \
+       libgstvaapi$(GST_VAAPI_MAJOR_VERSION).install           \
+       libgstvaapi-dev.install.in                              \
+       libgstvaapi-dev.install                                 \
+       libgstvaapi-drm.install.in                              \
+       libgstvaapi-drm-$(GST_VAAPI_MAJOR_VERSION).install      \
+       libgstvaapi-x11.install.in                              \
+       libgstvaapi-x11-$(GST_VAAPI_MAJOR_VERSION).install      \
+       libgstvaapi-glx.install.in                              \
+       libgstvaapi-glx-$(GST_VAAPI_MAJOR_VERSION).install      \
+       libgstvaapi-wayland.install.in                          \
+       libgstvaapi-wayland-$(GST_VAAPI_MAJOR_VERSION).install  \
+       rules                                                   \
+       $(NULL)
+
+DEBIANGENFILES = \
+       control                                                 \
+       changelog                                               \
+       gstreamer$(GST_MAJORMINOR)-vaapi.install                \
+       gstreamer$(GST_MAJORMINOR)-vaapi-doc.install            \
+       libgstvaapi$(GST_VAAPI_MAJOR_VERSION).install           \
+       libgstvaapi-dev.install                                 \
+       libgstvaapi-drm-$(GST_VAAPI_MAJOR_VERSION).install      \
+       libgstvaapi-x11-$(GST_VAAPI_MAJOR_VERSION).install      \
+       libgstvaapi-glx-$(GST_VAAPI_MAJOR_VERSION).install      \
+       libgstvaapi-wayland-$(GST_VAAPI_MAJOR_VERSION).install  \
+       $(NULL)
+
+EXTRA_DIST = \
+       $(DEBIANFILES)
+
+# Extra clean files so that maintainer-clean removes *everything*
+MAINTAINERCLEANFILES = Makefile.in $(DEBIANGENFILES)
diff --git a/debian.upstream/changelog.in b/debian.upstream/changelog.in
new file mode 100644 (file)
index 0000000..92f9d3d
--- /dev/null
@@ -0,0 +1,5 @@
+gstreamer@GST_MAJORMINOR@-vaapi (@PACKAGE_VERSION@-1) unstable; urgency=low
+
+  * Autogenerated package, see NEWS file for ChangeLog.
+
+ -- Gwenole Beauchesne <gwenole.beauchesne@intel.com>  @TODAY@
diff --git a/debian.upstream/compat b/debian.upstream/compat
new file mode 100644 (file)
index 0000000..7ed6ff8
--- /dev/null
@@ -0,0 +1 @@
+5
diff --git a/debian.upstream/control.in b/debian.upstream/control.in
new file mode 100644 (file)
index 0000000..960f72e
--- /dev/null
@@ -0,0 +1,99 @@
+Source: gstreamer@GST_MAJORMINOR@-vaapi
+Section: libs
+Priority: optional
+Maintainer: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
+Build-Depends: debhelper (>= 5),
+              cdbs,
+              libglib2.0-dev (>= @GLIB_VERSION_REQUIRED@),
+              libgstreamer@GST_MAJORMINOR@-dev (>= @GST_VERSION_REQUIRED@),
+              libgstreamer-plugins-base@GST_MAJORMINOR@-dev (>= @GST_PLUGINS_BASE_VERSION_REQUIRED@),
+              libva-dev (>= @LIBVA_PACKAGE_VERSION@)
+Build-Depends-Indep: gtk-doc-tools (>= @GTKDOC_VERSION@)
+Standards-Version: 3.7.2
+
+Package: gstreamer@GST_MAJORMINOR@-vaapi
+Section: libs
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Suggests: gstreamer@GST_MAJORMINOR@-vaapi-doc
+Description: VA-API plugins for GStreamer
+ This package contains GStreamer plugins for VA-API support:
+ - `vaapidecode': decode bitstreams using VA-API
+ - `vaapiupload': converts from YUV pixels to VA surfaces 
+ - `vaapidownload': convert from VA surfaces to YUV pixels
+ - `vaapipostproc': postprocess VA surfaces, e.g. deinterlacing
+ - `vaapisink': a VA-API based video sink
+
+Package: gstreamer@GST_MAJORMINOR@-vaapi-doc
+Architecture: all
+Section: doc
+Recommends: libgstvaapi@GST_VAAPI_MAJOR_VERSION@-dev (= ${source:Version})
+Description: GStreamer VA-API documentation and manuals
+ This packages contains documentation for libraries and elements.
+
+Package: gstreamer@GST_MAJORMINOR@-vaapi-dbg
+Section: libdevel
+Architecture: any
+Depends: gstreamer@GST_MAJORMINOR@-vaapi (= ${Source-Version})
+Description: VA-API plugins for GStreamer
+ VA-API support plugins for GStreamer.
+ .
+ This package contains the debug files.
+
+Package: libgstvaapi@GST_VAAPI_MAJOR_VERSION@
+Section: libs
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: GStreamer libraries from the "vaapi" set
+ VA-API support libraries for GStreamer.
+ .
+ This package contains common libraries for the "vaapi" set.
+
+Package: libgstvaapi-drm-@GST_VAAPI_MAJOR_VERSION@
+Section: libs
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: GStreamer libraries from the "vaapi" set
+ VA-API support libraries for GStreamer.
+ .
+ This package contains headless libraries for the "vaapi" set.
+
+Package: libgstvaapi-x11-@GST_VAAPI_MAJOR_VERSION@
+Section: libs
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: GStreamer libraries from the "vaapi" set
+ VA-API support libraries for GStreamer.
+ .
+ This package contains x11 libraries for the "vaapi" set.
+
+Package: libgstvaapi-glx-@GST_VAAPI_MAJOR_VERSION@
+Section: libs
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: GStreamer libraries from the "vaapi" set
+ VA-API support libraries for GStreamer.
+ .
+ This package contains glx libraries for the "vaapi" set.
+
+Package: libgstvaapi-wayland-@GST_VAAPI_MAJOR_VERSION@
+Section: libs
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: GStreamer libraries from the "vaapi" set
+ VA-API support libraries for GStreamer.
+ .
+ This package contains Wayland libraries for the "vaapi" set.
+
+Package: libgstvaapi-dev
+Architecture: any
+Section: libdevel
+Depends: ${shlibs:Depends}, ${misc:Depends},
+        libgstvaapi@GST_VAAPI_MAJOR_VERSION@ (= ${Source-Version}),
+        libgstvaapi-x11-@GST_VAAPI_MAJOR_VERSION@ (= ${Source-Version}),
+        libgstvaapi-glx-@GST_VAAPI_MAJOR_VERSION@ (= ${Source-Version})
+Description: GStreamer development files for libraries from the "vaapi" set
+ GStreamer/VA-API development files.
+ .
+ This package contains development files for GStreamer libraries for
+ the "vaapi" set.
diff --git a/debian.upstream/copyright b/debian.upstream/copyright
new file mode 100644 (file)
index 0000000..bb733ae
--- /dev/null
@@ -0,0 +1,35 @@
+This package is maintained by:
+Gwenole Beauchesne <gwenole.beauchesne@intel.com>
+
+Copyright:
+
+    gstreamer-vaapi helper libraries
+    and plugins elements: LGPL (v2.1 or later)
+
+License:
+
+    Copyright (C) 2010-2011, Splitted-Desktop Systems.
+    Copyright (C) 2011-2012, Intel Corporation.
+    Copyright (C) 2011, Collabora Ltd.
+
+    gstreamer-vaapi helper libraries and plugins elements are available under
+    the terms of the GNU Lesser General Public License v2.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; 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
+
+On Debian GNU/Linux systems, the complete text of the GNU Lesser General
+Public License can be found in `/usr/share/common-licenses/LGPL-2.1'.
+
diff --git a/debian.upstream/gstreamer-vaapi-doc.install.in b/debian.upstream/gstreamer-vaapi-doc.install.in
new file mode 100644 (file)
index 0000000..ff84ca1
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/share/doc/gstreamer@GST_MAJORMINOR@-vaapi
diff --git a/debian.upstream/gstreamer-vaapi.install.in b/debian.upstream/gstreamer-vaapi.install.in
new file mode 100644 (file)
index 0000000..5af8fbb
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/lib/gstreamer-@GST_MAJORMINOR@/libgstvaapi*.so
diff --git a/debian.upstream/libgstvaapi-dev.install.in b/debian.upstream/libgstvaapi-dev.install.in
new file mode 100644 (file)
index 0000000..a940c52
--- /dev/null
@@ -0,0 +1,3 @@
+debian/tmp/usr/lib/libgstvaapi*.so
+debian/tmp/usr/lib/pkgconfig/gstreamer-vaapi*.pc
+debian/tmp/usr/include/gstreamer-@GST_MAJORMINOR@/gst/vaapi/*.h
diff --git a/debian.upstream/libgstvaapi-drm.install.in b/debian.upstream/libgstvaapi-drm.install.in
new file mode 100644 (file)
index 0000000..de8b898
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/lib/libgstvaapi-drm-@GST_MAJORMINOR@.so.*
diff --git a/debian.upstream/libgstvaapi-glx.install.in b/debian.upstream/libgstvaapi-glx.install.in
new file mode 100644 (file)
index 0000000..cd7352a
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/lib/libgstvaapi-glx-@GST_MAJORMINOR@.so.*
diff --git a/debian.upstream/libgstvaapi-wayland.install.in b/debian.upstream/libgstvaapi-wayland.install.in
new file mode 100644 (file)
index 0000000..e1740b5
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/lib/libgstvaapi-wayland-@GST_MAJORMINOR@.so.*
diff --git a/debian.upstream/libgstvaapi-x11.install.in b/debian.upstream/libgstvaapi-x11.install.in
new file mode 100644 (file)
index 0000000..8754fb8
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/lib/libgstvaapi-x11-@GST_MAJORMINOR@.so.*
diff --git a/debian.upstream/libgstvaapi.install.in b/debian.upstream/libgstvaapi.install.in
new file mode 100644 (file)
index 0000000..e585a6b
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/lib/libgstvaapi-@GST_MAJORMINOR@.so.*
diff --git a/debian.upstream/rules b/debian.upstream/rules
new file mode 100755 (executable)
index 0000000..0ec96be
--- /dev/null
@@ -0,0 +1,29 @@
+#!/usr/bin/make -f
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/class/autotools.mk
+include /usr/share/cdbs/1/rules/simple-patchsys.mk
+include /usr/share/cdbs/1/rules/utils.mk
+
+gst_pkgname = $(shell dpkg-parsechangelog | grep ^Source: | cut -d' ' -f2)
+
+# Allow SMP build
+ifeq ($(DEBIAN_BUILD_NCPUS),)
+       DEBIAN_BUILD_NCPUS = $(shell /usr/bin/getconf _NPROCESSORS_ONLN)
+endif
+ifneq ($(DEBIAN_BUILD_NCPUS),)
+       EXTRA_MAKE_FLAGS += -j$(DEBIAN_BUILD_NCPUS)
+endif
+MAKE += $(EXTRA_MAKE_FLAGS)
+
+# Allow HTML documentation build
+indep_conf_flags = \
+       --with-html-dir=\$${prefix}/share/doc/$(gst_pkgname)
+
+# only build the docs if gtk-doc-tools is installed, i.e. binary-indep is
+# called
+ifeq ($(shell test "`dpkg -l gtk-doc-tools | grep ^ii`" && echo binary-indep),binary-indep)
+indep_conf_flags += --enable-gtk-doc
+endif
+
+DEB_CONFIGURE_EXTRA_FLAGS += $(indep_conf_flags)
diff --git a/docs/Makefile.am b/docs/Makefile.am
new file mode 100644 (file)
index 0000000..58bb287
--- /dev/null
@@ -0,0 +1,10 @@
+SUBDIRS =
+
+if ENABLE_GTK_DOC
+SUBDIRS += reference
+endif
+
+DIST_SUBDIRS = reference
+
+# Extra clean files so that maintainer-clean removes *everything*
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
new file mode 100644 (file)
index 0000000..3eef00e
--- /dev/null
@@ -0,0 +1,4 @@
+SUBDIRS = libs plugins
+
+# Extra clean files so that maintainer-clean removes *everything*
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/docs/reference/libs/Makefile.am b/docs/reference/libs/Makefile.am
new file mode 100644 (file)
index 0000000..d4747b3
--- /dev/null
@@ -0,0 +1,140 @@
+## Process this file with automake to produce Makefile.in
+
+# We require automake 1.6 at least.
+AUTOMAKE_OPTIONS = 1.6
+
+# This is a blank Makefile.am for using gtk-doc.
+# Copy this to your project's API docs directory and modify the variables to
+# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
+# of using the various options.
+
+# The name of the module, e.g. 'glib'.
+DOC_MODULE = libs
+
+# The top-level SGML file. You can change this if you want to.
+DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.xml
+
+# The directory containing the source code. Relative to $(srcdir).
+# gtk-doc will search all .c & .h files beneath here for inline comments
+# documenting the functions and macros.
+# e.g. DOC_SOURCE_DIR=../../../gtk
+DOC_SOURCE_DIR = $(top_srcdir)/gst-libs/gst/vaapi
+
+# Extra options to pass to gtkdoc-scangobj. Not normally needed.
+SCANGOBJ_OPTIONS = --type-init-func="g_type_init()"
+
+# List files used by scanobj
+SCANOBJ_TYPES  = $(srcdir)/$(DOC_MODULE).core.types
+SCANOBJ_TYPES += $(srcdir)/$(DOC_MODULE).x11.types
+if USE_GLX
+SCANOBJ_TYPES += $(srcdir)/$(DOC_MODULE).glx.types
+endif
+
+# Extra options to supply to gtkdoc-scan.
+# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
+SCAN_OPTIONS = --deprecated-guards="GST_VAAPI_DISABLE_DEPRECATED"
+
+# Extra options to supply to gtkdoc-mkdb.
+# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
+MKDB_OPTIONS = --sgml-mode --output-format=xml --name-space=$(DOC_MODULE)
+
+# Extra options to supply to gtkdoc-mktmpl
+# e.g. MKTMPL_OPTIONS=--only-section-tmpl
+MKTMPL_OPTIONS =
+
+# Extra options to supply to gtkdoc-fixref. Not normally needed.
+# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
+FIXXREF_OPTIONS = \
+       --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html/glib \
+       --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html/gobject \
+       --extra-dir=$(CAIRO_PREFIX)/share/gtk-doc/html/cairo \
+       --extra-dir=$(PANGO_PREFIX)/share/gtk-doc/html/pango
+
+# Used for dependencies. The docs will be rebuilt if any of these change.
+# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
+# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
+HFILE_GLOB = $(top_srcdir)/gst-libs/gst/vaapi/*.h
+CFILE_GLOB = $(top_srcdir)/gst-libs/gst/vaapi/*.c $(srcdir)/$(DOC_MODULE).types
+
+# Header files to ignore when scanning.
+# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
+IGNORE_HFILES = \
+       gstvaapi_priv.h \
+       gstvaapicompat.h \
+       gstvaapidebug.h \
+       gstvaapidecoder_priv.h \
+       gstvaapidisplay_priv.h \
+       gstvaapidisplay_glx_priv.h \
+       gstvaapidisplay_x11_priv.h \
+       gstvaapiobject_priv.h \
+       gstvaapiutils.h \
+       gstvaapiutils_glx.h \
+       gstvaapiutils_gst.h \
+       gstvaapiutils_x11.h \
+       $(NULL)
+
+EXTRA_HFILES = \
+       $(NULL)
+
+# Images to copy into HTML directory.
+# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
+HTML_IMAGES = \
+       $(NULL)
+
+# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
+# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
+content_files = \
+       $(NULL)
+
+# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
+# These files must be listed here *and* in content_files
+# e.g. expand_content_files=running.sgml
+expand_content_files = \
+       $(NULL)
+
+# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
+# Only needed if you are using gtkdoc-scangobj to dynamically query widget
+# signals and properties.
+# e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
+# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
+
+INCLUDES = \
+       $(GLIB_CFLAGS) \
+       $(GST_CFLAGS) \
+       -I$(top_srcdir) \
+       -I$(top_srcdir)/gst-libs \
+       -I$(top_srcdir)/gst-libs/gst/vaapi
+
+GTKDOC_LIBS = \
+       $(GLIB_LIBS) \
+       $(GST_LIBS) \
+       $(top_builddir)/gst-libs/gst/vaapi/libgstvaapi-$(GST_MAJORMINOR).la
+
+GTKDOC_LIBS += \
+       $(top_builddir)/gst-libs/gst/vaapi/libgstvaapi-x11-$(GST_MAJORMINOR).la
+
+if USE_GLX
+GTKDOC_LIBS += \
+       $(top_builddir)/gst-libs/gst/vaapi/libgstvaapi-glx-$(GST_MAJORMINOR).la
+endif
+
+$(srcdir)/$(DOC_MODULE).types: $(SCANOBJ_TYPES)
+       cat $(SCANOBJ_TYPES) > $@
+
+# This includes the standard gtk-doc make rules, copied by gtkdocize.
+include $(top_srcdir)/gtk-doc.make
+
+# Other files to distribute
+# e.g. EXTRA_DIST += version.xml.in
+EXTRA_DIST += \
+       libs-docs.xml.in \
+       libs.core.types \
+       libs.x11.types \
+       libs.glx.types \
+       $(NULL)
+
+DISTCLEANFILES = $(srcdir)/$(DOC_MODULE).types
+BUILT_SOURCES  = $(srcdir)/$(DOC_MODULE).types
+
+# Extra clean files so that maintainer-clean removes *everything*
+MAINTAINERCLEANFILES = Makefile.in lib-docs.xml
diff --git a/docs/reference/libs/libs-docs.xml.in b/docs/reference/libs/libs-docs.xml.in
new file mode 100644 (file)
index 0000000..34b1665
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+               "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
+<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
+  <bookinfo>
+    <title>GStreamer VA-API Plugins @GST_MAJORMINOR@ Library Reference Manual</title>
+  </bookinfo>
+
+  <chapter>
+    <title>gst-plugins-vaapi Library</title>
+    <xi:include href="xml/gstvaapitypes.xml"/>
+    <xi:include href="xml/gstvaapivalue.xml"/>
+    <xi:include href="xml/gstvaapiparamspecs.xml"/>
+    <xi:include href="xml/gstvaapidisplay.xml"/>
+    <xi:include href="xml/gstvaapidisplay_x11.xml"/>
+    <xi:include href="xml/gstvaapidisplay_glx.xml"/>
+    <xi:include href="xml/gstvaapiwindow.xml"/>
+    <xi:include href="xml/gstvaapiwindow_x11.xml"/>
+    <xi:include href="xml/gstvaapiwindow_glx.xml"/>
+    <xi:include href="xml/gstvaapiobject.xml"/>
+    <xi:include href="xml/gstvaapisurface.xml"/>
+    <xi:include href="xml/gstvaapiimage.xml"/>
+    <xi:include href="xml/gstvaapiimageformat.xml"/>
+    <xi:include href="xml/gstvaapisubpicture.xml"/>
+    <xi:include href="xml/gstvaapitexture.xml"/>
+    <xi:include href="xml/gstvaapiprofile.xml"/>
+    <xi:include href="xml/gstvaapivideopool.xml"/>
+    <xi:include href="xml/gstvaapisurfacepool.xml"/>
+    <xi:include href="xml/gstvaapiimagepool.xml"/>
+    <xi:include href="xml/gstvaapivideobuffer.xml"/>
+    <xi:include href="xml/gstvaapicontext.xml"/>
+    <xi:include href="xml/gstvaapidecoder.xml"/>
+    <xi:include href="xml/gstvaapidecoder_mpeg2.xml"/>
+    <xi:include href="xml/gstvaapidecoder_mpeg4.xml"/>
+    <xi:include href="xml/gstvaapidecoder_h264.xml"/>
+    <xi:include href="xml/gstvaapidecoder_vc1.xml"/>
+    <xi:include href="xml/gstvaapidecoder_ffmpeg.xml"/>
+    <xi:include href="xml/gstvaapisurfaceproxy.xml"/>
+  </chapter>
+
+  <chapter id="object-tree">
+    <title>Object Hierarchy</title>
+    <xi:include href="xml/tree_index.sgml"/>
+  </chapter>
+
+  <index id="api-index-full">
+    <title>API Index</title>
+    <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
+  </index>
+
+  <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
+</book>
diff --git a/docs/reference/libs/libs-overrides.txt b/docs/reference/libs/libs-overrides.txt
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/docs/reference/libs/libs-sections.txt b/docs/reference/libs/libs-sections.txt
new file mode 100644 (file)
index 0000000..1d9869a
--- /dev/null
@@ -0,0 +1,566 @@
+<SECTION>
+<FILE>gstvaapisurfacepool</FILE>
+<TITLE>GstVaapiSurfacePool</TITLE>
+GstVaapiSurfacePool
+GstVaapiSurfacePoolClass
+gst_vaapi_surface_pool_new
+<SUBSECTION Standard>
+GST_VAAPI_SURFACE_POOL
+GST_VAAPI_IS_SURFACE_POOL
+GST_VAAPI_TYPE_SURFACE_POOL
+gst_vaapi_surface_pool_get_type
+GST_VAAPI_SURFACE_POOL_CLASS
+GST_VAAPI_IS_SURFACE_POOL_CLASS
+GST_VAAPI_SURFACE_POOL_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapivideopool</FILE>
+<TITLE>GstVaapiVideoPool</TITLE>
+GstVaapiVideoPool
+GstVaapiVideoPoolClass
+gst_vaapi_video_pool_get_display
+gst_vaapi_video_pool_get_caps
+gst_vaapi_video_pool_get_object
+gst_vaapi_video_pool_put_object
+gst_vaapi_video_pool_add_object
+gst_vaapi_video_pool_add_objects
+gst_vaapi_video_pool_get_capacity
+gst_vaapi_video_pool_set_capacity
+gst_vaapi_video_pool_get_size
+gst_vaapi_video_pool_reserve
+<SUBSECTION Standard>
+GST_VAAPI_VIDEO_POOL
+GST_VAAPI_IS_VIDEO_POOL
+GST_VAAPI_TYPE_VIDEO_POOL
+gst_vaapi_video_pool_get_type
+GST_VAAPI_VIDEO_POOL_CLASS
+GST_VAAPI_IS_VIDEO_POOL_CLASS
+GST_VAAPI_VIDEO_POOL_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapidisplay_x11</FILE>
+<TITLE>GstVaapiDisplayX11</TITLE>
+GstVaapiDisplayX11
+GstVaapiDisplayX11Class
+gst_vaapi_display_x11_new
+gst_vaapi_display_x11_new_with_display
+gst_vaapi_display_x11_get_display
+gst_vaapi_display_x11_get_screen
+<SUBSECTION Standard>
+GST_VAAPI_DISPLAY_X11
+GST_VAAPI_IS_DISPLAY_X11
+GST_VAAPI_TYPE_DISPLAY_X11
+gst_vaapi_display_x11_get_type
+GST_VAAPI_DISPLAY_X11_CLASS
+GST_VAAPI_IS_DISPLAY_X11_CLASS
+GST_VAAPI_DISPLAY_X11_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapiwindow_x11</FILE>
+<TITLE>GstVaapiWindowX11</TITLE>
+GstVaapiWindowX11
+GstVaapiWindowX11Class
+GST_VAAPI_WINDOW_XWINDOW
+gst_vaapi_window_x11_new
+gst_vaapi_window_x11_new_with_xid
+gst_vaapi_window_x11_get_xid
+gst_vaapi_window_x11_is_foreign_xid
+<SUBSECTION Standard>
+GST_VAAPI_WINDOW_X11
+GST_VAAPI_IS_WINDOW_X11
+GST_VAAPI_TYPE_WINDOW_X11
+gst_vaapi_window_x11_get_type
+GST_VAAPI_WINDOW_X11_CLASS
+GST_VAAPI_IS_WINDOW_X11_CLASS
+GST_VAAPI_WINDOW_X11_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapidisplay_glx</FILE>
+<TITLE>GstVaapiDisplayGLX</TITLE>
+GstVaapiDisplayGLX
+GstVaapiDisplayGLXClass
+gst_vaapi_display_glx_new
+gst_vaapi_display_glx_new_with_display
+<SUBSECTION Standard>
+GST_VAAPI_DISPLAY_GLX
+GST_VAAPI_IS_DISPLAY_GLX
+GST_VAAPI_TYPE_DISPLAY_GLX
+gst_vaapi_display_glx_get_type
+GST_VAAPI_DISPLAY_GLX_CLASS
+GST_VAAPI_IS_DISPLAY_GLX_CLASS
+GST_VAAPI_DISPLAY_GLX_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapiwindow_glx</FILE>
+<TITLE>GstVaapiWindowGLX</TITLE>
+GstVaapiWindowGLX
+GstVaapiWindowGLXClass
+gst_vaapi_window_glx_new
+gst_vaapi_window_glx_new_with_xid
+gst_vaapi_window_glx_get_context
+gst_vaapi_window_glx_set_context
+gst_vaapi_window_glx_make_current
+gst_vaapi_window_glx_swap_buffers
+gst_vaapi_window_glx_put_texture
+<SUBSECTION Standard>
+GST_VAAPI_WINDOW_GLX
+GST_VAAPI_IS_WINDOW_GLX
+GST_VAAPI_TYPE_WINDOW_GLX
+gst_vaapi_window_glx_get_type
+GST_VAAPI_WINDOW_GLX_CLASS
+GST_VAAPI_IS_WINDOW_GLX_CLASS
+GST_VAAPI_WINDOW_GLX_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapidisplay</FILE>
+<TITLE>GstVaapiDisplay</TITLE>
+GstVaapiDisplay
+GstVaapiDisplayClass
+gst_vaapi_display_new_with_display
+gst_vaapi_display_lock
+gst_vaapi_display_unlock
+gst_vaapi_display_sync
+gst_vaapi_display_flush
+gst_vaapi_display_get_display
+gst_vaapi_display_get_width
+gst_vaapi_display_get_height
+gst_vaapi_display_get_size
+gst_vaapi_display_get_pixel_aspect_ratio
+gst_vaapi_display_get_decode_caps
+gst_vaapi_display_has_decoder
+gst_vaapi_display_get_encode_caps
+gst_vaapi_display_has_encoder
+gst_vaapi_display_get_image_caps
+gst_vaapi_display_has_image_format
+gst_vaapi_display_get_subpicture_caps
+gst_vaapi_display_has_subpicture_format
+<SUBSECTION Standard>
+GST_VAAPI_DISPLAY
+GST_VAAPI_IS_DISPLAY
+GST_VAAPI_TYPE_DISPLAY
+gst_vaapi_display_get_type
+GST_VAAPI_DISPLAY_CLASS
+GST_VAAPI_IS_DISPLAY_CLASS
+GST_VAAPI_DISPLAY_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapiimagepool</FILE>
+<TITLE>GstVaapiImagePool</TITLE>
+GstVaapiImagePool
+GstVaapiImagePoolClass
+gst_vaapi_image_pool_new
+<SUBSECTION Standard>
+GST_VAAPI_IMAGE_POOL
+GST_VAAPI_IS_IMAGE_POOL
+GST_VAAPI_TYPE_IMAGE_POOL
+gst_vaapi_image_pool_get_type
+GST_VAAPI_IMAGE_POOL_CLASS
+GST_VAAPI_IS_IMAGE_POOL_CLASS
+GST_VAAPI_IMAGE_POOL_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapivideobuffer</FILE>
+<TITLE>GstVaapiVideoBuffer</TITLE>
+GstVaapiVideoBuffer
+GstVaapiVideoBufferClass
+gst_vaapi_video_buffer_typed_new
+gst_vaapi_video_buffer_typed_new_from_pool
+gst_vaapi_video_buffer_typed_new_from_buffer
+gst_vaapi_video_buffer_typed_new_with_image
+gst_vaapi_video_buffer_typed_new_with_surface
+gst_vaapi_video_buffer_typed_new_with_surface_proxy
+gst_vaapi_video_buffer_get_display
+gst_vaapi_video_buffer_get_image
+gst_vaapi_video_buffer_set_image
+gst_vaapi_video_buffer_set_image_from_pool
+gst_vaapi_video_buffer_get_surface
+gst_vaapi_video_buffer_get_surface_proxy
+gst_vaapi_video_buffer_set_surface
+gst_vaapi_video_buffer_set_surface_proxy
+gst_vaapi_video_buffer_set_surface_from_pool
+gst_vaapi_video_buffer_get_render_flags
+gst_vaapi_video_buffer_set_render_flags
+<SUBSECTION Standard>
+GST_VAAPI_VIDEO_BUFFER
+GST_VAAPI_IS_VIDEO_BUFFER
+GST_VAAPI_TYPE_VIDEO_BUFFER
+gst_vaapi_video_buffer_get_type
+GST_VAAPI_VIDEO_BUFFER_CLASS
+GST_VAAPI_IS_VIDEO_BUFFER_CLASS
+GST_VAAPI_VIDEO_BUFFER_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapitypes</FILE>
+<TITLE>Basic data structures</TITLE>
+GstVaapiID
+GST_VAAPI_ID_FORMAT
+GST_VAAPI_ID_ARGS
+GST_VAAPI_ID
+GST_VAAPI_ID_NONE
+GstVaapiPoint
+GstVaapiRectangle
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapivalue</FILE>
+<TITLE></TITLE>
+GST_VAAPI_TYPE_ID
+gst_vaapi_value_get_id
+gst_vaapi_value_set_id
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapiparamspecs</FILE>
+<TITLE></TITLE>
+GstVaapiParamSpecID
+gst_vaapi_param_spec_id
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapiwindow</FILE>
+<TITLE>GstVaapiWindow</TITLE>
+GstVaapiWindow
+GstVaapiWindowClass
+gst_vaapi_window_get_display
+gst_vaapi_window_show
+gst_vaapi_window_hide
+gst_vaapi_window_get_fullscreen
+gst_vaapi_window_set_fullscreen
+gst_vaapi_window_get_width
+gst_vaapi_window_get_height
+gst_vaapi_window_get_size
+gst_vaapi_window_set_width
+gst_vaapi_window_set_height
+gst_vaapi_window_set_size
+gst_vaapi_window_put_surface
+<SUBSECTION Standard>
+GST_VAAPI_WINDOW
+GST_VAAPI_IS_WINDOW
+GST_VAAPI_TYPE_WINDOW
+gst_vaapi_window_get_type
+GST_VAAPI_WINDOW_CLASS
+GST_VAAPI_IS_WINDOW_CLASS
+GST_VAAPI_WINDOW_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapiobject</FILE>
+<TITLE>GstVaapiObject</TITLE>
+GstVaapiObject
+GstVaapiObjectClass
+gst_vaapi_object_get_display
+gst_vaapi_object_lock_display
+gst_vaapi_object_unlock_display
+gst_vaapi_object_get_id
+<SUBSECTION Standard>
+GST_VAAPI_OBJECT
+GST_VAAPI_IS_OBJECT
+GST_VAAPI_TYPE_OBJECT
+gst_vaapi_object_get_type
+GST_VAAPI_OBJECT_CLASS
+GST_VAAPI_IS_OBJECT_CLASS
+GST_VAAPI_OBJECT_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapiimage</FILE>
+GST_VAAPI_IMAGE_FORMAT
+GST_VAAPI_IMAGE_WIDTH
+GST_VAAPI_IMAGE_HEIGHT
+<TITLE>GstVaapiImage</TITLE>
+GstVaapiImage
+GstVaapiImageClass
+gst_vaapi_image_new
+gst_vaapi_image_new_with_image
+gst_vaapi_image_get_id
+gst_vaapi_image_get_image
+gst_vaapi_image_get_format
+gst_vaapi_image_get_width
+gst_vaapi_image_get_height
+gst_vaapi_image_get_size
+gst_vaapi_image_is_linear
+gst_vaapi_image_is_mapped
+gst_vaapi_image_map
+gst_vaapi_image_unmap
+gst_vaapi_image_get_plane_count
+gst_vaapi_image_get_plane
+gst_vaapi_image_get_pitch
+gst_vaapi_image_get_data_size
+gst_vaapi_image_get_buffer
+gst_vaapi_image_get_raw
+gst_vaapi_image_update_from_buffer
+<SUBSECTION Standard>
+GST_VAAPI_IMAGE
+GST_VAAPI_IS_IMAGE
+GST_VAAPI_TYPE_IMAGE
+gst_vaapi_image_get_type
+GST_VAAPI_IMAGE_CLASS
+GST_VAAPI_IS_IMAGE_CLASS
+GST_VAAPI_IMAGE_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapisurface</FILE>
+GstVaapiChromaType
+GstVaapiSurfaceStatus
+GstVaapiSurfaceRenderFlags
+<TITLE>GstVaapiSurface</TITLE>
+GstVaapiSurface
+GstVaapiSurfaceClass
+gst_vaapi_surface_new
+gst_vaapi_surface_get_id
+gst_vaapi_surface_get_chroma_type
+gst_vaapi_surface_get_width
+gst_vaapi_surface_get_height
+gst_vaapi_surface_get_size
+gst_vaapi_surface_derive_image
+gst_vaapi_surface_get_image
+gst_vaapi_surface_put_image
+gst_vaapi_surface_associate_subpicture
+gst_vaapi_surface_deassociate_subpicture
+gst_vaapi_surface_sync
+gst_vaapi_surface_query_status
+<SUBSECTION Standard>
+GST_VAAPI_SURFACE
+GST_VAAPI_IS_SURFACE
+GST_VAAPI_TYPE_SURFACE
+gst_vaapi_surface_get_type
+GST_VAAPI_SURFACE_CLASS
+GST_VAAPI_IS_SURFACE_CLASS
+GST_VAAPI_SURFACE_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapisubpicture</FILE>
+<TITLE>GstVaapiSubpicture</TITLE>
+GstVaapiSubpicture
+GstVaapiSubpictureClass
+gst_vaapi_subpicture_new
+gst_vaapi_subpicture_get_id
+gst_vaapi_subpicture_get_image
+gst_vaapi_subpicture_set_image
+<SUBSECTION Standard>
+GST_VAAPI_SUBPICTURE
+GST_VAAPI_IS_SUBPICTURE
+GST_VAAPI_TYPE_SUBPICTURE
+gst_vaapi_subpicture_get_type
+GST_VAAPI_SUBPICTURE_CLASS
+GST_VAAPI_IS_SUBPICTURE_CLASS
+GST_VAAPI_SUBPICTURE_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapiimageformat</FILE>
+<TITLE>GstVaapiImageFormat</TITLE>
+GstVaapiImageFormat
+gst_vaapi_image_format_is_rgb
+gst_vaapi_image_format_is_yuv
+gst_vaapi_image_format
+gst_vaapi_image_format_from_caps
+gst_vaapi_image_format_from_fourcc
+gst_vaapi_image_format_from_video
+gst_vaapi_image_format_get_va_format
+gst_vaapi_image_format_get_caps
+gst_vaapi_image_format_get_score
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapiprofile</FILE>
+<TITLE>GstVaapiProfile</TITLE>
+GstVaapiCodec
+GstVaapiProfile
+GstVaapiEntrypoint
+gst_vaapi_profile
+gst_vaapi_profile_from_caps
+gst_vaapi_profile_get_va_profile
+gst_vaapi_profile_get_caps
+gst_vaapi_profile_get_codec
+gst_vaapi_entrypoint
+gst_vaapi_entrypoint_get_va_entrypoint
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapitexture</FILE>
+<TITLE>GstVaapiTexture</TITLE>
+GstVaapiTexture
+GstVaapiTextureClass
+gst_vaapi_texture_new
+gst_vaapi_texture_new_with_texture
+gst_vaapi_texture_get_id
+gst_vaapi_texture_get_target
+gst_vaapi_texture_get_format
+gst_vaapi_texture_get_width
+gst_vaapi_texture_get_height
+gst_vaapi_texture_get_size
+gst_vaapi_texture_put_surface
+<SUBSECTION Standard>
+GST_VAAPI_TEXTURE
+GST_VAAPI_IS_TEXTURE
+GST_VAAPI_TYPE_TEXTURE
+gst_vaapi_texture_get_type
+GST_VAAPI_TEXTURE_CLASS
+GST_VAAPI_IS_TEXTURE_CLASS
+GST_VAAPI_TEXTURE_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapicontext</FILE>
+<TITLE>GstVaapiContext</TITLE>
+GstVaapiContext
+GstVaapiContextClass
+gst_vaapi_context_new
+gst_vaapi_context_reset
+gst_vaapi_context_get_id
+gst_vaapi_context_get_profile
+gst_vaapi_context_set_profile
+gst_vaapi_context_get_entrypoint
+gst_vaapi_context_get_size
+gst_vaapi_context_get_surface
+gst_vaapi_context_get_surface_count
+gst_vaapi_context_put_surface
+gst_vaapi_context_find_surface_by_id
+gst_vaapi_context_apply_composition
+<SUBSECTION Standard>
+GST_VAAPI_CONTEXT
+GST_VAAPI_IS_CONTEXT
+GST_VAAPI_TYPE_CONTEXT
+gst_vaapi_context_get_type
+GST_VAAPI_CONTEXT_CLASS
+GST_VAAPI_IS_CONTEXT_CLASS
+GST_VAAPI_CONTEXT_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapidecoder</FILE>
+GstVaapiDecoderStatus
+<TITLE>GstVaapiDecoder</TITLE>
+GstVaapiDecoder
+GstVaapiDecoderClass
+gst_vaapi_decoder_get_caps
+gst_vaapi_decoder_put_buffer
+gst_vaapi_decoder_get_surface
+<SUBSECTION Standard>
+GST_VAAPI_DECODER
+GST_VAAPI_IS_DECODER
+GST_VAAPI_TYPE_DECODER
+gst_vaapi_decoder_get_type
+GST_VAAPI_DECODER_CLASS
+GST_VAAPI_IS_DECODER_CLASS
+GST_VAAPI_DECODER_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapidecoder_jpeg</FILE>
+<TITLE>GstVaapiDecoderJpeg</TITLE>
+GstVaapiDecoderJpeg
+GstVaapiDecoderJpegClass
+gst_vaapi_decoder_jpeg_new
+<SUBSECTION Standard>
+GST_VAAPI_DECODER_JPEG
+GST_VAAPI_IS_DECODER_JPEG
+GST_VAAPI_TYPE_DECODER_JPEG
+gst_vaapi_decoder_jpeg_get_type
+GST_VAAPI_DECODER_JPEG_CLASS
+GST_VAAPI_IS_DECODER_JPEG_CLASS
+GST_VAAPI_DECODER_JPEG_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapidecoder_mpeg2</FILE>
+<TITLE>GstVaapiDecoderMpeg2</TITLE>
+GstVaapiDecoderMpeg2
+GstVaapiDecoderMpeg2Class
+gst_vaapi_decoder_mpeg2_new
+<SUBSECTION Standard>
+GST_VAAPI_DECODER_MPEG2
+GST_VAAPI_IS_DECODER_MPEG2
+GST_VAAPI_TYPE_DECODER_MPEG2
+gst_vaapi_decoder_mpeg2_get_type
+GST_VAAPI_DECODER_MPEG2_CLASS
+GST_VAAPI_IS_DECODER_MPEG2_CLASS
+GST_VAAPI_DECODER_MPEG2_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapidecoder_mpeg4</FILE>
+<TITLE>GstVaapiDecoderMpeg4</TITLE>
+GstVaapiDecoderMpeg4
+GstVaapiDecoderMpeg4Class
+gst_vaapi_decoder_mpeg4_new
+<SUBSECTION Standard>
+GST_VAAPI_DECODER_MPEG4
+GST_VAAPI_IS_DECODER_MPEG4
+GST_VAAPI_TYPE_DECODER_MPEG4
+gst_vaapi_decoder_mpeg4_get_type
+GST_VAAPI_DECODER_MPEG4_CLASS
+GST_VAAPI_IS_DECODER_MPEG4_CLASS
+GST_VAAPI_DECODER_MPEG4_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapidecoder_h264</FILE>
+<TITLE>GstVaapiDecoderH264</TITLE>
+GstVaapiDecoderH264
+GstVaapiDecoderH264Class
+gst_vaapi_decoder_h264_new
+<SUBSECTION Standard>
+GST_VAAPI_DECODER_H264
+GST_VAAPI_IS_DECODER_H264
+GST_VAAPI_TYPE_DECODER_H264
+gst_vaapi_decoder_h264_get_type
+GST_VAAPI_DECODER_H264_CLASS
+GST_VAAPI_IS_DECODER_H264_CLASS
+GST_VAAPI_DECODER_H264_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapidecoder_vc1</FILE>
+<TITLE>GstVaapiDecoderVC1</TITLE>
+GstVaapiDecoderVC1
+GstVaapiDecoderVC1Class
+gst_vaapi_decoder_vc1_new
+<SUBSECTION Standard>
+GST_VAAPI_DECODER_VC1
+GST_VAAPI_IS_DECODER_VC1
+GST_VAAPI_TYPE_DECODER_VC1
+gst_vaapi_decoder_vc1_get_type
+GST_VAAPI_DECODER_VC1_CLASS
+GST_VAAPI_IS_DECODER_VC1_CLASS
+GST_VAAPI_DECODER_VC1_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapisurfaceproxy</FILE>
+<TITLE>GstVaapiSurfaceProxy</TITLE>
+GstVaapiSurfaceProxy
+GstVaapiSurfaceProxyClass
+gst_vaapi_surface_proxy_new
+gst_vaapi_surface_proxy_get_context
+gst_vaapi_surface_proxy_set_context
+gst_vaapi_surface_proxy_get_surface
+gst_vaapi_surface_proxy_get_surface_id
+gst_vaapi_surface_proxy_set_surface
+gst_vaapi_surface_proxy_get_timestamp
+gst_vaapi_surface_proxy_set_timestamp
+gst_vaapi_surface_proxy_get_interlaced
+gst_vaapi_surface_proxy_set_interlaced
+gst_vaapi_surface_proxy_get_tff
+gst_vaapi_surface_proxy_set_tff
+<SUBSECTION Standard>
+GST_VAAPI_SURFACE_PROXY
+GST_VAAPI_IS_SURFACE_PROXY
+GST_VAAPI_TYPE_SURFACE_PROXY
+gst_vaapi_surface_proxy_get_type
+GST_VAAPI_SURFACE_PROXY_CLASS
+GST_VAAPI_IS_SURFACE_PROXY_CLASS
+GST_VAAPI_SURFACE_PROXY_GET_CLASS
+</SECTION>
diff --git a/docs/reference/libs/libs.core.types b/docs/reference/libs/libs.core.types
new file mode 100644 (file)
index 0000000..b779fd6
--- /dev/null
@@ -0,0 +1,14 @@
+gst_vaapi_context_get_type
+gst_vaapi_decoder_get_type
+gst_vaapi_display_get_type
+gst_vaapi_image_get_type
+gst_vaapi_image_pool_get_type
+gst_vaapi_object_get_type
+gst_vaapi_subpicture_get_type
+gst_vaapi_surface_get_type
+gst_vaapi_surface_pool_get_type
+gst_vaapi_surface_proxy_get_type
+gst_vaapi_video_buffer_get_type
+gst_vaapi_video_pool_get_type
+gst_vaapi_video_sink_get_type
+gst_vaapi_window_get_type
diff --git a/docs/reference/libs/libs.glx.types b/docs/reference/libs/libs.glx.types
new file mode 100644 (file)
index 0000000..6ecd354
--- /dev/null
@@ -0,0 +1,3 @@
+gst_vaapi_display_glx_get_type
+gst_vaapi_texture_get_type
+gst_vaapi_window_glx_get_type
diff --git a/docs/reference/libs/libs.x11.types b/docs/reference/libs/libs.x11.types
new file mode 100644 (file)
index 0000000..c083ce0
--- /dev/null
@@ -0,0 +1,2 @@
+gst_vaapi_display_x11_get_type
+gst_vaapi_window_x11_get_type
diff --git a/docs/reference/plugins/Makefile.am b/docs/reference/plugins/Makefile.am
new file mode 100644 (file)
index 0000000..0bb388c
--- /dev/null
@@ -0,0 +1,108 @@
+## Process this file with automake to produce Makefile.in
+
+# We require automake 1.6 at least.
+AUTOMAKE_OPTIONS = 1.6
+
+# This is a blank Makefile.am for using gtk-doc.
+# Copy this to your project's API docs directory and modify the variables to
+# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
+# of using the various options.
+
+# The name of the module, e.g. 'glib'.
+DOC_MODULE = plugins
+
+# The top-level SGML file. You can change this if you want to.
+DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.xml
+
+# The directory containing the source code. Relative to $(srcdir).
+# gtk-doc will search all .c & .h files beneath here for inline comments
+# documenting the functions and macros.
+# e.g. DOC_SOURCE_DIR=../../../gtk
+DOC_SOURCE_DIR = $(top_srcdir)/gst
+
+# Extra options to pass to gtkdoc-scangobj. Not normally needed.
+SCANGOBJ_OPTIONS = --type-init-func="gst_init(NULL, NULL)"
+
+# Extra options to supply to gtkdoc-scan.
+# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
+SCAN_OPTIONS = --deprecated-guards="GST_VAAPI_DISABLE_DEPRECATED"
+
+# Extra options to supply to gtkdoc-mkdb.
+# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
+MKDB_OPTIONS = --sgml-mode --output-format=xml --name-space=$(DOC_MODULE)
+
+# Extra options to supply to gtkdoc-mktmpl
+# e.g. MKTMPL_OPTIONS=--only-section-tmpl
+MKTMPL_OPTIONS =
+
+# Extra options to supply to gtkdoc-fixref. Not normally needed.
+# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
+FIXXREF_OPTIONS = \
+       --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html/glib \
+       --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html/gobject \
+       --extra-dir=$(CAIRO_PREFIX)/share/gtk-doc/html/cairo \
+       --extra-dir=$(PANGO_PREFIX)/share/gtk-doc/html/pango
+
+# Used for dependencies. The docs will be rebuilt if any of these change.
+# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
+# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
+HFILE_GLOB = $(top_srcdir)/gst/*/*.h
+CFILE_GLOB = $(top_srcdir)/gst/*/*.c
+
+# Header files to ignore when scanning.
+# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
+IGNORE_HFILES = \
+       $(NULL)
+
+EXTRA_HFILES = \
+       $(NULL)
+
+# Images to copy into HTML directory.
+# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
+HTML_IMAGES = \
+       $(NULL)
+
+# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
+# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
+content_files = \
+       $(NULL)
+
+# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
+# These files must be listed here *and* in content_files
+# e.g. expand_content_files=running.sgml
+expand_content_files = \
+       $(NULL)
+
+# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
+# Only needed if you are using gtkdoc-scangobj to dynamically query widget
+# signals and properties.
+# e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
+# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
+
+INCLUDES = \
+       -I$(top_srcdir) \
+       -I$(top_srcdir)/gst-libs \
+       -I$(top_srcdir)/gst-libs/gst/vaapi \
+       $(GLIB_CFLAGS) \
+       $(GST_CFLAGS) \
+       $(NULL)
+
+GTKDOC_LIBS = \
+       $(top_builddir)/gst-libs/gst/vaapi/libgstvaapi-$(GST_MAJORMINOR).la \
+       $(top_builddir)/gst-libs/gst/vaapi/libgstvaapi-x11-$(GST_MAJORMINOR).la \
+       $(top_builddir)/gst/vaapi/libgstvaapi.la \
+       $(GLIB_LIBS) \
+       $(GST_LIBS) \
+       $(NULL)
+
+# This includes the standard gtk-doc make rules, copied by gtkdocize.
+include $(top_srcdir)/gtk-doc.make
+
+# Other files to distribute
+# e.g. EXTRA_DIST += version.xml.in
+EXTRA_DIST += \
+       $(DOC_MODULE)-docs.xml.in \
+       $(NULL)
+
+# Extra clean files so that maintainer-clean removes *everything*
+MAINTAINERCLEANFILES = Makefile.in $(DOC_MODULE)-docs.xml
diff --git a/docs/reference/plugins/plugins-docs.xml.in b/docs/reference/plugins/plugins-docs.xml.in
new file mode 100644 (file)
index 0000000..3532a55
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
+[
+  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+]>
+<book id="index">
+  <bookinfo>
+    <title>GStreamer VA-API Plugins @GST_MAJORMINOR@ Plugins Reference Manual</title>
+  </bookinfo>
+
+  <chapter>
+    <title>gst-plugins-vaapi Plugins</title>
+    <xi:include href="xml/gstvaapidecode.xml"/>
+    <xi:include href="xml/gstvaapipostproc.xml"/>
+    <xi:include href="xml/gstvaapidownload.xml"/>
+    <xi:include href="xml/gstvaapiupload.xml"/>
+    <xi:include href="xml/gstvaapisink.xml"/>
+  </chapter>
+
+  <chapter id="object-tree">
+    <title>Object Hierarchy</title>
+    <xi:include href="xml/tree_index.sgml"/>
+  </chapter>
+
+  <index id="api-index-full">
+    <title>API Index</title>
+    <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
+  </index>
+
+  <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
+</book>
diff --git a/docs/reference/plugins/plugins-overrides.txt b/docs/reference/plugins/plugins-overrides.txt
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/docs/reference/plugins/plugins-sections.txt b/docs/reference/plugins/plugins-sections.txt
new file mode 100644 (file)
index 0000000..58f3fe8
--- /dev/null
@@ -0,0 +1,69 @@
+<SECTION>
+<FILE>gstvaapisink</FILE>
+<TITLE>GstVaapiSink</TITLE>
+GstVaapiSink
+<SUBSECTION Standard>
+GST_VAAPISINK
+GST_IS_VAAPISINK
+GST_TYPE_VAAPISINK
+gst_vaapisink_get_type
+GST_VAAPISINK_CLASS
+GST_IS_VAAPISINK_CLASS
+GST_VAAPISINK_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapidecode</FILE>
+<TITLE>GstVaapiDecode</TITLE>
+GstVaapiDecode
+<SUBSECTION Standard>
+GST_VAAPIDECODE
+GST_IS_VAAPIDECODE
+GST_TYPE_VAAPIDECODE
+gst_vaapidecode_get_type
+GST_VAAPIDECODE_CLASS
+GST_IS_VAAPIDECODE_CLASS
+GST_VAAPIDECODE_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapipostproc</FILE>
+<TITLE>GstVaapiPostproc</TITLE>
+GstVaapiPostproc
+<SUBSECTION Standard>
+GST_VAAPIPOSTPROC
+GST_IS_VAAPIPOSTPROC
+GST_TYPE_VAAPIPOSTPROC
+gst_vaapipostproc_get_type
+GST_VAAPIPOSTPROC_CLASS
+GST_IS_VAAPIPOSTPROC_CLASS
+GST_VAAPIPOSTPROC_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapiupload</FILE>
+<TITLE>GstVaapiUpload</TITLE>
+GstVaapiUpload
+<SUBSECTION Standard>
+GST_VAAPIUPLOAD
+GST_IS_VAAPIUPLOAD
+GST_TYPE_VAAPIUPLOAD
+gst_vaapiupload_get_type
+GST_VAAPIUPLOAD_CLASS
+GST_IS_VAAPIUPLOAD_CLASS
+GST_VAAPIUPLOAD_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gstvaapidownload</FILE>
+<TITLE>GstVaapiDownload</TITLE>
+GstVaapiDownload
+<SUBSECTION Standard>
+GST_VAAPIDOWNLOAD
+GST_IS_VAAPIDOWNLOAD
+GST_TYPE_VAAPIDOWNLOAD
+gst_vaapidownload_get_type
+GST_VAAPIDOWNLOAD_CLASS
+GST_IS_VAAPIDOWNLOAD_CLASS
+GST_VAAPIDOWNLOAD_GET_CLASS
+</SECTION>
diff --git a/docs/reference/plugins/plugins.types b/docs/reference/plugins/plugins.types
new file mode 100644 (file)
index 0000000..4117580
--- /dev/null
@@ -0,0 +1,5 @@
+gst_vaapidecode_get_type
+gst_vaapidownload_get_type
+gst_vaapipostproc_get_type
+gst_vaapisink_get_type
+gst_vaapiupload_get_type
index 37d365d..06d14db 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS = vaapi
+SUBDIRS = codecparsers vaapi
 
 # Extra clean files so that maintainer-clean removes *everything*
-MAINTAINERCLEANFILES = Makefile.in
+MAINTAINERCLEANFILES = Makefile.in $(gen_headers)
diff --git a/gst-libs/gst/codecparsers/Makefile.am b/gst-libs/gst/codecparsers/Makefile.am
new file mode 100644 (file)
index 0000000..aa10113
--- /dev/null
@@ -0,0 +1,43 @@
+noinst_LTLIBRARIES =                           \
+       libgstvaapi-codecparsers.la             \
+       $(NULL)
+
+libgstvaapi_codecparsers_cflags =              \
+       -DGST_USE_UNSTABLE_API                  \
+       -I$(top_srcdir)/gst-libs                \
+       $(GST_BASE_CFLAGS)                      \
+       $(GST_CFLAGS)                           \
+       $(NULL)
+
+libgstvaapi_codecparsers_libs =                        \
+       $(GST_BASE_LIBS)                        \
+       $(GST_LIBS)                             \
+       $(NULL)
+
+libgstvaapi_codecparsers_source_c =            \
+       gstjpegparser.c                         \
+       $(NULL)
+
+libgstvaapi_codecparsers_source_h =            \
+       gstjpegparser.h                         \
+       $(NULL)
+
+libgstvaapi_codecparsers_la_SOURCES =          \
+       $(libgstvaapi_codecparsers_source_c)    \
+       $(libgstvaapi_codecparsers_source_h)    \
+       $(NULL)
+
+libgstvaapi_codecparsers_la_CFLAGS =           \
+       $(libgstvaapi_codecparsers_cflags)      \
+       $(NULL)
+
+libgstvaapi_codecparsers_la_LIBADD =           \
+       $(libgstvaapi_codecparsers_libs)        \
+       $(NULL)
+
+libgstvaapi_codecparsers_la_LDFLAGS =          \
+       $(GST_ALL_LDFLAGS)                      \
+       $(NULL)
+
+# Extra clean files so that maintainer-clean removes *everything*
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/gst-libs/gst/codecparsers/gstjpegparser.c b/gst-libs/gst/codecparsers/gstjpegparser.c
new file mode 100644 (file)
index 0000000..ca597ad
--- /dev/null
@@ -0,0 +1,610 @@
+/*
+ *  gstjpegparser.c - JPEG parser
+ *
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include <string.h>
+#include <gst/base/gstbytereader.h>
+#include "gstjpegparser.h"
+
+#ifndef GST_DISABLE_GST_DEBUG
+
+#define GST_CAT_DEFAULT ensure_debug_category()
+
+static GstDebugCategory *
+ensure_debug_category (void)
+{
+  static gsize cat_gonce = 0;
+
+  if (g_once_init_enter (&cat_gonce)) {
+    gsize cat_done;
+
+    cat_done = (gsize) _gst_debug_category_new ("codecparsers_jpeg", 0,
+        "GstJpegCodecParser");
+
+    g_once_init_leave (&cat_gonce, cat_done);
+  }
+
+  return (GstDebugCategory *) cat_gonce;
+}
+#else
+
+#define ensure_debug_category() /* NOOP */
+
+#endif /* GST_DISABLE_GST_DEBUG */
+
+#define DEBUG_PRINT_COMMENT 0
+
+#define READ_UINT8(reader, val) G_STMT_START {                  \
+    if (!gst_byte_reader_get_uint8 ((reader), &(val))) {        \
+      GST_WARNING ("failed to read uint8");                     \
+      goto failed;                                              \
+    }                                                           \
+  } G_STMT_END
+
+#define READ_UINT16(reader, val) G_STMT_START {                 \
+    if (!gst_byte_reader_get_uint16_be ((reader), &(val))) {    \
+      GST_WARNING ("failed to read uint16");                    \
+      goto failed;                                              \
+    }                                                           \
+  } G_STMT_END
+
+#define READ_BYTES(reader, buf, length) G_STMT_START {          \
+    const guint8 *vals;                                         \
+    if (!gst_byte_reader_get_data (reader, length, &vals)) {    \
+      GST_WARNING ("failed to read bytes, size:%d", length);    \
+      goto failed;                                              \
+    }                                                           \
+    memcpy (buf, vals, length);                                 \
+  } G_STMT_END
+
+#define U_READ_UINT8(reader, val) G_STMT_START {                \
+    (val) = gst_byte_reader_get_uint8_unchecked(reader);        \
+  } G_STMT_END
+
+#define U_READ_UINT16(reader, val) G_STMT_START {               \
+    (val) = gst_byte_reader_get_uint16_be_unchecked(reader);    \
+  } G_STMT_END
+
+
+/* Table used to address an 8x8 matrix in zig-zag order */
+/* *INDENT-OFF* */
+static const guint8 zigzag_index[64] = {
+  0,   1,  8, 16,  9,  2,  3, 10,
+  17, 24, 32, 25, 18, 11,  4,  5,
+  12, 19, 26, 33, 40, 48, 41, 34,
+  27, 20, 13,  6,  7, 14, 21, 28,
+  35, 42, 49, 56, 57, 50, 43, 36,
+  29, 22, 15, 23, 30, 37, 44, 51,
+  58, 59, 52, 45, 38, 31, 39, 46,
+  53, 60, 61, 54, 47, 55, 62, 63
+};
+/* *INDENT-ON* */
+
+/* Table K.1 - Luminance quantization table */
+/* *INDENT-OFF* */
+static const guint8 default_luminance_quant_table[64] = {
+  16,  11,  10,  16,  24,  40,  51,  61,
+  12,  12,  14,  19,  26,  58,  60,  55,
+  14,  13,  16,  24,  40,  57,  69,  56,
+  14,  17,  22,  29,  51,  87,  80,  62,
+  18,  22,  37,  56,  68, 109, 103,  77,
+  24,  35,  55,  64,  81, 104, 113,  92,
+  49,  64,  78,  87, 103, 121, 120, 101,
+  72,  92,  95,  98, 112, 100, 103,  99
+};
+/* *INDENT-ON* */
+
+/* Table K.2 - Chrominance quantization table */
+/* *INDENT-OFF* */
+static const guint8 default_chrominance_quant_table[64] = {
+  17,  18,  24,  47,  99,  99,  99,  99,
+  18,  21,  26,  66,  99,  99,  99,  99,
+  24,  26,  56,  99,  99,  99,  99,  99,
+  47,  66,  99,  99,  99,  99,  99,  99,
+  99,  99,  99,  99,  99,  99,  99,  99,
+  99,  99,  99,  99,  99,  99,  99,  99,
+  99,  99,  99,  99,  99,  99,  99,  99,
+  99,  99,  99,  99,  99,  99,  99,  99
+};
+/* *INDENT-ON* */
+
+typedef struct _GstJpegHuffmanTableEntry GstJpegHuffmanTableEntry;
+struct _GstJpegHuffmanTableEntry
+{
+  guint8 value;                 /* category */
+  guint8 length;                /* code length in bits */
+};
+
+/* Table K.3 - Table for luminance DC coefficient differences */
+static const GstJpegHuffmanTableEntry default_luminance_dc_table[] = {
+  {0x00, 2}, {0x01, 3}, {0x02, 3}, {0x03, 3}, {0x04, 3}, {0x05, 3},
+  {0x06, 4}, {0x07, 5}, {0x08, 6}, {0x09, 7}, {0x0a, 8}, {0x0b, 9}
+};
+
+/* Table K.4 - Table for chrominance DC coefficient differences */
+static const GstJpegHuffmanTableEntry default_chrominance_dc_table[] = {
+  {0x00, 2}, {0x01, 2}, {0x02, 2}, {0x03, 3}, {0x04, 4}, {0x05, 5},
+  {0x06, 6}, {0x07, 7}, {0x08, 8}, {0x09, 9}, {0x0a, 10}, {0x0b, 11}
+};
+
+/* Table K.5 - Table for luminance AC coefficients */
+/* *INDENT-OFF* */
+static const GstJpegHuffmanTableEntry default_luminance_ac_table[] = {
+  {0x00,  4}, {0x01,  2}, {0x02,  2}, {0x03,  3}, {0x04,  4}, {0x05,  5},
+  {0x06,  7}, {0x07,  8}, {0x08, 10}, {0x09, 16}, {0x0a, 16}, {0x11,  4},
+  {0x12,  5}, {0x13,  7}, {0x14,  9}, {0x15, 11}, {0x16, 16}, {0x17, 16},
+  {0x18, 16}, {0x19, 16}, {0x1a, 16}, {0x21,  5}, {0x22,  8}, {0x23, 10},
+  {0x24, 12}, {0x25, 16}, {0x26, 16}, {0x27, 16}, {0x28, 16}, {0x29, 16},
+  {0x2a, 16}, {0x31,  6}, {0x32,  9}, {0x33, 12}, {0x34, 16}, {0x35, 16},
+  {0x36, 16}, {0x37, 16}, {0x38, 16}, {0x39, 16}, {0x3a, 16}, {0x41,  6},
+  {0x42, 10}, {0x43, 16}, {0x44, 16}, {0x45, 16}, {0x46, 16}, {0x47, 16},
+  {0x48, 16}, {0x49, 16}, {0x4a, 16}, {0x51,  7}, {0x52, 11}, {0x53, 16},
+  {0x54, 16}, {0x55, 16}, {0x56, 16}, {0x57, 16}, {0x58, 16}, {0x59, 16},
+  {0x5a, 16}, {0x61,  7}, {0x62, 12}, {0x63, 16}, {0x64, 16}, {0x65, 16},
+  {0x66, 16}, {0x67, 16}, {0x68, 16}, {0x69, 16}, {0x6a, 16}, {0x71,  8},
+  {0x72, 12}, {0x73, 16}, {0x74, 16}, {0x75, 16}, {0x76, 16}, {0x77, 16},
+  {0x78, 16}, {0x79, 16}, {0x7a, 16}, {0x81,  9}, {0x82, 15}, {0x83, 16},
+  {0x84, 16}, {0x85, 16}, {0x86, 16}, {0x87, 16}, {0x88, 16}, {0x89, 16},
+  {0x8a, 16}, {0x91,  9}, {0x92, 16}, {0x93, 16}, {0x94, 16}, {0x95, 16},
+  {0x96, 16}, {0x97, 16}, {0x98, 16}, {0x99, 16}, {0x9a, 16}, {0xa1,  9},
+  {0xa2, 16}, {0xa3, 16}, {0xa4, 16}, {0xa5, 16}, {0xa6, 16}, {0xa7, 16},
+  {0xa8, 16}, {0xa9, 16}, {0xaa, 16}, {0xb1, 10}, {0xb2, 16}, {0xb3, 16},
+  {0xb4, 16}, {0xb5, 16}, {0xb6, 16}, {0xb7, 16}, {0xb8, 16}, {0xb9, 16},
+  {0xba, 16}, {0xc1, 10}, {0xc2, 16}, {0xc3, 16}, {0xc4, 16}, {0xc5, 16},
+  {0xc6, 16}, {0xc7, 16}, {0xc8, 16}, {0xc9, 16}, {0xca, 16}, {0xd1, 11},
+  {0xd2, 16}, {0xd3, 16}, {0xd4, 16}, {0xd5, 16}, {0xd6, 16}, {0xd7, 16},
+  {0xd8, 16}, {0xd9, 16}, {0xda, 16}, {0xe1, 16}, {0xe2, 16}, {0xe3, 16},
+  {0xe4, 16}, {0xe5, 16}, {0xe6, 16}, {0xe7, 16}, {0xe8, 16}, {0xe9, 16},
+  {0xea, 16}, {0xf0, 11}, {0xf1, 16}, {0xf2, 16}, {0xf3, 16}, {0xf4, 16},
+  {0xf5, 16}, {0xf6, 16}, {0xf7, 16}, {0xf8, 16}, {0xf9, 16}, {0xfa, 16}
+};
+/* *INDENT-ON* */
+
+/* Table K.6 - Table for chrominance AC coefficients */
+/* *INDENT-OFF* */
+static const GstJpegHuffmanTableEntry default_chrominance_ac_table[] = {
+  {0x00,  2}, {0x01,  2}, {0x02,  3}, {0x03,  4}, {0x04,  5}, {0x05,  5},
+  {0x06,  6}, {0x07,  7}, {0x08,  9}, {0x09, 10}, {0x0a, 12}, {0x11,  4},
+  {0x12,  6}, {0x13,  8}, {0x14,  9}, {0x15, 11}, {0x16, 12}, {0x17, 16},
+  {0x18, 16}, {0x19, 16}, {0x1a, 16}, {0x21,  5}, {0x22,  8}, {0x23, 10},
+  {0x24, 12}, {0x25, 15}, {0x26, 16}, {0x27, 16}, {0x28, 16}, {0x29, 16},
+  {0x2a, 16}, {0x31,  5}, {0x32,  8}, {0x33, 10}, {0x34, 12}, {0x35, 16},
+  {0x36, 16}, {0x37, 16}, {0x38, 16}, {0x39, 16}, {0x3a, 16}, {0x41,  6},
+  {0x42,  9}, {0x43, 16}, {0x44, 16}, {0x45, 16}, {0x46, 16}, {0x47, 16},
+  {0x48, 16}, {0x49, 16}, {0x4a, 16}, {0x51,  6}, {0x52, 10}, {0x53, 16},
+  {0x54, 16}, {0x55, 16}, {0x56, 16}, {0x57, 16}, {0x58, 16}, {0x59, 16},
+  {0x5a, 16}, {0x61,  7}, {0x62, 11}, {0x63, 16}, {0x64, 16}, {0x65, 16},
+  {0x66, 16}, {0x67, 16}, {0x68, 16}, {0x69, 16}, {0x6a, 16}, {0x71,  7},
+  {0x72, 11}, {0x73, 16}, {0x74, 16}, {0x75, 16}, {0x76, 16}, {0x77, 16},
+  {0x78, 16}, {0x79, 16}, {0x7a, 16}, {0x81,  8}, {0x82, 16}, {0x83, 16},
+  {0x84, 16}, {0x85, 16}, {0x86, 16}, {0x87, 16}, {0x88, 16}, {0x89, 16},
+  {0x8a, 16}, {0x91,  9}, {0x92, 16}, {0x93, 16}, {0x94, 16}, {0x95, 16},
+  {0x96, 16}, {0x97, 16}, {0x98, 16}, {0x99, 16}, {0x9a, 16}, {0xa1,  9},
+  {0xa2, 16}, {0xa3, 16}, {0xa4, 16}, {0xa5, 16}, {0xa6, 16}, {0xa7, 16},
+  {0xa8, 16}, {0xa9, 16}, {0xaa, 16}, {0xb1,  9}, {0xb2, 16}, {0xb3, 16},
+  {0xb4, 16}, {0xb5, 16}, {0xb6, 16}, {0xb7, 16}, {0xb8, 16}, {0xb9, 16},
+  {0xba, 16}, {0xc1,  9}, {0xc2, 16}, {0xc3, 16}, {0xc4, 16}, {0xc5, 16},
+  {0xc6, 16}, {0xc7, 16}, {0xc8, 16}, {0xc9, 16}, {0xca, 16}, {0xd1, 11},
+  {0xd2, 16}, {0xd3, 16}, {0xd4, 16}, {0xd5, 16}, {0xd6, 16}, {0xd7, 16},
+  {0xd8, 16}, {0xd9, 16}, {0xda, 16}, {0xe1, 14}, {0xe2, 16}, {0xe3, 16},
+  {0xe4, 16}, {0xe5, 16}, {0xe6, 16}, {0xe7, 16}, {0xe8, 16}, {0xe9, 16},
+  {0xea, 16}, {0xf0, 10}, {0xf1, 15}, {0xf2, 16}, {0xf3, 16}, {0xf4, 16},
+  {0xf5, 16}, {0xf6, 16}, {0xf7, 16}, {0xf8, 16}, {0xf9, 16}, {0xfa, 16}
+};
+/* *INDENT-ON* */
+
+static inline gboolean
+jpeg_parse_to_next_marker (GstByteReader * br, guint8 * marker)
+{
+  gint ofs;
+
+  ofs = gst_jpeg_scan_for_marker_code (br->data, br->size, br->byte);
+  if (ofs < 0)
+    return FALSE;
+
+  if (marker)
+    *marker = br->data[ofs + 1];
+  gst_byte_reader_skip (br, ofs - br->byte + 2);
+  return TRUE;
+}
+
+gint
+gst_jpeg_scan_for_marker_code (const guint8 * data, gsize size, guint offset)
+{
+  guint i;
+
+  g_return_val_if_fail (data != NULL, -1);
+  g_return_val_if_fail (size > offset, -1);
+
+  for (i = offset; i < size - 1;) {
+    if (data[i] != 0xff)
+      i++;
+    else {
+      const guint8 v = data[i + 1];
+      if (v >= 0xc0 && v <= 0xfe)
+        return i;
+      i += 2;
+    }
+  }
+  return -1;
+}
+
+gboolean
+gst_jpeg_parse_frame_hdr (GstJpegFrameHdr * frame_hdr,
+    const guint8 * data, gsize size, guint offset)
+{
+  GstByteReader br;
+  guint16 length;
+  guint8 val;
+  guint i;
+
+  g_return_val_if_fail (frame_hdr != NULL, FALSE);
+  g_return_val_if_fail (data != NULL, FALSE);
+  g_return_val_if_fail (size > offset, FALSE);
+
+  size -= offset;
+  gst_byte_reader_init (&br, &data[offset], size);
+  g_return_val_if_fail (size >= 8, FALSE);
+
+  U_READ_UINT16 (&br, length);  /* Lf */
+  g_return_val_if_fail (size >= length, FALSE);
+
+  U_READ_UINT8 (&br, frame_hdr->sample_precision);
+  U_READ_UINT16 (&br, frame_hdr->height);
+  U_READ_UINT16 (&br, frame_hdr->width);
+  U_READ_UINT8 (&br, frame_hdr->num_components);
+  g_return_val_if_fail (frame_hdr->num_components <=
+      GST_JPEG_MAX_SCAN_COMPONENTS, FALSE);
+
+  length -= 8;
+  g_return_val_if_fail (length >= 3 * frame_hdr->num_components, FALSE);
+  for (i = 0; i < frame_hdr->num_components; i++) {
+    U_READ_UINT8 (&br, frame_hdr->components[i].identifier);
+    U_READ_UINT8 (&br, val);
+    frame_hdr->components[i].horizontal_factor = (val >> 4) & 0x0F;
+    frame_hdr->components[i].vertical_factor = (val & 0x0F);
+    U_READ_UINT8 (&br, frame_hdr->components[i].quant_table_selector);
+    g_return_val_if_fail ((frame_hdr->components[i].horizontal_factor <= 4 &&
+            frame_hdr->components[i].vertical_factor <= 4 &&
+            frame_hdr->components[i].quant_table_selector < 4), FALSE);
+    length -= 3;
+  }
+
+  g_assert (length == 0);
+  return TRUE;
+}
+
+gboolean
+gst_jpeg_parse_scan_hdr (GstJpegScanHdr * scan_hdr,
+    const guint8 * data, gsize size, guint offset)
+{
+  GstByteReader br;
+  guint16 length;
+  guint8 val;
+  guint i;
+
+  g_return_val_if_fail (scan_hdr != NULL, FALSE);
+  g_return_val_if_fail (data != NULL, FALSE);
+  g_return_val_if_fail (size > offset, FALSE);
+
+  size -= offset;
+  gst_byte_reader_init (&br, &data[offset], size);
+  g_return_val_if_fail (size >= 3, FALSE);
+
+  U_READ_UINT16 (&br, length);  /* Ls */
+  g_return_val_if_fail (size >= length, FALSE);
+
+  U_READ_UINT8 (&br, scan_hdr->num_components);
+  g_return_val_if_fail (scan_hdr->num_components <=
+      GST_JPEG_MAX_SCAN_COMPONENTS, FALSE);
+
+  length -= 3;
+  g_return_val_if_fail (length >= 2 * scan_hdr->num_components, FALSE);
+  for (i = 0; i < scan_hdr->num_components; i++) {
+    U_READ_UINT8 (&br, scan_hdr->components[i].component_selector);
+    U_READ_UINT8 (&br, val);
+    scan_hdr->components[i].dc_selector = (val >> 4) & 0x0F;
+    scan_hdr->components[i].ac_selector = val & 0x0F;
+    g_return_val_if_fail ((scan_hdr->components[i].dc_selector < 4 &&
+            scan_hdr->components[i].ac_selector < 4), FALSE);
+    length -= 2;
+  }
+
+  /* FIXME: Ss, Se, Ah, Al */
+  g_assert (length == 3);
+  return TRUE;
+}
+
+gboolean
+gst_jpeg_parse_huffman_table (GstJpegHuffmanTables * huf_tables,
+    const guint8 * data, gsize size, guint offset)
+{
+  GstByteReader br;
+  GstJpegHuffmanTable *huf_table;
+  guint16 length;
+  guint8 val, table_class, table_index;
+  guint32 value_count;
+  guint i;
+
+  g_return_val_if_fail (huf_tables != NULL, FALSE);
+  g_return_val_if_fail (data != NULL, FALSE);
+  g_return_val_if_fail (size > offset, FALSE);
+
+  size -= offset;
+  gst_byte_reader_init (&br, &data[offset], size);
+  g_return_val_if_fail (size >= 2, FALSE);
+
+  U_READ_UINT16 (&br, length);  /* Lh */
+  g_return_val_if_fail (size >= length, FALSE);
+
+  while (gst_byte_reader_get_remaining (&br)) {
+    U_READ_UINT8 (&br, val);
+    table_class = ((val >> 4) & 0x0F);
+    table_index = (val & 0x0F);
+    g_return_val_if_fail (table_index < GST_JPEG_MAX_SCAN_COMPONENTS, FALSE);
+    if (table_class == 0) {
+      huf_table = &huf_tables->dc_tables[table_index];
+    } else {
+      huf_table = &huf_tables->ac_tables[table_index];
+    }
+    READ_BYTES (&br, huf_table->huf_bits, 16);
+    value_count = 0;
+    for (i = 0; i < 16; i++)
+      value_count += huf_table->huf_bits[i];
+    READ_BYTES (&br, huf_table->huf_values, value_count);
+    huf_table->valid = TRUE;
+  }
+  return TRUE;
+
+failed:
+  return FALSE;
+}
+
+gboolean
+gst_jpeg_parse_quant_table (GstJpegQuantTables * quant_tables,
+    const guint8 * data, gsize size, guint offset)
+{
+  GstByteReader br;
+  GstJpegQuantTable *quant_table;
+  guint16 length;
+  guint8 val, table_index;
+  guint i;
+
+  g_return_val_if_fail (quant_tables != NULL, FALSE);
+  g_return_val_if_fail (data != NULL, FALSE);
+  g_return_val_if_fail (size > offset, FALSE);
+
+  size -= offset;
+  gst_byte_reader_init (&br, &data[offset], size);
+  g_return_val_if_fail (size >= 2, FALSE);
+
+  U_READ_UINT16 (&br, length);  /* Lq */
+  g_return_val_if_fail (size >= length, FALSE);
+
+  while (gst_byte_reader_get_remaining (&br)) {
+    U_READ_UINT8 (&br, val);
+    table_index = (val & 0x0f);
+    g_return_val_if_fail (table_index < GST_JPEG_MAX_SCAN_COMPONENTS, FALSE);
+    quant_table = &quant_tables->quant_tables[table_index];
+    quant_table->quant_precision = ((val >> 4) & 0x0f);
+
+    g_return_val_if_fail (gst_byte_reader_get_remaining (&br) >=
+        GST_JPEG_MAX_QUANT_ELEMENTS * (1 + ! !quant_table->quant_precision),
+        FALSE);
+    for (i = 0; i < GST_JPEG_MAX_QUANT_ELEMENTS; i++) {
+      if (!quant_table->quant_precision) {      /* 8-bit values */
+        U_READ_UINT8 (&br, val);
+        quant_table->quant_table[i] = val;
+      } else {                  /* 16-bit values */
+        U_READ_UINT16 (&br, quant_table->quant_table[i]);
+      }
+    }
+    quant_table->valid = TRUE;
+  }
+  return TRUE;
+}
+
+gboolean
+gst_jpeg_parse_restart_interval (guint * interval,
+    const guint8 * data, gsize size, guint offset)
+{
+  GstByteReader br;
+  guint16 length, val;
+
+  g_return_val_if_fail (interval != NULL, FALSE);
+  g_return_val_if_fail (data != NULL, FALSE);
+  g_return_val_if_fail (size > offset, FALSE);
+
+  size -= offset;
+  gst_byte_reader_init (&br, &data[offset], size);
+  g_return_val_if_fail (size >= 4, FALSE);
+
+  U_READ_UINT16 (&br, length);  /* Lr */
+  g_return_val_if_fail (size >= length, FALSE);
+
+  U_READ_UINT16 (&br, val);
+  *interval = val;
+  return TRUE;
+}
+
+static int
+compare_huffman_table_entry (const void *a, const void *b)
+{
+  const GstJpegHuffmanTableEntry *const e1 = *(GstJpegHuffmanTableEntry **) a;
+  const GstJpegHuffmanTableEntry *const e2 = *(GstJpegHuffmanTableEntry **) b;
+
+  if (e1->length == e2->length)
+    return (gint) e1->value - (gint) e2->value;
+  return (gint) e1->length - (gint) e2->length;
+}
+
+static void
+build_huffman_table (GstJpegHuffmanTable * huf_table,
+    const GstJpegHuffmanTableEntry * entries, guint num_entries)
+{
+  const GstJpegHuffmanTableEntry *sorted_entries[256];
+  guint i, j, n;
+
+  g_assert (num_entries <= G_N_ELEMENTS (sorted_entries));
+
+  for (i = 0; i < num_entries; i++)
+    sorted_entries[i] = &entries[i];
+  qsort (sorted_entries, num_entries, sizeof (sorted_entries[0]),
+      compare_huffman_table_entry);
+
+  for (i = 0, j = 1, n = 0; i < num_entries; i++) {
+    const GstJpegHuffmanTableEntry *const e = sorted_entries[i];
+    if (e->length != j) {
+      huf_table->huf_bits[j++ - 1] = n;
+      for (; j < e->length; j++)
+        huf_table->huf_bits[j - 1] = 0;
+      n = 0;
+    }
+    huf_table->huf_values[i] = e->value;
+    n++;
+  }
+
+  for (; j < G_N_ELEMENTS (huf_table->huf_bits); j++)
+    huf_table->huf_bits[j] = 0;
+  for (; i < G_N_ELEMENTS (huf_table->huf_values); i++)
+    huf_table->huf_values[i] = 0;
+  huf_table->valid = TRUE;
+}
+
+void
+gst_jpeg_get_default_huffman_tables (GstJpegHuffmanTables * huf_tables)
+{
+  g_assert (huf_tables);
+
+  /* Build DC tables */
+  build_huffman_table (&huf_tables->dc_tables[0], default_luminance_dc_table,
+      G_N_ELEMENTS (default_luminance_dc_table));
+  build_huffman_table (&huf_tables->dc_tables[1], default_chrominance_dc_table,
+      G_N_ELEMENTS (default_chrominance_dc_table));
+  memcpy (&huf_tables->dc_tables[2], &huf_tables->dc_tables[1],
+      sizeof (huf_tables->dc_tables[2]));
+
+  /* Build AC tables */
+  build_huffman_table (&huf_tables->ac_tables[0], default_luminance_ac_table,
+      G_N_ELEMENTS (default_luminance_ac_table));
+  build_huffman_table (&huf_tables->ac_tables[1], default_chrominance_ac_table,
+      G_N_ELEMENTS (default_chrominance_ac_table));
+  memcpy (&huf_tables->ac_tables[2], &huf_tables->ac_tables[1],
+      sizeof (huf_tables->ac_tables[2]));
+}
+
+static void
+build_quant_table (GstJpegQuantTable * quant_table, const guint8 values[64])
+{
+  guint i;
+
+  for (i = 0; i < 64; i++)
+    quant_table->quant_table[i] = values[zigzag_index[i]];
+  quant_table->quant_precision = 0;     /* Pq = 0 (8-bit precision) */
+  quant_table->valid = TRUE;
+}
+
+void
+gst_jpeg_get_default_quantization_tables (GstJpegQuantTables * quant_tables)
+{
+  g_assert (quant_tables);
+
+  build_quant_table (&quant_tables->quant_tables[0],
+      default_luminance_quant_table);
+  build_quant_table (&quant_tables->quant_tables[1],
+      default_chrominance_quant_table);
+  build_quant_table (&quant_tables->quant_tables[2],
+      default_chrominance_quant_table);
+}
+
+gboolean
+gst_jpeg_parse (GstJpegMarkerSegment * seg,
+    const guint8 * data, gsize size, guint offset)
+{
+  GstByteReader br;
+  guint16 length;
+
+  g_return_val_if_fail (seg != NULL, FALSE);
+
+  if (size <= offset) {
+    GST_DEBUG ("failed to parse from offset %u, buffer is too small", offset);
+    return FALSE;
+  }
+
+  size -= offset;
+  gst_byte_reader_init (&br, &data[offset], size);
+
+  if (!jpeg_parse_to_next_marker (&br, &seg->marker)) {
+    GST_DEBUG ("failed to find marker code");
+    return FALSE;
+  }
+
+  seg->offset = offset + gst_byte_reader_get_pos (&br);
+  seg->size = -1;
+
+  /* Try to find end of segment */
+  switch (seg->marker) {
+    case GST_JPEG_MARKER_SOI:
+    case GST_JPEG_MARKER_EOI:
+    fixed_size_segment:
+      seg->size = 2;
+      break;
+
+    case (GST_JPEG_MARKER_SOF_MIN + 0):        /* Lf */
+    case (GST_JPEG_MARKER_SOF_MIN + 1):        /* Lf */
+    case (GST_JPEG_MARKER_SOF_MIN + 2):        /* Lf */
+    case (GST_JPEG_MARKER_SOF_MIN + 3):        /* Lf */
+    case (GST_JPEG_MARKER_SOF_MIN + 9):        /* Lf */
+    case (GST_JPEG_MARKER_SOF_MIN + 10):       /* Lf */
+    case (GST_JPEG_MARKER_SOF_MIN + 11):       /* Lf */
+    case GST_JPEG_MARKER_SOS:  /* Ls */
+    case GST_JPEG_MARKER_DQT:  /* Lq */
+    case GST_JPEG_MARKER_DHT:  /* Lh */
+    case GST_JPEG_MARKER_DAC:  /* La */
+    case GST_JPEG_MARKER_DRI:  /* Lr */
+    case GST_JPEG_MARKER_COM:  /* Lc */
+    case GST_JPEG_MARKER_DNL:  /* Ld */
+    variable_size_segment:
+      READ_UINT16 (&br, length);
+      seg->size = length;
+      break;
+
+    default:
+      /* Application data segment length (Lp) */
+      if (seg->marker >= GST_JPEG_MARKER_APP_MIN &&
+          seg->marker <= GST_JPEG_MARKER_APP_MAX)
+        goto variable_size_segment;
+
+      /* Restart markers (fixed size, two bytes only) */
+      if (seg->marker >= GST_JPEG_MARKER_RST_MIN &&
+          seg->marker <= GST_JPEG_MARKER_RST_MAX)
+        goto fixed_size_segment;
+
+      /* Fallback: scan for next marker */
+      if (!jpeg_parse_to_next_marker (&br, NULL))
+        goto failed;
+      seg->size = gst_byte_reader_get_pos (&br) - seg->offset;
+      break;
+  }
+  return TRUE;
+
+failed:
+  return FALSE;
+}
diff --git a/gst-libs/gst/codecparsers/gstjpegparser.h b/gst-libs/gst/codecparsers/gstjpegparser.h
new file mode 100644 (file)
index 0000000..7237584
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ *  gstjpegparser.h - JPEG parser
+ *
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_JPEG_PARSER_H
+#define GST_JPEG_PARSER_H
+
+#ifndef GST_USE_UNSTABLE_API
+#  warning "The JPEG parsing library is unstable API and may change in future."
+#  warning "You can define GST_USE_UNSTABLE_API to avoid this warning."
+#endif
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+/**
+ * GST_JPEG_MAX_FRAME_COMPONENTS:
+ *
+ * Maximum number of image components in a frame (Nf).
+ */
+#define GST_JPEG_MAX_FRAME_COMPONENTS   256
+
+/**
+ * GST_JPEG_MAX_SCAN_COMPONENTS:
+ *
+ * Maximum number of image components in a scan (Ns).
+ */
+#define GST_JPEG_MAX_SCAN_COMPONENTS    4
+
+/**
+ * GST_JPEG_MAX_QUANT_ELEMENTS:
+ *
+ * Number of elements in the quantization table.
+ */
+#define GST_JPEG_MAX_QUANT_ELEMENTS     64
+
+typedef struct _GstJpegQuantTable       GstJpegQuantTable;
+typedef struct _GstJpegQuantTables      GstJpegQuantTables;
+typedef struct _GstJpegHuffmanTable     GstJpegHuffmanTable;
+typedef struct _GstJpegHuffmanTables    GstJpegHuffmanTables;
+typedef struct _GstJpegScanComponent    GstJpegScanComponent;
+typedef struct _GstJpegScanHdr          GstJpegScanHdr;
+typedef struct _GstJpegFrameComponent   GstJpegFrameComponent;
+typedef struct _GstJpegFrameHdr         GstJpegFrameHdr;
+typedef struct _GstJpegMarkerSegment    GstJpegMarkerSegment;
+
+/**
+ * GstJpegMarkerCode:
+ * @GST_JPEG_MARKER_SOF_MIN: Start of frame min marker code
+ * @GST_JPEG_MARKER_SOF_MAX: Start of frame max marker code
+ * @GST_JPEG_MARKER_DHT: Huffman tabler marker code
+ * @GST_JPEG_MARKER_DAC: Arithmetic coding marker code
+ * @GST_JPEG_MARKER_RST_MIN: Restart interval min marker code
+ * @GST_JPEG_MARKER_RST_MAX: Restart interval max marker code
+ * @GST_JPEG_MARKER_SOI: Start of image marker code
+ * @GST_JPEG_MARKER_EOI: End of image marker code
+ * @GST_JPEG_MARKER_SOS: Start of scan marker code
+ * @GST_JPEG_MARKER_DQT: Define quantization table marker code
+ * @GST_JPEG_MARKER_DNL: Define number of lines marker code
+ * @GST_JPEG_MARKER_DRI: Define restart interval marker code
+ * @GST_JPEG_MARKER_APP_MIN: Application segment min marker code
+ * @GST_JPEG_MARKER_APP_MAX: Application segment max marker code
+ * @GST_JPEG_MARKER_COM: Comment marker code
+ *
+ * Indicates the type of JPEG segment.
+ */
+typedef enum {
+  GST_JPEG_MARKER_SOF_MIN       = 0xC0,
+  GST_JPEG_MARKER_SOF_MAX       = 0xCF,
+  GST_JPEG_MARKER_DHT           = 0xC4,
+  GST_JPEG_MARKER_DAC           = 0xCC,
+  GST_JPEG_MARKER_RST_MIN       = 0xD0,
+  GST_JPEG_MARKER_RST_MAX       = 0xD7,
+  GST_JPEG_MARKER_SOI           = 0xD8,
+  GST_JPEG_MARKER_EOI           = 0xD9,
+  GST_JPEG_MARKER_SOS           = 0xDA,
+  GST_JPEG_MARKER_DQT           = 0xDB,
+  GST_JPEG_MARKER_DNL           = 0xDC,
+  GST_JPEG_MARKER_DRI           = 0xDD,
+  GST_JPEG_MARKER_APP_MIN       = 0xE0,
+  GST_JPEG_MARKER_APP_MAX       = 0xEF,
+  GST_JPEG_MARKER_COM           = 0xFE,
+} GstJpegMarkerCode;
+
+/**
+ * GstJpegProfile:
+ * @GST_JPEG_PROFILE_BASELINE: Baseline DCT
+ * @GST_JPEG_PROFILE_EXTENDED: Extended sequential DCT
+ * @GST_JPEG_PROFILE_PROGRESSIVE: Progressive DCT
+ * @GST_JPEG_PROFILE_LOSSLESS: Lossless (sequential)
+ *
+ * JPEG encoding processes.
+ */
+typedef enum {
+  GST_JPEG_PROFILE_BASELINE     = 0x00,
+  GST_JPEG_PROFILE_EXTENDED     = 0x01,
+  GST_JPEG_PROFILE_PROGRESSIVE  = 0x02,
+  GST_JPEG_PROFILE_LOSSLESS     = 0x03,
+} GstJpegProfile;
+
+/**
+ * GstJpegEntropyCodingMode:
+ * @GST_JPEG_ENTROPY_CODING_HUFFMAN: Huffman coding
+ * @GST_JPEG_ENTROPY_CODING_ARITHMETIC: arithmetic coding
+ *
+ * JPEG entropy coding mode.
+ */
+typedef enum {
+  GST_JPEG_ENTROPY_CODING_HUFFMAN       = 0x00,
+  GST_JPEG_ENTROPY_CODING_ARITHMETIC    = 0x08
+} GstJpegEntropyCodingMode;
+
+/**
+ * GstJpegQuantTable:
+ * @quant_precision: Quantization table element precision (Pq)
+ * @quant_table: Quantization table elements (Qk)
+ * @valid: If the quantization table is valid, which means it has
+ *   already been parsed
+ *
+ * Quantization table.
+ */
+struct _GstJpegQuantTable
+{
+  guint8 quant_precision;
+  guint16 quant_table[GST_JPEG_MAX_QUANT_ELEMENTS];
+  gboolean valid;
+};
+
+/**
+ * GstJpegQuantTables:
+ * @quant_tables: All quantization tables
+ *
+ * Helper data structure that holds all quantization tables used to
+ * decode an image.
+ */
+struct _GstJpegQuantTables
+{
+  GstJpegQuantTable quant_tables[GST_JPEG_MAX_SCAN_COMPONENTS];
+};
+
+/**
+ * GstJpegHuffmanTable:
+ * @huf_bits: Number of Huffman codes of length i + 1 (Li)
+ * @huf_vales: Value associated with each Huffman code (Vij)
+ * @valid: If the Huffman table is valid, which means it has already
+ *   been parsed
+ *
+ * Huffman table.
+ */
+struct _GstJpegHuffmanTable
+{
+  guint8 huf_bits[16];
+  guint8 huf_values[256];
+  gboolean valid;
+};
+
+/**
+ * GstJpegHuffmanTables:
+ * @dc_tables: DC Huffman tables
+ * @ac_tables: AC Huffman tables
+ *
+ * Helper data structure that holds all AC/DC Huffman tables used to
+ * decode an image.
+ */
+struct _GstJpegHuffmanTables
+{
+  GstJpegHuffmanTable dc_tables[GST_JPEG_MAX_SCAN_COMPONENTS];
+  GstJpegHuffmanTable ac_tables[GST_JPEG_MAX_SCAN_COMPONENTS];
+};
+
+/**
+ * GstJpegScanComponent:
+ * @component_selector: Scan component selector (Csj)
+ * @dc_selector: DC entropy coding table destination selector (Tdj)
+ * @ac_selector: AC entropy coding table destination selector (Taj)
+
+ * Component-specification parameters.
+ */
+struct _GstJpegScanComponent
+{
+    guint8 component_selector;          /* 0 .. 255     */
+    guint8 dc_selector;                 /* 0 .. 3       */
+    guint8 ac_selector;                 /* 0 .. 3       */
+};
+
+/**
+ * GstJpegScanHdr:
+ * @num_components: Number of image components in scan (Ns)
+ * @components: Image components
+ *
+ * Scan header.
+ */
+struct _GstJpegScanHdr
+{
+  guint8 num_components;                /* 1 .. 4       */
+  GstJpegScanComponent components[GST_JPEG_MAX_SCAN_COMPONENTS];
+};
+
+/**
+ * GstJpegFrameComponent:
+ * @identifier: Component identifier (Ci)
+ * @horizontal_factor: Horizontal sampling factor (Hi)
+ * @vertical_factor: Vertical sampling factor (Vi)
+ * @quant_table_selector: Quantization table destination selector (Tqi)
+ *
+ * Component-specification parameters.
+ */
+struct _GstJpegFrameComponent
+{
+  guint8 identifier;                    /* 0 .. 255     */
+  guint8 horizontal_factor;             /* 1 .. 4       */
+  guint8 vertical_factor;               /* 1 .. 4       */
+  guint8 quant_table_selector;          /* 0 .. 3       */
+};
+
+/**
+ * GstJpegFrameHdr:
+ * @sample_precision: Sample precision (P)
+ * @height: Number of lines (Y)
+ * @width: Number of samples per line (X)
+ * @num_components: Number of image components in frame (Nf)
+ * @components: Image components
+ * @restart_interval: Number of MCU in the restart interval (Ri)
+ *
+ * Frame header.
+ */
+struct _GstJpegFrameHdr
+{
+  guint8 sample_precision;              /* 2 .. 16      */
+  guint16 width;                        /* 1 .. 65535   */
+  guint16 height;                       /* 0 .. 65535   */
+  guint8 num_components;                /* 1 .. 255     */
+  GstJpegFrameComponent components[GST_JPEG_MAX_FRAME_COMPONENTS];
+};
+
+/**
+ * GstJpegMarkerSegment:
+ * @type: The type of the segment that starts at @offset
+ * @offset: The offset to the segment start in bytes. This is the
+ *   exact start of the segment, no marker code included
+ * @size: The size in bytes of the segment, or -1 if the end was not
+ *   found. It is the exact size of the segment, no marker code included
+ *
+ * A structure that contains the type of a segment, its offset and its size.
+ */
+struct _GstJpegMarkerSegment
+{
+  guint8 marker;
+  guint offset;
+  gint size;
+};
+
+/**
+ * gst_jpeg_scan_for_marker_code:
+ * @data: The data to parse
+ * @size: The size of @data
+ * @offset: The offset from which to start parsing
+ *
+ * Scans the JPEG bitstream contained in @data for the next marker
+ * code. If found, the function returns an offset to the marker code,
+ * including the 0xff prefix code but excluding any extra fill bytes.
+ *
+ * Returns: offset to the marker code if found, or -1 if not found.
+ */
+gint            gst_jpeg_scan_for_marker_code   (const guint8 * data,
+                                                 gsize size,
+                                                 guint offset);
+
+/**
+ * gst_jpeg_parse:
+ * @data: The data to parse
+ * @size: The size of @data
+ * @offset: The offset from which to start parsing
+ *
+ * Parses the JPEG bitstream contained in @data, and returns the
+ * detected segment as a #GstJpegMarkerSegment.
+ *
+ * Returns: TRUE if a packet start code was found.
+ */
+gboolean        gst_jpeg_parse                  (GstJpegMarkerSegment * seg,
+                                                 const guint8 * data,
+                                                 gsize size,
+                                                 guint offset);
+
+/**
+ * gst_jpeg_parse_frame_hdr:
+ * @hdr: (out): The #GstJpegFrameHdr structure to fill in
+ * @data: The data from which to parse the frame header
+ * @size: The size of @data
+ * @offset: The offset in bytes from which to start parsing @data
+ *
+ * Parses the @hdr JPEG frame header structure members from @data.
+ *
+ * Returns: TRUE if the frame header was correctly parsed.
+ */
+gboolean        gst_jpeg_parse_frame_hdr        (GstJpegFrameHdr * hdr,
+                                                 const guint8 * data,
+                                                 gsize size,
+                                                 guint offset);
+
+/**
+ * gst_jpeg_parse_scan_hdr:
+ * @hdr: (out): The #GstJpegScanHdr structure to fill in
+ * @data: The data from which to parse the scan header
+ * @size: The size of @data
+ * @offset: The offset in bytes from which to start parsing @data
+ *
+ * Parses the @hdr JPEG scan header structure members from @data.
+ *
+ * Returns: TRUE if the scan header was correctly parsed
+ */
+gboolean        gst_jpeg_parse_scan_hdr         (GstJpegScanHdr * hdr,
+                                                 const guint8 * data,
+                                                 gsize size,
+                                                 guint offset);
+
+/**
+ * gst_jpeg_parse_quantization_table:
+ * @quant_tables: (out): The #GstJpegQuantizationTable structure to fill in
+ * @num_quant_tables: The number of allocated quantization tables in @quant_tables
+ * @data: The data from which to parse the quantization table
+ * @size: The size of @data
+ * @offset: The offset in bytes from which to start parsing @data
+ *
+ * Parses the JPEG quantization table structure members from @data.
+ *
+ * Note: @quant_tables represents the complete set of possible
+ * quantization tables. However, the parser will only write to the
+ * quantization table specified by the table destination identifier
+ * (Tq). While doing so, the @valid flag of the specified quantization
+ * table will also be set to %TRUE.
+ *
+ * Returns: TRUE if the quantization table was correctly parsed.
+ */
+gboolean        gst_jpeg_parse_quant_table      (GstJpegQuantTables *quant_tables,
+                                                 const guint8 * data,
+                                                 gsize size,
+                                                 guint offset);
+
+/**
+ * gst_jpeg_parse_huffman_table:
+ * @huf_tables: (out): The #GstJpegHuffmanTable structure to fill in
+ * @data: The data from which to parse the Huffman table
+ * @size: The size of @data
+ * @offset: The offset in bytes from which to start parsing @data
+ *
+ * Parses the JPEG Huffman table structure members from @data.
+ *
+ * Note: @huf_tables represents the complete set of possible Huffman
+ * tables. However, the parser will only write to the Huffman table
+ * specified by the table destination identifier (Th). While doing so,
+ * the @valid flag of the specified Huffman table will also be set to
+ * %TRUE;
+ *
+ * Returns: TRUE if the Huffman table was correctly parsed.
+ */
+gboolean        gst_jpeg_parse_huffman_table    (GstJpegHuffmanTables *huf_tables,
+                                                 const guint8 * data,
+                                                 gsize size,
+                                                 guint offset);
+
+/**
+ * gst_jpeg_parse_restart_interval:
+ * @interval: (out): The parsed restart interval value
+ * @data: The data from which to parse the restart interval specification
+ * @size: The size of @data
+ * @offset: The offset in bytes from which to start parsing @data
+ *
+ * Returns: TRUE if the restart interval value was correctly parsed.
+ */
+gboolean        gst_jpeg_parse_restart_interval (guint * interval,
+                                                 const guint8 * data,
+                                                 gsize size,
+                                                 guint offset);
+
+/**
+ * gst_jpeg_get_default_huffman_tables:
+ * @huf_tables: (out): The default DC/AC Huffman tables to fill in
+ *
+ * Fills in @huf_tables with the default AC/DC Huffman tables, as
+ * specified by the JPEG standard.
+ */
+void gst_jpeg_get_default_huffman_tables (GstJpegHuffmanTables *huf_tables);
+
+/**
+ * gst_jpeg_get_default_quantization_table:
+ * @quant_tables: (out): The default luma/chroma quant-tables in zigzag mode
+ *
+ * Fills in @quant_tables with the default quantization tables, as
+ * specified by the JPEG standard.
+ */
+void gst_jpeg_get_default_quantization_tables (GstJpegQuantTables *quant_tables);
+
+G_END_DECLS
+
+#endif /* GST_JPEG_PARSER_H */
index 0984d1c..76ff704 100644 (file)
 lib_LTLIBRARIES = libgstvaapi-@GST_MAJORMINOR@.la
 
-libgstvaapi_@GST_MAJORMINOR@_la_SOURCES = \
-       $(NULL)
+if USE_DRM
+lib_LTLIBRARIES += libgstvaapi-drm-@GST_MAJORMINOR@.la
+endif
+
+if USE_X11
+lib_LTLIBRARIES += libgstvaapi-x11-@GST_MAJORMINOR@.la
+endif
+
+if USE_GLX
+lib_LTLIBRARIES += libgstvaapi-glx-@GST_MAJORMINOR@.la
+endif
 
-libgstvaapi_@GST_MAJORMINOR@includedir = \
+if USE_WAYLAND
+lib_LTLIBRARIES += libgstvaapi-wayland-@GST_MAJORMINOR@.la
+endif
+
+libgstvaapi_includedir =                       \
        $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/vaapi
 
-libgstvaapi_@GST_MAJORMINOR@include_HEADERS = \
+libgstvaapi_cflags =                           \
+       -DGST_USE_UNSTABLE_API                  \
+       -I$(top_srcdir)/gst-libs                \
+       $(GST_BASE_CFLAGS)                      \
+       $(GST_BASEVIDEO_CFLAGS)                 \
+       $(GST_VIDEO_CFLAGS)                     \
+       $(GST_CFLAGS)                           \
+       $(GST_CODEC_PARSERS_CFLAGS)             \
+       $(LIBVA_CFLAGS)                         \
+       $(LIBVA_TPI_CFLAGS)                             \
+       $(NULL)
+
+libgstvaapi_libs =                             \
+       $(GST_BASE_LIBS)                        \
+       $(GST_BASEVIDEO_LIBS)                   \
+       $(GST_LIBS)                             \
+       $(GST_VIDEO_LIBS)                       \
+       $(GST_CODEC_PARSERS_LIBS)               \
+       $(LIBVA_LIBS)                           \
+       $(LIBVA_TPI_LIBS)                               \
+       $(NULL)
+
+libgstvaapi_source_c =                         \
+       gstvaapicodec_objects.c                 \
+       gstvaapicontext.c                       \
+       gstvaapidecoder.c                       \
+       gstvaapidecoder_dpb.c                   \
+       gstvaapidecoder_h264.c                  \
+       gstvaapidecoder_mpeg2.c                 \
+       gstvaapidecoder_mpeg4.c                 \
+       gstvaapidecoder_objects.c               \
+       gstvaapidecoder_vc1.c                   \
+       gstvaapidisplay.c                       \
+       gstvaapidisplaycache.c                  \
+       gstvaapiimage.c                         \
+       gstvaapiimageformat.c                   \
+       gstvaapiimagepool.c                     \
+       gstvaapiobject.c                        \
+       gstvaapiparamspecs.c                    \
+       gstvaapiprofile.c                       \
+       gstvaapisubpicture.c                    \
+       gstvaapisurface.c                       \
+       gstvaapisurfacepool.c                   \
+       gstvaapisurfaceproxy.c                  \
+       gstvaapisurface_userptr.c                       \
+       gstvaapiutils.c                         \
+       gstvaapivalue.c                         \
+       gstvaapivideobuffer.c                   \
+       gstvaapivideopool.c                     \
+       gstvaapiwindow.c                        \
+       $(NULL)
+
+libgstvaapi_source_h =                         \
+       gstvaapicontext.h                       \
+       gstvaapidecoder.h                       \
+       gstvaapidecoder_h264.h                  \
+       gstvaapidecoder_mpeg2.h                 \
+       gstvaapidecoder_mpeg4.h                 \
+       gstvaapidecoder_vc1.h                   \
+       gstvaapidisplay.h                       \
+       gstvaapidisplaycache.h                  \
+       gstvaapiimage.h                         \
+       gstvaapiimageformat.h                   \
+       gstvaapiimagepool.h                     \
+       gstvaapiobject.h                        \
+       gstvaapiparamspecs.h                    \
+       gstvaapiprofile.h                       \
+       gstvaapisubpicture.h                    \
+       gstvaapisurface.h                       \
+       gstvaapisurfacepool.h                   \
+       gstvaapisurfaceproxy.h                  \
+       gstvaapisurface_userptr.h                       \
+       gstvaapitypes.h                         \
+       gstvaapivalue.h                         \
+       gstvaapivideobuffer.h                   \
+       gstvaapivideopool.h                     \
+       gstvaapiwindow.h                        \
+       $(NULL)
+
+if USE_ENCODERS
+libgstvaapi_source_c +=         \
+    gstvaapiencoder.c           \
+    gstvaapibaseencoder.c       \
+    gstvaapiencoder_h264.c      \
+    gstvaapiencoder_h263.c      \
+    gstvaapiencoder_mpeg4.c     \
+    $(NULL)
+
+libgstvaapi_source_h +=         \
+       gstvaapiencoder.h           \
+    gstvaapibaseencoder.h       \
+    gstvaapiencoder_h264.h      \
+    gstvaapiencoder_h263.h      \
+    gstvaapiencoder_mpeg4.h     \
+    $(NULL)
+
+endif
+
+libgstvaapi_source_priv_h =                    \
+       glibcompat.h                            \
+       gstvaapi_priv.h                         \
+       gstvaapicodec_objects.h                 \
+       gstvaapicompat.h                        \
+       gstvaapidebug.h                         \
+       gstvaapidecoder_dpb.h                   \
+       gstvaapidecoder_objects.h               \
+       gstvaapidecoder_priv.h                  \
+       gstvaapidisplay_priv.h                  \
+       gstvaapiobject_priv.h                   \
+       gstvaapisurface_priv.h                  \
+       gstvaapiutils.h                         \
+       gstvaapivideobuffer_priv.h              \
+       gstvaapiworkarounds.h                   \
+       sysdeps.h                               \
+       $(NULL)
+
+if USE_JPEG_DECODER
+libgstvaapi_source_c += gstvaapidecoder_jpeg.c
+libgstvaapi_source_h += gstvaapidecoder_jpeg.h
+endif
+
+libgstvaapi_drm_source_c =                     \
+       gstvaapidisplay_drm.c                   \
+       gstvaapiwindow_drm.c                    \
+       gstvaapiutils.c                         \
+       $(NULL)
+
+libgstvaapi_drm_source_h =                     \
+       gstvaapidisplay_drm.h                   \
+       gstvaapiwindow_drm.h                    \
+       $(NULL)
+
+libgstvaapi_drm_source_priv_h =                        \
+       gstvaapicompat.h                        \
+       gstvaapidisplay_drm_priv.h              \
+       gstvaapiutils.h                         \
+       $(NULL)
+
+libgstvaapi_x11_source_c =                     \
+       gstvaapidisplay_x11.c                   \
+       gstvaapiutils.c                         \
+       gstvaapiutils_x11.c                     \
+       gstvaapiwindow_x11.c                    \
+       $(NULL)
+
+libgstvaapi_x11_source_h =                     \
+       gstvaapidisplay_x11.h                   \
+       gstvaapiwindow_x11.h                    \
+       $(NULL)
+
+libgstvaapi_x11_source_priv_h =                        \
+       gstvaapicompat.h                        \
+       gstvaapidisplay_x11_priv.h              \
+       gstvaapiutils.h                         \
+       gstvaapiutils_x11.h                     \
+       $(NULL)
+
+libgstvaapi_glx_source_c =                     \
+       gstvaapidisplay_glx.c                   \
+       gstvaapitexture.c                       \
+       gstvaapiutils.c                         \
+       gstvaapiutils_glx.c                     \
+       gstvaapiutils_x11.c                     \
+       gstvaapivideobuffer_glx.c               \
+       gstvaapivideoconverter_glx.c            \
+       gstvaapiwindow_glx.c                    \
+       $(NULL)
+
+libgstvaapi_glx_source_h =                     \
+       gstvaapidisplay_glx.h                   \
+       gstvaapitexture.h                       \
+       gstvaapivideobuffer_glx.h               \
+       gstvaapivideoconverter_glx.h            \
+       gstvaapiwindow_glx.h                    \
+       $(NULL)
+
+libgstvaapi_glx_source_priv_h =                        \
+       gstvaapicompat.h                        \
+       gstvaapidisplay_glx_priv.h              \
+       gstvaapiutils.h                         \
+       gstvaapiutils_glx.h                     \
+       gstvaapiutils_x11.h                     \
+       $(NULL)
+
+libgstvaapi_wayland_source_c =                 \
+       gstvaapidisplay_wayland.c               \
+       gstvaapiutils.c                         \
+       gstvaapiwindow_wayland.c                \
+       $(NULL)
+
+libgstvaapi_wayland_source_h =                 \
+       gstvaapidisplay_wayland.h               \
+       gstvaapiwindow_wayland.h                \
+       $(NULL)
+
+libgstvaapi_wayland_source_priv_h =            \
+       gstvaapicompat.h                        \
+       gstvaapidisplay_wayland_priv.h          \
+       gstvaapiutils.h                         \
+       $(NULL)
+
+if USE_LOCAL_CODEC_PARSERS
+libgstvaapi_libs += \
+       $(top_builddir)/gst-libs/gst/codecparsers/libgstvaapi-codecparsers.la
+endif
+
+libgstvaapi_@GST_MAJORMINOR@_la_SOURCES =      \
+       $(libgstvaapi_source_c)                 \
+       $(libgstvaapi_source_priv_h)            \
+       $(NULL)
+
+libgstvaapi_@GST_MAJORMINOR@include_HEADERS =  \
+       $(libgstvaapi_source_h)                 \
+       $(NULL)
+
+libgstvaapi_@GST_MAJORMINOR@includedir =       \
+       $(libgstvaapi_includedir)
+
+libgstvaapi_@GST_MAJORMINOR@_la_CFLAGS =       \
+       $(libgstvaapi_cflags)                   \
+       $(NULL)
+
+libgstvaapi_@GST_MAJORMINOR@_la_LIBADD =       \
+       $(libgstvaapi_libs)                     \
+       $(NULL)
+
+libgstvaapi_@GST_MAJORMINOR@_la_LDFLAGS =      \
+       $(GST_ALL_LDFLAGS)                      \
+       $(NULL)
+
+libgstvaapi_drm_@GST_MAJORMINOR@_la_SOURCES =  \
+       $(libgstvaapi_drm_source_c)             \
+       $(libgstvaapi_drm_source_priv_h)        \
+       $(NULL)
+
+libgstvaapi_drm_@GST_MAJORMINOR@include_HEADERS = \
+       $(libgstvaapi_drm_source_h)             \
+       $(NULL)
+
+libgstvaapi_drm_@GST_MAJORMINOR@includedir =   \
+       $(libgstvaapi_includedir)
+
+libgstvaapi_drm_@GST_MAJORMINOR@_la_CFLAGS =   \
+       -DGST_USE_UNSTABLE_API                  \
+       -I$(top_srcdir)/gst-libs                \
+       $(GLIB_CFLAGS)                          \
+       $(GST_BASE_CFLAGS)                      \
+       $(UDEV_CFLAGS)                          \
+       $(DRM_CFLAGS)                           \
+       $(LIBVA_DRM_CFLAGS)                     \
+       $(NULL)
+
+libgstvaapi_drm_@GST_MAJORMINOR@_la_LIBADD =   \
+       $(GLIB_LIBS)                            \
+       $(UDEV_LIBS)                            \
+       $(DRM_LIBS)                             \
+       $(LIBVA_DRM_LIBS)                       \
+       libgstvaapi-@GST_MAJORMINOR@.la         \
+       $(NULL)
+
+libgstvaapi_drm_@GST_MAJORMINOR@_la_LDFLAGS =  \
+       $(GST_ALL_LDFLAGS)                      \
+       $(NULL)
+
+libgstvaapi_x11_@GST_MAJORMINOR@_la_SOURCES =  \
+       $(libgstvaapi_x11_source_c)             \
+       $(libgstvaapi_x11_source_priv_h)        \
+       $(NULL)
+
+libgstvaapi_x11_@GST_MAJORMINOR@include_HEADERS = \
+       $(libgstvaapi_x11_source_h)             \
+       $(NULL)
+
+libgstvaapi_x11_@GST_MAJORMINOR@includedir =   \
+       $(libgstvaapi_includedir)
+
+libgstvaapi_x11_@GST_MAJORMINOR@_la_CFLAGS =   \
+       -DGST_USE_UNSTABLE_API                  \
+       -I$(top_srcdir)/gst-libs                \
+       $(GLIB_CFLAGS)                          \
+       $(GST_BASE_CFLAGS)                      \
+       $(X11_CFLAGS)                           \
+       $(XRANDR_CFLAGS)                        \
+       $(LIBVA_X11_CFLAGS)                     \
+       $(NULL)
+
+libgstvaapi_x11_@GST_MAJORMINOR@_la_LIBADD =   \
+       $(GLIB_LIBS)                            \
+       $(X11_LIBS)                             \
+       $(XRANDR_LIBS)                          \
+       $(LIBVA_X11_LIBS)                       \
+       libgstvaapi-@GST_MAJORMINOR@.la         \
+       $(NULL)
+
+libgstvaapi_x11_@GST_MAJORMINOR@_la_LDFLAGS =  \
+       $(GST_ALL_LDFLAGS)                      \
+       $(NULL)
+
+libgstvaapi_glx_@GST_MAJORMINOR@_la_SOURCES =  \
+       $(libgstvaapi_glx_source_c)             \
+       $(libgstvaapi_glx_source_priv_h)        \
+       $(NULL)
+
+libgstvaapi_glx_@GST_MAJORMINOR@include_HEADERS = \
+       $(libgstvaapi_glx_source_h)             \
+       $(NULL)
+
+libgstvaapi_glx_@GST_MAJORMINOR@includedir =   \
+       $(libgstvaapi_includedir)
+
+libgstvaapi_glx_@GST_MAJORMINOR@_la_CFLAGS =   \
+       -DGST_USE_UNSTABLE_API                  \
+       -I$(top_srcdir)/gst-libs                \
+       $(GLIB_CFLAGS)                          \
+       $(GST_BASE_CFLAGS)                      \
+       $(GL_CFLAGS)                            \
+       $(LIBVA_GLX_CFLAGS)                     \
+       $(NULL)
+
+libgstvaapi_glx_@GST_MAJORMINOR@_la_LIBADD =   \
+       $(GLIB_LIBS)                            \
+       $(GL_LIBS)                              \
+       $(LIBVA_GLX_LIBS)                       \
+       libgstvaapi-x11-@GST_MAJORMINOR@.la     \
+       $(NULL)
+
+libgstvaapi_glx_@GST_MAJORMINOR@_la_LDFLAGS =  \
+       $(GST_ALL_LDFLAGS)                      \
+       $(NULL)
+
+libgstvaapi_wayland_@GST_MAJORMINOR@_la_SOURCES = \
+       $(libgstvaapi_wayland_source_c)         \
+       $(libgstvaapi_wayland_source_priv_h)    \
+       $(NULL)
+
+libgstvaapi_wayland_@GST_MAJORMINOR@include_HEADERS = \
+       $(libgstvaapi_wayland_source_h)         \
+       $(NULL)
+
+libgstvaapi_wayland_@GST_MAJORMINOR@includedir = \
+       $(libgstvaapi_includedir)
+
+libgstvaapi_wayland_@GST_MAJORMINOR@_la_CFLAGS = \
+       -DGST_USE_UNSTABLE_API                  \
+       -I$(top_srcdir)/gst-libs                \
+       $(GLIB_CFLAGS)                          \
+       $(GST_BASE_CFLAGS)                      \
+       $(WAYLAND_CFLAGS)                       \
+       $(LIBVA_WAYLAND_CFLAGS)                 \
+       $(NULL)
+
+libgstvaapi_wayland_@GST_MAJORMINOR@_la_LIBADD = \
+       $(GLIB_LIBS)                            \
+       $(WAYLAND_LIBS)                         \
+       $(LIBVA_WAYLAND_LIBS)                   \
+       libgstvaapi-@GST_MAJORMINOR@.la         \
+       $(NULL)
+
+libgstvaapi_wayland_@GST_MAJORMINOR@_la_LDFLAGS = \
+       $(GST_ALL_LDFLAGS)                      \
        $(NULL)
 
 # Extra clean files so that maintainer-clean removes *everything*
diff --git a/gst-libs/gst/vaapi/glibcompat.h b/gst-libs/gst/vaapi/glibcompat.h
new file mode 100644 (file)
index 0000000..30a8563
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ *  glibcompat.h - System-dependent definitions
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GLIB_COMPAT_H
+#define GLIB_COMPAT_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#if !GLIB_CHECK_VERSION(2,27,2)
+static inline void
+g_list_free_full(GList *list, GDestroyNotify free_func)
+{
+    g_list_foreach(list, (GFunc)free_func, NULL);
+    g_list_free(list);
+}
+#endif
+
+#if !GLIB_CHECK_VERSION(2,28,0)
+static inline void
+g_clear_object_inline(volatile GObject **object_ptr)
+{
+    gpointer * const ptr = (gpointer)object_ptr;
+    gpointer old;
+
+    do {
+        old = g_atomic_pointer_get(ptr);
+    } while G_UNLIKELY(!g_atomic_pointer_compare_and_exchange(ptr, old, NULL));
+
+    if (old)
+        g_object_unref(old);
+}
+#undef  g_clear_object
+#define g_clear_object(obj) g_clear_object_inline((volatile GObject **)(obj))
+#endif
+
+#if GLIB_CHECK_VERSION(2,31,2)
+#define GStaticMutex                    GMutex
+#undef  g_static_mutex_init
+#define g_static_mutex_init(mutex)      g_mutex_init(mutex)
+#undef  g_static_mutex_free
+#define g_static_mutex_free(mutex)      g_mutex_clear(mutex)
+#undef  g_static_mutex_lock
+#define g_static_mutex_lock(mutex)      g_mutex_lock(mutex)
+#undef  g_static_mutex_unlock
+#define g_static_mutex_unlock(mutex)    g_mutex_unlock(mutex)
+
+#define GStaticRecMutex                 GRecMutex
+#undef  g_static_rec_mutex_init
+#define g_static_rec_mutex_init(mutex)  g_rec_mutex_init(mutex)
+#undef  g_static_rec_mutex_free
+#define g_static_rec_mutex_free(mutex)  g_rec_mutex_clear(mutex)
+#undef  g_static_rec_mutex_lock
+#define g_static_rec_mutex_lock(mutex)  g_rec_mutex_lock(mutex)
+#undef  g_static_rec_mutex_unlock
+#define g_static_rec_mutex_unlock(m)    g_rec_mutex_unlock(m)
+#endif
+
+#endif /* GLIB_COMPAT_H */
diff --git a/gst-libs/gst/vaapi/gstvaapi_priv.h b/gst-libs/gst/vaapi/gstvaapi_priv.h
new file mode 100644 (file)
index 0000000..8416b83
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  gstvaapi_priv.h - Helper to include all private headers
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_PRIV_H
+#define GST_VAAPI_PRIV_H
+
+#include <gst/vaapi/gstvaapiobject_priv.h>
+#include <gst/vaapi/gstvaapidisplay_priv.h>
+
+#endif /* GST_VAAPI_PRIV_H */
diff --git a/gst-libs/gst/vaapi/gstvaapibaseencoder.c b/gst-libs/gst/vaapi/gstvaapibaseencoder.c
new file mode 100644 (file)
index 0000000..d4fefec
--- /dev/null
@@ -0,0 +1,1006 @@
+/*
+ *  gstvaapibaseencoder.c - VA-API base encoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "gstvaapibaseencoder.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <glib-object.h>
+
+#include <X11/Xlib.h>
+
+#include <va/va.h>
+#include "va/va_x11.h"
+
+#include "gst/gstclock.h"
+#include "gst/gstvalue.h"
+
+#include "gstvaapiobject.h"
+#include "gstvaapiobject_priv.h"
+#include "gstvaapicontext.h"
+#include "gstvaapisurface.h"
+#include "gstvaapisurfacepool.h"
+#include "gstvaapivideobuffer.h"
+#include "gstvaapidisplay_priv.h"
+#include "gstvaapidebug.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_vaapi_base_encoder_debug);
+#define GST_CAT_DEFAULT gst_vaapi_base_encoder_debug
+
+#define VA_INVALID_PROFILE 0xffffffff
+#define DEFAULT_VA_CODEDBUF_NUM  4
+#define GST_VAAPI_ENCODER_SURFACE_COUNT 3
+
+#define GST_VAAPI_BASE_ENCODER_LOCK(encoder)              \
+    G_STMT_START {                                        \
+      g_static_rec_mutex_lock(                            \
+        &((GstVaapiBaseEncoder*)(encoder))->priv->mutex); \
+    } G_STMT_END
+
+#define GST_VAAPI_BASE_ENCODER_UNLOCK(encoder)             \
+    G_STMT_START {                                         \
+      g_static_rec_mutex_unlock(                           \
+        &((GstVaapiBaseEncoder*)(encoder))->priv->mutex);  \
+    } G_STMT_END
+
+struct _GstVaapiBaseEncoderPrivate {
+  guint32           format;   /*NV12, I420,*/
+  VAProfile         profile;
+  /*total encoded frames*/
+  guint32           frame_count;
+  VABufferID       *coded_bufs;
+  guint32           coded_buf_num;
+  GStaticRecMutex   mutex;
+  GQueue           *idle_buf_queue;
+  GQueue           *busy_buf_queue;
+
+  GstVaapiSurfacePool            *surfaces_pool;
+  GstVaapiBaseEncoderNotifyStatus notify_status;
+  gpointer                        user_data;
+
+  guint             buffer_sharing_flag : 1;
+  guint             buffer_notify_flag : 1;
+  guint             need_flush        : 1;
+};
+
+G_DEFINE_TYPE(GstVaapiBaseEncoder, gst_vaapi_base_encoder, GST_TYPE_VAAPI_ENCODER)
+
+typedef struct _GstVaapiEncoderBufferInfo      GstVaapiEncoderBufferInfo;
+typedef struct _GstVaapiEncoderBufferInfoClass GstVaapiEncoderBufferInfoClass;
+
+#define GST_TYPE_VAAPI_ENCODER_BUFFER_INFO  \
+    (gst_vaapi_encoder_buffer_info_get_type())
+
+#define GST_VAAPI_ENCODER_BUFFER_INFO(obj)                          \
+    (G_TYPE_CHECK_INSTANCE_CAST ((obj),                             \
+                                 GST_TYPE_VAAPI_ENCODER_BUFFER_INFO,\
+                                 GstVaapiEncoderBufferInfo))
+
+struct _GstVaapiEncoderBufferInfo {
+  GObject              base;
+  GstVaapiBaseEncoder *encoder;
+  VABufferID          *id;
+  GstClockTime         timestamp;
+  GstClockTime         duration;
+
+  void                *data;
+
+  guint32              is_key    : 1;
+  guint32              is_mapped : 1;
+};
+
+struct _GstVaapiEncoderBufferInfoClass {
+  GObjectClass   base_class;
+};
+
+G_DEFINE_TYPE(
+    GstVaapiEncoderBufferInfo,
+    gst_vaapi_encoder_buffer_info,
+    G_TYPE_OBJECT)
+
+static gboolean
+gst_vaapi_encoder_buffer_info_map(
+    GstVaapiEncoderBufferInfo *info,
+    void **buf
+)
+{
+  g_return_val_if_fail(info, FALSE);
+  g_return_val_if_fail(info->encoder && info->id && buf, FALSE);
+
+  GstVaapiDisplay *display = ENCODER_DISPLAY(info->encoder);
+  VADisplay va_dpy = ENCODER_VA_DISPLAY(info->encoder);
+  VAStatus va_status = VA_STATUS_SUCCESS;
+
+  if (info->is_mapped)
+    return TRUE;
+
+  GST_VAAPI_DISPLAY_LOCK(display);
+  va_status = vaMapBuffer(va_dpy, *info->id, &info->data);
+  GST_VAAPI_DISPLAY_UNLOCK(display);
+
+  g_return_val_if_fail(va_status == VA_STATUS_SUCCESS, FALSE);
+  info->is_mapped = TRUE;
+  *buf = info->data;
+  return TRUE;
+}
+
+static gboolean
+gst_vaapi_encoder_buffer_info_unmap(
+    GstVaapiEncoderBufferInfo *info
+)
+{
+  g_return_val_if_fail(info, FALSE);
+  g_return_val_if_fail(info->encoder && info->id, FALSE);
+
+  GstVaapiDisplay *display = ENCODER_DISPLAY(info->encoder);
+  VADisplay va_dpy = ENCODER_VA_DISPLAY(info->encoder);
+  VAStatus va_status = VA_STATUS_SUCCESS;
+
+  if (!info->is_mapped)
+    return TRUE;
+
+  GST_VAAPI_DISPLAY_LOCK(display);
+  va_status = vaUnmapBuffer(va_dpy, *info->id);
+  GST_VAAPI_DISPLAY_UNLOCK(display);
+  info->data = NULL;
+  info->is_mapped = FALSE;
+
+  g_return_val_if_fail(va_status == VA_STATUS_SUCCESS, FALSE);
+  return TRUE;
+}
+
+static GstVaapiEncoderBufferInfo*
+pop_busy_buffer_info(GstVaapiBaseEncoder *encoder)
+{
+  GstVaapiBaseEncoderPrivate *priv = encoder->priv;
+  GstVaapiEncoderBufferInfo *info = NULL;
+
+  g_return_val_if_fail(priv->busy_buf_queue, NULL);
+
+  GST_VAAPI_BASE_ENCODER_LOCK(encoder);
+
+  if (g_queue_is_empty(priv->busy_buf_queue))
+    goto end;
+
+  info = (GstVaapiEncoderBufferInfo*)g_queue_pop_head(priv->busy_buf_queue);
+
+end:
+  GST_VAAPI_BASE_ENCODER_UNLOCK(encoder);
+  return info;
+}
+
+static void
+push_busy_buffer_info(
+    GstVaapiBaseEncoder *encoder,
+    GstVaapiEncoderBufferInfo *info)
+{
+  GstVaapiBaseEncoderPrivate *priv = encoder->priv;
+
+  GST_VAAPI_BASE_ENCODER_LOCK(encoder);
+  g_queue_push_tail(priv->busy_buf_queue, info);
+  GST_VAAPI_BASE_ENCODER_UNLOCK(encoder);
+}
+
+static VABufferID *
+pop_idle_buffer_id(GstVaapiBaseEncoder *encoder)
+{
+  GstVaapiBaseEncoderPrivate *priv = encoder->priv;
+  VABufferID *coded_buf = NULL;
+
+  g_return_val_if_fail(priv->idle_buf_queue, NULL);
+
+  GST_VAAPI_BASE_ENCODER_LOCK(encoder);
+
+  if (g_queue_is_empty(priv->idle_buf_queue))
+    goto end;
+
+  coded_buf = (VABufferID*)g_queue_pop_head(priv->idle_buf_queue);
+
+end:
+  GST_VAAPI_BASE_ENCODER_UNLOCK(encoder);
+  return coded_buf;
+}
+
+static void
+push_idle_buffer_id(
+    GstVaapiBaseEncoder *encoder,
+    VABufferID *buf
+)
+{
+  GstVaapiBaseEncoderPrivate *priv = encoder->priv;
+
+  GST_VAAPI_BASE_ENCODER_LOCK(encoder);
+  g_queue_push_tail(priv->idle_buf_queue, buf);
+  GST_VAAPI_BASE_ENCODER_UNLOCK(encoder);
+}
+
+static void
+gst_vaapi_encoder_buffer_info_init(
+    GstVaapiEncoderBufferInfo *info
+)
+{
+    info->encoder   = NULL;
+    info->id        = NULL;
+    info->timestamp = 0;
+    info->duration  = 0;
+    info->data      = NULL;
+    info->is_key    = FALSE;
+    info->is_mapped = FALSE;
+}
+
+static void
+gst_vaapi_encoder_buffer_info_finalize(GObject *object)
+{
+  GstVaapiEncoderBufferInfo *info = GST_VAAPI_ENCODER_BUFFER_INFO(object);
+
+  if (info->id && *info->id != VA_INVALID_ID && info->encoder) {
+    if (info->is_mapped)
+      gst_vaapi_encoder_buffer_info_unmap(info);
+    push_idle_buffer_id(info->encoder, info->id);
+  }
+
+  if (info->encoder) {
+    g_object_unref(info->encoder);
+    info->encoder = NULL;
+  }
+  info->id = NULL;
+}
+
+static GstVaapiEncoderBufferInfo*
+gst_vaapi_encoder_buffer_info_new(
+    GstVaapiBaseEncoder *encoder
+)
+{
+    GstVaapiEncoderBufferInfo *ret;
+
+    g_return_val_if_fail(encoder, NULL);
+
+    ret = GST_VAAPI_ENCODER_BUFFER_INFO(
+            g_object_new(GST_TYPE_VAAPI_ENCODER_BUFFER_INFO,
+                         NULL));
+    if (!ret)
+        return NULL;
+    ret->encoder = g_object_ref(encoder);
+    return ret;
+}
+
+static void
+gst_vaapi_encoder_buffer_info_class_init(
+    GstVaapiEncoderBufferInfoClass *klass
+)
+{
+  GObjectClass * const obj_class = G_OBJECT_CLASS(klass);
+
+  obj_class->finalize = gst_vaapi_encoder_buffer_info_finalize;
+}
+
+void
+gst_vaapi_base_encoder_set_frame_notify(
+    GstVaapiBaseEncoder *encoder,
+    gboolean flag
+)
+{
+  GstVaapiBaseEncoderPrivate *priv = encoder->priv;
+  priv->buffer_notify_flag = flag;
+}
+
+gboolean
+gst_vaapi_base_encoder_set_va_profile(
+    GstVaapiBaseEncoder *encoder,
+    guint profile
+)
+{
+  GstVaapiBaseEncoderPrivate *priv = encoder->priv;
+  priv->profile = profile;
+  return TRUE;
+}
+
+void
+gst_vaapi_base_encoder_set_input_format(
+    GstVaapiBaseEncoder* encoder,
+    guint32 format
+)
+{
+  GstVaapiBaseEncoderPrivate *priv = encoder->priv;
+  priv->format = format;
+}
+
+gboolean
+gst_vaapi_base_encoder_set_notify_status(
+    GstVaapiBaseEncoder *encoder,
+    GstVaapiBaseEncoderNotifyStatus func,
+    gpointer             user_data
+)
+{
+  GstVaapiBaseEncoderPrivate *priv = encoder->priv;
+
+  priv->notify_status = func;
+  priv->user_data = user_data;
+  return TRUE;
+}
+
+void
+gst_vaapi_base_encoder_set_buffer_sharing(
+    GstVaapiBaseEncoder *encoder,
+    gboolean is_buffer_sharing
+)
+{
+  GstVaapiBaseEncoderPrivate *priv = encoder->priv;
+
+  priv->buffer_sharing_flag = is_buffer_sharing;
+}
+
+static gboolean
+default_validate_encoder_parameters(
+    GstVaapiBaseEncoder *encoder
+)
+{
+  if (!ENCODER_WIDTH(encoder) ||
+      !ENCODER_HEIGHT(encoder) ||
+      !ENCODER_FPS(encoder)) {
+    return FALSE;
+  }
+  return TRUE;
+}
+
+static gboolean
+base_encoder_alloc_coded_buffers(
+    GstVaapiBaseEncoder *base_encoder,
+    GstVaapiContext *context
+)
+{
+  GstVaapiBaseEncoderPrivate *priv = base_encoder->priv;
+  VADisplay va_dpy;
+  VAContextID context_id;
+  VAStatus va_status = VA_STATUS_SUCCESS;
+  guint i = 0;
+  gboolean ret = TRUE;
+  guint32 buffer_size =
+      (ENCODER_WIDTH(base_encoder) * ENCODER_HEIGHT(base_encoder) * 400) /
+      (16*16);
+
+  ENCODER_ASSERT(context);
+  ENCODER_ASSERT(priv->idle_buf_queue);
+  ENCODER_ASSERT(!priv->coded_bufs);
+
+  va_dpy = ENCODER_VA_DISPLAY(base_encoder);
+  context_id = gst_vaapi_context_get_id(context);
+
+  priv->coded_bufs = (VABufferID*)
+      g_malloc0(priv->coded_buf_num * sizeof(priv->coded_bufs[0]));
+
+  for (i = 0; i < priv->coded_buf_num; i++) {
+    va_status = vaCreateBuffer(va_dpy,
+                               context_id,
+                               VAEncCodedBufferType,
+                               buffer_size, 1,
+                               NULL,
+                               &priv->coded_bufs[i]);
+    if (VA_STATUS_SUCCESS != va_status)
+      break;
+  }
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+                       FALSE,
+                       "create coded buffer failed.");
+
+  /* init queue idle_buf_queue */
+  GST_VAAPI_BASE_ENCODER_LOCK(base_encoder);
+  for (i = 0; i < priv->coded_buf_num; i++) {
+    g_queue_push_head(priv->idle_buf_queue, &priv->coded_bufs[i]);
+  }
+  GST_VAAPI_BASE_ENCODER_UNLOCK(base_encoder);
+
+end:
+  return ret;
+
+}
+
+static EncoderStatus
+release_coded_buffers(GstVaapiBaseEncoder *base_encoder)
+{
+  VAStatus va_status = VA_STATUS_SUCCESS;
+  GstVaapiBaseEncoderPrivate *priv = base_encoder->priv;
+  GstVaapiDisplay *display = ENCODER_DISPLAY(base_encoder);
+  guint32 available_buf_count = priv->coded_buf_num;
+  GstVaapiEncoderBufferInfo *info;
+  guint32 i;
+
+  ENCODER_ASSERT(display);
+  VAAPI_UNUSED_ARG(va_status);
+  VADisplay va_dpy = gst_vaapi_display_get_display(display);
+
+  /* wait clear all available coded buffers */
+  GST_VAAPI_BASE_ENCODER_LOCK(base_encoder);
+  if (available_buf_count) {
+    while (!g_queue_is_empty(priv->busy_buf_queue)) {
+      info = (GstVaapiEncoderBufferInfo*)g_queue_pop_head(priv->busy_buf_queue);
+      g_object_unref(info);
+    }
+    while(!g_queue_is_empty(priv->idle_buf_queue)) {
+      g_queue_pop_head(priv->idle_buf_queue);
+      available_buf_count--;
+    }
+  }
+  GST_VAAPI_BASE_ENCODER_UNLOCK(base_encoder);
+  ENCODER_ASSERT(available_buf_count == 0);
+
+  for (i = 0; i < priv->coded_buf_num; i++) {
+    va_status = vaDestroyBuffer(va_dpy, priv->coded_bufs[i]);
+  }
+
+  return ENCODER_NO_ERROR;
+}
+
+static EncoderStatus
+gst_vaapi_base_encoder_close_default(GstVaapiEncoder* encoder)
+{
+  GstVaapiBaseEncoder* base_encoder = GST_VAAPI_BASE_ENCODER(encoder);
+  GstVaapiBaseEncoderClass *base_class =
+      GST_VAAPI_BASE_ENCODER_GET_CLASS(encoder);
+  GstVaapiBaseEncoderPrivate *priv = base_encoder->priv;
+  EncoderStatus ret = ENCODER_NO_ERROR;
+
+  /* release buffers first */
+  priv->need_flush = FALSE;
+
+  if (base_class->release_resource) {
+    base_class->release_resource(base_encoder);
+  }
+  release_coded_buffers(base_encoder);
+  priv->frame_count = 0;
+
+  return ret;
+}
+
+static EncoderStatus
+gst_vaapi_base_encoder_open_default(
+    GstVaapiEncoder* encoder,
+    GstVaapiContext **context
+)
+{
+  GstVaapiBaseEncoder* base_encoder = GST_VAAPI_BASE_ENCODER(encoder);
+  GstVaapiBaseEncoderClass *base_class =
+      GST_VAAPI_BASE_ENCODER_GET_CLASS(encoder);
+  GstVaapiBaseEncoderPrivate *priv = base_encoder->priv;
+  GstVaapiDisplay *display = ENCODER_DISPLAY(encoder);
+
+  GstVaapiContext *out_context = NULL;
+
+  EncoderStatus ret = ENCODER_NO_ERROR;
+  gboolean check_attri_ret = TRUE;
+  /*check and set default values*/
+  if (base_class->validate_attributes) {
+    check_attri_ret = base_class->validate_attributes(base_encoder);
+  } else {
+    check_attri_ret = default_validate_encoder_parameters(base_encoder);
+  }
+  ENCODER_CHECK_STATUS(check_attri_ret,
+                       ENCODER_PARAMETER_ERR,
+                       "vaapi encoder paramerter error.");
+  ENCODER_CHECK_STATUS(VA_INVALID_PROFILE != priv->profile,
+                       ENCODER_PROFILE_ERR,
+                       "vaapi encoder profile not set.");
+
+  ENCODER_ASSERT(ENCODER_DISPLAY(encoder));
+
+  out_context = gst_vaapi_context_new(display,
+                        gst_vaapi_profile(priv->profile),
+                        gst_vaapi_entrypoint(VAEntrypointEncSlice),
+                        ENCODER_RATE_CONTROL(encoder),
+                        ENCODER_WIDTH(encoder),
+                        ENCODER_HEIGHT(encoder),
+                        GST_VAAPI_ENCODER_SURFACE_COUNT);
+  ENCODER_CHECK_STATUS(out_context,
+                       ENCODER_CONTEXT_ERR,
+                       "gst_vaapi_context_new failed.");
+  ENCODER_CHECK_STATUS(VA_INVALID_ID != GST_VAAPI_OBJECT_ID(out_context),
+                       ENCODER_CONTEXT_ERR,
+                       "gst_vaapi_context_new failed.");
+
+  if (base_class->pre_alloc_resource) {
+    ENCODER_CHECK_STATUS(
+        base_class->pre_alloc_resource(base_encoder, out_context),
+        ENCODER_MEM_ERR,
+        "encoder <pre_alloc_resource> failed."
+    );
+  }
+  ENCODER_CHECK_STATUS(
+    base_encoder_alloc_coded_buffers(base_encoder, out_context),
+    ENCODER_MEM_ERR,
+    "encoder <base_encoder_alloc_coded_buffers> failed."
+  );
+  *context = out_context;
+
+  return ENCODER_NO_ERROR;
+
+end:
+  // clear resources
+  if (ENCODER_NO_ERROR != ret) {
+    gst_vaapi_base_encoder_close_default(encoder);
+    if (out_context) {
+      g_object_unref(out_context);
+    }
+  }
+  return ret;
+}
+
+static EncoderStatus
+query_encoding_status(
+    GstVaapiBaseEncoder *base_encoder,
+    GstVaapiSurface *buffer_surface
+)
+{
+  EncoderStatus ret = ENCODER_NO_ERROR;
+  GstVaapiSurfaceStatus surface_status;
+
+  ENCODER_CHECK_STATUS(gst_vaapi_surface_sync(buffer_surface),
+                       ENCODER_SURFACE_ERR,
+                       "gst_vaapi_surface_sync failed.");
+
+  ENCODER_CHECK_STATUS(
+      gst_vaapi_surface_query_status(buffer_surface, &surface_status),
+      ENCODER_SURFACE_ERR,
+      "gst_vaapi_surface_query_status failed."
+      );
+  if (GST_VAAPI_SURFACE_STATUS_SKIPPED & surface_status) {
+    ENCODER_LOG_ERROR("frame skipped"); /* not sure continue or not */
+  }
+
+  return ENCODER_NO_ERROR;
+
+end:
+  return ret;
+}
+
+static inline guint
+get_buf_list_size(VACodedBufferSegment *buf_list)
+{
+  guint size = 0;
+  while(buf_list) {
+    size += buf_list->size;
+    buf_list = (VACodedBufferSegment*)buf_list->next;
+  }
+  return size;
+}
+
+static inline guint
+move_buf_list_to_buf(
+    VACodedBufferSegment *buf_list,
+    guint8 *data,
+    guint max_len
+)
+{
+    guint left_size = max_len;
+    guint cur_size;
+    while (buf_list && left_size) {
+      if (buf_list->size <= left_size)
+        cur_size = buf_list->size;
+      else
+        cur_size = left_size;
+      memcpy(data, buf_list->buf, cur_size);
+      data += cur_size;
+      buf_list = (VACodedBufferSegment*)buf_list->next;
+      left_size -= cur_size;
+    }
+    return max_len - left_size;
+}
+
+static EncoderStatus
+gst_vaapi_base_encoder_get_coded_buffer(
+    GstVaapiEncoder* base,
+    GstBuffer **out_buf
+)
+{
+  GstVaapiBaseEncoder *encoder = GST_VAAPI_BASE_ENCODER(base);
+  GstVaapiBaseEncoderPrivate *priv = encoder->priv;
+  GstVaapiBaseEncoderClass   *klass =
+      GST_VAAPI_BASE_ENCODER_GET_CLASS(encoder);
+  GstVaapiEncoderBufferInfo* info;
+  EncoderStatus ret;
+  VACodedBufferSegment *buf_list = NULL;
+  GstBuffer* buffer = NULL;
+  guint buf_size;
+
+  while((info = pop_busy_buffer_info(encoder)) == NULL){
+    ret = ENCODER_NO_BUSY_BUF;
+    if (!priv->notify_status ||
+        !priv->notify_status(encoder, ret, priv->user_data))
+      goto end;
+  }
+  ret = ENCODER_NO_ERROR;
+
+  ENCODER_CHECK_STATUS(
+      info->id && *info->id != VA_INVALID_ID,
+      ENCODER_DATA_ERR,
+      "get invalid buffer info"
+      );
+
+  ENCODER_CHECK_STATUS(
+      gst_vaapi_encoder_buffer_info_map(info, (void**)&buf_list),
+      ENCODER_DATA_ERR,
+      "vaMapBuffer failed");
+
+  buf_size = get_buf_list_size(buf_list);
+  ENCODER_CHECK_STATUS(
+      buf_size,
+      ENCODER_DATA_ERR,
+      "encoded size:0");
+  buffer = gst_buffer_new_and_alloc(buf_size);
+  GST_BUFFER_SIZE(buffer) = move_buf_list_to_buf(
+                                buf_list,
+                                GST_BUFFER_DATA(buffer),
+                                buf_size);
+
+  if (priv->buffer_notify_flag && klass->notify_buffer) {
+    klass->notify_buffer(
+        encoder,
+        GST_BUFFER_DATA(buffer),
+        GST_BUFFER_SIZE(buffer));
+  }
+
+  if (klass->wrap_buffer) {
+    GstBuffer *new_buf = klass->wrap_buffer(encoder, buffer);
+    gst_buffer_unref(buffer);
+    buffer = new_buf;
+  }
+
+  if (buffer) {
+    GST_BUFFER_TIMESTAMP(buffer) = info->timestamp;
+    GST_BUFFER_DURATION(buffer) = info->duration;
+    if (!info->is_key)
+      GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT);
+  }
+  FPS_CALCULATION(vaapiencode);
+
+  *out_buf = buffer;
+
+end:
+  if (info) {
+    gst_vaapi_encoder_buffer_info_unmap(info);
+    g_object_unref(info);
+  }
+  return ret;
+}
+
+static GstVaapiVideoBuffer *
+_get_video_buffer(
+    GstVaapiBaseEncoder* encoder,
+    GstBuffer *buf
+)
+{
+  GstVaapiBaseEncoderPrivate *priv = encoder->priv;
+  GstBuffer *video_buffer;
+
+  if (priv->buffer_sharing_flag)
+    video_buffer = (GstBuffer *)buf->data;
+  else
+    video_buffer = buf;
+
+  if (GST_VAAPI_IS_VIDEO_BUFFER(video_buffer))
+    return GST_VAAPI_VIDEO_BUFFER(video_buffer);
+  return NULL;
+}
+
+static EncoderStatus
+gst_vaapi_base_encoder_encode_default(
+    GstVaapiEncoder* base,
+    GstBuffer *pic
+)
+{
+  GstVaapiBaseEncoder* encoder = GST_VAAPI_BASE_ENCODER(base);
+  GstVaapiBaseEncoderClass *base_class =
+      GST_VAAPI_BASE_ENCODER_GET_CLASS(encoder);
+  GstVaapiBaseEncoderPrivate *priv = encoder->priv;
+  GstVaapiDisplay *display = ENCODER_DISPLAY(encoder);
+  GstVaapiContext *context = ENCODER_CONTEXT(encoder);
+  EncoderStatus ret = ENCODER_NO_ERROR;
+  gboolean is_key = FALSE;
+  VABufferID* coded_buf = NULL;
+  GstVaapiSurface *buffer_surface = NULL;
+  gboolean is_prepared_buffer = FALSE;
+
+  ENCODER_ASSERT(display && context);
+
+  /* Video Buffer */
+  GstVaapiVideoBuffer *video_buffer = NULL;
+
+  ENCODER_CHECK_STATUS(pic || base_class->prepare_next_input_buffer,
+                       ENCODER_DATA_ERR,
+                       "Need a picture to encode");
+  if (!pic)
+    priv->need_flush = TRUE;
+
+again:
+  if (base_class->prepare_next_input_buffer) {
+    GstBuffer* tmp_buf = NULL;
+    ret = base_class->prepare_next_input_buffer(encoder,
+                                                pic,
+                                                priv->need_flush,
+                                                &tmp_buf);
+    priv->need_flush = FALSE;
+    if (ret != ENCODER_NO_ERROR || !tmp_buf)
+      goto end;
+
+    is_prepared_buffer = TRUE;
+    pic = tmp_buf;
+  }
+
+  video_buffer = _get_video_buffer(encoder, pic);
+  ENCODER_CHECK_STATUS(
+      video_buffer,
+      ENCODER_SURFACE_ERR,
+      "vaapi encoder doesn't has video buffer");
+
+  buffer_surface = gst_vaapi_video_buffer_get_surface(video_buffer);
+
+  while ((coded_buf = pop_idle_buffer_id(encoder)) == NULL) {
+    ret = ENCODER_NO_IDLE_BUF;
+    if (!priv->notify_status ||
+        !priv->notify_status(encoder, ret, priv->user_data))
+      goto end;
+  }
+  ret = ENCODER_NO_ERROR;
+
+  /* prepare frame*/
+  ret = base_class->render_frame(encoder,
+                                 buffer_surface,
+                                 priv->frame_count,
+                                 *coded_buf,
+                                 &is_key);
+  /* prepare failed, push back */
+  if (ENCODER_NO_ERROR != ret) {
+    push_idle_buffer_id(encoder, coded_buf);
+  }
+  ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret,
+                       ENCODER_PICTURE_ERR,
+                       "base_prepare_encoding failed");
+
+  /*query surface result*/
+  ret = query_encoding_status(encoder, buffer_surface);
+  if (ENCODER_NO_ERROR != ret) {
+    goto end;
+  }
+
+  /* Push coded buffer to another task */
+  GstVaapiEncoderBufferInfo* info = gst_vaapi_encoder_buffer_info_new(encoder);
+  info->id = coded_buf;
+  info->timestamp = GST_BUFFER_TIMESTAMP(pic);
+  info->duration = GST_BUFFER_DURATION(pic);
+  info->is_key = is_key;
+  push_busy_buffer_info(encoder, info);
+
+  priv->frame_count++;
+
+  if (is_prepared_buffer) {
+    if (pic)
+      gst_buffer_unref(pic);
+    pic = NULL;
+    buffer_surface = NULL;
+    coded_buf = NULL;
+    goto again;
+  }
+
+end:
+  if (ret < ENCODER_NO_ERROR && base_class->encode_frame_failed) {
+    base_class->encode_frame_failed(encoder, video_buffer);
+  }
+  if (pic && is_prepared_buffer)
+    gst_buffer_unref(pic);
+
+  return ret;
+}
+
+#if 0
+static EncoderStatus
+base_put_raw_buffer_to_surface(GstVaapiBaseEncoder *base_encoder,
+                               GstVaapiDisplay *display,
+                               GstBuffer *raw_pic,
+                               GstVaapiSurface *surface)
+{
+  EncoderStatus ret = ENCODER_NO_ERROR;
+  GstVaapiImage *image;
+  GstVaapiImageFormat image_format;
+  guint8 *y_src = NULL, *u_src = NULL, *v_src = NULL;
+  guint8 *y_dst = NULL, *u_dst = NULL, *v_dst = NULL;
+  int y_size = 0, u_size = 0;
+  int row = 0, col = 0;
+  guint32 plane_count = 0;
+  guint32 image_width = 0, image_height = 0;
+  guint32 pitchy = 0, pitchu = 0, pitchv = 0;
+  GstVaapiBaseEncoderPrivate *priv = base_encoder->priv;
+
+  ENCODER_ASSERT(display);
+  VAAPI_UNUSED_ARG(pitchv);
+  VAAPI_UNUSED_ARG(v_dst);
+  /*map image*/
+  image = gst_vaapi_surface_derive_image(surface);
+  gst_vaapi_image_map(image);
+
+  image_format = gst_vaapi_image_get_format(image);
+  image_width = gst_vaapi_image_get_width(image);
+  image_height = gst_vaapi_image_get_height(image);
+
+  /* copy buffer to surface */
+  ENCODER_ASSERT(GST_BUFFER_SIZE(raw_pic) >= y_size + (y_size>>1));
+
+  y_size = ENCODER_WIDTH(base_encoder) * ENCODER_HEIGHT(base_encoder);
+  u_size = ((ENCODER_WIDTH(base_encoder)+1) >> 1) * ((ENCODER_HEIGHT(base_encoder)+1) >> 1);
+
+  y_src = GST_BUFFER_DATA(raw_pic);
+  u_src = y_src + y_size;
+  v_src = u_src + u_size;
+
+  plane_count = gst_vaapi_image_get_plane_count(image);
+  y_dst = gst_vaapi_image_get_plane(image, 0);
+  u_dst = gst_vaapi_image_get_plane(image, 1);
+  pitchy = gst_vaapi_image_get_pitch(image, 0);
+  pitchu = gst_vaapi_image_get_pitch(image, 1);
+
+  if (plane_count > 2) {
+    v_dst = gst_vaapi_image_get_plane(image, 2);
+    pitchv = gst_vaapi_image_get_pitch(image, 2);
+  }
+
+  /* copy from avcenc.c*/
+  /* Y plane */
+  for (row = 0; row < image_height; row++) {
+      memcpy(y_dst, y_src, image_width);
+      y_dst += pitchy;
+      y_src += ENCODER_WIDTH(base_encoder);
+  }
+
+  if (GST_VAAPI_IMAGE_NV12 == image_format) { /* UV plane */
+    if (GST_VAAPI_IMAGE_I420 == priv->format) {
+      for (row = 0; row < image_height / 2; row++) {
+          for (col = 0; col < image_width / 2; col++) {
+              u_dst[col * 2] = u_src[col];
+              u_dst[col * 2 + 1] = v_src[col];
+          }
+
+          u_dst += pitchu;
+          u_src += (ENCODER_WIDTH(base_encoder)>>1);
+          v_src += (ENCODER_WIDTH(base_encoder)>>1);
+      }
+    } else if (GST_VAAPI_IMAGE_NV12 == priv->format){
+      for (row = 0; row < image_height / 2; row++) {
+        memcpy(u_dst, u_src, image_width);
+        u_src += ENCODER_WIDTH(base_encoder);
+        u_dst += pitchu;
+      }
+    } else {
+      ENCODER_ASSERT(0);
+    }
+  } else {
+      /* FIXME: fix this later */
+      ENCODER_ASSERT(0);
+  }
+
+  /*unmap image*/
+  g_object_unref(image);
+
+  return ret;
+}
+#endif
+
+static EncoderStatus
+gst_vaapi_base_encoder_flush_default(
+    GstVaapiEncoder* encoder
+)
+{
+  GstVaapiBaseEncoder* base_encoder = GST_VAAPI_BASE_ENCODER(encoder);
+  EncoderStatus ret = ENCODER_NO_ERROR;
+  GstVaapiBaseEncoderPrivate *priv = base_encoder->priv;
+
+  priv->frame_count = 0;
+  priv->need_flush = TRUE;
+  /*do we need destroy priv->seq_parameter? */
+
+  //end:
+  return ret;
+}
+
+
+static void
+gst_vaapi_base_encoder_finalize(GObject *object)
+{
+  /*free private buffers*/
+  GstVaapiEncoder *encoder = GST_VAAPI_ENCODER(object);
+  GstVaapiBaseEncoderPrivate *priv =
+      GST_VAAPI_BASE_ENCODER_GET_PRIVATE(object);
+
+  if (gst_vaapi_encoder_get_state(encoder) != VAAPI_ENC_NULL) {
+    gst_vaapi_encoder_uninitialize(encoder);
+  }
+
+  g_static_rec_mutex_free(&priv->mutex);
+  if (priv->idle_buf_queue)
+    g_queue_free(priv->idle_buf_queue);
+
+  if (priv->busy_buf_queue)
+    g_queue_free(priv->busy_buf_queue);
+
+  G_OBJECT_CLASS(gst_vaapi_base_encoder_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_base_encoder_init(GstVaapiBaseEncoder *encoder)
+{
+  GstVaapiBaseEncoderPrivate *priv =
+      GST_VAAPI_BASE_ENCODER_GET_PRIVATE(encoder);
+  ENCODER_ASSERT(priv);
+  encoder->priv = priv;
+
+  /* init private values*/
+  priv->format = 0;
+  priv->profile= VA_INVALID_PROFILE;
+  priv->frame_count = 0;
+  priv->buffer_sharing_flag = FALSE;
+  priv->buffer_notify_flag = FALSE;
+
+  priv->coded_bufs = NULL;
+  priv->coded_buf_num = DEFAULT_VA_CODEDBUF_NUM;
+  priv->idle_buf_queue = g_queue_new();
+  priv->busy_buf_queue = g_queue_new();
+  g_static_rec_mutex_init(&priv->mutex);
+
+  priv->notify_status = NULL;
+  priv->user_data = NULL;
+
+  priv->need_flush = FALSE;
+}
+
+static void
+gst_vaapi_base_encoder_class_init(GstVaapiBaseEncoderClass *klass)
+{
+  GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+  GstVaapiEncoderClass * const encoder_class = GST_VAAPI_ENCODER_CLASS(klass);
+  g_type_class_add_private(klass, sizeof(GstVaapiBaseEncoderPrivate));
+
+  GST_DEBUG_CATEGORY_INIT (gst_vaapi_base_encoder_debug,
+                           "gst_vaapi_base_encoder",
+                           0,
+                           "gst_vaapi_base_encoder element");
+
+  object_class->finalize = gst_vaapi_base_encoder_finalize;
+
+  encoder_class->open = gst_vaapi_base_encoder_open_default;
+  encoder_class->close = gst_vaapi_base_encoder_close_default;
+  encoder_class->encode = gst_vaapi_base_encoder_encode_default;
+  encoder_class->flush = gst_vaapi_base_encoder_flush_default;
+  encoder_class->get_buf = gst_vaapi_base_encoder_get_coded_buffer;
+  encoder_class->get_codec_data = NULL;
+
+  /* user defined functions*/
+  klass->validate_attributes = NULL;
+  klass->pre_alloc_resource = NULL;
+  klass->release_resource = NULL;
+  klass->prepare_next_input_buffer = NULL;
+  klass->render_frame = NULL;
+  klass->notify_buffer = NULL;
+  klass->wrap_buffer = NULL;
+  klass->encode_frame_failed = NULL;
+
+  /*
+  object_class->set_property = gst_vaapi_base_encoder_set_property;
+  object_class->get_property = gst_vaapi_base_encoder_get_property;
+  */
+}
diff --git a/gst-libs/gst/vaapi/gstvaapibaseencoder.h b/gst-libs/gst/vaapi/gstvaapibaseencoder.h
new file mode 100644 (file)
index 0000000..fe9679d
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ *  gstvaapibaseencoder.h - VA-API base encoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_BASE_ENCODER_H
+#define GST_VAAPI_BASE_ENCODER_H
+
+#include "gst/vaapi/gstvaapiencoder.h"
+#include "gst/vaapi/gstvaapivideobuffer.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GstVaapiBaseEncoder              GstVaapiBaseEncoder;
+typedef struct _GstVaapiBaseEncoderPrivate       GstVaapiBaseEncoderPrivate;
+typedef struct _GstVaapiBaseEncoderClass         GstVaapiBaseEncoderClass;
+
+#define GST_TYPE_VAAPI_BASE_ENCODER \
+    (gst_vaapi_base_encoder_get_type())
+
+#define GST_IS_VAAPI_BASE_ENCODER(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_BASE_ENCODER))
+
+#define GST_IS_VAAPI_BASE_ENCODER_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VAAPI_BASE_ENCODER))
+
+#define GST_VAAPI_BASE_ENCODER_GET_CLASS(obj)                  \
+    (G_TYPE_INSTANCE_GET_CLASS ((obj),                         \
+                                GST_TYPE_VAAPI_BASE_ENCODER,   \
+                                GstVaapiBaseEncoderClass))
+
+#define GST_VAAPI_BASE_ENCODER(obj)                            \
+(G_TYPE_CHECK_INSTANCE_CAST ((obj),                            \
+                             GST_TYPE_VAAPI_BASE_ENCODER,      \
+                             GstVaapiBaseEncoder))
+
+#define GST_VAAPI_BASE_ENCODER_CLASS(klass)                    \
+    (G_TYPE_CHECK_CLASS_CAST ((klass),                         \
+                              GST_TYPE_VAAPI_BASE_ENCODER,     \
+                              GstVaapiBaseEncoderClass))
+
+#define GST_VAAPI_BASE_ENCODER_GET_PRIVATE(obj)                \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                        \
+                                 GST_TYPE_VAAPI_BASE_ENCODER,  \
+                                 GstVaapiBaseEncoderPrivate))
+
+/* return: if true, continue; else, stop*/
+typedef gboolean
+  (*GstVaapiBaseEncoderNotifyStatus)(
+       GstVaapiBaseEncoder* encoder,
+       EncoderStatus status,
+       void* userdata);
+
+struct _GstVaapiBaseEncoder {
+  GstVaapiEncoder parent;
+
+  GstVaapiBaseEncoderPrivate *priv;
+};
+
+struct _GstVaapiBaseEncoderClass {
+  GstVaapiEncoderClass parent_class;
+
+  /* in <open> function*/
+  gboolean (*validate_attributes)   (GstVaapiBaseEncoder* encoder);
+  gboolean (*pre_alloc_resource)    (GstVaapiBaseEncoder *encoder,
+                                     GstVaapiContext* context);
+
+  /* in <close> function */
+  gboolean (*release_resource)      (GstVaapiBaseEncoder* encoder);
+
+  /* in <encode> function */
+  EncoderStatus (*prepare_next_input_buffer)(GstVaapiBaseEncoder* encoder,
+                                             GstBuffer *display_buf,
+                                             gboolean need_flush,
+                                             GstBuffer **out_buf);
+
+  EncoderStatus (*render_frame)     (GstVaapiBaseEncoder *encoder,
+                                     GstVaapiSurface *surface,
+                                     guint frame_index,
+                                     VABufferID coded_buf,
+                                     gboolean *is_key);
+
+  void (*encode_frame_failed)       (GstVaapiBaseEncoder *encoder,
+                                     GstVaapiVideoBuffer* buffer);
+
+  void (*notify_buffer)             (GstVaapiBaseEncoder *encoder,
+                                     guint8 *buf, guint32 size);
+
+  GstBuffer *(*wrap_buffer)         (GstVaapiBaseEncoder *encoder,
+                                     GstBuffer *buf);
+};
+
+GType
+gst_vaapi_base_encoder_get_type(void);
+
+void
+gst_vaapi_base_encoder_set_frame_notify(
+    GstVaapiBaseEncoder *encoder,
+    gboolean flag
+);
+
+gboolean
+gst_vaapi_base_encoder_set_va_profile(
+    GstVaapiBaseEncoder *encoder,
+    guint profile
+);
+void
+gst_vaapi_base_encoder_set_input_format(
+    GstVaapiBaseEncoder* encoder,
+    guint32 format
+);
+
+gboolean
+gst_vaapi_base_encoder_set_notify_status(
+    GstVaapiBaseEncoder *encoder,
+    GstVaapiBaseEncoderNotifyStatus func,
+    gpointer             user_data
+);
+
+void
+gst_vaapi_base_encoder_set_buffer_sharing(
+    GstVaapiBaseEncoder *encoder,
+    gboolean is_buffer_sharing
+);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_BASE_ENCODER_H */
diff --git a/gst-libs/gst/vaapi/gstvaapicodec_objects.c b/gst-libs/gst/vaapi/gstvaapicodec_objects.c
new file mode 100644 (file)
index 0000000..e79341d
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ *  gstvaapicodec_objects.c - VA codec objects abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "sysdeps.h"
+#include <string.h>
+#include <gst/vaapi/gstvaapicontext.h>
+#include "gstvaapicodec_objects.h"
+#include "gstvaapidecoder_priv.h"
+#include "gstvaapicompat.h"
+#include "gstvaapiutils.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+/* ------------------------------------------------------------------------- */
+/* --- Base Codec Object                                                 --- */
+/* ------------------------------------------------------------------------- */
+
+G_DEFINE_TYPE(GstVaapiCodecObject, gst_vaapi_codec_object, GST_TYPE_MINI_OBJECT)
+
+static void
+gst_vaapi_codec_object_finalize(GstMiniObject *object)
+{
+    GstVaapiCodecObject * const obj = GST_VAAPI_CODEC_OBJECT(object);
+
+    obj->codec = NULL;
+}
+
+static void
+gst_vaapi_codec_object_init(GstVaapiCodecObject *obj)
+{
+    obj->codec = NULL;
+}
+
+static gboolean
+gst_vaapi_codec_object_create(
+    GstVaapiCodecObject                      *obj,
+    const GstVaapiCodecObjectConstructorArgs *args
+)
+{
+    obj->codec = args->codec;
+    return TRUE;
+}
+
+static void
+gst_vaapi_codec_object_class_init(GstVaapiCodecObjectClass *klass)
+{
+    GstMiniObjectClass * const object_class = GST_MINI_OBJECT_CLASS(klass);
+
+    object_class->finalize = gst_vaapi_codec_object_finalize;
+    klass->construct       = gst_vaapi_codec_object_create;
+}
+
+GstVaapiCodecObject *
+gst_vaapi_codec_object_new(
+    GType              type,
+    GstVaapiCodecBase *codec,
+    gconstpointer      param,
+    guint              param_size,
+    gconstpointer      data,
+    guint              data_size
+)
+{
+    GstMiniObject *obj;
+    GstVaapiCodecObject *va_obj;
+    GstVaapiCodecObjectConstructorArgs args;
+
+    obj = gst_mini_object_new(type);
+    if (!obj)
+        return NULL;
+
+    va_obj = GST_VAAPI_CODEC_OBJECT(obj);
+    args.codec      = codec;
+    args.param      = param;
+    args.param_size = param_size;
+    args.data       = data;
+    args.data_size  = data_size;
+    args.flags      = 0;
+    if (gst_vaapi_codec_object_construct(va_obj, &args))
+        return va_obj;
+
+    gst_mini_object_unref(obj);
+    return NULL;
+}
+
+gboolean
+gst_vaapi_codec_object_construct(
+    GstVaapiCodecObject                      *obj,
+    const GstVaapiCodecObjectConstructorArgs *args
+)
+{
+    GstVaapiCodecObjectClass *klass;
+
+    g_return_val_if_fail(GST_VAAPI_CODEC_OBJECT(obj), FALSE);
+    g_return_val_if_fail(args->codec != NULL, FALSE);
+    g_return_val_if_fail(args->param_size > 0, FALSE);
+
+    if (GST_MINI_OBJECT_FLAG_IS_SET(obj, GST_VAAPI_CODEC_OBJECT_FLAG_CONSTRUCTED))
+        return TRUE;
+
+    klass = GST_VAAPI_CODEC_OBJECT_GET_CLASS(obj);
+    if (!klass || !klass->construct || !klass->construct(obj, args))
+        return FALSE;
+
+    GST_MINI_OBJECT_FLAG_SET(obj, GST_VAAPI_CODEC_OBJECT_FLAG_CONSTRUCTED);
+    return TRUE;
+}
+
+#define GET_DECODER(obj)    GST_VAAPI_DECODER_CAST((obj)->parent_instance.codec)
+#define GET_CONTEXT(obj)    GET_DECODER(obj)->priv->context
+#define GET_VA_DISPLAY(obj) GET_DECODER(obj)->priv->va_display
+#define GET_VA_CONTEXT(obj) GET_DECODER(obj)->priv->va_context
+
+/* ------------------------------------------------------------------------- */
+/* --- Inverse Quantization Matrices                                     --- */
+/* ------------------------------------------------------------------------- */
+
+GST_VAAPI_CODEC_DEFINE_TYPE(GstVaapiIqMatrix,
+                            gst_vaapi_iq_matrix,
+                            GST_VAAPI_TYPE_CODEC_OBJECT)
+
+static void
+gst_vaapi_iq_matrix_destroy(GstVaapiIqMatrix *iq_matrix)
+{
+    vaapi_destroy_buffer(GET_VA_DISPLAY(iq_matrix), &iq_matrix->param_id);
+    iq_matrix->param = NULL;
+}
+
+static gboolean
+gst_vaapi_iq_matrix_create(
+    GstVaapiIqMatrix                         *iq_matrix,
+    const GstVaapiCodecObjectConstructorArgs *args
+)
+{
+    return vaapi_create_buffer(GET_VA_DISPLAY(iq_matrix),
+                               GET_VA_CONTEXT(iq_matrix),
+                               VAIQMatrixBufferType,
+                               args->param_size,
+                               args->param,
+                               &iq_matrix->param_id,
+                               &iq_matrix->param);
+}
+
+static void
+gst_vaapi_iq_matrix_init(GstVaapiIqMatrix *iq_matrix)
+{
+    iq_matrix->param    = NULL;
+    iq_matrix->param_id = VA_INVALID_ID;
+}
+
+GstVaapiIqMatrix *
+gst_vaapi_iq_matrix_new(
+    GstVaapiDecoder *decoder,
+    gconstpointer    param,
+    guint            param_size
+)
+{
+    GstVaapiCodecObject *object;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), NULL);
+
+    object = gst_vaapi_codec_object_new(
+        GST_VAAPI_TYPE_IQ_MATRIX,
+        GST_VAAPI_CODEC_BASE(decoder),
+        param, param_size,
+        NULL, 0
+    );
+    if (!object)
+        return NULL;
+    return GST_VAAPI_IQ_MATRIX_CAST(object);
+}
+
+/* ------------------------------------------------------------------------- */
+/* --- VC-1 Bit Planes                                                   --- */
+/* ------------------------------------------------------------------------- */
+
+GST_VAAPI_CODEC_DEFINE_TYPE(GstVaapiBitPlane,
+                            gst_vaapi_bitplane,
+                            GST_VAAPI_TYPE_CODEC_OBJECT)
+
+static void
+gst_vaapi_bitplane_destroy(GstVaapiBitPlane *bitplane)
+{
+    vaapi_destroy_buffer(GET_VA_DISPLAY(bitplane), &bitplane->data_id);
+    bitplane->data = NULL;
+}
+
+static gboolean
+gst_vaapi_bitplane_create(
+    GstVaapiBitPlane                         *bitplane,
+    const GstVaapiCodecObjectConstructorArgs *args
+)
+{
+    return vaapi_create_buffer(GET_VA_DISPLAY(bitplane),
+                               GET_VA_CONTEXT(bitplane),
+                               VABitPlaneBufferType,
+                               args->param_size,
+                               args->param,
+                               &bitplane->data_id,
+                               (void **)&bitplane->data);
+}
+
+static void
+gst_vaapi_bitplane_init(GstVaapiBitPlane *bitplane)
+{
+    bitplane->data      = NULL;
+    bitplane->data_id   = VA_INVALID_ID;
+}
+
+GstVaapiBitPlane *
+gst_vaapi_bitplane_new(GstVaapiDecoder *decoder, guint8 *data, guint data_size)
+{
+    GstVaapiCodecObject *object;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), NULL);
+
+    object = gst_vaapi_codec_object_new(
+        GST_VAAPI_TYPE_BITPLANE,
+        GST_VAAPI_CODEC_BASE(decoder),
+        data, data_size,
+        NULL, 0
+    );
+    if (!object)
+        return NULL;
+    return GST_VAAPI_BITPLANE_CAST(object);
+}
+
+/* ------------------------------------------------------------------------- */
+/* --- JPEG Huffman Tables                                               --- */
+/* ------------------------------------------------------------------------- */
+
+#if USE_JPEG_DECODER
+GST_VAAPI_CODEC_DEFINE_TYPE(GstVaapiHuffmanTable,
+                            gst_vaapi_huffman_table,
+                            GST_VAAPI_TYPE_CODEC_OBJECT)
+
+static void
+gst_vaapi_huffman_table_destroy(GstVaapiHuffmanTable *huf_table)
+{
+    vaapi_destroy_buffer(GET_VA_DISPLAY(huf_table), &huf_table->param_id);
+    huf_table->param = NULL;
+}
+
+static gboolean
+gst_vaapi_huffman_table_create(
+    GstVaapiHuffmanTable                     *huf_table,
+    const GstVaapiCodecObjectConstructorArgs *args
+)
+{
+    return vaapi_create_buffer(GET_VA_DISPLAY(huf_table),
+                               GET_VA_CONTEXT(huf_table),
+                               VAHuffmanTableBufferType,
+                               args->param_size,
+                               args->param,
+                               &huf_table->param_id,
+                               (void **)&huf_table->param);
+}
+
+static void
+gst_vaapi_huffman_table_init(GstVaapiHuffmanTable *huf_table)
+{
+    huf_table->param    = NULL;
+    huf_table->param_id = VA_INVALID_ID;
+}
+
+GstVaapiHuffmanTable *
+gst_vaapi_huffman_table_new(
+    GstVaapiDecoder *decoder,
+    guint8          *data,
+    guint            data_size
+)
+{
+    GstVaapiCodecObject *object;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), NULL);
+
+    object = gst_vaapi_codec_object_new(
+        GST_VAAPI_TYPE_HUFFMAN_TABLE,
+        GST_VAAPI_CODEC_BASE(decoder),
+        data, data_size,
+        NULL, 0
+    );
+    if (!object)
+        return NULL;
+    return GST_VAAPI_HUFFMAN_TABLE_CAST(object);
+}
+#endif
diff --git a/gst-libs/gst/vaapi/gstvaapicodec_objects.h b/gst-libs/gst/vaapi/gstvaapicodec_objects.h
new file mode 100644 (file)
index 0000000..a064c15
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ *  gstvaapicodec_objects.h - VA codec objects abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_CODEC_COMMON_H
+#define GST_VAAPI_CODEC_COMMON_H
+
+#include <gst/gstminiobject.h>
+#include <gst/vaapi/gstvaapidecoder.h>
+
+G_BEGIN_DECLS
+
+typedef gpointer                                GstVaapiCodecBase;
+typedef struct _GstVaapiCodecObject             GstVaapiCodecObject;
+typedef struct _GstVaapiCodecObjectClass        GstVaapiCodecObjectClass;
+typedef struct _GstVaapiIqMatrix                GstVaapiIqMatrix;
+typedef struct _GstVaapiIqMatrixClass           GstVaapiIqMatrixClass;
+typedef struct _GstVaapiBitPlane                GstVaapiBitPlane;
+typedef struct _GstVaapiBitPlaneClass           GstVaapiBitPlaneClass;
+typedef struct _GstVaapiHuffmanTable            GstVaapiHuffmanTable;
+typedef struct _GstVaapiHuffmanTableClass       GstVaapiHuffmanTableClass;
+
+/* ------------------------------------------------------------------------- */
+/* --- Base Codec Object                                                 --- */
+/* ------------------------------------------------------------------------- */
+
+/* XXX: remove when a common base class for decoder and encoder is available */
+#define GST_VAAPI_CODEC_BASE(obj) \
+    ((GstVaapiCodecBase *)(obj))
+
+#define GST_VAAPI_TYPE_CODEC_OBJECT \
+    (gst_vaapi_codec_object_get_type())
+
+#define GST_VAAPI_CODEC_OBJECT(obj)                             \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_CODEC_OBJECT,    \
+                                GstVaapiCodecObject))
+
+#define GST_VAAPI_CODEC_OBJECT_CLASS(klass)                     \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_CODEC_OBJECT,       \
+                             GstVaapiCodecObjectClass))
+
+#define GST_VAAPI_IS_CODEC_OBJECT(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_CODEC_OBJECT))
+
+#define GST_VAAPI_IS_CODEC_OBJECT_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_CODEC_OBJECT))
+
+#define GST_VAAPI_CODEC_OBJECT_GET_CLASS(obj)                   \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_CODEC_OBJECT,     \
+                               GstVaapiCodecObjectClass))
+
+enum {
+    GST_VAAPI_CODEC_OBJECT_FLAG_CONSTRUCTED = (GST_MINI_OBJECT_FLAG_LAST << 0),
+    GST_VAAPI_CODEC_OBJECT_FLAG_LAST        = (GST_MINI_OBJECT_FLAG_LAST << 1)
+};
+
+typedef struct {
+    GstVaapiCodecObject        *obj;
+    GstVaapiCodecBase          *codec;
+    gconstpointer               param;
+    guint                       param_size;
+    gconstpointer               data;
+    guint                       data_size;
+    guint                       flags;
+} GstVaapiCodecObjectConstructorArgs;
+
+/**
+ * GstVaapiCodecObject:
+ *
+ * A #GstMiniObject holding the base codec object data
+ */
+struct _GstVaapiCodecObject {
+    /*< private >*/
+    GstMiniObject               parent_instance;
+    GstVaapiCodecBase          *codec;
+};
+
+/**
+ * GstVaapiCodecObjectClass:
+ *
+ * The #GstVaapiCodecObject base class.
+ */
+struct _GstVaapiCodecObjectClass {
+    /*< private >*/
+    GstMiniObjectClass          parent_class;
+
+    gboolean (*construct)      (GstVaapiCodecObject *obj,
+                                const GstVaapiCodecObjectConstructorArgs *args);
+};
+
+G_GNUC_INTERNAL
+GType
+gst_vaapi_codec_object_get_type(void) G_GNUC_CONST;
+
+G_GNUC_INTERNAL
+GstVaapiCodecObject *
+gst_vaapi_codec_object_new(
+    GType              type,
+    GstVaapiCodecBase *codec,
+    gconstpointer      param,
+    guint              param_size,
+    gconstpointer      data,
+    guint              data_size
+);
+
+G_GNUC_INTERNAL
+gboolean
+gst_vaapi_codec_object_construct(
+    GstVaapiCodecObject                      *obj,
+    const GstVaapiCodecObjectConstructorArgs *args
+);
+
+/* ------------------------------------------------------------------------- */
+/* --- Inverse Quantization Matrices                                     --- */
+/* ------------------------------------------------------------------------- */
+
+#define GST_VAAPI_TYPE_IQ_MATRIX \
+    (gst_vaapi_iq_matrix_get_type())
+
+#define GST_VAAPI_IQ_MATRIX_CAST(obj) \
+    ((GstVaapiIqMatrix *)(obj))
+
+#define GST_VAAPI_IQ_MATRIX(obj)                                \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_IQ_MATRIX,       \
+                                GstVaapiIqMatrix))
+
+#define GST_VAAPI_IQ_MATRIX_CLASS(klass)                        \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_IQ_MATRIX,          \
+                             GstVaapiIqMatrixClass))
+
+#define GST_VAAPI_IS_IQ_MATRIX(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_IQ_MATRIX))
+
+#define GST_VAAPI_IS_IQ_MATRIX_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_IQ_MATRIX))
+
+#define GST_VAAPI_IQ_MATRIX_GET_CLASS(obj)                      \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_IQ_MATRIX,        \
+                               GstVaapiIqMatrixClass))
+
+/**
+ * GstVaapiIqMatrix:
+ *
+ * A #GstVaapiCodecObject holding an inverse quantization matrix parameter.
+ */
+struct _GstVaapiIqMatrix {
+    /*< private >*/
+    GstVaapiCodecObject         parent_instance;
+    VABufferID                  param_id;
+
+    /*< public >*/
+    gpointer                    param;
+};
+
+/**
+ * GstVaapiIqMatrixClass:
+ *
+ * The #GstVaapiIqMatrix base class.
+ */
+struct _GstVaapiIqMatrixClass {
+    /*< private >*/
+    GstVaapiCodecObjectClass    parent_class;
+};
+
+G_GNUC_INTERNAL
+GType
+gst_vaapi_iq_matrix_get_type(void) G_GNUC_CONST;
+
+G_GNUC_INTERNAL
+GstVaapiIqMatrix *
+gst_vaapi_iq_matrix_new(
+    GstVaapiDecoder *decoder,
+    gconstpointer    param,
+    guint            param_size
+);
+
+/* ------------------------------------------------------------------------- */
+/* --- VC-1 Bit Planes                                                   --- */
+/* ------------------------------------------------------------------------- */
+
+#define GST_VAAPI_TYPE_BITPLANE \
+    (gst_vaapi_bitplane_get_type())
+
+#define GST_VAAPI_BITPLANE_CAST(obj) \
+    ((GstVaapiBitPlane *)(obj))
+
+#define GST_VAAPI_BITPLANE(obj)                                 \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_BITPLANE,        \
+                                GstVaapiBitPlane))
+
+#define GST_VAAPI_BITPLANE_CLASS(klass)                         \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_BITPLANE,           \
+                             GstVaapiBitPlaneClass))
+
+#define GST_VAAPI_IS_BITPLANE(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_BITPLANE))
+
+#define GST_VAAPI_IS_BITPLANE_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_BITPLANE))
+
+#define GST_VAAPI_BITPLANE_GET_CLASS(obj)                       \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_BITPLANE,         \
+                               GstVaapiBitPlaneClass))
+
+/**
+ * GstVaapiBitPlane:
+ *
+ * A #GstVaapiCodecObject holding a VC-1 bit plane parameter.
+ */
+struct _GstVaapiBitPlane {
+    /*< private >*/
+    GstVaapiCodecObject         parent_instance;
+    VABufferID                  data_id;
+
+    /*< public >*/
+    guint8                     *data;
+};
+
+/**
+ * GstVaapiBitPlaneClass:
+ *
+ * The #GstVaapiBitPlane base class.
+ */
+struct _GstVaapiBitPlaneClass {
+    /*< private >*/
+    GstVaapiCodecObjectClass    parent_class;
+};
+
+G_GNUC_INTERNAL
+GType
+gst_vaapi_bitplane_get_type(void) G_GNUC_CONST;
+
+G_GNUC_INTERNAL
+GstVaapiBitPlane *
+gst_vaapi_bitplane_new(GstVaapiDecoder *decoder, guint8 *data, guint data_size);
+
+/* ------------------------------------------------------------------------- */
+/* --- JPEG Huffman Tables                                               --- */
+/* ------------------------------------------------------------------------- */
+
+#define GST_VAAPI_TYPE_HUFFMAN_TABLE \
+    (gst_vaapi_huffman_table_get_type())
+
+#define GST_VAAPI_HUFFMAN_TABLE_CAST(obj) \
+    ((GstVaapiHuffmanTable *)(obj))
+
+#define GST_VAAPI_HUFFMAN_TABLE(obj)                            \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_HUFFMAN_TABLE,   \
+                                GstVaapiHuffmanTable))
+
+#define GST_VAAPI_HUFFMAN_TABLE_CLASS(klass)                    \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_HUFFMAN_TABLE,      \
+                             GstVaapiHuffmanTableClass))
+
+#define GST_VAAPI_IS_HUFFMAN_TABLE(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_HUFFMAN_TABLE))
+
+#define GST_VAAPI_IS_HUFFMAN_TABLE_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_HUFFMAN_TABLE))
+
+#define GST_VAAPI_HUFFMAN_TABLE_GET_CLASS(obj)                  \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_HUFFMAN_TABLE,    \
+                               GstVaapiHuffmanTableClass))
+
+/**
+ * GstVaapiHuffmanTable:
+ *
+ * A #GstVaapiCodecObject holding huffman table.
+ */
+struct _GstVaapiHuffmanTable {
+    /*< private >*/
+    GstVaapiCodecObject         parent_instance;
+    VABufferID                  param_id;
+
+    /*< public >*/
+    gpointer                    param;
+};
+
+/**
+ * GstVaapiHuffmanTableClass:
+ *
+ * The #GstVaapiHuffmanTable base class.
+ */
+struct _GstVaapiHuffmanTableClass {
+    /*< private >*/
+    GstVaapiCodecObjectClass    parent_class;
+};
+
+G_GNUC_INTERNAL
+GType
+gst_vaapi_huffman_table_get_type(void) G_GNUC_CONST;
+
+G_GNUC_INTERNAL
+GstVaapiHuffmanTable *
+gst_vaapi_huffman_table_new(
+    GstVaapiDecoder *decoder,
+    guint8          *data,
+    guint            data_size
+);
+
+/* ------------------------------------------------------------------------- */
+/* --- Helpers to create codec-dependent objects                         --- */
+/* ------------------------------------------------------------------------- */
+
+#define GST_VAAPI_CODEC_DEFINE_TYPE(type, prefix, base_type)            \
+G_DEFINE_TYPE(type, prefix, base_type)                                  \
+                                                                        \
+static void                                                             \
+prefix##_destroy(type *);                                               \
+                                                                        \
+static gboolean                                                         \
+prefix##_create(                                                        \
+    type *,                                                             \
+    const GstVaapiCodecObjectConstructorArgs *args                      \
+);                                                                      \
+                                                                        \
+static void                                                             \
+prefix##_finalize(GstMiniObject *object)                                \
+{                                                                       \
+    GstMiniObjectClass *parent_class;                                   \
+                                                                        \
+    prefix##_destroy((type *)object);                                   \
+                                                                        \
+    parent_class = GST_MINI_OBJECT_CLASS(prefix##_parent_class);        \
+    if (parent_class->finalize)                                         \
+        parent_class->finalize(object);                                 \
+}                                                                       \
+                                                                        \
+static gboolean                                                         \
+prefix##_construct(                                                     \
+    GstVaapiCodecObject                      *object,                   \
+    const GstVaapiCodecObjectConstructorArgs *args                      \
+)                                                                       \
+{                                                                       \
+    GstVaapiCodecObjectClass *parent_class;                             \
+                                                                        \
+    parent_class = GST_VAAPI_CODEC_OBJECT_CLASS(prefix##_parent_class); \
+    if (parent_class->construct) {                                      \
+        if (!parent_class->construct(object, args))                     \
+            return FALSE;                                               \
+    }                                                                   \
+    return prefix##_create((type *)object, args);                       \
+}                                                                       \
+                                                                        \
+static void                                                             \
+prefix##_class_init(type##Class *klass)                                 \
+{                                                                       \
+    GstMiniObjectClass * const object_class =                           \
+        GST_MINI_OBJECT_CLASS(klass);                                   \
+    GstVaapiCodecObjectClass * const codec_class =                      \
+        GST_VAAPI_CODEC_OBJECT_CLASS(klass);                            \
+                                                                        \
+    object_class->finalize = prefix##_finalize;                         \
+    codec_class->construct = prefix##_construct;                        \
+}
+
+#define GST_VAAPI_IQ_MATRIX_NEW(codec, decoder)                         \
+    gst_vaapi_iq_matrix_new(GST_VAAPI_DECODER_CAST(decoder),            \
+                            NULL, sizeof(VAIQMatrixBuffer##codec))
+
+#define GST_VAAPI_BITPLANE_NEW(decoder, size) \
+    gst_vaapi_bitplane_new(GST_VAAPI_DECODER_CAST(decoder), NULL, size)
+
+#define GST_VAAPI_HUFFMAN_TABLE_NEW(codec, decoder)                     \
+      gst_vaapi_huffman_table_new(GST_VAAPI_DECODER_CAST(decoder),      \
+                            NULL, sizeof(VAHuffmanTableBuffer##codec))
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_CODEC_OBJECTS_H */
diff --git a/gst-libs/gst/vaapi/gstvaapicompat.h b/gst-libs/gst/vaapi/gstvaapicompat.h
new file mode 100644 (file)
index 0000000..4a1f93d
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ *  gstvapicompat.h - VA-API compatibility glue
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_COMPAT_H
+#define GST_VAAPI_COMPAT_H
+
+#include <va/va.h>
+
+#ifdef HAVE_VA_VA_GLX_H
+# define USE_VAAPI_GLX 1
+#else
+# define USE_VAAPI_GLX 0
+#endif
+
+#if USE_VAAPI_GLX
+# include <va/va_glx.h>
+#else
+# define vaGetDisplayGLX(dpy) vaGetDisplay(dpy)
+#endif
+
+/* Compatibility glue with VA-API < 0.31 */
+#if !VA_CHECK_VERSION(0,31,0)
+#undef  vaSyncSurface
+#define vaSyncSurface(dpy, s)   (vaSyncSurface)((dpy), VA_INVALID_ID, (s))
+#undef  vaPutImage
+#define vaPutImage              vaPutImage2
+#undef  vaAssociateSubpicture
+#define vaAssociateSubpicture   vaAssociateSubpicture2
+#endif
+
+/* Compatibility glue with VA-API 0.34 */
+#if VA_CHECK_VERSION(0,34,0)
+# include <va/va_compat.h>
+#endif
+
+#endif /* GST_VAAPI_COMPAT_H */
diff --git a/gst-libs/gst/vaapi/gstvaapicontext.c b/gst-libs/gst/vaapi/gstvaapicontext.c
new file mode 100644 (file)
index 0000000..69f43a1
--- /dev/null
@@ -0,0 +1,1038 @@
+/*
+ *  gstvaapicontext.c - VA context abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapicontext
+ * @short_description: VA context abstraction
+ */
+
+#include "sysdeps.h"
+#include <assert.h>
+#include "gstvaapicompat.h"
+#include "gstvaapicontext.h"
+#include "gstvaapisurface.h"
+#include "gstvaapisurface_priv.h"
+#include "gstvaapisurfacepool.h"
+#include "gstvaapiimage.h"
+#include "gstvaapisubpicture.h"
+#include "gstvaapiutils.h"
+#include "gstvaapi_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiContext, gst_vaapi_context, GST_VAAPI_TYPE_OBJECT);
+
+#define GST_VAAPI_CONTEXT_GET_PRIVATE(obj)                      \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_CONTEXT,       \
+                                 GstVaapiContextPrivate))
+
+typedef struct _GstVaapiOverlayRectangle GstVaapiOverlayRectangle;
+struct _GstVaapiOverlayRectangle {
+    GstVaapiContext    *context;
+    GstVaapiSubpicture *subpicture;
+    GstVaapiRectangle   rect;
+    guint               seq_num;
+};
+
+/* XXX: optimize for the effective number of reference frames */
+struct _GstVaapiContextPrivate {
+    VAConfigID          config_id;
+    GPtrArray          *surfaces;
+    GstVaapiVideoPool  *surfaces_pool;
+    guint               surface_num;
+    GPtrArray          *overlay;
+    GstVaapiProfile     profile;
+    GstVaapiEntrypoint  entrypoint;
+    GstVaapiRateControl rate_control;
+    guint               width;
+    guint               height;
+    guint               is_constructed  : 1;
+};
+
+enum {
+    PROP_0,
+
+    PROP_PROFILE,
+    PROP_ENTRYPOINT,
+    PROP_WIDTH,
+    PROP_HEIGHT,
+    PROP_SURFACE_NUM,
+    PROP_RATE_CONTROL
+};
+
+static GstVaapiOverlayRectangle *
+overlay_rectangle_new(GstVaapiContext *context)
+{
+    GstVaapiOverlayRectangle *overlay;
+
+    overlay = g_slice_new0(GstVaapiOverlayRectangle);
+    if (!overlay)
+        return NULL;
+
+    overlay->context = context;
+    return overlay;
+}
+
+static void
+overlay_rectangle_destroy(GstVaapiOverlayRectangle *overlay)
+{
+    GstVaapiContextPrivate *priv;
+    guint i;
+
+    if (!overlay)
+        return;
+    priv = overlay->context->priv;
+
+    if (overlay->subpicture) {
+        if (priv->surfaces) {
+            GstVaapiSubpicture * const subpicture = overlay->subpicture;
+            for (i = 0; i < priv->surfaces->len; i++) {
+                GstVaapiSurface * const surface =
+                    g_ptr_array_index(priv->surfaces, i);
+                gst_vaapi_surface_deassociate_subpicture(surface, subpicture);
+            }
+        }
+        g_object_unref(overlay->subpicture);
+        overlay->subpicture = NULL;
+    }
+    g_slice_free(GstVaapiOverlayRectangle, overlay);
+}
+
+static void
+destroy_overlay_cb(gpointer data, gpointer user_data)
+{
+    GstVaapiOverlayRectangle * const overlay = data;
+
+    overlay_rectangle_destroy(overlay);
+}
+
+static void
+gst_vaapi_context_destroy_overlay(GstVaapiContext *context)
+{
+    GstVaapiContextPrivate * const priv = context->priv;
+
+    if (!priv->overlay)
+        return;
+
+    g_ptr_array_foreach(priv->overlay, destroy_overlay_cb, priv);
+    g_ptr_array_free(priv->overlay, TRUE);
+    priv->overlay = NULL;
+}
+
+static void
+unref_surface_cb(gpointer data, gpointer user_data)
+{
+    GstVaapiSurface * const surface = GST_VAAPI_SURFACE(data);
+
+    gst_vaapi_surface_set_parent_context(surface, NULL);
+    g_object_unref(surface);
+}
+
+static void
+gst_vaapi_context_destroy_surfaces(GstVaapiContext *context)
+{
+    GstVaapiContextPrivate * const priv = context->priv;
+
+    gst_vaapi_context_destroy_overlay(context);
+
+    if (priv->surfaces) {
+        g_ptr_array_foreach(priv->surfaces, unref_surface_cb, NULL);
+        g_ptr_array_free(priv->surfaces, TRUE);
+        priv->surfaces = NULL;
+    }
+
+    g_clear_object(&priv->surfaces_pool);
+}
+
+static void
+gst_vaapi_context_destroy(GstVaapiContext *context)
+{
+    GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(context);
+    GstVaapiContextPrivate * const priv = context->priv;
+    VAContextID context_id;
+    VAStatus status;
+
+    context_id = GST_VAAPI_OBJECT_ID(context);
+    GST_DEBUG("context %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(context_id));
+
+    if (context_id != VA_INVALID_ID) {
+        GST_VAAPI_DISPLAY_LOCK(display);
+        status = vaDestroyContext(
+            GST_VAAPI_DISPLAY_VADISPLAY(display),
+            context_id
+        );
+        GST_VAAPI_DISPLAY_UNLOCK(display);
+        if (!vaapi_check_status(status, "vaDestroyContext()"))
+            g_warning("failed to destroy context %" GST_VAAPI_ID_FORMAT,
+                      GST_VAAPI_ID_ARGS(context_id));
+        GST_VAAPI_OBJECT_ID(context) = VA_INVALID_ID;
+    }
+
+    if (priv->config_id != VA_INVALID_ID) {
+        GST_VAAPI_DISPLAY_LOCK(display);
+        status = vaDestroyConfig(
+            GST_VAAPI_DISPLAY_VADISPLAY(display),
+            priv->config_id
+        );
+        GST_VAAPI_DISPLAY_UNLOCK(display);
+        if (!vaapi_check_status(status, "vaDestroyConfig()"))
+            g_warning("failed to destroy config %" GST_VAAPI_ID_FORMAT,
+                      GST_VAAPI_ID_ARGS(priv->config_id));
+        priv->config_id = VA_INVALID_ID;
+    }
+}
+
+static gboolean
+gst_vaapi_context_create_overlay(GstVaapiContext *context)
+{
+    GstVaapiContextPrivate * const priv = context->priv;
+
+    if (!priv->overlay) {
+        priv->overlay = g_ptr_array_new();
+        if (!priv->overlay)
+            return FALSE;
+    }
+    return TRUE;
+}
+
+static gboolean
+gst_vaapi_context_increase_surfaces(GstVaapiContext *context,guint increment)
+{
+    GstVaapiContextPrivate * const priv = context->priv;
+    GstVaapiVideoPool * surface_pool;
+    GstVaapiSurface *surface;
+    guint i;
+
+    surface_pool = priv->surfaces_pool;
+    if (!priv->surfaces || !surface_pool)
+        return FALSE;
+
+    if ((priv->surfaces->len + increment) >
+        gst_vaapi_video_pool_get_capacity(surface_pool))
+        return FALSE;
+
+    for (i = 0; i < increment; ++i) {
+        surface = gst_vaapi_surface_new(
+            GST_VAAPI_OBJECT_DISPLAY(context),
+            GST_VAAPI_CHROMA_TYPE_YUV420,
+            priv->width, priv->height
+        );
+        if (!surface)
+            return FALSE;
+        g_ptr_array_add(priv->surfaces, surface);
+        if (!gst_vaapi_video_pool_add_object(priv->surfaces_pool, surface))
+            return FALSE;
+    }
+    priv->surface_num = priv->surfaces->len;
+    return TRUE;
+}
+
+
+static gboolean
+gst_vaapi_context_create_surfaces(GstVaapiContext *context, guint surface_num)
+{
+    GstVaapiContextPrivate * const priv = context->priv;
+    GstCaps *caps;
+    GstVaapiSurface *surface;
+    guint i, pool_capacity;
+
+    if (!gst_vaapi_context_create_overlay(context))
+        return FALSE;
+
+    if (!priv->surfaces) {
+        priv->surfaces = g_ptr_array_new();
+        if (!priv->surfaces)
+            return FALSE;
+    }
+
+    if (!priv->surfaces_pool) {
+        caps = gst_caps_new_simple(
+            GST_VAAPI_SURFACE_CAPS_NAME,
+            "type", G_TYPE_STRING, "vaapi",
+            "width",  G_TYPE_INT, priv->width,
+            "height", G_TYPE_INT, priv->height,
+            NULL
+        );
+        if (!caps)
+            return FALSE;
+        priv->surfaces_pool = gst_vaapi_surface_pool_new(
+            GST_VAAPI_OBJECT_DISPLAY(context),
+            caps
+        );
+        gst_caps_unref(caps);
+        if (!priv->surfaces_pool)
+            return FALSE;
+    }
+
+    pool_capacity =
+        ((gst_vaapi_profile_get_codec(priv->profile) == GST_VAAPI_CODEC_H264) ? 20 : 6);
+    if (pool_capacity < surface_num)
+        pool_capacity = surface_num;
+    gst_vaapi_video_pool_set_capacity(priv->surfaces_pool, pool_capacity);
+
+    for (i = priv->surfaces->len; i < surface_num; i++) {
+        surface = gst_vaapi_surface_new(
+            GST_VAAPI_OBJECT_DISPLAY(context),
+            GST_VAAPI_CHROMA_TYPE_YUV420,
+            priv->width, priv->height
+        );
+        if (!surface)
+            return FALSE;
+        g_ptr_array_add(priv->surfaces, surface);
+        if (!gst_vaapi_video_pool_add_object(priv->surfaces_pool, surface))
+            return FALSE;
+    }
+    priv->surface_num = priv->surfaces->len;
+    return TRUE;
+}
+
+static gboolean
+gst_vaapi_context_create(GstVaapiContext *context)
+{
+    GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(context);
+    GstVaapiContextPrivate * const priv = context->priv;
+    VAProfile va_profile;
+    VAEntrypoint va_entrypoint;
+    guint va_rate_control;
+    VAConfigAttrib attribs[2];
+    guint attribs_num;
+    VAContextID context_id;
+    VASurfaceID surface_id;
+    VAStatus status;
+    GArray *surfaces = NULL;
+    gboolean success = FALSE;
+    guint i;
+
+    if (!priv->surfaces && !gst_vaapi_context_create_surfaces(context, priv->surface_num))
+        goto end;
+
+    surfaces = g_array_sized_new(
+        FALSE,
+        FALSE,
+        sizeof(VASurfaceID),
+        priv->surfaces->len
+    );
+    if (!surfaces)
+        goto end;
+
+    for (i = 0; i < priv->surfaces->len; i++) {
+        GstVaapiSurface * const surface = g_ptr_array_index(priv->surfaces, i);
+        if (!surface)
+            goto end;
+        surface_id = GST_VAAPI_OBJECT_ID(surface);
+        g_array_append_val(surfaces, surface_id);
+    }
+    assert(surfaces->len == priv->surfaces->len);
+
+    if (!priv->profile || !priv->entrypoint)
+        goto end;
+    va_profile    = gst_vaapi_profile_get_va_profile(priv->profile);
+    va_entrypoint = gst_vaapi_entrypoint_get_va_entrypoint(priv->entrypoint);
+
+    GST_VAAPI_DISPLAY_LOCK(display);
+    attribs[0].type = VAConfigAttribRTFormat;
+    attribs[1].type = VAConfigAttribRateControl;
+    if (GST_VAAPI_ENTRYPOINT_SLICE_ENCODE == priv->entrypoint)
+      attribs_num = 2;
+    else
+      attribs_num = 1;
+
+    status = vaGetConfigAttributes(
+        GST_VAAPI_DISPLAY_VADISPLAY(display),
+        va_profile,
+        va_entrypoint,
+        attribs, attribs_num
+    );
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+    if (!vaapi_check_status(status, "vaGetConfigAttributes()"))
+        goto end;
+    if (!(attribs[0].value & VA_RT_FORMAT_YUV420))
+        goto end;
+    if (GST_VAAPI_ENTRYPOINT_SLICE_ENCODE == priv->entrypoint) {
+        va_rate_control = from_GstVaapiRateControl(priv->rate_control);
+        if (va_rate_control == VA_RC_NONE)
+            attribs[1].value = VA_RC_NONE;
+        if ((attribs[1].value & va_rate_control) != va_rate_control) {
+            GST_ERROR("encoder rate control:%s unsupported",
+                      string_of_VARateControl(va_rate_control));
+            goto end;
+        }
+        attribs[1].value = va_rate_control;
+    }
+
+    GST_VAAPI_DISPLAY_LOCK(display);
+    status = vaCreateConfig(
+        GST_VAAPI_DISPLAY_VADISPLAY(display),
+        va_profile,
+        va_entrypoint,
+        attribs, attribs_num,
+        &priv->config_id
+    );
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+    if (!vaapi_check_status(status, "vaCreateConfig()"))
+        goto end;
+
+    VASurfaceID *surface_ids = (VASurfaceID*)surfaces->data;
+    int          surface_num = surfaces->len;
+
+    GST_VAAPI_DISPLAY_LOCK(display);
+    status = vaCreateContext(
+        GST_VAAPI_DISPLAY_VADISPLAY(display),
+        priv->config_id,
+        priv->width, priv->height,
+        VA_PROGRESSIVE,
+        (VASurfaceID *)surface_ids, surface_num,
+        &context_id
+    );
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+    if (!vaapi_check_status(status, "vaCreateContext()"))
+        goto end;
+
+    GST_DEBUG("context %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(context_id));
+    GST_VAAPI_OBJECT_ID(context) = context_id;
+    success = TRUE;
+end:
+    if (surfaces)
+        g_array_free(surfaces, TRUE);
+    return success;
+}
+
+static void
+gst_vaapi_context_finalize(GObject *object)
+{
+    GstVaapiContext * const context = GST_VAAPI_CONTEXT(object);
+
+    gst_vaapi_context_destroy(context);
+    gst_vaapi_context_destroy_surfaces(context);
+
+    G_OBJECT_CLASS(gst_vaapi_context_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_context_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiContext        * const context = GST_VAAPI_CONTEXT(object);
+    GstVaapiContextPrivate * const priv    = context->priv;
+
+    switch (prop_id) {
+    case PROP_PROFILE:
+        gst_vaapi_context_set_profile(context, g_value_get_uint(value));
+        break;
+    case PROP_ENTRYPOINT:
+        priv->entrypoint = g_value_get_uint(value);
+        break;
+    case PROP_WIDTH:
+        priv->width = g_value_get_uint(value);
+        break;
+    case PROP_HEIGHT:
+        priv->height = g_value_get_uint(value);
+        break;
+    case PROP_SURFACE_NUM:
+        priv->surface_num = g_value_get_uint(value);
+        break;
+    case PROP_RATE_CONTROL:
+        priv->rate_control = g_value_get_uint(value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_context_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiContext        * const context = GST_VAAPI_CONTEXT(object);
+    GstVaapiContextPrivate * const priv    = context->priv;
+
+    switch (prop_id) {
+    case PROP_PROFILE:
+        g_value_set_uint(value, gst_vaapi_context_get_profile(context));
+        break;
+    case PROP_ENTRYPOINT:
+        g_value_set_uint(value, gst_vaapi_context_get_entrypoint(context));
+        break;
+    case PROP_WIDTH:
+        g_value_set_uint(value, priv->width);
+        break;
+    case PROP_HEIGHT:
+        g_value_set_uint(value, priv->height);
+        break;
+    case PROP_SURFACE_NUM:
+        g_value_set_uint(value, priv->surface_num);
+        break;
+    case PROP_RATE_CONTROL:
+        g_value_set_uint(value, priv->rate_control);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_context_class_init(GstVaapiContextClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiContextPrivate));
+
+    object_class->finalize     = gst_vaapi_context_finalize;
+    object_class->set_property = gst_vaapi_context_set_property;
+    object_class->get_property = gst_vaapi_context_get_property;
+
+    g_object_class_install_property
+        (object_class,
+         PROP_PROFILE,
+         g_param_spec_uint("profile",
+                           "Profile",
+                           "The profile used for decoding",
+                           0, G_MAXUINT32, 0,
+                           G_PARAM_READWRITE));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_ENTRYPOINT,
+         g_param_spec_uint("entrypoint",
+                           "Entrypoint",
+                           "The decoder entrypoint",
+                           0, G_MAXUINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_WIDTH,
+         g_param_spec_uint("width",
+                           "Width",
+                           "The width of decoded surfaces",
+                           0, G_MAXINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_HEIGHT,
+         g_param_spec_uint("height",
+                           "Height",
+                           "The height of the decoded surfaces",
+                           0, G_MAXINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_SURFACE_NUM,
+         g_param_spec_uint("surface_num",
+                           "Surface Number",
+                           "The decoded surfaces number",
+                           0, G_MAXINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+    g_object_class_install_property
+        (object_class,
+         PROP_RATE_CONTROL,
+         g_param_spec_uint("rate-control",
+                           "Bitrate Control",
+                           "Bitrate Control",
+                           0, G_MAXINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gst_vaapi_context_init(GstVaapiContext *context)
+{
+    GstVaapiContextPrivate *priv = GST_VAAPI_CONTEXT_GET_PRIVATE(context);
+
+    context->priv       = priv;
+    priv->config_id     = VA_INVALID_ID;
+    priv->surfaces      = NULL;
+    priv->surfaces_pool = NULL;
+    priv->overlay       = NULL;
+    priv->profile       = 0;
+    priv->entrypoint    = 0;
+    priv->rate_control  = GST_VAAPI_RATECONTROL_NONE;
+    priv->width         = 0;
+    priv->height        = 0;
+    priv->surface_num   = 0;
+}
+
+/**
+ * gst_vaapi_context_new:
+ * @display: a #GstVaapiDisplay
+ * @profile: a #GstVaapiProfile
+ * @entrypoint: a #GstVaapiEntrypoint
+ * @width: coded width from the bitstream
+ * @height: coded height from the bitstream
+ *
+ * Creates a new #GstVaapiContext with the specified codec @profile
+ * and @entrypoint.
+ *
+ * Return value: the newly allocated #GstVaapiContext object
+ */
+GstVaapiContext *
+gst_vaapi_context_new(
+    GstVaapiDisplay    *display,
+    GstVaapiProfile     profile,
+    GstVaapiEntrypoint  entrypoint,
+    GstVaapiRateControl rate_control,
+    unsigned int        width,
+    unsigned int        height,
+    unsigned int        surface_num
+)
+{
+    GstVaapiContext *context;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+    g_return_val_if_fail(profile, NULL);
+    g_return_val_if_fail(entrypoint, NULL);
+    g_return_val_if_fail(width > 0, NULL);
+    g_return_val_if_fail(height > 0, NULL);
+
+    context = g_object_new(
+        GST_VAAPI_TYPE_CONTEXT,
+        "display",      display,
+        "id",           GST_VAAPI_ID(VA_INVALID_ID),
+        "profile",      profile,
+        "entrypoint",   entrypoint,
+        "rate-control", rate_control,
+        "width",        width,
+        "height",       height,
+        "surface_num",  surface_num,
+        NULL
+    );
+    if (!context->priv->is_constructed) {
+        g_object_unref(context);
+        return NULL;
+    }
+    return context;
+}
+
+/**
+ * gst_vaapi_context_reset:
+ * @context: a #GstVaapiContext
+ * @profile: a #GstVaapiProfile
+ * @entrypoint: a #GstVaapiEntrypoint
+ * @width: coded width from the bitstream
+ * @height: coded height from the bitstream
+ *
+ * Resets @context to the specified codec @profile and @entrypoint.
+ * The surfaces will be reallocated if the coded size changed.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_context_reset(
+    GstVaapiContext    *context,
+    GstVaapiProfile     profile,
+    GstVaapiEntrypoint  entrypoint,
+    unsigned int        width,
+    unsigned int        height,
+    unsigned int        surface_num
+)
+{
+    GstVaapiContextPrivate * const priv = context->priv;
+    gboolean size_changed, codec_changed, surface_increased;
+
+    size_changed = priv->width != width || priv->height != height;
+    if (size_changed) {
+        gst_vaapi_context_destroy_surfaces(context);
+        priv->width  = width;
+        priv->height = height;
+    }
+
+    codec_changed = priv->profile != profile || priv->entrypoint != entrypoint;
+    if (codec_changed) {
+        gst_vaapi_context_destroy(context);
+        priv->profile    = profile;
+        priv->entrypoint = entrypoint;
+    }
+
+    surface_increased = !size_changed && priv->surfaces &&
+                        (priv->surfaces->len < surface_num);
+
+    if (size_changed && !gst_vaapi_context_create_surfaces(context, surface_num))
+        return FALSE;
+    if (surface_increased &&
+        !gst_vaapi_context_increase_surfaces(context,
+                                             surface_num - priv->surfaces->len))
+        return FALSE;
+
+    if (codec_changed && !gst_vaapi_context_create(context))
+        return FALSE;
+
+    priv->is_constructed = TRUE;
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_context_get_id:
+ * @context: a #GstVaapiContext
+ *
+ * Returns the underlying VAContextID of the @context.
+ *
+ * Return value: the underlying VA context id
+ */
+GstVaapiID
+gst_vaapi_context_get_id(GstVaapiContext *context)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), VA_INVALID_ID);
+
+    return GST_VAAPI_OBJECT_ID(context);
+}
+
+/**
+ * gst_vaapi_context_get_profile:
+ * @context: a #GstVaapiContext
+ *
+ * Returns the VA profile used by the @context.
+ *
+ * Return value: the VA profile used by the @context
+ */
+GstVaapiProfile
+gst_vaapi_context_get_profile(GstVaapiContext *context)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), 0);
+
+    return context->priv->profile;
+}
+
+/**
+ * gst_vaapi_context_set_profile:
+ * @context: a #GstVaapiContext
+ * @profile: the new #GstVaapiProfile to use
+ *
+ * Sets the new @profile to use with the @context. If @profile matches
+ * the previous profile, this call has no effect. Otherwise, the
+ * underlying VA context is recreated, while keeping the previously
+ * allocated surfaces.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_context_set_profile(GstVaapiContext *context, GstVaapiProfile profile)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), FALSE);
+    g_return_val_if_fail(profile, FALSE);
+
+    return gst_vaapi_context_reset(context,
+                                   profile,
+                                   context->priv->entrypoint,
+                                   context->priv->width,
+                                   context->priv->height,
+                                   context->priv->surface_num);
+}
+
+/**
+ * gst_vaapi_context_get_entrypoint:
+ * @context: a #GstVaapiContext
+ *
+ * Returns the VA entrypoint used by the @context
+ *
+ * Return value: the VA entrypoint used by the @context
+ */
+GstVaapiEntrypoint
+gst_vaapi_context_get_entrypoint(GstVaapiContext *context)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), 0);
+
+    return context->priv->entrypoint;
+}
+
+/**
+ * gst_vaapi_context_get_size:
+ * @context: a #GstVaapiContext
+ * @pwidth: return location for the width, or %NULL
+ * @pheight: return location for the height, or %NULL
+ *
+ * Retrieves the size of the surfaces attached to @context.
+ */
+void
+gst_vaapi_context_get_size(
+    GstVaapiContext *context,
+    guint           *pwidth,
+    guint           *pheight
+)
+{
+    g_return_if_fail(GST_VAAPI_IS_CONTEXT(context));
+
+    if (pwidth)
+        *pwidth = context->priv->width;
+
+    if (pheight)
+        *pheight = context->priv->height;
+}
+
+/**
+ * gst_vaapi_context_get_surface:
+ * @context: a #GstVaapiContext
+ *
+ * Acquires a free surface. The returned surface but be released with
+ * gst_vaapi_context_put_surface(). This function returns %NULL if
+ * there is no free surface available in the pool. The surfaces are
+ * pre-allocated during context creation though.
+ *
+ * Return value: a free surface, or %NULL if none is available
+ */
+GstVaapiSurface *
+gst_vaapi_context_get_surface(GstVaapiContext *context)
+{
+    GstVaapiSurface *surface;
+
+    g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), NULL);
+
+    surface = gst_vaapi_video_pool_get_object(context->priv->surfaces_pool);
+    if (!surface)
+        return NULL;
+
+    gst_vaapi_surface_set_parent_context(surface, context);
+    return surface;
+}
+
+/**
+ * gst_vaapi_context_get_surface_pool:
+ * @context: a #GstVaapiContext
+ *
+ * Reference the surface pool. The returned surface pool should be released with
+ * g_object_unref(). This function returns %NULL if
+ * there is the surface pool is empty. The surface pool is
+ * created during context creation though.
+ *
+ * Return value: surface pool, or %NULL if it is not created.
+ */
+
+GstVaapiSurfacePool *
+gst_vaapi_context_get_surface_pool(GstVaapiContext *context)
+{
+  g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), NULL);
+  return (GstVaapiSurfacePool*)g_object_ref(context->priv->surfaces_pool);
+}
+
+
+/**
+ * gst_vaapi_context_get_surface_count:
+ * @context: a #GstVaapiContext
+ *
+ * Retrieves the number of free surfaces left in the pool.
+ *
+ * Return value: the number of free surfaces available in the pool
+ */
+guint
+gst_vaapi_context_get_surface_count(GstVaapiContext *context)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), 0);
+
+    return gst_vaapi_video_pool_get_size(context->priv->surfaces_pool);
+}
+
+/**
+ * gst_vaapi_context_get_surface_left_capability:
+ * @context: a #GstVaapiContext
+ *
+ * Retrieves the number of unallocated surfaces left in the pool.
+ *
+ * Return value: the number of unallocated surfaces in the pool
+ */
+
+guint
+gst_vaapi_context_get_surface_left_capability(GstVaapiContext *context)
+{
+    GstVaapiContextPrivate * const priv = context->priv;
+
+    g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), 0);
+    g_return_val_if_fail(priv->surfaces, 0);
+
+    return (gst_vaapi_video_pool_get_capacity(priv->surfaces_pool) -
+            priv->surfaces->len);
+}
+
+/**
+ * gst_vaapi_context_put_surface:
+ * @context: a #GstVaapiContext
+ * @surface: the #GstVaapiSurface to release
+ *
+ * Releases a surface acquired by gst_vaapi_context_get_surface().
+ */
+void
+gst_vaapi_context_put_surface(GstVaapiContext *context, GstVaapiSurface *surface)
+{
+    g_return_if_fail(GST_VAAPI_IS_CONTEXT(context));
+    g_return_if_fail(GST_VAAPI_IS_SURFACE(surface));
+
+    gst_vaapi_surface_set_parent_context(surface, NULL);
+    gst_vaapi_video_pool_put_object(context->priv->surfaces_pool, surface);
+}
+
+/**
+ * gst_vaapi_context_find_surface_by_id:
+ * @context: a #GstVaapiContext
+ * @id: the VA surface id to find
+ *
+ * Finds VA surface by @id in the list of surfaces attached to the @context.
+ *
+ * Return value: the matching #GstVaapiSurface object, or %NULL if
+ *   none was found
+ */
+GstVaapiSurface *
+gst_vaapi_context_find_surface_by_id(GstVaapiContext *context, GstVaapiID id)
+{
+    GstVaapiContextPrivate *priv;
+    GstVaapiSurface *surface;
+    guint i;
+
+    g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), NULL);
+
+    priv = context->priv;
+    g_return_val_if_fail(priv->surfaces, NULL);
+
+    for (i = 0; i < priv->surfaces->len; i++) {
+        surface = g_ptr_array_index(priv->surfaces, i);
+        if (GST_VAAPI_OBJECT_ID(surface) == id)
+            return surface;
+    }
+    return NULL;
+}
+
+/* Check if composition changed */
+static gboolean
+gst_vaapi_context_composition_changed(
+    GstVaapiContext            *context,
+    GstVideoOverlayComposition *composition
+)
+{
+    GstVaapiContextPrivate * const priv = context->priv;
+    GstVaapiOverlayRectangle *overlay;
+    GstVideoOverlayRectangle *rect;
+    guint i, n_rectangles;
+
+    if (!priv->overlay || !composition)
+        return TRUE;
+
+    n_rectangles = gst_video_overlay_composition_n_rectangles(composition);
+    if (priv->overlay->len != n_rectangles)
+        return TRUE;
+
+    for (i = 0; i < n_rectangles; i++) {
+        rect = gst_video_overlay_composition_get_rectangle(composition, i);
+        g_return_val_if_fail(rect, TRUE);
+        overlay = g_ptr_array_index(priv->overlay, i);
+        g_return_val_if_fail(overlay, TRUE);
+        if (overlay->seq_num != gst_video_overlay_rectangle_get_seqnum(rect))
+            return TRUE;
+    }
+    return FALSE;
+}
+
+/**
+ * gst_vaapi_context_apply_composition:
+ * @context: a #GstVaapiContext
+ * @composition: a #GstVideoOverlayComposition
+ *
+ * Applies video composition planes to all surfaces bound to @context.
+ * This helper function resets any additional subpictures the user may
+ * have associated himself. A %NULL @composition will also clear all
+ * the existing subpictures.
+ *
+ * Return value: %TRUE if all composition planes could be applied,
+ *   %FALSE otherwise
+ */
+gboolean
+gst_vaapi_context_apply_composition(
+    GstVaapiContext            *context,
+    GstVideoOverlayComposition *composition
+)
+{
+    GstVaapiContextPrivate *priv;
+    GstVideoOverlayRectangle *rect;
+    GstVaapiOverlayRectangle *overlay = NULL;
+    GstVaapiDisplay *display;
+    guint i, j, n_rectangles;
+
+    g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), FALSE);
+
+    priv = context->priv;
+    if (!priv->surfaces)
+        return FALSE;
+
+    display = GST_VAAPI_OBJECT_DISPLAY(context);
+    if (!display)
+        return FALSE;
+
+    if (!gst_vaapi_context_composition_changed(context, composition))
+        return TRUE;
+    gst_vaapi_context_destroy_overlay(context);
+
+    if (!composition)
+        return TRUE;
+    if (!gst_vaapi_context_create_overlay(context))
+        return FALSE;
+
+    n_rectangles = gst_video_overlay_composition_n_rectangles(composition);
+    for (i = 0; i < n_rectangles; i++) {
+        rect = gst_video_overlay_composition_get_rectangle(composition, i);
+
+        overlay = overlay_rectangle_new(context);
+        if (!overlay) {
+            GST_WARNING("could not create VA overlay rectangle");
+            return FALSE;
+        }
+        overlay->seq_num = gst_video_overlay_rectangle_get_seqnum(rect);
+
+        overlay->subpicture = gst_vaapi_subpicture_new_from_overlay_rectangle(
+            display,
+            rect
+        );
+        if (!overlay->subpicture) {
+            overlay_rectangle_destroy(overlay);
+            return FALSE;
+        }
+
+        gst_video_overlay_rectangle_get_render_rectangle(
+            rect,
+            (gint *)&overlay->rect.x,
+            (gint *)&overlay->rect.y,
+            &overlay->rect.width,
+            &overlay->rect.height
+        );
+
+        for (j = 0; j < priv->surfaces->len; j++) {
+            GstVaapiSurface * const surface =
+                g_ptr_array_index(priv->surfaces, j);
+            if (!gst_vaapi_surface_associate_subpicture(surface,
+                         overlay->subpicture, NULL, &overlay->rect)) {
+                GST_WARNING("could not render overlay rectangle %p", rect);
+                overlay_rectangle_destroy(overlay);
+                return FALSE;
+            }
+        }
+        g_ptr_array_add(priv->overlay, overlay);
+    }
+    return TRUE;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapicontext.h b/gst-libs/gst/vaapi/gstvaapicontext.h
new file mode 100644 (file)
index 0000000..14b5e27
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ *  gstvaapicontext.h - VA context abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_CONTEXT_H
+#define GST_VAAPI_CONTEXT_H
+
+#include <gst/vaapi/gstvaapiobject.h>
+#include <gst/vaapi/gstvaapiprofile.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapisurface.h>
+#include <gst/video/video-overlay-composition.h>
+#include <gst/vaapi/gstvaapisurfacepool.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_CONTEXT \
+    (gst_vaapi_context_get_type())
+
+#define GST_VAAPI_CONTEXT(obj)                          \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                  \
+                                GST_VAAPI_TYPE_CONTEXT, \
+                                GstVaapiContext))
+
+#define GST_VAAPI_CONTEXT_CLASS(klass)                  \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                   \
+                             GST_VAAPI_TYPE_CONTEXT,    \
+                             GstVaapiContextClass))
+
+#define GST_VAAPI_IS_CONTEXT(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_CONTEXT))
+
+#define GST_VAAPI_IS_CONTEXT_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_CONTEXT))
+
+#define GST_VAAPI_CONTEXT_GET_CLASS(obj)                \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                   \
+                               GST_VAAPI_TYPE_CONTEXT,  \
+                               GstVaapiContextClass))
+
+typedef struct _GstVaapiContext                 GstVaapiContext;
+typedef struct _GstVaapiContextPrivate          GstVaapiContextPrivate;
+typedef struct _GstVaapiContextClass            GstVaapiContextClass;
+
+/**
+ * GstVaapiContext:
+ *
+ * A VA context wrapper.
+ */
+struct _GstVaapiContext {
+    /*< private >*/
+    GstVaapiObject parent_instance;
+
+    GstVaapiContextPrivate *priv;
+};
+
+/**
+ * GstVaapiContextClass:
+ *
+ * A VA context wrapper class.
+ */
+struct _GstVaapiContextClass {
+    /*< private >*/
+    GstVaapiObjectClass parent_class;
+};
+
+GType
+gst_vaapi_context_get_type(void) G_GNUC_CONST;
+
+GstVaapiContext *
+gst_vaapi_context_new(
+    GstVaapiDisplay    *display,
+    GstVaapiProfile     profile,
+    GstVaapiEntrypoint  entrypoint,
+    GstVaapiRateControl rate_control,
+    guint               width,
+    guint               height,
+    guint               surface_num
+);
+
+gboolean
+gst_vaapi_context_reset(
+    GstVaapiContext    *context,
+    GstVaapiProfile     profile,
+    GstVaapiEntrypoint  entrypoint,
+    unsigned int        width,
+    unsigned int        height,
+    unsigned int        surface_num
+);
+
+GstVaapiID
+gst_vaapi_context_get_id(GstVaapiContext *context);
+
+GstVaapiProfile
+gst_vaapi_context_get_profile(GstVaapiContext *context);
+
+gboolean
+gst_vaapi_context_set_profile(GstVaapiContext *context, GstVaapiProfile profile);
+
+GstVaapiEntrypoint
+gst_vaapi_context_get_entrypoint(GstVaapiContext *context);
+
+void
+gst_vaapi_context_get_size(
+    GstVaapiContext *context,
+    guint           *pwidth,
+    guint           *pheight
+);
+
+GstVaapiSurface *
+gst_vaapi_context_get_surface(GstVaapiContext *context);
+
+GstVaapiSurfacePool *
+gst_vaapi_context_get_surface_pool(GstVaapiContext *context);
+
+
+guint
+gst_vaapi_context_get_surface_count(GstVaapiContext *context);
+
+guint
+gst_vaapi_context_get_surface_left_capability(GstVaapiContext *context);
+
+void
+gst_vaapi_context_put_surface(GstVaapiContext *context, GstVaapiSurface *surface);
+
+GstVaapiSurface *
+gst_vaapi_context_find_surface_by_id(GstVaapiContext *context, GstVaapiID id);
+
+gboolean
+gst_vaapi_context_apply_composition(
+    GstVaapiContext            *context,
+    GstVideoOverlayComposition *composition
+);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_CONTEXT_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidebug.h b/gst-libs/gst/vaapi/gstvaapidebug.h
new file mode 100644 (file)
index 0000000..efcafaa
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  gstvaapidebug.h - VA-API debugging utilities
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DEBUG_H
+#define GST_VAAPI_DEBUG_H
+
+#include <gst/gstinfo.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <gst/gst.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+
+#if DEBUG
+GST_DEBUG_CATEGORY_EXTERN(gst_debug_vaapi);
+#define GST_CAT_DEFAULT gst_debug_vaapi
+#endif
+/* FPS Calculation for DEBUG */
+#define FPS_CALCULATION(objname)                     \
+    do{                                              \
+        static guint num_frame = 0;                  \
+        static struct timeval last_sys_time;         \
+        static struct timeval first_sys_time;        \
+        static int b_last_sys_time_init = FALSE;     \
+        if (!b_last_sys_time_init) {                 \
+          gettimeofday (&last_sys_time, NULL);       \
+          gettimeofday (&first_sys_time, NULL);      \
+          b_last_sys_time_init = TRUE;               \
+        } else {                                     \
+          if ((num_frame%50)==0) {                   \
+            double total, current;                   \
+            struct timeval cur_sys_time;             \
+            gettimeofday (&cur_sys_time, NULL);      \
+            total = (cur_sys_time.tv_sec - first_sys_time.tv_sec)*1.0f +       \
+                   (cur_sys_time.tv_usec - first_sys_time.tv_usec)/1000000.0f; \
+            current = (cur_sys_time.tv_sec - last_sys_time.tv_sec)*1.0f +      \
+                    (cur_sys_time.tv_usec - last_sys_time.tv_usec)/1000000.0f; \
+            printf("%s Current fps: %.2f, Total avg fps: %.2f\n",              \
+                    #objname, (float)50.0f/current, (float)num_frame/total);   \
+            last_sys_time = cur_sys_time;            \
+          }                                          \
+        }                                            \
+        ++num_frame;                                 \
+    }while(0)
+
+
+#endif /* GST_VAAPI_DEBUG_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder.c b/gst-libs/gst/vaapi/gstvaapidecoder.c
new file mode 100644 (file)
index 0000000..041967c
--- /dev/null
@@ -0,0 +1,670 @@
+/*
+ *  gstvaapidecoder.c - VA decoder abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapidecoder
+ * @short_description: VA decoder abstraction
+ */
+
+#include "sysdeps.h"
+#include "gstvaapicompat.h"
+#include "gstvaapidecoder.h"
+#include "gstvaapidecoder_priv.h"
+#include "gstvaapiutils.h"
+#include "gstvaapi_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiDecoder, gst_vaapi_decoder, G_TYPE_OBJECT);
+
+enum {
+    PROP_0,
+
+    PROP_DISPLAY,
+    PROP_CAPS,
+
+    N_PROPERTIES
+};
+
+static GParamSpec *g_properties[N_PROPERTIES] = { NULL, };
+
+static void
+destroy_buffer(GstBuffer *buffer)
+{
+    gst_buffer_unref(buffer);
+}
+
+static gboolean
+push_buffer(GstVaapiDecoder *decoder, GstBuffer *buffer)
+{
+    GstVaapiDecoderPrivate * const priv = decoder->priv;
+
+    if (!buffer) {
+        buffer = gst_buffer_new();
+        if (!buffer)
+            return FALSE;
+        GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_EOS);
+    }
+
+    GST_DEBUG("queue encoded data buffer %p (%d bytes)",
+              buffer, GST_BUFFER_SIZE(buffer));
+
+    g_queue_push_tail(priv->buffers, buffer);
+    return TRUE;
+}
+
+static void
+push_back_buffer(GstVaapiDecoder *decoder, GstBuffer *buffer)
+{
+    GstVaapiDecoderPrivate * const priv = decoder->priv;
+
+    GST_DEBUG("requeue encoded data buffer %p (%d bytes)",
+              buffer, GST_BUFFER_SIZE(buffer));
+
+    g_queue_push_head(priv->buffers, buffer);
+}
+
+static GstBuffer *
+pop_buffer(GstVaapiDecoder *decoder)
+{
+    GstVaapiDecoderPrivate * const priv = decoder->priv;
+    GstBuffer *buffer;
+
+    buffer = g_queue_pop_head(priv->buffers);
+    if (!buffer)
+        return NULL;
+
+    GST_DEBUG("dequeue buffer %p for decoding (%d bytes)",
+              buffer, GST_BUFFER_SIZE(buffer));
+
+    return buffer;
+}
+
+static GstVaapiDecoderStatus
+decode_step(GstVaapiDecoder *decoder)
+{
+    GstVaapiDecoderStatus status;
+    GstBuffer *buffer;
+
+    /* Decoding will fail if there is no surface left */
+    status = gst_vaapi_decoder_check_status(decoder);
+    if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+        return status;
+
+    do {
+        buffer = pop_buffer(decoder);
+        if (!buffer)
+            return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+
+        status = GST_VAAPI_DECODER_GET_CLASS(decoder)->decode(decoder, buffer);
+        GST_DEBUG("decode frame (status = %d)", status);
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS && GST_BUFFER_IS_EOS(buffer))
+            status = GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
+        gst_buffer_unref(buffer);
+    } while (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA);
+    return status;
+}
+
+static inline void
+push_surface(GstVaapiDecoder *decoder, GstVaapiSurfaceProxy *proxy)
+{
+    GstVaapiDecoderPrivate * const priv = decoder->priv;
+
+    GST_DEBUG("queue decoded surface %" GST_VAAPI_ID_FORMAT,
+              GST_VAAPI_ID_ARGS(gst_vaapi_surface_proxy_get_surface_id(proxy)));
+
+    g_queue_push_tail(priv->surfaces, proxy);
+}
+
+static inline GstVaapiSurfaceProxy *
+pop_surface(GstVaapiDecoder *decoder)
+{
+    GstVaapiDecoderPrivate * const priv = decoder->priv;
+
+    return g_queue_pop_head(priv->surfaces);
+}
+
+static inline void
+set_codec_data(GstVaapiDecoder *decoder, GstBuffer *codec_data)
+{
+    GstVaapiDecoderPrivate * const priv = decoder->priv;
+
+    if (priv->codec_data) {
+        gst_buffer_unref(priv->codec_data);
+        priv->codec_data = NULL;
+    }
+
+    if (codec_data)
+        priv->codec_data = gst_buffer_ref(codec_data);
+}
+
+static void
+set_caps(GstVaapiDecoder *decoder, GstCaps *caps)
+{
+    GstVaapiDecoderPrivate * const priv = decoder->priv;
+    GstStructure * const structure = gst_caps_get_structure(caps, 0);
+    GstVaapiProfile profile;
+    const GValue *v_codec_data;
+    gint v1, v2;
+    gboolean b;
+
+    profile = gst_vaapi_profile_from_caps(caps);
+    if (!profile)
+        return;
+
+    priv->caps = gst_caps_copy(caps);
+
+    priv->codec = gst_vaapi_profile_get_codec(profile);
+    if (!priv->codec)
+        return;
+
+    if (gst_structure_get_int(structure, "width", &v1))
+        priv->width = v1;
+    if (gst_structure_get_int(structure, "height", &v2))
+        priv->height = v2;
+
+    if (gst_structure_get_fraction(structure, "framerate", &v1, &v2)) {
+        priv->fps_n = v1;
+        priv->fps_d = v2;
+    }
+
+    if (gst_structure_get_fraction(structure, "pixel-aspect-ratio", &v1, &v2)) {
+        priv->par_n = v1;
+        priv->par_d = v2;
+    }
+
+    if (gst_structure_get_boolean(structure, "interlaced", &b))
+        priv->is_interlaced = b;
+
+    v_codec_data = gst_structure_get_value(structure, "codec_data");
+    if (v_codec_data)
+        set_codec_data(decoder, gst_value_get_buffer(v_codec_data));
+}
+
+static void
+clear_queue(GQueue *q, GDestroyNotify destroy)
+{
+    while (!g_queue_is_empty(q))
+        destroy(g_queue_pop_head(q));
+}
+
+static void
+gst_vaapi_decoder_finalize(GObject *object)
+{
+    GstVaapiDecoder * const        decoder = GST_VAAPI_DECODER(object);
+    GstVaapiDecoderPrivate * const priv    = decoder->priv;
+
+    set_codec_data(decoder, NULL);
+
+    if (priv->caps) {
+        gst_caps_unref(priv->caps);
+        priv->caps = NULL;
+    }
+
+    if (priv->context) {
+        g_object_unref(priv->context);
+        priv->context = NULL;
+        priv->va_context = VA_INVALID_ID;
+    }
+    if (priv->buffers) {
+        clear_queue(priv->buffers, (GDestroyNotify)destroy_buffer);
+        g_queue_free(priv->buffers);
+        priv->buffers = NULL;
+    }
+
+    if (priv->surfaces) {
+        clear_queue(priv->surfaces, (GDestroyNotify)g_object_unref);
+        g_queue_free(priv->surfaces);
+        priv->surfaces = NULL;
+    }
+
+    if (priv->display) {
+        g_object_unref(priv->display);
+        priv->display = NULL;
+        priv->va_display = NULL;
+    }
+
+    G_OBJECT_CLASS(gst_vaapi_decoder_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_decoder_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiDecoder * const        decoder = GST_VAAPI_DECODER(object);
+    GstVaapiDecoderPrivate * const priv    = decoder->priv;
+
+    switch (prop_id) {
+    case PROP_DISPLAY:
+        priv->display = g_object_ref(g_value_get_object(value));
+        if (priv->display)
+            priv->va_display = gst_vaapi_display_get_display(priv->display);
+        else
+            priv->va_display = NULL;
+        break;
+    case PROP_CAPS:
+        set_caps(decoder, g_value_get_pointer(value));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_decoder_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiDecoderPrivate * const priv = GST_VAAPI_DECODER(object)->priv;
+
+    switch (prop_id) {
+    case PROP_DISPLAY:
+        g_value_set_object(value, priv->display);
+        break;
+    case PROP_CAPS:
+        gst_value_set_caps(value, priv->caps);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_decoder_class_init(GstVaapiDecoderClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiDecoderPrivate));
+
+    object_class->finalize     = gst_vaapi_decoder_finalize;
+    object_class->set_property = gst_vaapi_decoder_set_property;
+    object_class->get_property = gst_vaapi_decoder_get_property;
+
+    /**
+     * GstVaapiDecoder:display:
+     *
+     * The #GstVaapiDisplay this decoder is bound to.
+     */
+    g_properties[PROP_DISPLAY] =
+         g_param_spec_object("display",
+                             "Display",
+                             "The GstVaapiDisplay this decoder is bound to",
+                             GST_VAAPI_TYPE_DISPLAY,
+                             G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
+
+    g_properties[PROP_CAPS] =
+         g_param_spec_pointer("caps",
+                              "Decoder caps",
+                              "The decoder caps",
+                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
+
+    g_object_class_install_properties(object_class, N_PROPERTIES, g_properties);
+}
+
+static void
+gst_vaapi_decoder_init(GstVaapiDecoder *decoder)
+{
+    GstVaapiDecoderPrivate *priv = GST_VAAPI_DECODER_GET_PRIVATE(decoder);
+
+    decoder->priv               = priv;
+    priv->display               = NULL;
+    priv->va_display            = NULL;
+    priv->context               = NULL;
+    priv->va_context            = VA_INVALID_ID;
+    priv->caps                  = NULL;
+    priv->codec                 = 0;
+    priv->codec_data            = NULL;
+    priv->width                 = 0;
+    priv->height                = 0;
+    priv->fps_n                 = 0;
+    priv->fps_d                 = 0;
+    priv->par_n                 = 0;
+    priv->par_d                 = 0;
+    priv->buffers               = g_queue_new();
+    priv->surfaces              = g_queue_new();
+    priv->is_interlaced         = FALSE;
+}
+
+/**
+ * gst_vaapi_decoder_get_caps:
+ * @decoder: a #GstVaapiDecoder
+ *
+ * Retrieves the @decoder caps. The deocder owns the returned caps, so
+ * use gst_caps_ref() whenever necessary.
+ *
+ * Return value: the @decoder caps
+ */
+GstCaps *
+gst_vaapi_decoder_get_caps(GstVaapiDecoder *decoder)
+{
+    return decoder->priv->caps;
+}
+
+/**
+ * gst_vaapi_decoder_put_buffer:
+ * @decoder: a #GstVaapiDecoder
+ * @buf: a #GstBuffer
+ *
+ * Queues a #GstBuffer to the HW decoder. The decoder holds a
+ * reference to @buf.
+ *
+ * Caller can notify an End-Of-Stream with @buf set to %NULL.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_decoder_put_buffer(GstVaapiDecoder *decoder, GstBuffer *buf)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), FALSE);
+
+    return push_buffer(decoder, buf ? gst_buffer_ref(buf) : NULL);
+}
+
+/**
+ * gst_vaapi_decoder_get_surface:
+ * @decoder: a #GstVaapiDecoder
+ * @pstatus: return location for the decoder status, or %NULL
+ *
+ * Flushes encoded buffers to the decoder and returns a decoded
+ * surface, if any.
+ *
+ * Return value: a #GstVaapiSurfaceProxy holding the decoded surface,
+ *   or %NULL if none is available (e.g. an error). Caller owns the
+ *   returned object. g_object_unref() after usage.
+ */
+GstVaapiSurfaceProxy *
+gst_vaapi_decoder_get_surface(
+    GstVaapiDecoder       *decoder,
+    GstVaapiDecoderStatus *pstatus
+)
+{
+    GstVaapiSurfaceProxy *proxy;
+    GstVaapiDecoderStatus status;
+
+    if (pstatus)
+        *pstatus = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), NULL);
+
+    proxy = pop_surface(decoder);
+    if (!proxy) {
+        do {
+            status = decode_step(decoder);
+        } while (status == GST_VAAPI_DECODER_STATUS_SUCCESS);
+        proxy = pop_surface(decoder);
+    }
+
+    if (proxy)
+        status = GST_VAAPI_DECODER_STATUS_SUCCESS;
+
+    if (pstatus)
+        *pstatus = status;
+    return proxy;
+}
+
+void
+gst_vaapi_decoder_clear_buffer(GstVaapiDecoder *decoder)
+{
+    GstVaapiDecoderPrivate * const priv = decoder->priv;
+    GstVaapiDecoderClass * const klass = GST_VAAPI_DECODER_GET_CLASS(decoder);
+
+    if (klass->clear_buffer)
+        klass->clear_buffer(decoder);
+
+    if (priv->buffers)
+        clear_queue(priv->buffers, (GDestroyNotify)destroy_buffer);
+
+    if (priv->surfaces)
+        clear_queue(priv->surfaces, (GDestroyNotify)g_object_unref);
+}
+
+void
+gst_vaapi_decoder_set_picture_size(
+    GstVaapiDecoder    *decoder,
+    guint               width,
+    guint               height
+)
+{
+    GstVaapiDecoderPrivate * const priv = decoder->priv;
+    gboolean size_changed = FALSE;
+
+    if (priv->width != width) {
+        GST_DEBUG("picture width changed to %d", width);
+        priv->width = width;
+        gst_caps_set_simple(priv->caps, "width", G_TYPE_INT, width, NULL);
+        size_changed = TRUE;
+    }
+
+    if (priv->height != height) {
+        GST_DEBUG("picture height changed to %d", height);
+        priv->height = height;
+        gst_caps_set_simple(priv->caps, "height", G_TYPE_INT, height, NULL);
+        size_changed = TRUE;
+    }
+
+    if (size_changed)
+        g_object_notify_by_pspec(G_OBJECT(decoder), g_properties[PROP_CAPS]);
+}
+
+void
+gst_vaapi_decoder_set_framerate(
+    GstVaapiDecoder    *decoder,
+    guint               fps_n,
+    guint               fps_d
+)
+{
+    GstVaapiDecoderPrivate * const priv = decoder->priv;
+
+    if (!fps_n || !fps_d)
+        return;
+
+    if (priv->fps_n != fps_n || priv->fps_d != fps_d) {
+        GST_DEBUG("framerate changed to %u/%u", fps_n, fps_d);
+        priv->fps_n = fps_n;
+        priv->fps_d = fps_d;
+        gst_caps_set_simple(
+            priv->caps,
+            "framerate", GST_TYPE_FRACTION, fps_n, fps_d,
+            NULL
+        );
+        g_object_notify_by_pspec(G_OBJECT(decoder), g_properties[PROP_CAPS]);
+    }
+}
+
+void
+gst_vaapi_decoder_set_pixel_aspect_ratio(
+    GstVaapiDecoder    *decoder,
+    guint               par_n,
+    guint               par_d
+)
+{
+    GstVaapiDecoderPrivate * const priv = decoder->priv;
+
+    if (!par_n || !par_d)
+        return;
+
+    if (priv->par_n != par_n || priv->par_d != par_d) {
+        GST_DEBUG("pixel-aspect-ratio changed to %u/%u", par_n, par_d);
+        priv->par_n = par_n;
+        priv->par_d = par_d;
+        gst_caps_set_simple(
+            priv->caps,
+            "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d,
+            NULL
+        );
+        g_object_notify_by_pspec(G_OBJECT(decoder), g_properties[PROP_CAPS]);
+    }
+}
+
+void
+gst_vaapi_decoder_set_interlaced(GstVaapiDecoder *decoder, gboolean interlaced)
+{
+    GstVaapiDecoderPrivate * const priv = decoder->priv;
+
+    if (priv->is_interlaced != interlaced) {
+        GST_DEBUG("interlaced changed to %s", interlaced ? "true" : "false");
+        priv->is_interlaced = interlaced;
+        gst_caps_set_simple(
+            priv->caps,
+            "interlaced", G_TYPE_BOOLEAN, interlaced,
+            NULL
+        );
+        g_object_notify_by_pspec(G_OBJECT(decoder), g_properties[PROP_CAPS]);
+    }
+}
+
+gboolean
+gst_vaapi_decoder_ensure_context(
+    GstVaapiDecoder    *decoder,
+    GstVaapiProfile     profile,
+    GstVaapiEntrypoint  entrypoint,
+    guint               width,
+    guint               height,
+    guint               surface_num
+)
+{
+    GstVaapiDecoderPrivate * const priv = decoder->priv;
+    gboolean ret = TRUE;
+
+    gst_vaapi_decoder_set_picture_size(decoder, width, height);
+
+    if (priv->context) {
+        ret = gst_vaapi_context_reset(priv->context,
+                                       profile, entrypoint,
+                                       width, height,
+                                       surface_num);
+        goto end;
+    }
+
+    priv->context = gst_vaapi_context_new(
+        priv->display,
+        profile,
+        entrypoint,
+        GST_VAAPI_RATECONTROL_NONE,
+        width,
+        height,
+        surface_num
+    );
+    if (!priv->context)
+        return FALSE;
+end:
+    priv->va_context = gst_vaapi_context_get_id(priv->context);
+    return ret;
+}
+
+gboolean
+gst_vaapi_decoder_push_buffer_sub(
+    GstVaapiDecoder *decoder,
+    GstBuffer       *buffer,
+    guint            offset,
+    guint            size
+)
+{
+    GstBuffer *subbuffer;
+
+    subbuffer = gst_buffer_create_sub(buffer, offset, size);
+    if (!subbuffer)
+        return FALSE;
+
+    push_back_buffer(decoder, subbuffer);
+    return TRUE;
+}
+
+void
+gst_vaapi_decoder_push_surface_proxy(
+    GstVaapiDecoder      *decoder,
+    GstVaapiSurfaceProxy *proxy
+)
+{
+    return push_surface(decoder, proxy);
+}
+
+static gboolean
+gst_vaapi_decoder_context_increase_surfaces(
+    GstVaapiDecoder *decoder,
+    guint            increment
+)
+{
+    GstVaapiDecoderPrivate * const priv = decoder->priv;
+    guint profile, entrypoint;
+    guint width, height;
+    guint surface_num;
+    gboolean ret = TRUE;
+
+    if (!increment)
+        return TRUE;
+
+    if (!priv->context ||
+         (gst_vaapi_context_get_surface_left_capability(priv->context) < increment))
+        return FALSE;
+    g_object_get(G_OBJECT(priv->context),
+                 "profile",     &profile,
+                 "entrypoint",  &entrypoint,
+                 "width",       &width,
+                 "height",      &height,
+                 "surface_num", &surface_num,
+                 NULL);
+    surface_num += increment;
+    ret = gst_vaapi_context_reset(priv->context,
+                                   (GstVaapiProfile)profile,
+                                   (GstVaapiEntrypoint)entrypoint,
+                                   width,
+                                   height,
+                                   surface_num);
+    priv->va_context = gst_vaapi_context_get_id(priv->context);
+    return ret;
+}
+
+GstVaapiDecoderStatus
+gst_vaapi_decoder_check_status(GstVaapiDecoder *decoder)
+{
+    GstVaapiDecoderPrivate * const priv = decoder->priv;
+    guint increment;
+
+    if (!priv->context || gst_vaapi_context_get_surface_count(priv->context) > 0)
+        return GST_VAAPI_DECODER_STATUS_SUCCESS;
+
+    increment = gst_vaapi_context_get_surface_left_capability(priv->context);
+    if (increment < 1) {
+        GST_DEBUG("decoder context surface pool is out of capability");
+        return GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE;
+    }
+    if (increment > 2)
+        increment = 2;
+
+    if (!gst_vaapi_decoder_context_increase_surfaces(decoder, increment)) {
+        GST_ERROR("increase decoder surface failed");
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder.h b/gst-libs/gst/vaapi/gstvaapidecoder.h
new file mode 100644 (file)
index 0000000..6858e4b
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ *  gstvaapidecoder.h - VA decoder abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DECODER_H
+#define GST_VAAPI_DECODER_H
+
+#include <gst/gstbuffer.h>
+#include <gst/vaapi/gstvaapicontext.h>
+#include <gst/vaapi/gstvaapisurfaceproxy.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_DECODER \
+    (gst_vaapi_decoder_get_type())
+
+#define GST_VAAPI_DECODER(obj)                          \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                  \
+                                GST_VAAPI_TYPE_DECODER, \
+                                GstVaapiDecoder))
+
+#define GST_VAAPI_DECODER_CLASS(klass)                  \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                   \
+                             GST_VAAPI_TYPE_DECODER,    \
+                             GstVaapiDecoderClass))
+
+#define GST_VAAPI_IS_DECODER(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_DECODER))
+
+#define GST_VAAPI_IS_DECODER_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_DECODER))
+
+#define GST_VAAPI_DECODER_GET_CLASS(obj)                \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                   \
+                               GST_VAAPI_TYPE_DECODER,  \
+                               GstVaapiDecoderClass))
+
+typedef enum _GstVaapiDecoderStatus             GstVaapiDecoderStatus;
+typedef struct _GstVaapiDecoder                 GstVaapiDecoder;
+typedef struct _GstVaapiDecoderPrivate          GstVaapiDecoderPrivate;
+typedef struct _GstVaapiDecoderClass            GstVaapiDecoderClass;
+
+/**
+ * GstVaapiDecoderStatus:
+ * @GST_VAAPI_DECODER_STATUS_SUCCESS: Success.
+ * @GST_VAAPI_DECODER_STATUS_END_OF_STREAM: End-Of-Stream.
+ * @GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED: No memory left.
+ * @GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED: Decoder initialization failure.
+ * @GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC: Unsupported codec.
+ * @GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA: Not enough input data to decode.
+ * @GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE: No surface left to hold the decoded picture.
+ * @GST_VAAPI_DECODER_STATUS_ERROR_INVALID_SURFACE: Invalid surface.
+ * @GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER: Invalid or unsupported bitstream data.
+ * @GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE: Unsupported codec profile.
+ * @GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT: Unsupported chroma format.
+ * @GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN: Unknown error.
+ *
+ * Decoder status for gst_vaapi_decoder_get_surface().
+ */
+enum _GstVaapiDecoderStatus {
+    GST_VAAPI_DECODER_STATUS_SUCCESS = 0,
+    GST_VAAPI_DECODER_STATUS_END_OF_STREAM,
+    GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED,
+    GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED,
+    GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC,
+    GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA,
+    GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE,
+    GST_VAAPI_DECODER_STATUS_ERROR_INVALID_SURFACE,
+    GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER,
+    GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE,
+    GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT,
+    GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN = -1
+};
+
+/**
+ * GstVaapiDecoder:
+ *
+ * A VA decoder base instance.
+ */
+struct _GstVaapiDecoder {
+    /*< private >*/
+    GObject parent_instance;
+
+    GstVaapiDecoderPrivate *priv;
+};
+
+/**
+ * GstVaapiDecoderClass:
+ *
+ * A VA decoder base class.
+ */
+struct _GstVaapiDecoderClass {
+    /*< private >*/
+    GObjectClass parent_class;
+
+    GstVaapiDecoderStatus (*decode)(GstVaapiDecoder *decoder, GstBuffer *buffer);
+    void                  (*clear_buffer)(GstVaapiDecoder *decoder);
+};
+
+GType
+gst_vaapi_decoder_get_type(void) G_GNUC_CONST;
+
+GstCaps *
+gst_vaapi_decoder_get_caps(GstVaapiDecoder *decoder);
+
+gboolean
+gst_vaapi_decoder_put_buffer(GstVaapiDecoder *decoder, GstBuffer *buf);
+
+GstVaapiSurfaceProxy *
+gst_vaapi_decoder_get_surface(
+    GstVaapiDecoder       *decoder,
+    GstVaapiDecoderStatus *pstatus
+);
+
+void
+gst_vaapi_decoder_clear_buffer(GstVaapiDecoder *decoder);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DECODER_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_dpb.c b/gst-libs/gst/vaapi/gstvaapidecoder_dpb.c
new file mode 100644 (file)
index 0000000..c5a5a76
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ *  gstvaapidecoder_dpb.c - Decoded Picture Buffer
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "sysdeps.h"
+#include "gstvaapidecoder_dpb.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+/* ------------------------------------------------------------------------- */
+/* --- Common Decoded Picture Buffer utilities                           --- */
+/* ------------------------------------------------------------------------- */
+
+static GstVaapiDpb *
+dpb_new(GType type, guint max_pictures)
+{
+    GstMiniObject *obj;
+    GstVaapiDpb *dpb;
+
+    g_return_val_if_fail(max_pictures > 0, NULL);
+
+    obj = gst_mini_object_new(type);
+    if (!obj)
+        return NULL;
+
+    dpb = GST_VAAPI_DPB_CAST(obj);
+    dpb->pictures = g_new0(GstVaapiPicture *, max_pictures);
+    if (!dpb->pictures)
+        goto error;
+    dpb->max_pictures = max_pictures;
+    return dpb;
+
+error:
+    gst_mini_object_unref(obj);
+    return NULL;
+}
+
+static gint
+dpb_get_oldest(GstVaapiDpb *dpb, gboolean output)
+{
+    gint i, lowest_pts_index;
+
+    for (i = 0; i < dpb->num_pictures; i++) {
+        if ((GST_VAAPI_PICTURE_IS_OUTPUT(dpb->pictures[i]) ^ output) == 0)
+            break;
+    }
+    if (i == dpb->num_pictures)
+        return -1;
+
+    lowest_pts_index = i++;
+    for (; i < dpb->num_pictures; i++) {
+        GstVaapiPicture * const picture = dpb->pictures[i];
+        if ((GST_VAAPI_PICTURE_IS_OUTPUT(picture) ^ output) != 0)
+            continue;
+        if (picture->poc < dpb->pictures[lowest_pts_index]->poc)
+            lowest_pts_index = i;
+    }
+    return lowest_pts_index;
+}
+
+static void
+dpb_remove_index(GstVaapiDpb *dpb, guint index)
+{
+    GstVaapiPicture ** const pictures = dpb->pictures;
+    guint num_pictures = --dpb->num_pictures;
+
+    if (index != num_pictures)
+        gst_vaapi_picture_replace(&pictures[index], pictures[num_pictures]);
+    gst_vaapi_picture_replace(&pictures[num_pictures], NULL);
+}
+
+static inline gboolean
+dpb_output(GstVaapiDpb *dpb, GstVaapiPicture *picture)
+{
+    return gst_vaapi_picture_output(picture);
+}
+
+static gboolean
+dpb_bump(GstVaapiDpb *dpb)
+{
+    gint index;
+    gboolean success;
+
+    index = dpb_get_oldest(dpb, FALSE);
+    if (index < 0)
+        return FALSE;
+
+    success = dpb_output(dpb, dpb->pictures[index]);
+    if (!GST_VAAPI_PICTURE_IS_REFERENCE(dpb->pictures[index]))
+        dpb_remove_index(dpb, index);
+    return success;
+}
+
+static void
+dpb_clear(GstVaapiDpb *dpb)
+{
+    guint i;
+
+    for (i = 0; i < dpb->num_pictures; i++)
+        gst_vaapi_picture_replace(&dpb->pictures[i], NULL);
+    dpb->num_pictures = 0;
+}
+
+/* ------------------------------------------------------------------------- */
+/* --- Base Decoded Picture Buffer                                       --- */
+/* ------------------------------------------------------------------------- */
+
+G_DEFINE_TYPE(GstVaapiDpb, gst_vaapi_dpb, GST_TYPE_MINI_OBJECT)
+
+static void
+gst_vaapi_dpb_base_flush(GstVaapiDpb *dpb)
+{
+    while (dpb_bump(dpb))
+        ;
+    dpb_clear(dpb);
+}
+
+static gboolean
+gst_vaapi_dpb_base_add(GstVaapiDpb *dpb, GstVaapiPicture *picture)
+{
+    guint i;
+
+    // Remove all unused pictures
+    i = 0;
+    while (i < dpb->num_pictures) {
+        GstVaapiPicture * const picture = dpb->pictures[i];
+        if (GST_VAAPI_PICTURE_IS_OUTPUT(picture) &&
+            !GST_VAAPI_PICTURE_IS_REFERENCE(picture))
+            dpb_remove_index(dpb, i);
+        else
+            i++;
+    }
+
+    // Store reference decoded picture into the DPB
+    if (GST_VAAPI_PICTURE_IS_REFERENCE(picture)) {
+        while (dpb->num_pictures == dpb->max_pictures) {
+            if (!dpb_bump(dpb))
+                return FALSE;
+        }
+    }
+
+    // Store non-reference decoded picture into the DPB
+    else {
+        if (GST_VAAPI_PICTURE_IS_SKIPPED(picture))
+            return TRUE;
+        while (dpb->num_pictures == dpb->max_pictures) {
+            for (i = 0; i < dpb->num_pictures; i++) {
+                if (!GST_VAAPI_PICTURE_IS_OUTPUT(picture) &&
+                    dpb->pictures[i]->poc < picture->poc)
+                    break;
+            }
+            if (i == dpb->num_pictures)
+                return dpb_output(dpb, picture);
+            if (!dpb_bump(dpb))
+                return FALSE;
+        }
+    }
+    gst_vaapi_picture_replace(&dpb->pictures[dpb->num_pictures++], picture);
+    return TRUE;
+}
+
+static void
+gst_vaapi_dpb_finalize(GstMiniObject *object)
+{
+    GstVaapiDpb * const dpb = GST_VAAPI_DPB_CAST(object);
+    GstMiniObjectClass *parent_class;
+
+    if (dpb->pictures) {
+        dpb_clear(dpb);
+        g_free(dpb->pictures);
+    }
+
+    parent_class = GST_MINI_OBJECT_CLASS(gst_vaapi_dpb_parent_class);
+    if (parent_class->finalize)
+        parent_class->finalize(object);
+}
+
+static void
+gst_vaapi_dpb_init(GstVaapiDpb *dpb)
+{
+    dpb->pictures     = NULL;
+    dpb->num_pictures = 0;
+    dpb->max_pictures = 0;
+}
+
+static void
+gst_vaapi_dpb_class_init(GstVaapiDpbClass *klass)
+{
+    GstMiniObjectClass * const object_class = GST_MINI_OBJECT_CLASS(klass);
+
+    object_class->finalize = gst_vaapi_dpb_finalize;
+    klass->flush           = gst_vaapi_dpb_base_flush;
+    klass->add             = gst_vaapi_dpb_base_add;
+}
+
+void
+gst_vaapi_dpb_flush(GstVaapiDpb *dpb)
+{
+    GstVaapiDpbClass *klass;
+
+    g_return_if_fail(GST_VAAPI_IS_DPB(dpb));
+
+    klass = GST_VAAPI_DPB_GET_CLASS(dpb);
+    if (G_UNLIKELY(!klass || !klass->add))
+        return;
+    klass->flush(dpb);
+}
+
+gboolean
+gst_vaapi_dpb_add(GstVaapiDpb *dpb, GstVaapiPicture *picture)
+{
+    GstVaapiDpbClass *klass;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DPB(dpb), FALSE);
+    g_return_val_if_fail(GST_VAAPI_IS_PICTURE(picture), FALSE);
+
+    klass = GST_VAAPI_DPB_GET_CLASS(dpb);
+    if (G_UNLIKELY(!klass || !klass->add))
+        return FALSE;
+    return klass->add(dpb, picture);
+}
+
+guint
+gst_vaapi_dpb_size(GstVaapiDpb *dpb)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DPB(dpb), 0);
+
+    return dpb->num_pictures;
+}
+
+/* ------------------------------------------------------------------------- */
+/* --- MPEG-2 Decoded Picture Buffer                                     --- */
+/* ------------------------------------------------------------------------- */
+
+/* At most two reference pictures for MPEG-2 */
+#define MAX_MPEG2_REFERENCES 2
+
+G_DEFINE_TYPE(GstVaapiDpbMpeg2, gst_vaapi_dpb_mpeg2, GST_VAAPI_TYPE_DPB)
+
+static gboolean
+gst_vaapi_dpb_mpeg2_add(GstVaapiDpb *dpb, GstVaapiPicture *picture)
+{
+    GstVaapiPicture *ref_picture;
+    gint index = -1;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DPB_MPEG2(dpb), FALSE);
+
+    /*
+     * Purpose: only store reference decoded pictures into the DPB
+     *
+     * This means:
+     * - non-reference decoded pictures are output immediately
+     * - ... thus causing older reference pictures to be output, if not already
+     * - the oldest reference picture is replaced with the new reference picture
+     */
+    if (G_LIKELY(dpb->num_pictures == MAX_MPEG2_REFERENCES)) {
+        index = (dpb->pictures[0]->poc > dpb->pictures[1]->poc);
+        ref_picture = dpb->pictures[index];
+        if (!GST_VAAPI_PICTURE_IS_OUTPUT(ref_picture)) {
+            if (!dpb_output(dpb, ref_picture))
+                return FALSE;
+        }
+    }
+
+    if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture))
+        return dpb_output(dpb, picture);
+
+    if (index < 0)
+        index = dpb->num_pictures++;
+    gst_vaapi_picture_replace(&dpb->pictures[index], picture);
+    return TRUE;
+}
+
+static void
+gst_vaapi_dpb_mpeg2_init(GstVaapiDpbMpeg2 *dpb)
+{
+}
+
+static void
+gst_vaapi_dpb_mpeg2_class_init(GstVaapiDpbMpeg2Class *klass)
+{
+    GstVaapiDpbClass * const dpb_class = GST_VAAPI_DPB_CLASS(klass);
+
+    dpb_class->add = gst_vaapi_dpb_mpeg2_add;
+}
+
+GstVaapiDpb *
+gst_vaapi_dpb_mpeg2_new(void)
+{
+    return dpb_new(GST_VAAPI_TYPE_DPB_MPEG2, MAX_MPEG2_REFERENCES);
+}
+
+void
+gst_vaapi_dpb_mpeg2_get_references(
+    GstVaapiDpb        *dpb,
+    GstVaapiPicture    *picture,
+    GstVaapiPicture   **prev_picture_ptr,
+    GstVaapiPicture   **next_picture_ptr
+)
+{
+    GstVaapiPicture *ref_picture, *ref_pictures[MAX_MPEG2_REFERENCES];
+    GstVaapiPicture **picture_ptr;
+    guint i, index;
+
+    g_return_if_fail(GST_VAAPI_IS_DPB_MPEG2(dpb));
+    g_return_if_fail(GST_VAAPI_IS_PICTURE(picture));
+
+    ref_pictures[0] = NULL;
+    ref_pictures[1] = NULL;
+    for (i = 0; i < dpb->num_pictures; i++) {
+        ref_picture = dpb->pictures[i];
+        index       = ref_picture->poc > picture->poc;
+        picture_ptr = &ref_pictures[index];
+        if (!*picture_ptr || ((*picture_ptr)->poc > ref_picture->poc) == index)
+            *picture_ptr = ref_picture;
+    }
+
+    if (prev_picture_ptr)
+        *prev_picture_ptr = ref_pictures[0];
+    if (next_picture_ptr)
+        *next_picture_ptr = ref_pictures[1];
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_dpb.h b/gst-libs/gst/vaapi/gstvaapidecoder_dpb.h
new file mode 100644 (file)
index 0000000..3cbaa48
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ *  gstvaapidecoder_dpb.h - Decoded Picture Buffer
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DECODER_DPB_H
+#define GST_VAAPI_DECODER_DPB_H
+
+#include <gst/vaapi/gstvaapidecoder_objects.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GstVaapiDpb             GstVaapiDpb;
+typedef struct _GstVaapiDpbClass        GstVaapiDpbClass;
+typedef struct _GstVaapiDpbMpeg2        GstVaapiDpbMpeg2;
+typedef struct _GstVaapiDpbMpeg2Class   GstVaapiDpbMpeg2Class;
+
+/* ------------------------------------------------------------------------- */
+/* --- Base Decoded Picture Buffer                                       --- */
+/* ------------------------------------------------------------------------- */
+
+#define GST_VAAPI_TYPE_DPB \
+    (gst_vaapi_dpb_get_type())
+
+#define GST_VAAPI_DPB_CAST(obj) \
+    ((GstVaapiDpb *)(obj))
+
+#define GST_VAAPI_DPB(obj)                              \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                  \
+                                GST_VAAPI_TYPE_DPB,     \
+                                GstVaapiDpb))
+
+#define GST_VAAPI_DPB_CLASS(klass)                      \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                   \
+                             GST_VAAPI_TYPE_DPB,        \
+                             GstVaapiDpbClass))
+
+#define GST_VAAPI_IS_DPB(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_DPB))
+
+#define GST_VAAPI_IS_DPB_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_DPB))
+
+#define GST_VAAPI_DPB_GET_CLASS(obj)                    \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                   \
+                               GST_VAAPI_TYPE_DPB,      \
+                               GstVaapiDpbClass))
+
+/**
+ * GstVaapiDpb:
+ *
+ * A decoded picture buffer (DPB) object.
+ */
+struct _GstVaapiDpb {
+    /*< private >*/
+    GstMiniObject       parent_instance;
+
+    /*< protected >*/
+    GstVaapiPicture   **pictures;
+    guint               num_pictures;
+    guint               max_pictures;
+};
+
+/**
+ * GstVaapiDpbClass:
+ *
+ * The #GstVaapiDpb base class.
+ */
+struct _GstVaapiDpbClass {
+    /*< private >*/
+    GstMiniObjectClass  parent_class;
+
+    /*< protected >*/
+    void              (*flush)  (GstVaapiDpb *dpb);
+    gboolean          (*add)    (GstVaapiDpb *dpb, GstVaapiPicture *picture);
+};
+
+G_GNUC_INTERNAL
+GType
+gst_vaapi_dpb_get_type(void) G_GNUC_CONST;
+
+G_GNUC_INTERNAL
+void
+gst_vaapi_dpb_flush(GstVaapiDpb *dpb);
+
+G_GNUC_INTERNAL
+gboolean
+gst_vaapi_dpb_add(GstVaapiDpb *dpb, GstVaapiPicture *picture);
+
+G_GNUC_INTERNAL
+guint
+gst_vaapi_dpb_size(GstVaapiDpb *dpb);
+
+static inline gpointer
+gst_vaapi_dpb_ref(gpointer ptr)
+{
+    return gst_mini_object_ref(GST_MINI_OBJECT(ptr));
+}
+
+static inline void
+gst_vaapi_dpb_unref(gpointer ptr)
+{
+    gst_mini_object_unref(GST_MINI_OBJECT(ptr));
+}
+
+/* ------------------------------------------------------------------------- */
+/* --- MPEG-2 Decoded Picture Buffer                                     --- */
+/* ------------------------------------------------------------------------- */
+
+#define GST_VAAPI_TYPE_DPB_MPEG2 \
+    (gst_vaapi_dpb_mpeg2_get_type())
+
+#define GST_VAAPI_DPB_MPEG2_CAST(obj) \
+    ((GstVaapiDpbMpeg2 *)(obj))
+
+#define GST_VAAPI_DPB_MPEG2(obj)                                \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_DPB_MPEG2,       \
+                                GstVaapiDpbMpeg2))
+
+#define GST_VAAPI_DPB_MPEG2_CLASS(klass)                        \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_DPB_MPEG2,          \
+                             GstVaapiDpbMpeg2Class))
+
+#define GST_VAAPI_IS_DPB_MPEG2(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_DPB_MPEG2))
+
+#define GST_VAAPI_IS_DPB_MPEG2_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_DPB_MPEG2))
+
+#define GST_VAAPI_DPB_MPEG2_GET_CLASS(obj)                      \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_DPB_MPEG2,        \
+                               GstVaapiDpbMpeg2Class))
+
+/**
+ * GstVaapiDpbMpeg2:
+ *
+ * A decoded picture buffer (DPB_MPEG2) object.
+ */
+struct _GstVaapiDpbMpeg2 {
+    /*< private >*/
+    GstVaapiDpb         parent_instance;
+};
+
+/**
+ * GstVaapiDpbMpeg2Class:
+ *
+ * The #GstVaapiDpbMpeg2 base class.
+ */
+struct _GstVaapiDpbMpeg2Class {
+    /*< private >*/
+    GstVaapiDpbClass    parent_class;
+};
+
+G_GNUC_INTERNAL
+GType
+gst_vaapi_dpb_mpeg2_get_type(void) G_GNUC_CONST;
+
+G_GNUC_INTERNAL
+GstVaapiDpb *
+gst_vaapi_dpb_mpeg2_new(void);
+
+G_GNUC_INTERNAL
+void
+gst_vaapi_dpb_mpeg2_get_references(
+    GstVaapiDpb        *dpb,
+    GstVaapiPicture    *picture,
+    GstVaapiPicture   **prev_picture_ptr,
+    GstVaapiPicture   **next_picture_ptr
+);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DECODER_DPB */
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_h264.c b/gst-libs/gst/vaapi/gstvaapidecoder_h264.c
new file mode 100644 (file)
index 0000000..232fc6f
--- /dev/null
@@ -0,0 +1,2536 @@
+/*
+ *  gstvaapidecoder_h264.c - H.264 decoder
+ *
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapidecoder_h264
+ * @short_description: H.264 decoder
+ */
+
+#include "sysdeps.h"
+#include <string.h>
+#include <stdlib.h>
+#include <gst/base/gstadapter.h>
+#include <gst/codecparsers/gsth264parser.h>
+#include "gstvaapidecoder_h264.h"
+#include "gstvaapidecoder_objects.h"
+#include "gstvaapidecoder_priv.h"
+#include "gstvaapidisplay_priv.h"
+#include "gstvaapiobject_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+typedef struct _GstVaapiPictureH264             GstVaapiPictureH264;
+typedef struct _GstVaapiPictureH264Class        GstVaapiPictureH264Class;
+typedef struct _GstVaapiSliceH264               GstVaapiSliceH264;
+typedef struct _GstVaapiSliceH264Class          GstVaapiSliceH264Class;
+
+/* ------------------------------------------------------------------------- */
+/* --- H.264 Pictures                                                    --- */
+/* ------------------------------------------------------------------------- */
+
+#define GST_VAAPI_TYPE_PICTURE_H264 \
+    (gst_vaapi_picture_h264_get_type())
+
+#define GST_VAAPI_PICTURE_H264_CAST(obj) \
+    ((GstVaapiPictureH264 *)(obj))
+
+#define GST_VAAPI_PICTURE_H264(obj)                             \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_PICTURE_H264,    \
+                                GstVaapiPictureH264))
+
+#define GST_VAAPI_PICTURE_H264_CLASS(klass)                     \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_PICTURE_H264,       \
+                             GstVaapiPictureH264Class))
+
+#define GST_VAAPI_IS_PICTURE_H264(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_PICTURE_H264))
+
+#define GST_VAAPI_IS_PICTURE_H264_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_PICTURE_H264))
+
+#define GST_VAAPI_PICTURE_H264_GET_CLASS(obj)                   \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_PICTURE_H264,     \
+                               GstVaapiPictureH264Class))
+
+struct _GstVaapiPictureH264 {
+    GstVaapiPicture             base;
+    VAPictureH264               info;
+    gint32                      poc;
+    gint32                      frame_num;              // Original frame_num from slice_header()
+    gint32                      frame_num_wrap;         // Temporary for ref pic marking: FrameNumWrap
+    gint32                      pic_num;                // Temporary for ref pic marking: PicNum
+    gint32                      long_term_pic_num;      // Temporary for ref pic marking: LongTermPicNum
+    guint                       is_idr                  : 1;
+    guint                       is_long_term            : 1;
+    guint                       field_pic_flag          : 1;
+    guint                       bottom_field_flag       : 1;
+    guint                       has_mmco_5              : 1;
+    guint                       output_flag             : 1;
+    guint                       output_needed           : 1;
+};
+
+struct _GstVaapiPictureH264Class {
+    /*< private >*/
+    GstVaapiPictureClass        parent_class;
+};
+
+GST_VAAPI_CODEC_DEFINE_TYPE(GstVaapiPictureH264,
+                            gst_vaapi_picture_h264,
+                            GST_VAAPI_TYPE_PICTURE)
+
+static void
+gst_vaapi_picture_h264_destroy(GstVaapiPictureH264 *decoder)
+{
+}
+
+static gboolean
+gst_vaapi_picture_h264_create(
+    GstVaapiPictureH264                      *picture,
+    const GstVaapiCodecObjectConstructorArgs *args
+)
+{
+    return TRUE;
+}
+
+static void
+gst_vaapi_picture_h264_init(GstVaapiPictureH264 *picture)
+{
+    VAPictureH264 *va_pic;
+
+    va_pic                      = &picture->info;
+    va_pic->flags               = 0;
+    va_pic->TopFieldOrderCnt    = 0;
+    va_pic->BottomFieldOrderCnt = 0;
+
+    picture->poc                = 0;
+    picture->is_long_term       = FALSE;
+    picture->is_idr             = FALSE;
+    picture->has_mmco_5         = FALSE;
+    picture->output_needed      = FALSE;
+}
+
+static inline GstVaapiPictureH264 *
+gst_vaapi_picture_h264_new(GstVaapiDecoderH264 *decoder)
+{
+    GstVaapiCodecObject *object;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), NULL);
+
+    object = gst_vaapi_codec_object_new(
+        GST_VAAPI_TYPE_PICTURE_H264,
+        GST_VAAPI_CODEC_BASE(decoder),
+        NULL, sizeof(VAPictureParameterBufferH264),
+        NULL, 0
+    );
+    if (!object)
+        return NULL;
+    return GST_VAAPI_PICTURE_H264_CAST(object);
+}
+
+/* ------------------------------------------------------------------------- */
+/* --- Slices                                                            --- */
+/* ------------------------------------------------------------------------- */
+
+#define GST_VAAPI_TYPE_SLICE_H264 \
+    (gst_vaapi_slice_h264_get_type())
+
+#define GST_VAAPI_SLICE_H264_CAST(obj) \
+    ((GstVaapiSliceH264 *)(obj))
+
+#define GST_VAAPI_SLICE_H264(obj)                               \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_SLICE_H264,      \
+                                GstVaapiSliceH264))
+
+#define GST_VAAPI_SLICE_H264_CLASS(klass)                       \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_SLICE_H264,         \
+                             GstVaapiSliceH264Class))
+
+#define GST_VAAPI_IS_SLICE_H264(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_SLICE_H264))
+
+#define GST_VAAPI_IS_SLICE_H264_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_SLICE_H264))
+
+#define GST_VAAPI_SLICE_H264_GET_CLASS(obj)                     \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_SLICE_H264,       \
+                               GstVaapiSliceH264Class))
+
+struct _GstVaapiSliceH264 {
+    GstVaapiSlice               base;
+    GstH264SliceHdr             slice_hdr;              // parsed slice_header()
+};
+
+struct _GstVaapiSliceH264Class {
+    /*< private >*/
+    GstVaapiSliceClass          parent_class;
+};
+
+GST_VAAPI_CODEC_DEFINE_TYPE(GstVaapiSliceH264,
+                            gst_vaapi_slice_h264,
+                            GST_VAAPI_TYPE_SLICE)
+
+static void
+gst_vaapi_slice_h264_destroy(GstVaapiSliceH264 *slice)
+{
+}
+
+static gboolean
+gst_vaapi_slice_h264_create(
+    GstVaapiSliceH264                        *slice,
+    const GstVaapiCodecObjectConstructorArgs *args
+)
+{
+    return TRUE;
+}
+
+static void
+gst_vaapi_slice_h264_init(GstVaapiSliceH264 *slice)
+{
+}
+
+static inline GstVaapiSliceH264 *
+gst_vaapi_slice_h264_new(
+    GstVaapiDecoderH264 *decoder,
+    const guint8        *data,
+    guint                data_size
+)
+{
+    GstVaapiCodecObject *object;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), NULL);
+
+    object = gst_vaapi_codec_object_new(
+        GST_VAAPI_TYPE_SLICE_H264,
+        GST_VAAPI_CODEC_BASE(decoder),
+        NULL, sizeof(VASliceParameterBufferH264),
+        data, data_size
+    );
+    if (!object)
+        return NULL;
+    return GST_VAAPI_SLICE_H264_CAST(object);
+}
+
+/* ------------------------------------------------------------------------- */
+/* --- H.264 Decoder                                                     --- */
+/* ------------------------------------------------------------------------- */
+
+G_DEFINE_TYPE(GstVaapiDecoderH264,
+              gst_vaapi_decoder_h264,
+              GST_VAAPI_TYPE_DECODER);
+
+#define GST_VAAPI_DECODER_H264_GET_PRIVATE(obj)                 \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_DECODER_H264,   \
+                                 GstVaapiDecoderH264Private))
+
+// Used for field_poc[]
+#define TOP_FIELD       0
+#define BOTTOM_FIELD    1
+
+struct _GstVaapiDecoderH264Private {
+    GstAdapter                 *adapter;
+    GstBuffer                  *sub_buffer;
+    GstH264NalParser           *parser;
+    GstH264SPS                 *sps;
+    GstH264SPS                  last_sps;
+    GstH264PPS                 *pps;
+    GstH264PPS                  last_pps;
+    GstVaapiPictureH264        *current_picture;
+    GstVaapiPictureH264        *dpb[16];
+    guint                       dpb_count;
+    guint                       dpb_size;
+    GstVaapiProfile             profile;
+    GstVaapiPictureH264        *short_ref[32];
+    guint                       short_ref_count;
+    GstVaapiPictureH264        *long_ref[32];
+    guint                       long_ref_count;
+    GstVaapiPictureH264        *RefPicList0[32];
+    guint                       RefPicList0_count;
+    GstVaapiPictureH264        *RefPicList1[32];
+    guint                       RefPicList1_count;
+    guint                       nal_length_size;
+    guint                       width;
+    guint                       height;
+    guint                       mb_x;
+    guint                       mb_y;
+    guint                       mb_width;
+    guint                       mb_height;
+    guint8                      scaling_list_4x4[6][16];
+    guint8                      scaling_list_8x8[6][64];
+    gint32                      field_poc[2];           // 0:TopFieldOrderCnt / 1:BottomFieldOrderCnt
+    gint32                      poc_msb;                // PicOrderCntMsb
+    gint32                      poc_lsb;                // pic_order_cnt_lsb (from slice_header())
+    gint32                      prev_poc_msb;           // prevPicOrderCntMsb
+    gint32                      prev_poc_lsb;           // prevPicOrderCntLsb
+    gint32                      frame_num_offset;       // FrameNumOffset
+    gint32                      prev_frame_num_offset;  // prevFrameNumOffset
+    gint32                      frame_num;              // frame_num (from slice_header())
+    gint32                      prev_frame_num;         // prevFrameNum
+    guint                       is_constructed          : 1;
+    guint                       is_opened               : 1;
+    guint                       is_avc                  : 1;
+    guint                       has_context             : 1;
+};
+
+static gboolean
+decode_picture_end(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture);
+
+static void
+clear_references(
+    GstVaapiDecoderH264  *decoder,
+    GstVaapiPictureH264 **pictures,
+    guint                *picture_count
+);
+
+static void
+dpb_remove_index(GstVaapiDecoderH264 *decoder, guint index)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    guint num_pictures = --priv->dpb_count;
+
+    if (index != num_pictures)
+        gst_vaapi_picture_replace(&priv->dpb[index], priv->dpb[num_pictures]);
+    gst_vaapi_picture_replace(&priv->dpb[num_pictures], NULL);
+}
+
+static inline gboolean
+dpb_output(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
+{
+    /* XXX: update cropping rectangle */
+    picture->output_needed = FALSE;
+    return gst_vaapi_picture_output(GST_VAAPI_PICTURE_CAST(picture));
+}
+
+static gboolean
+dpb_bump(GstVaapiDecoderH264 *decoder)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    guint i, lowest_poc_index;
+    gboolean success;
+
+    for (i = 0; i < priv->dpb_count; i++) {
+        if (priv->dpb[i]->output_needed)
+            break;
+    }
+    if (i == priv->dpb_count)
+        return FALSE;
+
+    lowest_poc_index = i++;
+    for (; i < priv->dpb_count; i++) {
+        GstVaapiPictureH264 * const picture = priv->dpb[i];
+        if (picture->output_needed && picture->poc < priv->dpb[lowest_poc_index]->poc)
+            lowest_poc_index = i;
+    }
+
+    success = dpb_output(decoder, priv->dpb[lowest_poc_index]);
+    if (!GST_VAAPI_PICTURE_IS_REFERENCE(priv->dpb[lowest_poc_index]))
+        dpb_remove_index(decoder, lowest_poc_index);
+    return success;
+}
+
+static void
+dpb_flush(GstVaapiDecoderH264 *decoder)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+
+    while (dpb_bump(decoder))
+        ;
+    clear_references(decoder, priv->dpb, &priv->dpb_count);
+}
+
+static gboolean
+dpb_add(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    guint i;
+
+    // Remove all unused pictures
+    if (picture->is_idr)
+        dpb_flush(decoder);
+    else {
+        i = 0;
+        while (i < priv->dpb_count) {
+            GstVaapiPictureH264 * const picture = priv->dpb[i];
+            if (!picture->output_needed &&
+                !GST_VAAPI_PICTURE_IS_REFERENCE(picture))
+                dpb_remove_index(decoder, i);
+            else
+                i++;
+        }
+    }
+
+    // C.4.5.1 - Storage and marking of a reference decoded picture into the DPB
+    if (GST_VAAPI_PICTURE_IS_REFERENCE(picture)) {
+        while (priv->dpb_count == priv->dpb_size) {
+            if (!dpb_bump(decoder))
+                return FALSE;
+        }
+        gst_vaapi_picture_replace(&priv->dpb[priv->dpb_count++], picture);
+        if (picture->output_flag)
+            picture->output_needed = TRUE;
+    }
+
+    // C.4.5.2 - Storage and marking of a non-reference decoded picture into the DPB
+    else {
+        if (!picture->output_flag)
+            return TRUE;
+        while (priv->dpb_count == priv->dpb_size) {
+            for (i = 0; i < priv->dpb_count; i++) {
+                if (priv->dpb[i]->output_needed &&
+                    priv->dpb[i]->poc < picture->poc)
+                    break;
+            }
+            if (i == priv->dpb_count)
+                return dpb_output(decoder, picture);
+            if (!dpb_bump(decoder))
+                return FALSE;
+        }
+        gst_vaapi_picture_replace(&priv->dpb[priv->dpb_count++], picture);
+        picture->output_needed = TRUE;
+    }
+    return TRUE;
+}
+
+static void
+dpb_reset(GstVaapiDecoderH264 *decoder, GstH264SPS *sps)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    guint max_dec_frame_buffering, MaxDpbMbs, PicSizeMbs;
+
+    /* Table A-1 - Level limits */
+    switch (sps->level_idc) {
+    case 10: MaxDpbMbs = 396;    break;
+    case 11: MaxDpbMbs = 900;    break;
+    case 12: MaxDpbMbs = 2376;   break;
+    case 13: MaxDpbMbs = 2376;   break;
+    case 20: MaxDpbMbs = 2376;   break;
+    case 21: MaxDpbMbs = 4752;   break;
+    case 22: MaxDpbMbs = 8100;   break;
+    case 30: MaxDpbMbs = 8100;   break;
+    case 31: MaxDpbMbs = 18000;  break;
+    case 32: MaxDpbMbs = 20480;  break;
+    case 40: MaxDpbMbs = 32768;  break;
+    case 41: MaxDpbMbs = 32768;  break;
+    case 42: MaxDpbMbs = 34816;  break;
+    case 50: MaxDpbMbs = 110400; break;
+    case 51: MaxDpbMbs = 184320; break;
+    default:
+        g_assert(0 && "unhandled level");
+        break;
+    }
+
+    PicSizeMbs = ((sps->pic_width_in_mbs_minus1 + 1) *
+                  (sps->pic_height_in_map_units_minus1 + 1) *
+                  (sps->frame_mbs_only_flag ? 1 : 2));
+    max_dec_frame_buffering = MaxDpbMbs / PicSizeMbs;
+    if (max_dec_frame_buffering > 8)
+        max_dec_frame_buffering = 8;
+
+    /* VUI parameters */
+    if (sps->vui_parameters_present_flag) {
+        GstH264VUIParams * const vui_params = &sps->vui_parameters;
+        if (vui_params->bitstream_restriction_flag)
+            max_dec_frame_buffering = vui_params->max_dec_frame_buffering;
+        else {
+            switch (sps->profile_idc) {
+            case 44:  // CAVLC 4:4:4 Intra profile
+            case 86:  // Scalable High profile
+            case 100: // High profile
+            case 110: // High 10 profile
+            case 122: // High 4:2:2 profile
+            case 244: // High 4:4:4 Predictive profile
+                if (sps->constraint_set3_flag)
+                    max_dec_frame_buffering = 0;
+                break;
+            }
+        }
+    }
+
+    if (max_dec_frame_buffering > 16)
+        max_dec_frame_buffering = 16;
+    else if (max_dec_frame_buffering < sps->num_ref_frames)
+        max_dec_frame_buffering = sps->num_ref_frames;
+    priv->dpb_size = MAX(1, max_dec_frame_buffering);
+    GST_DEBUG("DPB size %u", priv->dpb_size);
+}
+
+static GstVaapiDecoderStatus
+get_status(GstH264ParserResult result)
+{
+    GstVaapiDecoderStatus status;
+
+    switch (result) {
+    case GST_H264_PARSER_OK:
+        status = GST_VAAPI_DECODER_STATUS_SUCCESS;
+        break;
+    case GST_H264_PARSER_NO_NAL_END:
+        status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+        break;
+    case GST_H264_PARSER_ERROR:
+        status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+        break;
+    default:
+        status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+        break;
+    }
+    return status;
+}
+
+static inline GstH264DecRefPicMarking *
+get_dec_ref_pic_marking(GstVaapiPictureH264 *picture_h264)
+{
+    GstVaapiPicture * const picture = GST_VAAPI_PICTURE_CAST(picture_h264);
+    GstVaapiSliceH264 *slice;
+
+    slice = g_ptr_array_index(picture->slices, picture->slices->len - 1);
+    return &slice->slice_hdr.dec_ref_pic_marking;
+}
+
+static void
+gst_vaapi_decoder_h264_clear_buffer(GstVaapiDecoder *base)
+{
+    GstVaapiDecoderH264 * const decoder = GST_VAAPI_DECODER_H264(base);
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+
+    gst_vaapi_picture_replace(&priv->current_picture, NULL);
+    clear_references(decoder, priv->short_ref, &priv->short_ref_count);
+    clear_references(decoder, priv->long_ref,  &priv->long_ref_count );
+    clear_references(decoder, priv->dpb,       &priv->dpb_count      );
+
+    if (priv->sub_buffer) {
+        gst_buffer_unref(priv->sub_buffer);
+        priv->sub_buffer = NULL;
+    }
+
+    if (priv->adapter) {
+        gst_adapter_clear(priv->adapter);
+    }
+}
+
+static void
+gst_vaapi_decoder_h264_close(GstVaapiDecoderH264 *decoder)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+
+    gst_vaapi_decoder_h264_clear_buffer(GST_VAAPI_DECODER_CAST(decoder));
+
+    if (priv->parser) {
+        gst_h264_nal_parser_free(priv->parser);
+        priv->parser = NULL;
+    }
+
+    if (priv->adapter) {
+        g_object_unref(priv->adapter);
+        priv->adapter = NULL;
+    }
+}
+
+static gboolean
+gst_vaapi_decoder_h264_open(GstVaapiDecoderH264 *decoder, GstBuffer *buffer)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+
+    gst_vaapi_decoder_h264_close(decoder);
+
+    priv->adapter = gst_adapter_new();
+    if (!priv->adapter)
+        return FALSE;
+
+    priv->parser = gst_h264_nal_parser_new();
+    if (!priv->parser)
+        return FALSE;
+    return TRUE;
+}
+
+static void
+gst_vaapi_decoder_h264_destroy(GstVaapiDecoderH264 *decoder)
+{
+    gst_vaapi_decoder_h264_close(decoder);
+}
+
+static gboolean
+gst_vaapi_decoder_h264_create(GstVaapiDecoderH264 *decoder)
+{
+    if (!GST_VAAPI_DECODER_CODEC(decoder))
+        return FALSE;
+    return TRUE;
+}
+
+static inline guint
+min_surfaces_count(guint dbp_size)
+{
+    guint count = dbp_size + 4;
+
+    if (count < GST_DECODER_DEFAULT_SURFACES_COUNT)
+        count = GST_DECODER_DEFAULT_SURFACES_COUNT;
+    return count;
+}
+
+static GstVaapiDecoderStatus
+ensure_context(GstVaapiDecoderH264 *decoder, GstH264SPS *sps)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstVaapiProfile profiles[2];
+    GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
+    guint i, n_profiles = 0;
+    gboolean success, reset_context = FALSE;
+
+    if (!priv->has_context || priv->sps->profile_idc != sps->profile_idc) {
+        GST_DEBUG("profile changed");
+        reset_context = TRUE;
+
+        switch (sps->profile_idc) {
+        case 66:
+            profiles[n_profiles++] = GST_VAAPI_PROFILE_H264_BASELINE;
+            break;
+        case 77:
+            profiles[n_profiles++] = GST_VAAPI_PROFILE_H264_MAIN;
+            // fall-through
+        case 100:
+            profiles[n_profiles++] = GST_VAAPI_PROFILE_H264_HIGH;
+            break;
+        default:
+            GST_DEBUG("unsupported profile %d", sps->profile_idc);
+            return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
+        }
+
+        for (i = 0; i < n_profiles; i++) {
+            success = gst_vaapi_display_has_decoder(
+                GST_VAAPI_DECODER_DISPLAY(decoder),
+                profiles[i],
+                entrypoint
+            );
+            if (success)
+                break;
+        }
+        if (i == n_profiles)
+            return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
+        priv->profile = profiles[i];
+    }
+
+    if (!priv->has_context ||
+        priv->sps->chroma_format_idc != sps->chroma_format_idc) {
+        GST_DEBUG("chroma format changed");
+        reset_context = TRUE;
+
+        /* XXX: theoritically, we could handle 4:2:2 format */
+        if (sps->chroma_format_idc != 1)
+            return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT;
+    }
+
+    if (!priv->has_context              ||
+        priv->sps->width  != sps->width ||
+        priv->sps->height != sps->height) {
+        GST_DEBUG("size changed");
+        reset_context      = TRUE;
+
+        priv->width      = sps->width;
+        priv->height     = sps->height;
+        priv->mb_width   = sps->pic_width_in_mbs_minus1 + 1;
+        priv->mb_height  = sps->pic_height_in_map_units_minus1 + 1;
+        priv->mb_height *= 2 - sps->frame_mbs_only_flag;
+    }
+
+    if (reset_context) {
+        /* Reset DPB first*/
+        dpb_reset(decoder, sps);
+
+        success = gst_vaapi_decoder_ensure_context(
+            GST_VAAPI_DECODER(decoder),
+            priv->profile,
+            entrypoint,
+            priv->width,
+            priv->height,
+            min_surfaces_count(priv->dpb_size)
+        );
+        if (!success)
+            return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+        priv->has_context = TRUE;
+
+    }
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+ensure_quant_matrix(GstVaapiDecoderH264 *decoder, GstH264PPS *pps)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+
+    if (priv->pps != pps) {
+        memcpy(priv->scaling_list_4x4, pps->scaling_lists_4x4,
+               sizeof(priv->scaling_list_4x4));
+        memcpy(priv->scaling_list_8x8, pps->scaling_lists_8x8,
+               sizeof(priv->scaling_list_8x8));
+    }
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static gboolean
+decode_current_picture(GstVaapiDecoderH264 *decoder)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstVaapiPictureH264 * const picture = priv->current_picture;
+    gboolean success = FALSE;
+
+    if (!picture)
+        return TRUE;
+
+    if (!decode_picture_end(decoder, picture))
+        goto end;
+    if (!gst_vaapi_picture_decode(GST_VAAPI_PICTURE_CAST(picture)))
+        goto end;
+    success = TRUE;
+end:
+    gst_vaapi_picture_replace(&priv->current_picture, NULL);
+    return success;
+}
+
+static GstVaapiDecoderStatus
+decode_sps(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstH264SPS * const sps = &priv->last_sps;
+    GstH264ParserResult result;
+
+    GST_DEBUG("decode SPS");
+
+    if (priv->current_picture && !decode_current_picture(decoder))
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+
+    memset(sps, 0, sizeof(*sps));
+    result = gst_h264_parser_parse_sps(priv->parser, nalu, sps, TRUE);
+    if (result != GST_H264_PARSER_OK)
+        return get_status(result);
+
+    return ensure_context(decoder, sps);
+}
+
+static GstVaapiDecoderStatus
+decode_pps(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstH264PPS * const pps = &priv->last_pps;
+    GstH264ParserResult result;
+
+    GST_DEBUG("decode PPS");
+
+    if (priv->current_picture && !decode_current_picture(decoder))
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+
+    memset(pps, 0, sizeof(*pps));
+    result = gst_h264_parser_parse_pps(priv->parser, nalu, pps);
+    if (result != GST_H264_PARSER_OK)
+        return get_status(result);
+
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_sei(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstH264SEIMessage sei;
+    GstH264ParserResult result;
+
+    GST_DEBUG("decode SEI");
+
+    memset(&sei, 0, sizeof(sei));
+    result = gst_h264_parser_parse_sei(priv->parser, nalu, &sei);
+    if (result != GST_H264_PARSER_OK) {
+        GST_WARNING("failed to decode SEI, payload type:%d", sei.payloadType);
+        return get_status(result);
+    }
+
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_sequence_end(GstVaapiDecoderH264 *decoder)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+
+    GST_DEBUG("decode sequence-end");
+
+    if (priv->current_picture && !decode_current_picture(decoder))
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+    dpb_flush(decoder);
+    return GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
+}
+
+/* 8.2.1.1 - Decoding process for picture order count type 0 */
+static void
+init_picture_poc_0(
+    GstVaapiDecoderH264 *decoder,
+    GstVaapiPictureH264 *picture,
+    GstH264SliceHdr     *slice_hdr
+)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstH264PPS * const pps = slice_hdr->pps;
+    GstH264SPS * const sps = pps->sequence;
+    const gint32 MaxPicOrderCntLsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
+
+    GST_DEBUG("decode picture order count type 0");
+
+    // (8-3)
+    priv->poc_lsb = slice_hdr->pic_order_cnt_lsb;
+    if (priv->poc_lsb < priv->prev_poc_lsb &&
+        (priv->prev_poc_lsb - priv->poc_lsb) >= (MaxPicOrderCntLsb / 2))
+        priv->poc_msb = priv->prev_poc_msb + MaxPicOrderCntLsb;
+    else if (priv->poc_lsb > priv->prev_poc_lsb &&
+             (priv->poc_lsb - priv->prev_poc_lsb) > (MaxPicOrderCntLsb / 2))
+        priv->poc_msb = priv->prev_poc_msb - MaxPicOrderCntLsb;
+    else
+        priv->poc_msb = priv->prev_poc_msb;
+
+    // (8-4)
+    if (!slice_hdr->field_pic_flag || !slice_hdr->bottom_field_flag)
+        priv->field_poc[TOP_FIELD] = priv->poc_msb + priv->poc_lsb;
+
+    // (8-5)
+    if (!slice_hdr->field_pic_flag)
+        priv->field_poc[BOTTOM_FIELD] = priv->field_poc[TOP_FIELD] +
+            slice_hdr->delta_pic_order_cnt_bottom;
+    else if (slice_hdr->bottom_field_flag)
+        priv->field_poc[BOTTOM_FIELD] = priv->poc_msb + priv->poc_lsb;
+}
+
+/* 8.2.1.2 - Decoding process for picture order count type 1 */
+static void
+init_picture_poc_1(
+    GstVaapiDecoderH264 *decoder,
+    GstVaapiPictureH264 *picture,
+    GstH264SliceHdr     *slice_hdr
+)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstH264PPS * const pps = slice_hdr->pps;
+    GstH264SPS * const sps = pps->sequence;
+    const gint32 MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4);
+    gint32 abs_frame_num, expected_poc;
+    guint i;
+
+    GST_DEBUG("decode picture order count type 1");
+
+    // (8-6)
+    if (picture->is_idr)
+        priv->frame_num_offset = 0;
+    else if (priv->prev_frame_num > priv->frame_num)
+        priv->frame_num_offset = priv->prev_frame_num_offset + MaxFrameNum;
+    else
+        priv->frame_num_offset = priv->prev_frame_num_offset;
+
+    // (8-7)
+    if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0)
+        abs_frame_num = priv->frame_num_offset + priv->frame_num;
+    else
+        abs_frame_num = 0;
+    if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture) && abs_frame_num > 0)
+        abs_frame_num = abs_frame_num - 1;
+
+    if (abs_frame_num > 0) {
+        gint32 expected_delta_per_poc_cycle;
+        gint32 poc_cycle_cnt, frame_num_in_poc_cycle;
+
+        expected_delta_per_poc_cycle = 0;
+        for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++)
+            expected_delta_per_poc_cycle += sps->offset_for_ref_frame[i];
+
+        // (8-8)
+        poc_cycle_cnt = (abs_frame_num - 1) /
+            sps->num_ref_frames_in_pic_order_cnt_cycle;
+        frame_num_in_poc_cycle = (abs_frame_num - 1) %
+            sps->num_ref_frames_in_pic_order_cnt_cycle;
+
+        // (8-9)
+        expected_poc = poc_cycle_cnt * expected_delta_per_poc_cycle;
+        for (i = 0; i <= frame_num_in_poc_cycle; i++)
+            expected_poc += sps->offset_for_ref_frame[i];
+    }
+    else
+        expected_poc = 0;
+    if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture))
+        expected_poc += sps->offset_for_non_ref_pic;
+
+    // (8-10)
+    if (!slice_hdr->field_pic_flag) {
+        priv->field_poc[TOP_FIELD] = expected_poc +
+            slice_hdr->delta_pic_order_cnt[0];
+        priv->field_poc[BOTTOM_FIELD] = priv->field_poc[TOP_FIELD] +
+            sps->offset_for_top_to_bottom_field +
+            slice_hdr->delta_pic_order_cnt[1];
+    }
+    else if (!slice_hdr->bottom_field_flag)
+        priv->field_poc[TOP_FIELD] = expected_poc +
+            slice_hdr->delta_pic_order_cnt[0];
+    else
+        priv->field_poc[BOTTOM_FIELD] = expected_poc + 
+            sps->offset_for_top_to_bottom_field + slice_hdr->delta_pic_order_cnt[0];
+}
+
+/* 8.2.1.3 - Decoding process for picture order count type 2 */
+static void
+init_picture_poc_2(
+    GstVaapiDecoderH264 *decoder,
+    GstVaapiPictureH264 *picture,
+    GstH264SliceHdr     *slice_hdr
+)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstH264PPS * const pps = slice_hdr->pps;
+    GstH264SPS * const sps = pps->sequence;
+    const gint32 MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4);
+    guint temp_poc;
+
+    GST_DEBUG("decode picture order count type 2");
+
+    // (8-11)
+    if (picture->is_idr)
+        priv->frame_num_offset = 0;
+    else if (priv->prev_frame_num > priv->frame_num)
+        priv->frame_num_offset = priv->prev_frame_num_offset + MaxFrameNum;
+    else
+        priv->frame_num_offset = priv->prev_frame_num_offset;
+
+    // (8-12)
+    if (picture->is_idr)
+        temp_poc = 0;
+    else if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture))
+        temp_poc = 2 * (priv->frame_num_offset + priv->frame_num) - 1;
+    else
+        temp_poc = 2 * (priv->frame_num_offset + priv->frame_num);
+
+    // (8-13)
+    if (!slice_hdr->field_pic_flag) {
+        priv->field_poc[TOP_FIELD] = temp_poc;
+        priv->field_poc[BOTTOM_FIELD] = temp_poc;
+    }
+    else if (slice_hdr->bottom_field_flag)
+        priv->field_poc[BOTTOM_FIELD] = temp_poc;
+    else
+        priv->field_poc[TOP_FIELD] = temp_poc;
+}
+
+/* 8.2.1 - Decoding process for picture order count */
+static void
+init_picture_poc(
+    GstVaapiDecoderH264 *decoder,
+    GstVaapiPictureH264 *picture,
+    GstH264SliceHdr     *slice_hdr
+)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    VAPictureH264 * const pic = &picture->info;
+    GstH264PPS * const pps = slice_hdr->pps;
+    GstH264SPS * const sps = pps->sequence;
+
+    switch (sps->pic_order_cnt_type) {
+    case 0:
+        init_picture_poc_0(decoder, picture, slice_hdr);
+        break;
+    case 1:
+        init_picture_poc_1(decoder, picture, slice_hdr);
+        break;
+    case 2:
+        init_picture_poc_2(decoder, picture, slice_hdr);
+        break;
+    }
+
+    if (!(pic->flags & VA_PICTURE_H264_BOTTOM_FIELD))
+        pic->TopFieldOrderCnt = priv->field_poc[TOP_FIELD];
+    if (!(pic->flags & VA_PICTURE_H264_TOP_FIELD))
+        pic->BottomFieldOrderCnt = priv->field_poc[BOTTOM_FIELD];
+    picture->poc = MIN(pic->TopFieldOrderCnt, pic->BottomFieldOrderCnt);
+}
+
+static int
+compare_picture_pic_num_dec(const void *a, const void *b)
+{
+    const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
+    const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
+
+    return picB->pic_num - picA->pic_num;
+}
+
+static int
+compare_picture_long_term_pic_num_inc(const void *a, const void *b)
+{
+    const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
+    const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
+
+    return picA->long_term_pic_num - picB->long_term_pic_num;
+}
+
+static int
+compare_picture_poc_dec(const void *a, const void *b)
+{
+    const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
+    const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
+
+    return picB->poc - picA->poc;
+}
+
+static int
+compare_picture_poc_inc(const void *a, const void *b)
+{
+    const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
+    const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
+
+    return picA->poc - picB->poc;
+}
+
+static int
+compare_picture_frame_num_wrap_dec(const void *a, const void *b)
+{
+    const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
+    const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
+
+    return picB->frame_num_wrap - picA->frame_num_wrap;
+}
+
+static int
+compare_picture_long_term_frame_idx_inc(const void *a, const void *b)
+{
+    const GstVaapiPictureH264 * const picA = *(GstVaapiPictureH264 **)a;
+    const GstVaapiPictureH264 * const picB = *(GstVaapiPictureH264 **)b;
+
+    return picA->info.frame_idx - picB->info.frame_idx;
+}
+
+/* 8.2.4.1 - Decoding process for picture numbers */
+static void
+init_picture_refs_pic_num(
+    GstVaapiDecoderH264 *decoder,
+    GstVaapiPictureH264 *picture,
+    GstH264SliceHdr     *slice_hdr
+)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstH264PPS * const pps = slice_hdr->pps;
+    GstH264SPS * const sps = pps->sequence;
+    const gint32 MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4);
+    const guint field_flags = VA_PICTURE_H264_TOP_FIELD | VA_PICTURE_H264_BOTTOM_FIELD;
+    guint i;
+
+    GST_DEBUG("decode picture numbers");
+
+    for (i = 0; i < priv->short_ref_count; i++) {
+        GstVaapiPictureH264 * const pic = priv->short_ref[i];
+
+        // (8-27)
+        if (pic->frame_num > priv->frame_num)
+            pic->frame_num_wrap = pic->frame_num - MaxFrameNum;
+        else
+            pic->frame_num_wrap = pic->frame_num;
+
+        // (8-28, 8-30, 8-31)
+        if (!pic->field_pic_flag)
+            pic->pic_num = pic->frame_num_wrap;
+        else {
+            if (((picture->info.flags ^ pic->info.flags) & field_flags) == 0)
+                pic->pic_num = 2 * pic->frame_num_wrap + 1;
+            else
+                pic->pic_num = 2 * pic->frame_num_wrap;
+        }
+    }
+
+    for (i = 0; i < priv->long_ref_count; i++) {
+        GstVaapiPictureH264 * const pic = priv->long_ref[i];
+
+        // (8-29, 8-32, 8-33)
+        if (!pic->field_pic_flag)
+            pic->long_term_pic_num = pic->info.frame_idx;
+        else {
+            if (((picture->info.flags ^ pic->info.flags) & field_flags) == 0)
+                pic->long_term_pic_num = 2 * pic->info.frame_idx + 1;
+            else
+                pic->long_term_pic_num = 2 * pic->info.frame_idx;
+        }
+    }
+}
+
+#define SORT_REF_LIST(list, n, compare_func) \
+    qsort(list, n, sizeof(*(list)), compare_picture_##compare_func)
+
+static void
+init_picture_refs_p_slice(
+    GstVaapiDecoderH264 *decoder,
+    GstVaapiPictureH264 *picture,
+    GstH264SliceHdr     *slice_hdr
+)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstVaapiPictureH264 **ref_list;
+    guint i;
+
+    GST_DEBUG("decode reference picture list for P and SP slices");
+
+    if (!picture->field_pic_flag) {
+        /* 8.2.4.2.1 - P and SP slices in frames */
+        if (priv->short_ref_count > 0) {
+            ref_list = priv->RefPicList0;
+            for (i = 0; i < priv->short_ref_count; i++)
+                ref_list[i] = priv->short_ref[i];
+            SORT_REF_LIST(ref_list, i, pic_num_dec);
+            priv->RefPicList0_count += i;
+        }
+
+        if (priv->long_ref_count > 0) {
+            ref_list = &priv->RefPicList0[priv->RefPicList0_count];
+            for (i = 0; i < priv->long_ref_count; i++)
+                ref_list[i] = priv->long_ref[i];
+            SORT_REF_LIST(ref_list, i, long_term_pic_num_inc);
+            priv->RefPicList0_count += i;
+        }
+    }
+    else {
+        /* 8.2.4.2.2 - P and SP slices in fields */
+        GstVaapiPictureH264 *short_ref[32];
+        guint short_ref_count = 0;
+        GstVaapiPictureH264 *long_ref[32];
+        guint long_ref_count = 0;
+
+        // XXX: handle second field if current field is marked as
+        // "used for short-term reference"
+        if (priv->short_ref_count > 0) {
+            for (i = 0; i < priv->short_ref_count; i++)
+                short_ref[i] = priv->short_ref[i];
+            SORT_REF_LIST(short_ref, i, frame_num_wrap_dec);
+            short_ref_count = i;
+        }
+
+        // XXX: handle second field if current field is marked as
+        // "used for long-term reference"
+        if (priv->long_ref_count > 0) {
+            for (i = 0; i < priv->long_ref_count; i++)
+                long_ref[i] = priv->long_ref[i];
+            SORT_REF_LIST(long_ref, i, long_term_frame_idx_inc);
+            long_ref_count = i;
+        }
+
+        // XXX: handle 8.2.4.2.5
+    }
+}
+
+static void
+init_picture_refs_b_slice(
+    GstVaapiDecoderH264 *decoder,
+    GstVaapiPictureH264 *picture,
+    GstH264SliceHdr     *slice_hdr
+)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstVaapiPictureH264 **ref_list;
+    guint i, n;
+
+    GST_DEBUG("decode reference picture list for B slices");
+
+    if (!picture->field_pic_flag) {
+        /* 8.2.4.2.3 - B slices in frames */
+
+        /* RefPicList0 */
+        if (priv->short_ref_count > 0) {
+            // 1. Short-term references
+            ref_list = priv->RefPicList0;
+            for (n = 0, i = 0; i < priv->short_ref_count; i++) {
+                if (priv->short_ref[i]->poc < picture->poc)
+                    ref_list[n++] = priv->short_ref[i];
+            }
+            SORT_REF_LIST(ref_list, n, poc_dec);
+            priv->RefPicList0_count += n;
+
+            ref_list = &priv->RefPicList0[priv->RefPicList0_count];
+            for (n = 0, i = 0; i < priv->short_ref_count; i++) {
+                if (priv->short_ref[i]->poc >= picture->poc)
+                    ref_list[n++] = priv->short_ref[i];
+            }
+            SORT_REF_LIST(ref_list, n, poc_inc);
+            priv->RefPicList0_count += n;
+        }
+
+        if (priv->long_ref_count > 0) {
+            // 2. Long-term references
+            ref_list = &priv->RefPicList0[priv->RefPicList0_count];
+            for (n = 0, i = 0; i < priv->long_ref_count; i++)
+                ref_list[n++] = priv->long_ref[i];
+            SORT_REF_LIST(ref_list, n, long_term_pic_num_inc);
+            priv->RefPicList0_count += n;
+        }
+
+        /* RefPicList1 */
+        if (priv->short_ref_count > 0) {
+            // 1. Short-term references
+            ref_list = priv->RefPicList1;
+            for (n = 0, i = 0; i < priv->short_ref_count; i++) {
+                if (priv->short_ref[i]->poc > picture->poc)
+                    ref_list[n++] = priv->short_ref[i];
+            }
+            SORT_REF_LIST(ref_list, n, poc_inc);
+            priv->RefPicList1_count += n;
+
+            ref_list = &priv->RefPicList1[priv->RefPicList1_count];
+            for (n = 0, i = 0; i < priv->short_ref_count; i++) {
+                if (priv->short_ref[i]->poc <= picture->poc)
+                    ref_list[n++] = priv->short_ref[i];
+            }
+            SORT_REF_LIST(ref_list, n, poc_dec);
+            priv->RefPicList1_count += n;
+        }
+
+        if (priv->long_ref_count > 0) {
+            // 2. Long-term references
+            ref_list = &priv->RefPicList1[priv->RefPicList1_count];
+            for (n = 0, i = 0; i < priv->long_ref_count; i++)
+                ref_list[n++] = priv->long_ref[i];
+            SORT_REF_LIST(ref_list, n, long_term_pic_num_inc);
+            priv->RefPicList1_count += n;
+        }
+    }
+    else {
+        /* 8.2.4.2.4 - B slices in fields */
+        GstVaapiPictureH264 *short_ref0[32];
+        guint short_ref0_count = 0;
+        GstVaapiPictureH264 *short_ref1[32];
+        guint short_ref1_count = 0;
+        GstVaapiPictureH264 *long_ref[32];
+        guint long_ref_count = 0;
+
+        /* refFrameList0ShortTerm */
+        if (priv->short_ref_count > 0) {
+            ref_list = short_ref0;
+            for (n = 0, i = 0; i < priv->short_ref_count; i++) {
+                if (priv->short_ref[i]->poc <= picture->poc)
+                    ref_list[n++] = priv->short_ref[i];
+            }
+            SORT_REF_LIST(ref_list, n, poc_dec);
+            short_ref0_count += n;
+
+            ref_list = &short_ref0[short_ref0_count];
+            for (n = 0, i = 0; i < priv->short_ref_count; i++) {
+                if (priv->short_ref[i]->poc > picture->poc)
+                    ref_list[n++] = priv->short_ref[i];
+            }
+            SORT_REF_LIST(ref_list, n, poc_inc);
+            short_ref0_count += n;
+        }
+
+        /* refFrameList1ShortTerm */
+        if (priv->short_ref_count > 0) {
+            ref_list = short_ref1;
+            for (n = 0, i = 0; i < priv->short_ref_count; i++) {
+                if (priv->short_ref[i]->poc > picture->poc)
+                    ref_list[n++] = priv->short_ref[i];
+            }
+            SORT_REF_LIST(ref_list, n, poc_inc);
+            short_ref1_count += n;
+
+            ref_list = &short_ref1[short_ref1_count];
+            for (n = 0, i = 0; i < priv->short_ref_count; i++) {
+                if (priv->short_ref[i]->poc <= picture->poc)
+                    ref_list[n++] = priv->short_ref[i];
+            }
+            SORT_REF_LIST(ref_list, n, poc_dec);
+            short_ref1_count += n;
+        }
+
+        /* refFrameListLongTerm */
+        if (priv->long_ref_count > 0) {
+            for (i = 0; i < priv->long_ref_count; i++)
+                long_ref[i] = priv->long_ref[i];
+            SORT_REF_LIST(long_ref, i, long_term_frame_idx_inc);
+            long_ref_count = i;
+        }
+
+        // XXX: handle 8.2.4.2.5
+    }
+
+    /* Check whether RefPicList1 is identical to RefPicList0, then
+       swap if necessary */
+    if (priv->RefPicList1_count > 1 &&
+        priv->RefPicList1_count == priv->RefPicList0_count &&
+        memcmp(priv->RefPicList0, priv->RefPicList1,
+               priv->RefPicList0_count * sizeof(priv->RefPicList0[0])) == 0) {
+        GstVaapiPictureH264 * const tmp = priv->RefPicList1[0];
+        priv->RefPicList1[0] = priv->RefPicList1[1];
+        priv->RefPicList1[1] = tmp;
+    }
+}
+
+#undef SORT_REF_LIST
+
+static void
+clear_references(
+    GstVaapiDecoderH264  *decoder,
+    GstVaapiPictureH264 **pictures,
+    guint                *picture_count
+)
+{
+    const guint num_pictures = *picture_count;
+    guint i;
+
+    for (i = 0; i < num_pictures; i++)
+        gst_vaapi_picture_replace(&pictures[i], NULL);
+    *picture_count = 0;
+}
+
+static gboolean
+remove_reference_at(
+    GstVaapiDecoderH264  *decoder,
+    GstVaapiPictureH264 **pictures,
+    guint                *picture_count,
+    guint                 index
+)
+{
+    guint num_pictures = *picture_count;
+
+    g_return_val_if_fail(index < num_pictures, FALSE);
+
+    GST_VAAPI_PICTURE_FLAG_UNSET(pictures[index], GST_VAAPI_PICTURE_FLAG_REFERENCE);
+    if (index != --num_pictures)
+        gst_vaapi_picture_replace(&pictures[index], pictures[num_pictures]);
+    gst_vaapi_picture_replace(&pictures[num_pictures], NULL);
+    *picture_count = num_pictures;
+    return TRUE;
+}
+
+static gint
+find_short_term_reference(GstVaapiDecoderH264 *decoder, gint32 pic_num)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    guint i;
+
+    for (i = 0; i < priv->short_ref_count; i++) {
+        if (priv->short_ref[i]->pic_num == pic_num)
+            return i;
+    }
+    GST_ERROR("found no short-term reference picture with PicNum = %d",
+              pic_num);
+    return -1;
+}
+
+static gint
+find_long_term_reference(GstVaapiDecoderH264 *decoder, gint32 long_term_pic_num)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    guint i;
+
+    for (i = 0; i < priv->long_ref_count; i++) {
+        if (priv->long_ref[i]->long_term_pic_num == long_term_pic_num)
+            return i;
+    }
+    GST_ERROR("found no long-term reference picture with LongTermPicNum = %d",
+              long_term_pic_num);
+    return -1;
+}
+
+static void
+exec_picture_refs_modification_1(
+    GstVaapiDecoderH264           *decoder,
+    GstVaapiPictureH264           *picture,
+    GstH264SliceHdr               *slice_hdr,
+    guint                          list
+)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstH264PPS * const pps = slice_hdr->pps;
+    GstH264SPS * const sps = pps->sequence;
+    GstH264RefPicListModification *ref_pic_list_modification;
+    guint num_ref_pic_list_modifications;
+    GstVaapiPictureH264 **ref_list;
+    guint *ref_list_count_ptr, ref_list_count, ref_list_idx = 0;
+    guint i, j, n, num_refs;
+    gint found_ref_idx;
+    gint32 MaxPicNum, CurrPicNum, picNumPred;
+
+    GST_DEBUG("modification process of reference picture list %u", list);
+
+    if (list == 0) {
+        ref_pic_list_modification      = slice_hdr->ref_pic_list_modification_l0;
+        num_ref_pic_list_modifications = slice_hdr->n_ref_pic_list_modification_l0;
+        ref_list                       = priv->RefPicList0;
+        ref_list_count_ptr             = &priv->RefPicList0_count;
+        num_refs                       = slice_hdr->num_ref_idx_l0_active_minus1 + 1;
+    }
+    else {
+        ref_pic_list_modification      = slice_hdr->ref_pic_list_modification_l1;
+        num_ref_pic_list_modifications = slice_hdr->n_ref_pic_list_modification_l1;
+        ref_list                       = priv->RefPicList1;
+        ref_list_count_ptr             = &priv->RefPicList1_count;
+        num_refs                       = slice_hdr->num_ref_idx_l1_active_minus1 + 1;
+    }
+    ref_list_count = *ref_list_count_ptr;
+
+    if (picture->field_pic_flag) {
+        MaxPicNum  = 1 << (sps->log2_max_frame_num_minus4 + 5); // 2 * MaxFrameNum
+        CurrPicNum = 2 * slice_hdr->frame_num + 1;              // 2 * frame_num + 1
+    }
+    else {
+        MaxPicNum  = 1 << (sps->log2_max_frame_num_minus4 + 4); // MaxFrameNum
+        CurrPicNum = slice_hdr->frame_num;                      // frame_num
+    }
+
+    picNumPred = CurrPicNum;
+
+    for (i = 0; i < num_ref_pic_list_modifications; i++) {
+        GstH264RefPicListModification * const l = &ref_pic_list_modification[i];
+        if (l->modification_of_pic_nums_idc == 3)
+            break;
+
+        /* 8.2.4.3.1 - Short-term reference pictures */
+        if (l->modification_of_pic_nums_idc == 0 || l->modification_of_pic_nums_idc == 1) {
+            gint32 abs_diff_pic_num = l->value.abs_diff_pic_num_minus1 + 1;
+            gint32 picNum, picNumNoWrap;
+
+            // (8-34)
+            if (l->modification_of_pic_nums_idc == 0) {
+                picNumNoWrap = picNumPred - abs_diff_pic_num;
+                if (picNumNoWrap < 0)
+                    picNumNoWrap += MaxPicNum;
+            }
+
+            // (8-35)
+            else {
+                picNumNoWrap = picNumPred + abs_diff_pic_num;
+                if (picNumNoWrap >= MaxPicNum)
+                    picNumNoWrap -= MaxPicNum;
+            }
+            picNumPred = picNumNoWrap;
+
+            // (8-36)
+            picNum = picNumNoWrap;
+            if (picNum > CurrPicNum)
+                picNum -= MaxPicNum;
+
+            // (8-37)
+            for (j = num_refs; j > ref_list_idx; j--)
+                ref_list[j] = ref_list[j - 1];
+            found_ref_idx = find_short_term_reference(decoder, picNum);
+            ref_list[ref_list_idx++] =
+                found_ref_idx >= 0 ? priv->short_ref[found_ref_idx] : NULL;
+            n = ref_list_idx;
+            for (j = ref_list_idx; j <= num_refs; j++) {
+                gint32 PicNumF;
+                if (!ref_list[j])
+                    continue;
+                PicNumF = ref_list[j]->is_long_term ?
+                    MaxPicNum : ref_list[j]->pic_num;
+                if (PicNumF != picNum)
+                    ref_list[n++] = ref_list[j];
+            }
+        }
+
+        /* 8.2.4.3.2 - Long-term reference pictures */
+        else {
+
+            for (j = num_refs; j > ref_list_idx; j--)
+                ref_list[j] = ref_list[j - 1];
+            found_ref_idx =
+                find_long_term_reference(decoder, l->value.long_term_pic_num);
+            ref_list[ref_list_idx++] =
+                found_ref_idx >= 0 ? priv->long_ref[found_ref_idx] : NULL;
+            n = ref_list_idx;
+            for (j = ref_list_idx; j <= num_refs; j++) {
+                gint32 LongTermPicNumF;
+                if (!ref_list[j])
+                    continue;
+                LongTermPicNumF = ref_list[j]->is_long_term ?
+                    ref_list[j]->long_term_pic_num : INT_MAX;
+                if (LongTermPicNumF != l->value.long_term_pic_num)
+                    ref_list[n++] = ref_list[j];
+            }
+        }
+    }
+
+#if DEBUG
+    for (i = 0; i < num_refs; i++)
+        if (!ref_list[i])
+            GST_ERROR("list %u entry %u is empty", list, i);
+#endif
+    *ref_list_count_ptr = num_refs;
+}
+
+/* 8.2.4.3 - Modification process for reference picture lists */
+static void
+exec_picture_refs_modification(
+    GstVaapiDecoderH264 *decoder,
+    GstVaapiPictureH264 *picture,
+    GstH264SliceHdr     *slice_hdr
+)
+{
+    GST_DEBUG("execute ref_pic_list_modification()");
+
+    /* RefPicList0 */
+    if (!GST_H264_IS_I_SLICE(slice_hdr) && !GST_H264_IS_SI_SLICE(slice_hdr) &&
+        slice_hdr->ref_pic_list_modification_flag_l0)
+        exec_picture_refs_modification_1(decoder, picture, slice_hdr, 0);
+
+    /* RefPicList1 */
+    if (GST_H264_IS_B_SLICE(slice_hdr) &&
+        slice_hdr->ref_pic_list_modification_flag_l1)
+        exec_picture_refs_modification_1(decoder, picture, slice_hdr, 1);
+}
+
+static gboolean
+init_picture_refs(
+    GstVaapiDecoderH264 *decoder,
+    GstVaapiPictureH264 *picture,
+    GstH264SliceHdr     *slice_hdr
+)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstVaapiPicture * const base_picture = &picture->base;
+    guint i, num_refs;
+
+    init_picture_refs_pic_num(decoder, picture, slice_hdr);
+
+    priv->RefPicList0_count = 0;
+    priv->RefPicList1_count = 0;
+
+    switch (base_picture->type) {
+    case GST_VAAPI_PICTURE_TYPE_P:
+    case GST_VAAPI_PICTURE_TYPE_SP:
+        init_picture_refs_p_slice(decoder, picture, slice_hdr);
+        break;
+    case GST_VAAPI_PICTURE_TYPE_B:
+        init_picture_refs_b_slice(decoder, picture, slice_hdr);
+        break;
+    default:
+        break;
+    }
+
+    exec_picture_refs_modification(decoder, picture, slice_hdr);
+
+    switch (base_picture->type) {
+    case GST_VAAPI_PICTURE_TYPE_B:
+        num_refs = 1 + slice_hdr->num_ref_idx_l1_active_minus1;
+        for (i = priv->RefPicList1_count; i < num_refs; i++)
+            priv->RefPicList1[i] = NULL;
+        priv->RefPicList1_count = num_refs;
+
+        // fall-through
+    case GST_VAAPI_PICTURE_TYPE_P:
+    case GST_VAAPI_PICTURE_TYPE_SP:
+        num_refs = 1 + slice_hdr->num_ref_idx_l0_active_minus1;
+        for (i = priv->RefPicList0_count; i < num_refs; i++)
+            priv->RefPicList0[i] = NULL;
+        priv->RefPicList0_count = num_refs;
+        break;
+    default:
+        break;
+    }
+    return TRUE;
+}
+
+static gboolean
+init_picture(
+    GstVaapiDecoderH264 *decoder,
+    GstVaapiPictureH264 *picture,
+    GstH264SliceHdr     *slice_hdr,
+    GstH264NalUnit      *nalu
+)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstVaapiPicture * const base_picture = &picture->base;
+    VAPictureH264 *pic;
+    guint i;
+
+    priv->frame_num             = slice_hdr->frame_num;
+    picture->frame_num          = priv->frame_num;
+    picture->frame_num_wrap     = priv->frame_num;
+    picture->is_idr             = nalu->type == GST_H264_NAL_SLICE_IDR;
+    picture->field_pic_flag     = slice_hdr->field_pic_flag;
+    picture->bottom_field_flag  = slice_hdr->bottom_field_flag;
+    picture->output_flag        = TRUE; /* XXX: conformant to Annex A only */
+    base_picture->pts           = gst_adapter_prev_timestamp(priv->adapter, NULL);
+
+    /* Reset decoder state for IDR pictures */
+    if (picture->is_idr) {
+        GST_DEBUG("<IDR>");
+        clear_references(decoder, priv->short_ref, &priv->short_ref_count);
+        clear_references(decoder, priv->long_ref,  &priv->long_ref_count );
+        priv->prev_poc_msb = 0;
+        priv->prev_poc_lsb = 0;
+    }
+
+    /* Initialize VA picture info */
+    pic = &picture->info;
+    pic->picture_id = picture->base.surface_id;
+    pic->frame_idx  = priv->frame_num;
+    if (picture->field_pic_flag) {
+        if (picture->bottom_field_flag)
+            pic->flags |= VA_PICTURE_H264_BOTTOM_FIELD;
+        else
+            pic->flags |= VA_PICTURE_H264_TOP_FIELD;
+    }
+
+    /* Initialize base picture */
+    switch (slice_hdr->type % 5) {
+    case GST_H264_P_SLICE:
+        base_picture->type = GST_VAAPI_PICTURE_TYPE_P;
+        break;
+    case GST_H264_B_SLICE:
+        base_picture->type = GST_VAAPI_PICTURE_TYPE_B;
+        break;
+    case GST_H264_I_SLICE:
+        base_picture->type = GST_VAAPI_PICTURE_TYPE_I;
+        break;
+    case GST_H264_SP_SLICE:
+        base_picture->type = GST_VAAPI_PICTURE_TYPE_SP;
+        break;
+    case GST_H264_SI_SLICE:
+        base_picture->type = GST_VAAPI_PICTURE_TYPE_SI;
+        break;
+    }
+
+    if (nalu->ref_idc) {
+        GstH264DecRefPicMarking * const dec_ref_pic_marking =
+            &slice_hdr->dec_ref_pic_marking;
+        GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
+        if (picture->is_idr) {
+            if (dec_ref_pic_marking->long_term_reference_flag)
+                picture->is_long_term = TRUE;
+        }
+        else if (dec_ref_pic_marking->adaptive_ref_pic_marking_mode_flag) {
+            for (i = 0; i < dec_ref_pic_marking->n_ref_pic_marking; i++) {
+                GstH264RefPicMarking * const ref_pic_marking =
+                    &dec_ref_pic_marking->ref_pic_marking[i];
+                switch (ref_pic_marking->memory_management_control_operation) {
+                case 3:
+                case 6:
+                    picture->is_long_term = TRUE;
+                    pic->frame_idx = ref_pic_marking->long_term_frame_idx;
+                    break;
+                case 5:
+                    picture->has_mmco_5 = TRUE;
+                    break;
+                }
+            }
+        }
+        if (picture->is_long_term)
+            pic->flags |= VA_PICTURE_H264_LONG_TERM_REFERENCE;
+        else
+            pic->flags |= VA_PICTURE_H264_SHORT_TERM_REFERENCE;
+    }
+
+    init_picture_poc(decoder, picture, slice_hdr);
+    if (!init_picture_refs(decoder, picture, slice_hdr)) {
+        GST_DEBUG("failed to initialize references");
+        return FALSE;
+    }
+    return TRUE;
+}
+
+/* 8.2.5.3 - Sliding window decoded reference picture marking process */
+static gboolean
+exec_ref_pic_marking_sliding_window(GstVaapiDecoderH264 *decoder)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstH264SPS * const sps = priv->sps;
+    guint i, max_num_ref_frames, lowest_frame_num_index;
+    gint32 lowest_frame_num;
+
+    GST_DEBUG("reference picture marking process (sliding window)");
+
+    max_num_ref_frames = sps->num_ref_frames;
+    if (max_num_ref_frames == 0)
+        max_num_ref_frames = 1;
+
+    if (priv->short_ref_count + priv->long_ref_count < max_num_ref_frames)
+        return TRUE;
+    if (priv->short_ref_count < 1)
+        return FALSE;
+
+    lowest_frame_num = priv->short_ref[0]->frame_num_wrap;
+    lowest_frame_num_index = 0;
+    for (i = 1; i < priv->short_ref_count; i++) {
+        if (priv->short_ref[i]->frame_num_wrap < lowest_frame_num) {
+            lowest_frame_num = priv->short_ref[i]->frame_num_wrap;
+            lowest_frame_num_index = i;
+        }
+    }
+
+    remove_reference_at(
+        decoder,
+        priv->short_ref, &priv->short_ref_count,
+        lowest_frame_num_index
+    );
+    return TRUE;
+}
+
+/* 8.2.5.4. Adaptive memory control decoded reference picture marking process */
+static gboolean
+exec_ref_pic_marking_adaptive(
+    GstVaapiDecoderH264     *decoder,
+    GstVaapiPictureH264     *picture,
+    GstH264DecRefPicMarking *dec_ref_pic_marking
+)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    gint32 pic_num, ref_idx;
+    guint i;
+
+    GST_DEBUG("reference picture marking process (adaptive memory control)");
+
+    for (i = 0; i < dec_ref_pic_marking->n_ref_pic_marking; i++) {
+        GstH264RefPicMarking * const ref_pic_marking =
+            &dec_ref_pic_marking->ref_pic_marking[i];
+
+        switch (ref_pic_marking->memory_management_control_operation) {
+        case 1:
+            // Mark short-term reference picture as "unused for reference"
+            if (!picture->field_pic_flag)
+                pic_num = picture->frame_num_wrap;
+            else
+                pic_num = 2 * picture->frame_num_wrap + 1;
+            pic_num -= ref_pic_marking->difference_of_pic_nums_minus1 + 1;
+            ref_idx = find_short_term_reference(decoder, pic_num);
+            if (ref_idx < 0)
+                break;
+            remove_reference_at(
+                decoder,
+                priv->short_ref, &priv->short_ref_count,
+                ref_idx
+            );
+            break;
+        case 2:
+            // Mark long-term reference picture as "unused for reference"
+            pic_num = picture->long_term_pic_num;
+            ref_idx = find_long_term_reference(decoder, pic_num);
+            if (ref_idx < 0)
+                break;
+            remove_reference_at(
+                decoder,
+                priv->long_ref, &priv->long_ref_count,
+                ref_idx
+            );
+            break;
+        case 3:
+            // Assign LongTermFrameIdx to a short-term reference picture
+            if (!picture->field_pic_flag)
+                pic_num = picture->frame_num_wrap;
+            else
+                pic_num = 2 * picture->frame_num_wrap + 1;
+            pic_num -= ref_pic_marking->difference_of_pic_nums_minus1 + 1;
+            ref_idx = find_short_term_reference(decoder, pic_num);
+            if (ref_idx < 0)
+                break;
+            break;
+        case 5:
+            // Mark all reference pictures as "unused for reference"
+            clear_references(decoder, priv->short_ref, &priv->short_ref_count);
+            clear_references(decoder, priv->long_ref,  &priv->long_ref_count );
+            break;
+        default:
+            g_assert(0 && "unhandled MMCO");
+            break;
+        }
+    }
+    return TRUE;
+}
+
+/* 8.2.5 - Execute reference picture marking process */
+static gboolean
+exec_ref_pic_marking(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstVaapiPictureH264 **picture_ptr;
+
+    if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture))
+        return TRUE;
+
+    if (!picture->is_idr) {
+        GstH264DecRefPicMarking * const dec_ref_pic_marking =
+            get_dec_ref_pic_marking(picture);
+        if (dec_ref_pic_marking->adaptive_ref_pic_marking_mode_flag) {
+            if (!exec_ref_pic_marking_adaptive(decoder, picture, dec_ref_pic_marking))
+                return FALSE;
+        }
+        else {
+            if (!exec_ref_pic_marking_sliding_window(decoder))
+                return FALSE;
+        }
+    }
+
+    if (picture->is_long_term)
+        picture_ptr = &priv->long_ref[priv->long_ref_count++];
+    else
+        picture_ptr = &priv->short_ref[priv->short_ref_count++];
+    gst_vaapi_picture_replace(picture_ptr, picture);
+    return TRUE;
+}
+
+/* Update picture order count */
+static void
+exit_picture_poc(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstH264SPS * const sps = priv->sps;
+
+    switch (sps->pic_order_cnt_type) {
+    case 0:
+        if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture))
+            break;
+        if (picture->has_mmco_5) {
+            priv->prev_poc_msb = 0;
+            if (!picture->field_pic_flag || !picture->bottom_field_flag)
+                priv->prev_poc_lsb = picture->info.TopFieldOrderCnt;
+            else
+                priv->prev_poc_lsb = 0;
+        }
+        else {
+            priv->prev_poc_msb = priv->poc_msb;
+            priv->prev_poc_lsb = priv->poc_lsb;
+        }
+        break;
+    case 1:
+    case 2:
+        priv->prev_frame_num = priv->frame_num;
+        if (picture->has_mmco_5)
+            priv->prev_frame_num_offset = 0;
+        else
+            priv->prev_frame_num_offset = priv->frame_num_offset;
+        break;
+    }
+}
+
+static inline gboolean
+exit_picture(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
+{
+    /* Update picture order count */
+    exit_picture_poc(decoder, picture);
+
+    /* Decoded reference picture marking process */
+    if (!exec_ref_pic_marking(decoder, picture))
+        return FALSE;
+    return TRUE;
+}
+
+static void
+vaapi_init_picture(VAPictureH264 *pic)
+{
+    pic->picture_id           = VA_INVALID_ID;
+    pic->frame_idx            = 0;
+    pic->flags                = VA_PICTURE_H264_INVALID;
+    pic->TopFieldOrderCnt     = 0;
+    pic->BottomFieldOrderCnt  = 0;
+}
+
+static gboolean
+fill_picture(
+    GstVaapiDecoderH264 *decoder,
+    GstVaapiPictureH264 *picture,
+    GstH264SliceHdr     *slice_hdr,
+    GstH264NalUnit      *nalu
+)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstVaapiPicture * const base_picture = &picture->base;
+    GstH264SPS * const sps = priv->sps;
+    GstH264PPS * const pps = priv->pps;
+    VAPictureParameterBufferH264 * const pic_param = base_picture->param;
+    guint i, n;
+
+    /* Fill in VAPictureParameterBufferH264 */
+    pic_param->CurrPic = picture->info;
+    for (i = 0, n = 0; i < priv->short_ref_count; i++)
+        pic_param->ReferenceFrames[n++] = priv->short_ref[i]->info;
+    for (i = 0; i < priv->long_ref_count; i++)
+        pic_param->ReferenceFrames[n++] = priv->long_ref[i]->info;
+    for (; n < G_N_ELEMENTS(pic_param->ReferenceFrames); n++)
+        vaapi_init_picture(&pic_param->ReferenceFrames[n]);
+
+#define COPY_FIELD(s, f) \
+    pic_param->f = (s)->f
+
+#define COPY_BFM(a, s, f) \
+    pic_param->a.bits.f = (s)->f
+
+    pic_param->picture_width_in_mbs_minus1      = priv->mb_width  - 1;
+    pic_param->picture_height_in_mbs_minus1     = priv->mb_height - 1;
+    pic_param->frame_num                        = priv->frame_num;
+
+    COPY_FIELD(sps, bit_depth_luma_minus8);
+    COPY_FIELD(sps, bit_depth_chroma_minus8);
+    COPY_FIELD(sps, num_ref_frames);
+    COPY_FIELD(pps, num_slice_groups_minus1);
+    COPY_FIELD(pps, slice_group_map_type);
+    COPY_FIELD(pps, slice_group_change_rate_minus1);
+    COPY_FIELD(pps, pic_init_qp_minus26);
+    COPY_FIELD(pps, pic_init_qs_minus26);
+    COPY_FIELD(pps, chroma_qp_index_offset);
+    COPY_FIELD(pps, second_chroma_qp_index_offset);
+
+    pic_param->seq_fields.value                                         = 0; /* reset all bits */
+    pic_param->seq_fields.bits.residual_colour_transform_flag           = sps->separate_colour_plane_flag;
+    pic_param->seq_fields.bits.MinLumaBiPredSize8x8                     = sps->level_idc >= 31; /* A.3.3.2 */
+
+    COPY_BFM(seq_fields, sps, chroma_format_idc);
+    COPY_BFM(seq_fields, sps, gaps_in_frame_num_value_allowed_flag);
+    COPY_BFM(seq_fields, sps, frame_mbs_only_flag); 
+    COPY_BFM(seq_fields, sps, mb_adaptive_frame_field_flag); 
+    COPY_BFM(seq_fields, sps, direct_8x8_inference_flag); 
+    COPY_BFM(seq_fields, sps, log2_max_frame_num_minus4);
+    COPY_BFM(seq_fields, sps, pic_order_cnt_type);
+    COPY_BFM(seq_fields, sps, log2_max_pic_order_cnt_lsb_minus4);
+    COPY_BFM(seq_fields, sps, delta_pic_order_always_zero_flag);
+
+    pic_param->pic_fields.value                                         = 0; /* reset all bits */
+    pic_param->pic_fields.bits.field_pic_flag                           = slice_hdr->field_pic_flag;
+    pic_param->pic_fields.bits.reference_pic_flag                       = GST_VAAPI_PICTURE_IS_REFERENCE(picture);
+
+    COPY_BFM(pic_fields, pps, entropy_coding_mode_flag);
+    COPY_BFM(pic_fields, pps, weighted_pred_flag);
+    COPY_BFM(pic_fields, pps, weighted_bipred_idc);
+    COPY_BFM(pic_fields, pps, transform_8x8_mode_flag);
+    COPY_BFM(pic_fields, pps, constrained_intra_pred_flag);
+    COPY_BFM(pic_fields, pps, pic_order_present_flag);
+    COPY_BFM(pic_fields, pps, deblocking_filter_control_present_flag);
+    COPY_BFM(pic_fields, pps, redundant_pic_cnt_present_flag);
+    return TRUE;
+}
+
+static gboolean
+fill_quant_matrix(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    VAIQMatrixBufferH264 * const iq_matrix = picture->base.iq_matrix->param;
+
+    /* XXX: we can only support 4:2:0 or 4:2:2 since ScalingLists8x8[]
+       is not large enough to hold lists for 4:4:4 */
+    if (priv->sps->chroma_format_idc == 3 &&
+        sizeof(iq_matrix->ScalingList8x8) != sizeof(priv->scaling_list_8x8))
+        return FALSE;
+
+    /* Fill in VAIQMatrixBufferH264 */
+    memcpy(iq_matrix->ScalingList4x4, priv->scaling_list_4x4,
+           sizeof(iq_matrix->ScalingList4x4));
+    memcpy(iq_matrix->ScalingList8x8, priv->scaling_list_8x8,
+           sizeof(iq_matrix->ScalingList8x8));
+    return TRUE;
+}
+
+static GstVaapiDecoderStatus
+decode_picture(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu, GstH264SliceHdr *slice_hdr)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstVaapiPictureH264 *picture;
+    GstVaapiDecoderStatus status;
+    GstH264PPS * const pps = slice_hdr->pps;
+    GstH264SPS * const sps = pps->sequence;
+
+    status = ensure_context(decoder, sps);
+    if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
+        GST_DEBUG("failed to reset context");
+        return status;
+    }
+
+    if (priv->current_picture && !decode_current_picture(decoder))
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+
+    picture = gst_vaapi_picture_h264_new(decoder);
+    if (!picture) {
+        GST_DEBUG("failed to allocate picture");
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+    priv->current_picture = picture;
+
+    picture->base.iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(H264, decoder);
+    if (!picture->base.iq_matrix) {
+        GST_DEBUG("failed to allocate IQ matrix");
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+
+    status = ensure_quant_matrix(decoder, pps);
+    if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
+        GST_DEBUG("failed to reset quantizer matrix");
+        return status;
+    }
+
+    priv->sps = sps;
+    priv->pps = pps;
+
+    if (!init_picture(decoder, picture, slice_hdr, nalu))
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+    if (!fill_picture(decoder, picture, slice_hdr, nalu))
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static gboolean
+decode_picture_end(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
+{
+    if (!fill_quant_matrix(decoder, picture))
+        return FALSE;
+    if (!exit_picture(decoder, picture))
+        return FALSE;
+    if (!dpb_add(decoder, picture))
+        return FALSE;
+    return TRUE;
+}
+
+#ifndef HAVE_GST_H264_SLICE_HDR_EPB_COUNT
+static guint
+get_epb_count(const guint8 *buf, guint buf_size, guint header_size)
+{
+    guint i, n = 0;
+
+    if (buf_size > header_size)
+        buf_size = header_size;
+
+    for (i = 2; i < buf_size; i++) {
+        if (!buf[i - 2] && !buf[i - 1] && buf[i] == 0x03)
+            i += 2, n++;
+    }
+    return n;
+}
+#endif
+
+static inline guint
+get_slice_data_bit_offset(GstH264SliceHdr *slice_hdr, GstH264NalUnit *nalu)
+{
+    guint epb_count;
+
+#ifdef HAVE_GST_H264_SLICE_HDR_EPB_COUNT
+    epb_count = slice_hdr->n_emulation_prevention_bytes;
+#else
+    epb_count = get_epb_count(
+        nalu->data + nalu->offset,
+        nalu->size,
+        slice_hdr->header_size / 8
+    );
+#endif
+    return 8 /* nal_unit_type */ + slice_hdr->header_size - epb_count * 8;
+}
+
+static gboolean
+fill_pred_weight_table(GstVaapiDecoderH264 *decoder, GstVaapiSliceH264 *slice)
+{
+    GstH264SliceHdr * const slice_hdr = &slice->slice_hdr;
+    GstH264PPS * const pps = slice_hdr->pps;
+    GstH264SPS * const sps = pps->sequence;
+    GstH264PredWeightTable * const w = &slice_hdr->pred_weight_table;
+    VASliceParameterBufferH264 * const slice_param = slice->base.param;
+    guint num_weight_tables = 0;
+    gint i, j;
+
+    if (pps->weighted_pred_flag &&
+        (GST_H264_IS_P_SLICE(slice_hdr) || GST_H264_IS_SP_SLICE(slice_hdr)))
+        num_weight_tables = 1;
+    else if (pps->weighted_bipred_idc == 1 && GST_H264_IS_B_SLICE(slice_hdr))
+        num_weight_tables = 2;
+    else
+        num_weight_tables = 0;
+
+    slice_param->luma_log2_weight_denom   = w->luma_log2_weight_denom;
+    slice_param->chroma_log2_weight_denom = w->chroma_log2_weight_denom;
+    slice_param->luma_weight_l0_flag      = 0;
+    slice_param->chroma_weight_l0_flag    = 0;
+    slice_param->luma_weight_l1_flag      = 0;
+    slice_param->chroma_weight_l1_flag    = 0;
+
+    if (num_weight_tables < 1)
+        return TRUE;
+
+    slice_param->luma_weight_l0_flag = 1;
+    for (i = 0; i <= slice_param->num_ref_idx_l0_active_minus1; i++) {
+        slice_param->luma_weight_l0[i] = w->luma_weight_l0[i];
+        slice_param->luma_offset_l0[i] = w->luma_offset_l0[i];
+    }
+
+    slice_param->chroma_weight_l0_flag = sps->chroma_array_type != 0;
+    if (slice_param->chroma_weight_l0_flag) {
+        for (i = 0; i <= slice_param->num_ref_idx_l0_active_minus1; i++) {
+            for (j = 0; j < 2; j++) {
+                slice_param->chroma_weight_l0[i][j] = w->chroma_weight_l0[i][j];
+                slice_param->chroma_offset_l0[i][j] = w->chroma_offset_l0[i][j];
+            }
+        }
+    }
+
+    if (num_weight_tables < 2)
+        return TRUE;
+
+    slice_param->luma_weight_l1_flag = 1;
+    for (i = 0; i <= slice_param->num_ref_idx_l1_active_minus1; i++) {
+        slice_param->luma_weight_l1[i] = w->luma_weight_l1[i];
+        slice_param->luma_offset_l1[i] = w->luma_offset_l1[i];
+    }
+
+    slice_param->chroma_weight_l1_flag = sps->chroma_array_type != 0;
+    if (slice_param->chroma_weight_l1_flag) {
+        for (i = 0; i <= slice_param->num_ref_idx_l1_active_minus1; i++) {
+            for (j = 0; j < 2; j++) {
+                slice_param->chroma_weight_l1[i][j] = w->chroma_weight_l1[i][j];
+                slice_param->chroma_offset_l1[i][j] = w->chroma_offset_l1[i][j];
+            }
+        }
+    }
+    return TRUE;
+}
+
+static gboolean
+fill_RefPicList(GstVaapiDecoderH264 *decoder, GstVaapiSliceH264 *slice)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstH264SliceHdr * const slice_hdr = &slice->slice_hdr;
+    VASliceParameterBufferH264 * const slice_param = slice->base.param;
+    guint i, num_ref_lists = 0;
+
+    slice_param->num_ref_idx_l0_active_minus1 = 0;
+    slice_param->num_ref_idx_l1_active_minus1 = 0;
+
+    if (GST_H264_IS_B_SLICE(slice_hdr))
+        num_ref_lists = 2;
+    else if (GST_H264_IS_I_SLICE(slice_hdr))
+        num_ref_lists = 0;
+    else
+        num_ref_lists = 1;
+
+    if (num_ref_lists < 1)
+        return TRUE;
+
+    slice_param->num_ref_idx_l0_active_minus1 =
+        slice_hdr->num_ref_idx_l0_active_minus1;
+
+    for (i = 0; i < priv->RefPicList0_count && priv->RefPicList0[i]; i++)
+        slice_param->RefPicList0[i] = priv->RefPicList0[i]->info;
+    for (; i <= slice_param->num_ref_idx_l0_active_minus1; i++)
+        vaapi_init_picture(&slice_param->RefPicList0[i]);
+
+    if (num_ref_lists < 2)
+        return TRUE;
+
+    slice_param->num_ref_idx_l1_active_minus1 =
+        slice_hdr->num_ref_idx_l1_active_minus1;
+
+    for (i = 0; i < priv->RefPicList1_count && priv->RefPicList1[i]; i++)
+        slice_param->RefPicList1[i] = priv->RefPicList1[i]->info;
+    for (; i <= slice_param->num_ref_idx_l1_active_minus1; i++)
+        vaapi_init_picture(&slice_param->RefPicList1[i]);
+    return TRUE;
+}
+
+static gboolean
+fill_slice(
+    GstVaapiDecoderH264 *decoder,
+    GstVaapiSliceH264   *slice,
+    GstH264NalUnit      *nalu
+)
+{
+    GstH264SliceHdr * const slice_hdr = &slice->slice_hdr;
+    VASliceParameterBufferH264 * const slice_param = slice->base.param;
+
+    /* Fill in VASliceParameterBufferH264 */
+    slice_param->slice_data_bit_offset          = get_slice_data_bit_offset(slice_hdr, nalu);
+    slice_param->first_mb_in_slice              = slice_hdr->first_mb_in_slice;
+    slice_param->slice_type                     = slice_hdr->type % 5;
+    slice_param->direct_spatial_mv_pred_flag    = slice_hdr->direct_spatial_mv_pred_flag;
+    slice_param->cabac_init_idc                 = slice_hdr->cabac_init_idc;
+    slice_param->slice_qp_delta                 = slice_hdr->slice_qp_delta;
+    slice_param->disable_deblocking_filter_idc  = slice_hdr->disable_deblocking_filter_idc;
+    slice_param->slice_alpha_c0_offset_div2     = slice_hdr->slice_alpha_c0_offset_div2;
+    slice_param->slice_beta_offset_div2         = slice_hdr->slice_beta_offset_div2;
+
+    if (!fill_RefPicList(decoder, slice))
+        return FALSE;
+    if (!fill_pred_weight_table(decoder, slice))
+        return FALSE;
+    return TRUE;
+}
+
+static GstVaapiDecoderStatus
+decode_slice(GstVaapiDecoderH264 *decoder, GstH264NalUnit *nalu)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstVaapiDecoderStatus status;
+    GstVaapiPictureH264 *picture;
+    GstVaapiSliceH264 *slice = NULL;
+    GstH264SliceHdr *slice_hdr;
+    GstH264ParserResult result;
+
+    GST_DEBUG("slice (%u bytes)", nalu->size);
+
+    slice = gst_vaapi_slice_h264_new(
+        decoder,
+        nalu->data + nalu->offset,
+        nalu->size
+    );
+    if (!slice) {
+        GST_DEBUG("failed to allocate slice");
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+
+    slice_hdr = &slice->slice_hdr;
+    memset(slice_hdr, 0, sizeof(*slice_hdr));
+    result = gst_h264_parser_parse_slice_hdr(priv->parser, nalu, slice_hdr, TRUE, TRUE);
+    if (result != GST_H264_PARSER_OK) {
+        status = get_status(result);
+        goto error;
+    }
+
+    if (slice_hdr->first_mb_in_slice == 0) {
+        status = decode_picture(decoder, nalu, slice_hdr);
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            goto error;
+    }
+    picture = priv->current_picture;
+
+    priv->mb_x = slice_hdr->first_mb_in_slice % priv->mb_width;
+    priv->mb_y = slice_hdr->first_mb_in_slice / priv->mb_width; // FIXME: MBAFF or field
+
+    if (!fill_slice(decoder, slice, nalu)) {
+        status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+        goto error;
+    }
+    gst_vaapi_picture_add_slice(
+        GST_VAAPI_PICTURE_CAST(picture),
+        GST_VAAPI_SLICE_CAST(slice)
+    );
+
+    /* Commit picture for decoding if we reached the last slice */
+    if (++priv->mb_y >= priv->mb_height) {
+        if (!decode_current_picture(decoder)) {
+            status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+            goto error;
+        }
+        GST_DEBUG("done");
+    }
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+
+error:
+    if (slice)
+        gst_mini_object_unref(GST_MINI_OBJECT(slice));
+    return status;
+}
+
+static GstVaapiDecoderStatus
+decode_buffer(GstVaapiDecoderH264 *decoder, GstBuffer *buffer)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstVaapiDecoderStatus status;
+    GstH264ParserResult result;
+    GstH264NalUnit nalu;
+    guchar *buf;
+    guint buf_size, ofs;
+
+    buf      = GST_BUFFER_DATA(buffer);
+    buf_size = GST_BUFFER_SIZE(buffer);
+    if (!buf && buf_size == 0)
+        return decode_sequence_end(decoder);
+
+    gst_buffer_ref(buffer);
+    gst_adapter_push(priv->adapter, buffer);
+
+    if (priv->sub_buffer) {
+        buffer = gst_buffer_merge(priv->sub_buffer, buffer);
+        if (!buffer)
+            return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+        gst_buffer_unref(priv->sub_buffer);
+        priv->sub_buffer = NULL;
+    }
+
+    buf      = GST_BUFFER_DATA(buffer);
+    buf_size = GST_BUFFER_SIZE(buffer);
+    ofs      = 0;
+    do {
+        if (priv->is_avc) {
+            result = gst_h264_parser_identify_nalu_avc(
+                priv->parser,
+                buf, ofs, buf_size, priv->nal_length_size,
+                &nalu
+            );
+        }
+        else {
+            result = gst_h264_parser_identify_nalu(
+                priv->parser,
+                buf, ofs, buf_size,
+                &nalu
+            );
+        }
+        status = get_status(result);
+
+        if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA) {
+            priv->sub_buffer = gst_buffer_create_sub(buffer, ofs, buf_size - ofs);
+            break;
+        }
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            break;
+
+        ofs = nalu.offset - ofs;
+        if (gst_adapter_available(priv->adapter) >= ofs)
+            gst_adapter_flush(priv->adapter, ofs);
+
+        switch (nalu.type) {
+        case GST_H264_NAL_SLICE_IDR:
+            /* fall-through. IDR specifics are handled in init_picture() */
+        case GST_H264_NAL_SLICE:
+            status = decode_slice(decoder, &nalu);
+            break;
+        case GST_H264_NAL_SPS:
+            status = decode_sps(decoder, &nalu);
+            break;
+        case GST_H264_NAL_PPS:
+            status = decode_pps(decoder, &nalu);
+            break;
+        case GST_H264_NAL_SEI:
+            status = decode_sei(decoder, &nalu);
+            break;
+        case GST_H264_NAL_SEQ_END:
+            status = decode_sequence_end(decoder);
+            break;
+        case GST_H264_NAL_AU_DELIMITER:
+            /* skip all Access Unit NALs */
+            status = GST_VAAPI_DECODER_STATUS_SUCCESS;
+            break;
+        case GST_H264_NAL_FILLER_DATA:
+            /* skip all Filler Data NALs */
+            status = GST_VAAPI_DECODER_STATUS_SUCCESS;
+            break;
+        default:
+            GST_DEBUG("unsupported NAL unit type %d", nalu.type);
+            status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+            break;
+        }
+
+        if (gst_adapter_available(priv->adapter) >= nalu.size)
+            gst_adapter_flush(priv->adapter, nalu.size);
+        ofs = nalu.offset + nalu.size;
+    } while (status == GST_VAAPI_DECODER_STATUS_SUCCESS && ofs < buf_size);
+    return status;
+}
+
+static GstVaapiDecoderStatus
+decode_codec_data(GstVaapiDecoderH264 *decoder, GstBuffer *buffer)
+{
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstVaapiDecoderStatus status;
+    GstH264NalUnit nalu;
+    GstH264ParserResult result;
+    guchar *buf;
+    guint buf_size;
+    guint i, ofs, num_sps, num_pps;
+
+    buf      = GST_BUFFER_DATA(buffer);
+    buf_size = GST_BUFFER_SIZE(buffer);
+    if (!buf || buf_size == 0)
+        return GST_VAAPI_DECODER_STATUS_SUCCESS;
+
+    if (buf_size < 8)
+        return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+
+    if (buf[0] != 1) {
+        GST_DEBUG("failed to decode codec-data, not in avcC format");
+        return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+    }
+
+    priv->nal_length_size = (buf[4] & 0x03) + 1;
+
+    num_sps = buf[5] & 0x1f;
+    ofs = 6;
+
+    for (i = 0; i < num_sps; i++) {
+        result = gst_h264_parser_identify_nalu_avc(
+            priv->parser,
+            buf, ofs, buf_size, 2,
+            &nalu
+        );
+        if (result != GST_H264_PARSER_OK)
+            return get_status(result);
+
+        status = decode_sps(decoder, &nalu);
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            return status;
+        ofs = nalu.offset + nalu.size;
+    }
+
+    num_pps = buf[ofs];
+    ofs++;
+
+    for (i = 0; i < num_pps; i++) {
+        result = gst_h264_parser_identify_nalu_avc(
+            priv->parser,
+            buf, ofs, buf_size, 2,
+            &nalu
+        );
+        if (result != GST_H264_PARSER_OK)
+            return get_status(result);
+
+        status = decode_pps(decoder, &nalu);
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            return status;
+        ofs = nalu.offset + nalu.size;
+    }
+
+    priv->is_avc = TRUE;
+    return status;
+}
+
+GstVaapiDecoderStatus
+gst_vaapi_decoder_h264_decode(GstVaapiDecoder *base, GstBuffer *buffer)
+{
+    GstVaapiDecoderH264 * const decoder = GST_VAAPI_DECODER_H264(base);
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GstVaapiDecoderStatus status;
+    GstBuffer *codec_data;
+
+    g_return_val_if_fail(priv->is_constructed,
+                         GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED);
+
+    if (!priv->is_opened) {
+        priv->is_opened = gst_vaapi_decoder_h264_open(decoder, buffer);
+        if (!priv->is_opened)
+            return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
+
+        codec_data = GST_VAAPI_DECODER_CODEC_DATA(decoder);
+        if (codec_data) {
+            status = decode_codec_data(decoder, codec_data);
+            if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+                return status;
+        }
+     }
+     return decode_buffer(decoder, buffer);
+}
+
+static void
+gst_vaapi_decoder_h264_finalize(GObject *object)
+{
+    GstVaapiDecoderH264 * const decoder = GST_VAAPI_DECODER_H264(object);
+
+    gst_vaapi_decoder_h264_destroy(decoder);
+
+    G_OBJECT_CLASS(gst_vaapi_decoder_h264_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_decoder_h264_constructed(GObject *object)
+{
+    GstVaapiDecoderH264 * const decoder = GST_VAAPI_DECODER_H264(object);
+    GstVaapiDecoderH264Private * const priv = decoder->priv;
+    GObjectClass *parent_class;
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_decoder_h264_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+
+    priv->is_constructed = gst_vaapi_decoder_h264_create(decoder);
+}
+
+static void
+gst_vaapi_decoder_h264_class_init(GstVaapiDecoderH264Class *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiDecoderH264Private));
+
+    object_class->finalize      = gst_vaapi_decoder_h264_finalize;
+    object_class->constructed   = gst_vaapi_decoder_h264_constructed;
+
+    decoder_class->decode       = gst_vaapi_decoder_h264_decode;
+    decoder_class->clear_buffer = gst_vaapi_decoder_h264_clear_buffer;
+}
+
+static void
+gst_vaapi_decoder_h264_init(GstVaapiDecoderH264 *decoder)
+{
+    GstVaapiDecoderH264Private *priv;
+
+    priv                        = GST_VAAPI_DECODER_H264_GET_PRIVATE(decoder);
+    decoder->priv               = priv;
+    priv->parser                = NULL;
+    priv->sps                   = &priv->last_sps;
+    priv->pps                   = &priv->last_pps;
+    priv->current_picture       = NULL;
+    priv->dpb_count             = 0;
+    priv->dpb_size              = 0;
+    priv->profile               = GST_VAAPI_PROFILE_H264_HIGH;
+    priv->short_ref_count       = 0;
+    priv->long_ref_count        = 0;
+    priv->RefPicList0_count     = 0;
+    priv->RefPicList1_count     = 0;
+    priv->nal_length_size       = 0;
+    priv->width                 = 0;
+    priv->height                = 0;
+    priv->mb_x                  = 0;
+    priv->mb_y                  = 0;
+    priv->mb_width              = 0;
+    priv->mb_height             = 0;
+    priv->adapter               = NULL;
+    priv->sub_buffer            = NULL;
+    priv->field_poc[0]          = 0;
+    priv->field_poc[1]          = 0;
+    priv->poc_msb               = 0;
+    priv->poc_lsb               = 0;
+    priv->prev_poc_msb          = 0;
+    priv->prev_poc_lsb          = 0;
+    priv->frame_num_offset      = 0;
+    priv->prev_frame_num_offset = 0;
+    priv->frame_num             = 0;
+    priv->prev_frame_num        = 0;
+    priv->is_constructed        = FALSE;
+    priv->is_opened             = FALSE;
+    priv->is_avc                = FALSE;
+    priv->has_context           = FALSE;
+
+    memset(priv->dpb, 0, sizeof(priv->dpb));
+    memset(priv->short_ref, 0, sizeof(priv->short_ref));
+    memset(priv->long_ref, 0, sizeof(priv->long_ref));
+    memset(priv->RefPicList0, 0, sizeof(priv->RefPicList0));
+    memset(priv->RefPicList1, 0, sizeof(priv->RefPicList1));
+}
+
+/**
+ * gst_vaapi_decoder_h264_new:
+ * @display: a #GstVaapiDisplay
+ * @caps: a #GstCaps holding codec information
+ *
+ * Creates a new #GstVaapiDecoder for MPEG-2 decoding.  The @caps can
+ * hold extra information like codec-data and pictured coded size.
+ *
+ * Return value: the newly allocated #GstVaapiDecoder object
+ */
+GstVaapiDecoder *
+gst_vaapi_decoder_h264_new(GstVaapiDisplay *display, GstCaps *caps)
+{
+    GstVaapiDecoderH264 *decoder;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+    g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
+
+    decoder = g_object_new(
+        GST_VAAPI_TYPE_DECODER_H264,
+        "display",      display,
+        "caps",         caps,
+        NULL
+    );
+    if (!decoder->priv->is_constructed) {
+        g_object_unref(decoder);
+        return NULL;
+    }
+    return GST_VAAPI_DECODER_CAST(decoder);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_h264.h b/gst-libs/gst/vaapi/gstvaapidecoder_h264.h
new file mode 100644 (file)
index 0000000..79a08f1
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ *  gstvaapidecoder_h264.h - H.264 decoder
+ *
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DECODER_H264_H
+#define GST_VAAPI_DECODER_H264_H
+
+#include <gst/vaapi/gstvaapidecoder.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_DECODER_H264 \
+    (gst_vaapi_decoder_h264_get_type())
+
+#define GST_VAAPI_DECODER_H264(obj)                            \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                         \
+                                GST_VAAPI_TYPE_DECODER_H264,   \
+                                GstVaapiDecoderH264))
+
+#define GST_VAAPI_DECODER_H264_CLASS(klass)                    \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                          \
+                             GST_VAAPI_TYPE_DECODER_H264,      \
+                             GstVaapiDecoderH264Class))
+
+#define GST_VAAPI_IS_DECODER_H264(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_DECODER_H264))
+
+#define GST_VAAPI_IS_DECODER_H264_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_DECODER_H264))
+
+#define GST_VAAPI_DECODER_H264_GET_CLASS(obj)                  \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                          \
+                               GST_VAAPI_TYPE_DECODER_H264,    \
+                               GstVaapiDecoderH264Class))
+
+typedef struct _GstVaapiDecoderH264             GstVaapiDecoderH264;
+typedef struct _GstVaapiDecoderH264Private      GstVaapiDecoderH264Private;
+typedef struct _GstVaapiDecoderH264Class        GstVaapiDecoderH264Class;
+
+/**
+ * GstVaapiDecoderH264:
+ *
+ * A decoder based on H264.
+ */
+struct _GstVaapiDecoderH264 {
+    /*< private >*/
+    GstVaapiDecoder parent_instance;
+
+    GstVaapiDecoderH264Private *priv;
+};
+
+/**
+ * GstVaapiDecoderH264Class:
+ *
+ * A decoder class based on H264.
+ */
+struct _GstVaapiDecoderH264Class {
+    /*< private >*/
+    GstVaapiDecoderClass parent_class;
+};
+
+GType
+gst_vaapi_decoder_h264_get_type(void) G_GNUC_CONST;
+
+GstVaapiDecoder *
+gst_vaapi_decoder_h264_new(GstVaapiDisplay *display, GstCaps *caps);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DECODER_H264_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_jpeg.c b/gst-libs/gst/vaapi/gstvaapidecoder_jpeg.c
new file mode 100644 (file)
index 0000000..121f067
--- /dev/null
@@ -0,0 +1,718 @@
+/*
+ *  gstvaapidecoder_jpeg.c - JPEG decoder
+ *
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapidecoder_jpeg
+ * @short_description: JPEG decoder
+ */
+
+#include "sysdeps.h"
+#include <string.h>
+#include <gst/codecparsers/gstjpegparser.h>
+#include "gstvaapicompat.h"
+#include "gstvaapidecoder_jpeg.h"
+#include "gstvaapidecoder_objects.h"
+#include "gstvaapidecoder_priv.h"
+#include "gstvaapidisplay_priv.h"
+#include "gstvaapiobject_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiDecoderJpeg,
+              gst_vaapi_decoder_jpeg,
+              GST_VAAPI_TYPE_DECODER);
+
+#define GST_VAAPI_DECODER_JPEG_GET_PRIVATE(obj)                 \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_DECODER_JPEG,   \
+                                 GstVaapiDecoderJpegPrivate))
+
+struct _GstVaapiDecoderJpegPrivate {
+    GstVaapiProfile             profile;
+    guint                       width;
+    guint                       height;
+    GstVaapiPicture            *current_picture;
+    GstJpegFrameHdr             frame_hdr;
+    GstJpegHuffmanTables        huf_tables;
+    GstJpegQuantTables          quant_tables;
+    gboolean                    has_huf_table;
+    gboolean                    has_quant_table;
+    guint                       mcu_restart;
+    guint                       is_opened       : 1;
+    guint                       profile_changed : 1;
+    guint                       is_constructed  : 1;
+};
+
+typedef struct _GstJpegScanSegment GstJpegScanSegment;
+struct _GstJpegScanSegment {
+    guint                       header_offset;
+    guint                       header_size;
+    guint                       data_offset;
+    guint                       data_size;
+    guint                       is_valid        : 1;
+};
+
+static void
+gst_vaapi_decoder_jpeg_close(GstVaapiDecoderJpeg *decoder)
+{
+    GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+
+    gst_vaapi_picture_replace(&priv->current_picture, NULL);
+
+    /* Reset all */
+    priv->profile               = GST_VAAPI_PROFILE_JPEG_BASELINE;
+    priv->width                 = 0;
+    priv->height                = 0;
+    priv->is_opened             = FALSE;
+    priv->profile_changed       = TRUE;
+}
+
+static gboolean
+gst_vaapi_decoder_jpeg_open(GstVaapiDecoderJpeg *decoder, GstBuffer *buffer)
+{
+    gst_vaapi_decoder_jpeg_close(decoder);
+
+    return TRUE;
+}
+
+static void
+gst_vaapi_decoder_jpeg_destroy(GstVaapiDecoderJpeg *decoder)
+{
+    gst_vaapi_decoder_jpeg_close(decoder);
+}
+
+static gboolean
+gst_vaapi_decoder_jpeg_create(GstVaapiDecoderJpeg *decoder)
+{
+    if (!GST_VAAPI_DECODER_CODEC(decoder))
+        return FALSE;
+    return TRUE;
+}
+
+static GstVaapiDecoderStatus
+ensure_context(GstVaapiDecoderJpeg *decoder)
+{
+    GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+    GstVaapiProfile profiles[2];
+    GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
+    guint i, n_profiles = 0;
+    gboolean reset_context = FALSE;
+
+    if (priv->profile_changed) {
+        GST_DEBUG("profile changed");
+        priv->profile_changed = FALSE;
+        reset_context         = TRUE;
+
+        profiles[n_profiles++] = priv->profile;
+        //if (priv->profile == GST_VAAPI_PROFILE_JPEG_EXTENDED)
+        //    profiles[n_profiles++] = GST_VAAPI_PROFILE_JPEG_BASELINE;
+
+        for (i = 0; i < n_profiles; i++) {
+            if (gst_vaapi_display_has_decoder(GST_VAAPI_DECODER_DISPLAY(decoder),
+                                              profiles[i], entrypoint))
+                break;
+        }
+        if (i == n_profiles)
+            return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
+        priv->profile = profiles[i];
+    }
+
+    if (reset_context) {
+        reset_context = gst_vaapi_decoder_ensure_context(
+            GST_VAAPI_DECODER(decoder),
+            priv->profile,
+            entrypoint,
+            priv->width,
+            priv->height,
+            GST_DECODER_DEFAULT_SURFACES_COUNT
+        );
+        if (!reset_context)
+            return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+    }
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static gboolean
+decode_current_picture(GstVaapiDecoderJpeg *decoder)
+{
+    GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+    GstVaapiPicture * const picture = priv->current_picture;
+    gboolean success = TRUE;
+
+    if (picture) {
+        if (!gst_vaapi_picture_decode(picture))
+            success = FALSE;
+        else if (!gst_vaapi_picture_output(picture))
+            success = FALSE;
+        gst_vaapi_picture_replace(&priv->current_picture, NULL);
+    }
+    return success;
+}
+
+static gboolean
+fill_picture(
+    GstVaapiDecoderJpeg *decoder, 
+    GstVaapiPicture     *picture,
+    GstJpegFrameHdr     *jpeg_frame_hdr
+)
+{
+    VAPictureParameterBufferJPEGBaseline *pic_param = picture->param;
+    guint i;
+
+    g_assert(pic_param);
+
+    memset(pic_param, 0, sizeof(VAPictureParameterBufferJPEGBaseline));
+    pic_param->picture_width    = jpeg_frame_hdr->width;
+    pic_param->picture_height   = jpeg_frame_hdr->height;
+
+    pic_param->num_components   = jpeg_frame_hdr->num_components;
+    if (jpeg_frame_hdr->num_components > 4)
+        return FALSE;
+    for (i = 0; i < pic_param->num_components; i++) {
+        pic_param->components[i].component_id =
+            jpeg_frame_hdr->components[i].identifier;
+        pic_param->components[i].h_sampling_factor =
+            jpeg_frame_hdr->components[i].horizontal_factor;
+        pic_param->components[i].v_sampling_factor =
+            jpeg_frame_hdr->components[i].vertical_factor;
+        pic_param->components[i].quantiser_table_selector =
+            jpeg_frame_hdr->components[i].quant_table_selector;
+    }
+    return TRUE;
+}
+
+static gboolean
+fill_quantization_table(
+    GstVaapiDecoderJpeg *decoder, 
+    GstVaapiPicture     *picture
+)
+{
+    GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+    VAIQMatrixBufferJPEGBaseline *iq_matrix;
+    guint i, j, num_tables;
+
+    if (!priv->has_quant_table)
+        gst_jpeg_get_default_quantization_tables(&priv->quant_tables);
+    
+    picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(JPEGBaseline, decoder);
+    g_assert(picture->iq_matrix);
+    iq_matrix = picture->iq_matrix->param;
+
+    num_tables = MIN(G_N_ELEMENTS(iq_matrix->quantiser_table),
+                     GST_JPEG_MAX_QUANT_ELEMENTS);
+
+    for (i = 0; i < num_tables; i++) {
+        GstJpegQuantTable * const quant_table =
+            &priv->quant_tables.quant_tables[i];
+
+        iq_matrix->load_quantiser_table[i] = quant_table->valid;
+        if (!iq_matrix->load_quantiser_table[i])
+            continue;
+
+        g_assert(quant_table->quant_precision == 0);
+        for (j = 0; j < GST_JPEG_MAX_QUANT_ELEMENTS; j++)
+            iq_matrix->quantiser_table[i][j] = quant_table->quant_table[j];
+        iq_matrix->load_quantiser_table[i] = 1;
+        quant_table->valid = FALSE;
+    }
+    return TRUE;
+}
+
+static gboolean
+fill_huffman_table(
+    GstVaapiDecoderJpeg *decoder, 
+    GstVaapiPicture     *picture
+)
+{
+    GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+    GstJpegHuffmanTables * const huf_tables = &priv->huf_tables;
+    VAHuffmanTableBufferJPEGBaseline *huffman_table;
+    guint i, num_tables;
+
+    if (!priv->has_huf_table)
+        gst_jpeg_get_default_huffman_tables(&priv->huf_tables);
+    
+    picture->huf_table = GST_VAAPI_HUFFMAN_TABLE_NEW(JPEGBaseline, decoder);
+    g_assert(picture->huf_table);
+    huffman_table = picture->huf_table->param;
+
+    num_tables = MIN(G_N_ELEMENTS(huffman_table->huffman_table),
+                     GST_JPEG_MAX_SCAN_COMPONENTS);
+
+    for (i = 0; i < num_tables; i++) {
+        huffman_table->load_huffman_table[i] =
+            huf_tables->dc_tables[i].valid && huf_tables->ac_tables[i].valid;
+        if (!huffman_table->load_huffman_table[i])
+            continue;
+
+        memcpy(huffman_table->huffman_table[i].num_dc_codes,
+               huf_tables->dc_tables[i].huf_bits,
+               sizeof(huffman_table->huffman_table[i].num_dc_codes));
+        memcpy(huffman_table->huffman_table[i].dc_values,
+               huf_tables->dc_tables[i].huf_values,
+               sizeof(huffman_table->huffman_table[i].dc_values));
+        memcpy(huffman_table->huffman_table[i].num_ac_codes,
+               huf_tables->ac_tables[i].huf_bits,
+               sizeof(huffman_table->huffman_table[i].num_ac_codes));
+        memcpy(huffman_table->huffman_table[i].ac_values,
+               huf_tables->ac_tables[i].huf_values,
+               sizeof(huffman_table->huffman_table[i].ac_values));
+        memset(huffman_table->huffman_table[i].pad,
+               0,
+               sizeof(huffman_table->huffman_table[i].pad));
+    }
+    return TRUE;
+}
+
+static guint
+get_max_horizontal_samples(GstJpegFrameHdr *frame_hdr)
+{
+    guint i, max_factor = 0;
+
+    for (i = 0; i < frame_hdr->num_components; i++) {
+        if (frame_hdr->components[i].horizontal_factor > max_factor)
+            max_factor = frame_hdr->components[i].horizontal_factor;
+    }
+    return max_factor;
+}
+
+static guint
+get_max_vertical_samples(GstJpegFrameHdr *frame_hdr)
+{
+    guint i, max_factor = 0;
+
+    for (i = 0; i < frame_hdr->num_components; i++) {
+        if (frame_hdr->components[i].vertical_factor > max_factor)
+            max_factor = frame_hdr->components[i].vertical_factor;
+    }
+    return max_factor;
+}
+
+static GstVaapiDecoderStatus
+decode_picture(
+    GstVaapiDecoderJpeg *decoder, 
+    guint8               profile,
+    guchar              *buf,
+    guint                buf_size,
+    GstClockTime         pts
+)
+{
+    GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+    GstJpegFrameHdr * const frame_hdr = &priv->frame_hdr;
+    GstVaapiPicture *picture;
+    GstVaapiDecoderStatus status;
+
+    switch (profile) {
+    case GST_JPEG_MARKER_SOF_MIN:
+        priv->profile = GST_VAAPI_PROFILE_JPEG_BASELINE;
+        break;
+    default:
+        GST_ERROR("unsupported profile %d", profile);
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
+    }
+
+    memset(frame_hdr, 0, sizeof(*frame_hdr));
+    if (!gst_jpeg_parse_frame_hdr(frame_hdr, buf, buf_size, 0)) {
+        GST_ERROR("failed to parse image");
+        return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+    }
+    priv->height = frame_hdr->height;
+    priv->width  = frame_hdr->width;
+
+    status = ensure_context(decoder);
+    if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
+        GST_ERROR("failed to reset context");
+        return status;
+    }
+
+    if (priv->current_picture && !decode_current_picture(decoder))
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+
+    picture = GST_VAAPI_PICTURE_NEW(JPEGBaseline, decoder);
+    if (!picture) {
+        GST_ERROR("failed to allocate picture");
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+    gst_vaapi_picture_replace(&priv->current_picture, picture);
+    gst_vaapi_picture_unref(picture);
+
+    if (!fill_picture(decoder, picture, frame_hdr))
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+
+    /* Update presentation time */
+    picture->pts = pts;
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_huffman_table(
+    GstVaapiDecoderJpeg *decoder,
+    guchar              *buf,
+    guint                buf_size
+)
+{
+    GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+
+    if (!gst_jpeg_parse_huffman_table(&priv->huf_tables, buf, buf_size, 0)) {
+        GST_DEBUG("failed to parse Huffman table");
+        return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+    }
+    priv->has_huf_table = TRUE;
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_quant_table(
+    GstVaapiDecoderJpeg *decoder,
+    guchar              *buf,
+    guint                buf_size
+)
+{
+    GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+
+    if (!gst_jpeg_parse_quant_table(&priv->quant_tables, buf, buf_size, 0)) {
+        GST_DEBUG("failed to parse quantization table");
+        return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+    }
+    priv->has_quant_table = TRUE;
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_restart_interval(
+    GstVaapiDecoderJpeg *decoder,
+    guchar              *buf,
+    guint                buf_size
+)
+{
+    GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+
+    if (!gst_jpeg_parse_restart_interval(&priv->mcu_restart, buf, buf_size, 0)) {
+        GST_DEBUG("failed to parse restart interval");
+        return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+    }
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_scan(
+    GstVaapiDecoderJpeg *decoder,
+    guchar              *scan_header,
+    guint                scan_header_size,
+    guchar              *scan_data,
+    guint                scan_data_size)
+{
+    GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+    GstVaapiPicture *picture = priv->current_picture;
+    VASliceParameterBufferJPEGBaseline *slice_param;
+    GstVaapiSlice *gst_slice;
+    guint total_h_samples, total_v_samples;
+    GstJpegScanHdr  scan_hdr;
+    guint i;
+
+    if (!picture) {
+        GST_ERROR("There is no VAPicture before decoding scan.");
+        return GST_VAAPI_DECODER_STATUS_ERROR_INVALID_SURFACE;
+    }
+
+    if (!fill_quantization_table(decoder, picture)) {
+        GST_ERROR("failed to fill in quantization table");
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+    }
+
+    if (!fill_huffman_table(decoder, picture)) {
+        GST_ERROR("failed to fill in huffman table");
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+    }
+
+    memset(&scan_hdr, 0, sizeof(scan_hdr));
+    if (!gst_jpeg_parse_scan_hdr(&scan_hdr, scan_header, scan_header_size, 0)) {
+        GST_DEBUG("Jpeg parsed scan failed.");
+        return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+    }
+
+    gst_slice = GST_VAAPI_SLICE_NEW(JPEGBaseline, decoder, scan_data, scan_data_size);
+    gst_vaapi_picture_add_slice(picture, gst_slice);
+
+    slice_param = gst_slice->param;
+    slice_param->num_components = scan_hdr.num_components;
+    for (i = 0; i < scan_hdr.num_components; i++) {
+        slice_param->components[i].component_selector =
+            scan_hdr.components[i].component_selector;
+        slice_param->components[i].dc_table_selector =
+            scan_hdr.components[i].dc_selector;
+        slice_param->components[i].ac_table_selector =
+            scan_hdr.components[i].ac_selector;
+    }
+    slice_param->restart_interval = priv->mcu_restart;
+    if (scan_hdr.num_components == 1) { /*non-interleaved*/
+        slice_param->slice_horizontal_position = 0;
+        slice_param->slice_vertical_position = 0;
+        /* Y mcu numbers*/
+        if (slice_param->components[0].component_selector == priv->frame_hdr.components[0].identifier) {
+            slice_param->num_mcus = (priv->frame_hdr.width/8)*(priv->frame_hdr.height/8);
+        } else { /*Cr, Cb mcu numbers*/
+            slice_param->num_mcus = (priv->frame_hdr.width/16)*(priv->frame_hdr.height/16);
+        }
+    } else { /* interleaved */
+        slice_param->slice_horizontal_position = 0;
+        slice_param->slice_vertical_position = 0;
+        total_v_samples = get_max_vertical_samples(&priv->frame_hdr);
+        total_h_samples = get_max_horizontal_samples(&priv->frame_hdr);
+        slice_param->num_mcus = ((priv->frame_hdr.width + total_h_samples*8 - 1)/(total_h_samples*8)) *
+                                ((priv->frame_hdr.height + total_v_samples*8 -1)/(total_v_samples*8));
+    }
+
+    if (picture->slices && picture->slices->len)
+        return GST_VAAPI_DECODER_STATUS_SUCCESS;
+    return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+}
+
+static GstVaapiDecoderStatus
+decode_buffer(GstVaapiDecoderJpeg *decoder, GstBuffer *buffer)
+{
+    GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+    GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+    GstJpegMarkerSegment seg;
+    GstJpegScanSegment scan_seg;
+    GstClockTime pts;
+    guchar *buf;
+    guint buf_size, ofs;
+    gboolean append_ecs;
+
+    buf      = GST_BUFFER_DATA(buffer);
+    buf_size = GST_BUFFER_SIZE(buffer);
+    if (!buf && buf_size == 0)
+        return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+
+    memset(&scan_seg, 0, sizeof(scan_seg));
+
+    pts = GST_BUFFER_TIMESTAMP(buffer);
+    ofs = 0;
+    while (gst_jpeg_parse(&seg, buf, buf_size, ofs)) {
+        if (seg.size < 0) {
+            GST_DEBUG("buffer to short for parsing");
+            return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+        }
+        ofs += seg.size;
+
+        /* Decode scan, if complete */
+        if (seg.marker == GST_JPEG_MARKER_EOI && scan_seg.header_size > 0) {
+            scan_seg.data_size = seg.offset - scan_seg.data_offset;
+            scan_seg.is_valid  = TRUE;
+        }
+        if (scan_seg.is_valid) {
+            status = decode_scan(
+                decoder,
+                buf + scan_seg.header_offset,
+                scan_seg.header_size,
+                buf + scan_seg.data_offset,
+                scan_seg.data_size
+            );
+            if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+                break;
+            memset(&scan_seg, 0, sizeof(scan_seg));
+        }
+
+        append_ecs = TRUE;
+        switch (seg.marker) {
+        case GST_JPEG_MARKER_SOI:
+            priv->has_quant_table = FALSE;
+            priv->has_huf_table   = FALSE;
+            priv->mcu_restart     = 0;
+            status = GST_VAAPI_DECODER_STATUS_SUCCESS;
+            break;
+        case GST_JPEG_MARKER_EOI:
+            if (decode_current_picture(decoder)) {
+                /* Get out of the loop, trailing data is not needed */
+                status = GST_VAAPI_DECODER_STATUS_SUCCESS;
+                goto end;
+            }
+            status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+            break;
+        case GST_JPEG_MARKER_DHT:
+            status = decode_huffman_table(decoder, buf + seg.offset, seg.size);
+            break;
+        case GST_JPEG_MARKER_DQT:
+            status = decode_quant_table(decoder, buf + seg.offset, seg.size);
+            break;
+        case GST_JPEG_MARKER_DRI:
+            status = decode_restart_interval(decoder, buf + seg.offset, seg.size);
+            break;
+        case GST_JPEG_MARKER_DAC:
+            GST_ERROR("unsupported arithmetic coding mode");
+            status = GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
+            break;
+        case GST_JPEG_MARKER_SOS:
+            scan_seg.header_offset = seg.offset;
+            scan_seg.header_size   = seg.size;
+            scan_seg.data_offset   = seg.offset + seg.size;
+            scan_seg.data_size     = 0;
+            append_ecs             = FALSE;
+            break;
+        default:
+            /* Restart marker */
+            if (seg.marker >= GST_JPEG_MARKER_RST_MIN &&
+                seg.marker <= GST_JPEG_MARKER_RST_MAX) {
+                append_ecs = FALSE;
+                break;
+            }
+
+            /* Frame header */
+            if (seg.marker >= GST_JPEG_MARKER_SOF_MIN &&
+                seg.marker <= GST_JPEG_MARKER_SOF_MAX) {
+                status = decode_picture(
+                    decoder,
+                    seg.marker,
+                    buf + seg.offset, seg.size,
+                    pts
+                );
+                break;
+            }
+
+            /* Application segments */
+            if (seg.marker >= GST_JPEG_MARKER_APP_MIN &&
+                seg.marker <= GST_JPEG_MARKER_APP_MAX) {
+                status = GST_VAAPI_DECODER_STATUS_SUCCESS;
+                break;
+            }
+
+            GST_WARNING("unsupported marker (0x%02x)", seg.marker);
+            status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+            break;
+        }
+
+        /* Append entropy coded segments */
+        if (append_ecs)
+            scan_seg.data_size = seg.offset - scan_seg.data_offset;
+
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            break;
+    }
+end:
+    return status;
+}
+
+GstVaapiDecoderStatus
+gst_vaapi_decoder_jpeg_decode(GstVaapiDecoder *base, GstBuffer *buffer)
+{
+    GstVaapiDecoderJpeg * const decoder = GST_VAAPI_DECODER_JPEG(base);
+    GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+
+    if (!priv->is_opened) {
+        priv->is_opened = gst_vaapi_decoder_jpeg_open(decoder, buffer);
+        if (!priv->is_opened)
+            return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
+    }
+    return decode_buffer(decoder, buffer);
+}
+
+static void
+gst_vaapi_decoder_jpeg_finalize(GObject *object)
+{
+    GstVaapiDecoderJpeg * const decoder = GST_VAAPI_DECODER_JPEG(object);
+
+    gst_vaapi_decoder_jpeg_destroy(decoder);
+
+    G_OBJECT_CLASS(gst_vaapi_decoder_jpeg_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_decoder_jpeg_constructed(GObject *object)
+{
+    GstVaapiDecoderJpeg * const decoder = GST_VAAPI_DECODER_JPEG(object);
+    GstVaapiDecoderJpegPrivate * const priv = decoder->priv;
+    GObjectClass *parent_class;
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_decoder_jpeg_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+
+    priv->is_constructed = gst_vaapi_decoder_jpeg_create(decoder);
+}
+
+static void
+gst_vaapi_decoder_jpeg_class_init(GstVaapiDecoderJpegClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiDecoderJpegPrivate));
+
+    object_class->finalize      = gst_vaapi_decoder_jpeg_finalize;
+    object_class->constructed   = gst_vaapi_decoder_jpeg_constructed;
+
+    decoder_class->decode       = gst_vaapi_decoder_jpeg_decode;
+}
+
+static void
+gst_vaapi_decoder_jpeg_init(GstVaapiDecoderJpeg *decoder)
+{
+    GstVaapiDecoderJpegPrivate *priv;
+
+    priv                        = GST_VAAPI_DECODER_JPEG_GET_PRIVATE(decoder);
+    decoder->priv               = priv;
+    priv->profile               = GST_VAAPI_PROFILE_JPEG_BASELINE;
+    priv->width                 = 0;
+    priv->height                = 0;
+    priv->current_picture       = NULL;
+    priv->has_huf_table         = FALSE;
+    priv->has_quant_table       = FALSE;
+    priv->mcu_restart           = 0;
+    priv->is_opened             = FALSE;
+    priv->profile_changed       = TRUE;
+    priv->is_constructed        = FALSE;
+    memset(&priv->frame_hdr, 0, sizeof(priv->frame_hdr));
+    memset(&priv->huf_tables, 0, sizeof(priv->huf_tables));
+    memset(&priv->quant_tables, 0, sizeof(priv->quant_tables));
+}
+
+/**
+ * gst_vaapi_decoder_jpeg_new:
+ * @display: a #GstVaapiDisplay
+ * @caps: a #GstCaps holding codec information
+ *
+ * Creates a new #GstVaapiDecoder for JPEG decoding.  The @caps can
+ * hold extra information like codec-data and pictured coded size.
+ *
+ * Return value: the newly allocated #GstVaapiDecoder object
+ */
+GstVaapiDecoder *
+gst_vaapi_decoder_jpeg_new(GstVaapiDisplay *display, GstCaps *caps)
+{
+    GstVaapiDecoderJpeg *decoder;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+    g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
+
+    decoder = g_object_new(
+        GST_VAAPI_TYPE_DECODER_JPEG,
+        "display",      display,
+        "caps",         caps,
+        NULL
+    );
+    if (!decoder->priv->is_constructed) {
+        g_object_unref(decoder);
+        return NULL;
+    }
+    return GST_VAAPI_DECODER_CAST(decoder);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_jpeg.h b/gst-libs/gst/vaapi/gstvaapidecoder_jpeg.h
new file mode 100644 (file)
index 0000000..cd3b975
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ *  gstvaapidecoder_jpeg.h - JPEG decoder
+ *
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DECODER_JPEG_H
+#define GST_VAAPI_DECODER_JPEG_H
+
+#include <gst/vaapi/gstvaapidecoder.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_DECODER_JPEG \
+    (gst_vaapi_decoder_jpeg_get_type())
+
+#define GST_VAAPI_DECODER_JPEG(obj)                             \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_DECODER_JPEG,    \
+                                GstVaapiDecoderJpeg))
+
+#define GST_VAAPI_DECODER_JPEG_CLASS(klass)                     \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_DECODER_JPEG,       \
+                             GstVaapiDecoderJpegClass))
+
+#define GST_VAAPI_IS_DECODER_JPEG(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_DECODER_JPEG))
+
+#define GST_VAAPI_IS_DECODER_JPEG_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_DECODER_JPEG))
+
+#define GST_VAAPI_DECODER_JPEG_GET_CLASS(obj)                   \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_DECODER_JPEG,     \
+                               GstVaapiDecoderJpegClass))
+
+typedef struct _GstVaapiDecoderJpeg             GstVaapiDecoderJpeg;
+typedef struct _GstVaapiDecoderJpegPrivate      GstVaapiDecoderJpegPrivate;
+typedef struct _GstVaapiDecoderJpegClass        GstVaapiDecoderJpegClass;
+
+/**
+ * GstVaapiDecoderJpeg:
+ *
+ * A decoder based on Jpeg.
+ */
+struct _GstVaapiDecoderJpeg {
+    /*< private >*/
+    GstVaapiDecoder parent_instance;
+
+    GstVaapiDecoderJpegPrivate *priv;
+};
+
+/**
+ * GstVaapiDecoderJpegClass:
+ *
+ * A decoder class based on Jpeg.
+ */
+struct _GstVaapiDecoderJpegClass {
+    /*< private >*/
+    GstVaapiDecoderClass parent_class;
+};
+
+GType
+gst_vaapi_decoder_jpeg_get_type(void) G_GNUC_CONST;
+
+GstVaapiDecoder *
+gst_vaapi_decoder_jpeg_new(GstVaapiDisplay *display, GstCaps *caps);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DECODER_JPEG_H */
+
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_mpeg2.c b/gst-libs/gst/vaapi/gstvaapidecoder_mpeg2.c
new file mode 100644 (file)
index 0000000..136c9b1
--- /dev/null
@@ -0,0 +1,1202 @@
+/*
+ *  gstvaapidecoder_mpeg2.c - MPEG-2 decoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapidecoder_mpeg2
+ * @short_description: MPEG-2 decoder
+ */
+
+#include "sysdeps.h"
+#include <string.h>
+#include <gst/base/gstbitreader.h>
+#include <gst/codecparsers/gstmpegvideoparser.h>
+#include "gstvaapidecoder_mpeg2.h"
+#include "gstvaapidecoder_objects.h"
+#include "gstvaapidecoder_dpb.h"
+#include "gstvaapidecoder_priv.h"
+#include "gstvaapidisplay_priv.h"
+#include "gstvaapiobject_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiDecoderMpeg2,
+              gst_vaapi_decoder_mpeg2,
+              GST_VAAPI_TYPE_DECODER);
+
+#define GST_VAAPI_DECODER_MPEG2_GET_PRIVATE(obj)                \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_DECODER_MPEG2,  \
+                                 GstVaapiDecoderMpeg2Private))
+
+#define READ_UINT8(br, val, nbits) G_STMT_START {  \
+  if (!gst_bit_reader_get_bits_uint8 (br, &val, nbits)) { \
+    GST_WARNING ("failed to read uint8, nbits: %d", nbits); \
+    goto failed; \
+  } \
+} G_STMT_END
+
+#define SKIP(reader, nbits) G_STMT_START { \
+  if (!gst_bit_reader_skip (reader, nbits)) { \
+    GST_WARNING ("failed to skip nbits: %d", nbits); \
+    goto failed; \
+  } \
+} G_STMT_END
+
+/* PTS Generator */
+typedef struct _PTSGenerator PTSGenerator;
+struct _PTSGenerator {
+    GstClockTime        gop_pts; // Current GOP PTS
+    GstClockTime        max_pts; // Max picture PTS
+    guint               gop_tsn; // Absolute GOP TSN
+    guint               max_tsn; // Max picture TSN, relative to last GOP TSN
+    guint               ovl_tsn; // How many times TSN overflowed since GOP
+    guint               lst_tsn; // Last picture TSN
+    guint               fps_n;
+    guint               fps_d;
+};
+
+static void
+pts_init(PTSGenerator *tsg)
+{
+    tsg->gop_pts = GST_CLOCK_TIME_NONE;
+    tsg->max_pts = GST_CLOCK_TIME_NONE;
+    tsg->gop_tsn = 0;
+    tsg->max_tsn = 0;
+    tsg->ovl_tsn = 0;
+    tsg->lst_tsn = 0;
+    tsg->fps_n   = 0;
+    tsg->fps_d   = 0;
+}
+
+static inline GstClockTime
+pts_get_duration(PTSGenerator *tsg, guint num_frames)
+{
+    return gst_util_uint64_scale(num_frames,
+                                 GST_SECOND * tsg->fps_d, tsg->fps_n);
+}
+
+static inline guint
+pts_get_poc(PTSGenerator *tsg)
+{
+    return tsg->gop_tsn + tsg->ovl_tsn * 1024 + tsg->lst_tsn;
+}
+
+static void
+pts_set_framerate(PTSGenerator *tsg, guint fps_n, guint fps_d)
+{
+    tsg->fps_n = fps_n;
+    tsg->fps_d = fps_d;
+}
+
+static void
+pts_sync(PTSGenerator *tsg, GstClockTime gop_pts)
+{
+    guint gop_tsn;
+
+    if (!GST_CLOCK_TIME_IS_VALID(gop_pts) ||
+        (GST_CLOCK_TIME_IS_VALID(tsg->max_pts) && tsg->max_pts >= gop_pts)) {
+        /* Invalid GOP PTS, interpolate from the last known picture PTS */
+        if (GST_CLOCK_TIME_IS_VALID(tsg->max_pts)) {
+            gop_pts = tsg->max_pts + pts_get_duration(tsg, 1);
+            gop_tsn = tsg->gop_tsn + tsg->ovl_tsn * 1024 + tsg->max_tsn + 1;
+        }
+        else {
+            gop_pts = 0;
+            gop_tsn = 0;
+        }
+    }
+    else {
+        /* Interpolate GOP TSN from this valid PTS */
+        if (GST_CLOCK_TIME_IS_VALID(tsg->gop_pts))
+            gop_tsn = tsg->gop_tsn + gst_util_uint64_scale(
+                gop_pts - tsg->gop_pts + pts_get_duration(tsg, 1) - 1,
+                tsg->fps_n, GST_SECOND * tsg->fps_d);
+        else
+            gop_tsn = 0;
+    }
+
+    tsg->gop_pts = gop_pts;
+    tsg->gop_tsn = gop_tsn;
+    tsg->max_tsn = 0;
+    tsg->ovl_tsn = 0;
+    tsg->lst_tsn = 0;
+}
+
+static GstClockTime
+pts_eval(PTSGenerator *tsg, GstClockTime pic_pts, guint pic_tsn)
+{
+    GstClockTime pts;
+
+    if (!GST_CLOCK_TIME_IS_VALID(tsg->gop_pts))
+        tsg->gop_pts = 0;
+
+    pts = tsg->gop_pts + pts_get_duration(tsg, tsg->ovl_tsn * 1024 + pic_tsn);
+
+    if (!GST_CLOCK_TIME_IS_VALID(tsg->max_pts) || tsg->max_pts < pts)
+        tsg->max_pts = pts;
+
+    if (tsg->max_tsn < pic_tsn)
+        tsg->max_tsn = pic_tsn;
+    else if (tsg->max_tsn == 1023 && pic_tsn < tsg->lst_tsn) { /* TSN wrapped */
+        tsg->max_tsn = pic_tsn;
+        tsg->ovl_tsn++;
+    }
+    tsg->lst_tsn = pic_tsn;
+    return pts;
+}
+
+struct _GstVaapiDecoderMpeg2Private {
+    GstVaapiProfile             profile;
+    GstVaapiProfile             hw_profile;
+    guint                       width;
+    guint                       height;
+    guint                       fps_n;
+    guint                       fps_d;
+    GstMpegVideoSequenceHdr     seq_hdr;
+    GstMpegVideoSequenceExt     seq_ext;
+    GstMpegVideoPictureHdr      pic_hdr;
+    GstMpegVideoPictureExt      pic_ext;
+    GstMpegVideoQuantMatrixExt  quant_matrix_ext;
+    GstVaapiPicture            *current_picture;
+    GstVaapiDpb                *dpb;
+    GstAdapter                 *adapter;
+    PTSGenerator                tsg;
+    guint                       is_constructed          : 1;
+    guint                       is_opened               : 1;
+    guint                       has_seq_ext             : 1;
+    guint                       has_seq_scalable_ext    : 1;
+    guint                       has_pic_ext             : 1;
+    guint                       has_quant_matrix_ext    : 1;
+    guint                       size_changed            : 1;
+    guint                       profile_changed         : 1;
+    guint                       quant_matrix_changed    : 1;
+    guint                       progressive_sequence    : 1;
+    guint                       closed_gop              : 1;
+    guint                       broken_link             : 1;
+};
+
+/* VLC decoder from gst-plugins-bad */
+typedef struct _VLCTable VLCTable;
+struct _VLCTable {
+    gint  value;
+    guint cword;
+    guint cbits;
+};
+
+static gboolean
+decode_vlc(GstBitReader *br, gint *res, const VLCTable *table, guint length)
+{
+    guint8 i;
+    guint cbits = 0;
+    guint32 value = 0;
+
+    for (i = 0; i < length; i++) {
+        if (cbits != table[i].cbits) {
+            cbits = table[i].cbits;
+            if (!gst_bit_reader_peek_bits_uint32(br, &value, cbits)) {
+                goto failed;
+            }
+        }
+
+        if (value == table[i].cword) {
+            SKIP(br, cbits);
+            if (res)
+                *res = table[i].value;
+            return TRUE;
+        }
+    }
+    GST_DEBUG("failed to find VLC code");
+
+failed:
+    GST_WARNING("failed to decode VLC, returning");
+    return FALSE;
+}
+
+enum {
+    GST_MPEG_VIDEO_MACROBLOCK_ESCAPE = -1,
+};
+
+/* Table B-1: Variable length codes for macroblock_address_increment */
+static const VLCTable mpeg2_mbaddr_vlc_table[] = {
+    {  1, 0x01,  1 },
+    {  2, 0x03,  3 },
+    {  3, 0x02,  3 },
+    {  4, 0x03,  4 },
+    {  5, 0x02,  4 },
+    {  6, 0x03,  5 },
+    {  7, 0x02,  5 },
+    {  8, 0x07,  7 },
+    {  9, 0x06,  7 },
+    { 10, 0x0b,  8 },
+    { 11, 0x0a,  8 },
+    { 12, 0x09,  8 },
+    { 13, 0x08,  8 },
+    { 14, 0x07,  8 },
+    { 15, 0x06,  8 },
+    { 16, 0x17, 10 },
+    { 17, 0x16, 10 },
+    { 18, 0x15, 10 },
+    { 19, 0x14, 10 },
+    { 20, 0x13, 10 },
+    { 21, 0x12, 10 },
+    { 22, 0x23, 11 },
+    { 23, 0x22, 11 },
+    { 24, 0x21, 11 },
+    { 25, 0x20, 11 },
+    { 26, 0x1f, 11 },
+    { 27, 0x1e, 11 },
+    { 28, 0x1d, 11 },
+    { 29, 0x1c, 11 },
+    { 30, 0x1b, 11 },
+    { 31, 0x1a, 11 },
+    { 32, 0x19, 11 },
+    { 33, 0x18, 11 },
+    { GST_MPEG_VIDEO_MACROBLOCK_ESCAPE, 0x08, 11 }
+};
+
+static void
+gst_vaapi_decoder_mpeg2_clear_buffer(GstVaapiDecoder *base)
+{
+    GstVaapiDecoderMpeg2* const decoder = GST_VAAPI_DECODER_MPEG2(base);
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+
+    priv->closed_gop            = FALSE;
+    priv->broken_link           = FALSE;
+
+    gst_vaapi_picture_replace(&priv->current_picture, NULL);
+
+    pts_init(&priv->tsg);
+    pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
+
+    if (priv->dpb) {
+        gst_vaapi_dpb_flush(priv->dpb);
+    }
+
+    if (priv->adapter) {
+        gst_adapter_clear(priv->adapter);
+    }
+}
+
+static void
+gst_vaapi_decoder_mpeg2_close(GstVaapiDecoderMpeg2 *decoder)
+{
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+
+    gst_vaapi_picture_replace(&priv->current_picture, NULL);
+
+    if (priv->dpb) {
+        gst_vaapi_dpb_unref(priv->dpb);
+        priv->dpb = NULL;
+    }
+
+    if (priv->adapter) {
+        gst_adapter_clear(priv->adapter);
+        g_object_unref(priv->adapter);
+        priv->adapter = NULL;
+    }
+}
+
+static gboolean
+gst_vaapi_decoder_mpeg2_open(GstVaapiDecoderMpeg2 *decoder, GstBuffer *buffer)
+{
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+
+    gst_vaapi_decoder_mpeg2_close(decoder);
+
+    priv->adapter = gst_adapter_new();
+    if (!priv->adapter)
+       return FALSE;
+
+    priv->dpb = gst_vaapi_dpb_mpeg2_new();
+    if (!priv->dpb)
+        return FALSE;
+
+    pts_init(&priv->tsg);
+    return TRUE;
+}
+
+static void
+gst_vaapi_decoder_mpeg2_destroy(GstVaapiDecoderMpeg2 *decoder)
+{
+    gst_vaapi_decoder_mpeg2_close(decoder);
+}
+
+static gboolean
+gst_vaapi_decoder_mpeg2_create(GstVaapiDecoderMpeg2 *decoder)
+{
+    if (!GST_VAAPI_DECODER_CODEC(decoder))
+        return FALSE;
+    return TRUE;
+}
+
+static inline void
+copy_quant_matrix(guint8 dst[64], const guint8 src[64])
+{
+    memcpy(dst, src, 64);
+}
+
+static const char *
+get_profile_str(GstVaapiProfile profile)
+{
+    char *str;
+
+    switch (profile) {
+    case GST_VAAPI_PROFILE_MPEG2_SIMPLE:    str = "simple";     break;
+    case GST_VAAPI_PROFILE_MPEG2_MAIN:      str = "main";       break;
+    case GST_VAAPI_PROFILE_MPEG2_HIGH:      str = "high";       break;
+    default:                                str = "<unknown>";  break;
+    }
+    return str;
+}
+
+static GstVaapiProfile
+get_profile(GstVaapiDecoderMpeg2 *decoder, GstVaapiEntrypoint entrypoint)
+{
+    GstVaapiDisplay * const va_display = GST_VAAPI_DECODER_DISPLAY(decoder);
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+    GstVaapiProfile profile = priv->profile;
+
+    do {
+        /* Return immediately if the exact same profile was found */
+        if (gst_vaapi_display_has_decoder(va_display, profile, entrypoint))
+            break;
+
+        /* Otherwise, try to map to a higher profile */
+        switch (profile) {
+        case GST_VAAPI_PROFILE_MPEG2_SIMPLE:
+            profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
+            break;
+        case GST_VAAPI_PROFILE_MPEG2_MAIN:
+            profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
+            break;
+        case GST_VAAPI_PROFILE_MPEG2_HIGH:
+            // Try to map to main profile if no high profile specific bits used
+            if (priv->profile == profile    &&
+                !priv->has_seq_scalable_ext &&
+                (priv->has_seq_ext && priv->seq_ext.chroma_format == 1)) {
+                profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
+                break;
+            }
+            // fall-through
+        default:
+            profile = GST_VAAPI_PROFILE_UNKNOWN;
+            break;
+        }
+    } while (profile != GST_VAAPI_PROFILE_UNKNOWN);
+
+    if (profile != priv->profile)
+        GST_INFO("forced %s profile to %s profile",
+                 get_profile_str(priv->profile), get_profile_str(profile));
+    return profile;
+}
+
+static GstVaapiDecoderStatus
+ensure_context(GstVaapiDecoderMpeg2 *decoder)
+{
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+    GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
+    gboolean reset_context = FALSE;
+
+    if (priv->profile_changed) {
+        GST_DEBUG("profile changed");
+        priv->profile_changed = FALSE;
+        reset_context         = TRUE;
+
+        priv->hw_profile = get_profile(decoder, entrypoint);
+        if (priv->hw_profile == GST_VAAPI_PROFILE_UNKNOWN)
+            return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
+    }
+
+    if (priv->size_changed) {
+        GST_DEBUG("size changed");
+        priv->size_changed = FALSE;
+        reset_context      = TRUE;
+    }
+
+    if (reset_context) {
+        reset_context = gst_vaapi_decoder_ensure_context(
+            GST_VAAPI_DECODER(decoder),
+            priv->hw_profile,
+            entrypoint,
+            priv->width,
+            priv->height,
+            GST_DECODER_DEFAULT_SURFACES_COUNT
+        );
+        if (!reset_context)
+            return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+    }
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+ensure_quant_matrix(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
+{
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+    VAIQMatrixBufferMPEG2 *iq_matrix;
+    guint8 *intra_quant_matrix = NULL;
+    guint8 *non_intra_quant_matrix = NULL;
+    guint8 *chroma_intra_quant_matrix = NULL;
+    guint8 *chroma_non_intra_quant_matrix = NULL;
+
+    if (!priv->quant_matrix_changed)
+        return GST_VAAPI_DECODER_STATUS_SUCCESS;
+
+    priv->quant_matrix_changed = FALSE;
+
+    picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(MPEG2, decoder);
+    if (!picture->iq_matrix) {
+        GST_ERROR("failed to allocate IQ matrix");
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+    iq_matrix = picture->iq_matrix->param;
+
+    intra_quant_matrix     = priv->seq_hdr.intra_quantizer_matrix;
+    non_intra_quant_matrix = priv->seq_hdr.non_intra_quantizer_matrix;
+    if (priv->has_quant_matrix_ext) {
+        if (priv->quant_matrix_ext.load_intra_quantiser_matrix)
+            intra_quant_matrix = priv->quant_matrix_ext.intra_quantiser_matrix;
+        if (priv->quant_matrix_ext.load_non_intra_quantiser_matrix)
+            non_intra_quant_matrix = priv->quant_matrix_ext.non_intra_quantiser_matrix;
+        if (priv->quant_matrix_ext.load_chroma_intra_quantiser_matrix)
+            chroma_intra_quant_matrix = priv->quant_matrix_ext.chroma_intra_quantiser_matrix;
+        if (priv->quant_matrix_ext.load_chroma_non_intra_quantiser_matrix)
+            chroma_non_intra_quant_matrix = priv->quant_matrix_ext.chroma_non_intra_quantiser_matrix;
+    }
+
+    iq_matrix->load_intra_quantiser_matrix = intra_quant_matrix != NULL;
+    if (intra_quant_matrix)
+        copy_quant_matrix(iq_matrix->intra_quantiser_matrix,
+                          intra_quant_matrix);
+
+    iq_matrix->load_non_intra_quantiser_matrix = non_intra_quant_matrix != NULL;
+    if (non_intra_quant_matrix)
+        copy_quant_matrix(iq_matrix->non_intra_quantiser_matrix,
+                          non_intra_quant_matrix);
+
+    iq_matrix->load_chroma_intra_quantiser_matrix = chroma_intra_quant_matrix != NULL;
+    if (chroma_intra_quant_matrix)
+        copy_quant_matrix(iq_matrix->chroma_intra_quantiser_matrix,
+                          chroma_intra_quant_matrix);
+
+    iq_matrix->load_chroma_non_intra_quantiser_matrix = chroma_non_intra_quant_matrix != NULL;
+    if (chroma_non_intra_quant_matrix)
+        copy_quant_matrix(iq_matrix->chroma_non_intra_quantiser_matrix,
+                          chroma_non_intra_quant_matrix);
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static gboolean
+decode_current_picture(GstVaapiDecoderMpeg2 *decoder)
+{
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+    GstVaapiPicture * const picture = priv->current_picture;
+
+    if (picture) {
+        if (!gst_vaapi_picture_decode(picture))
+            return FALSE;
+        if (GST_VAAPI_PICTURE_IS_COMPLETE(picture)) {
+            if (!gst_vaapi_dpb_add(priv->dpb, picture))
+                return FALSE;
+            gst_vaapi_picture_replace(&priv->current_picture, NULL);
+        }
+    }
+    return TRUE;
+}
+
+static GstVaapiDecoderStatus
+decode_sequence(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
+{
+    GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+    GstMpegVideoSequenceHdr * const seq_hdr = &priv->seq_hdr;
+
+    if (!gst_mpeg_video_parse_sequence_header(seq_hdr, buf, buf_size, 4)) {
+        GST_ERROR("failed to parse sequence header");
+        return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+    }
+
+    priv->fps_n = seq_hdr->fps_n;
+    priv->fps_d = seq_hdr->fps_d;
+    pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
+    gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
+
+    priv->width                 = seq_hdr->width;
+    priv->height                = seq_hdr->height;
+    priv->has_seq_ext           = FALSE;
+    priv->size_changed          = TRUE;
+    priv->quant_matrix_changed  = TRUE;
+    priv->progressive_sequence  = TRUE;
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_sequence_ext(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
+{
+    GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+    GstMpegVideoSequenceExt * const seq_ext = &priv->seq_ext;
+    GstVaapiProfile profile;
+    guint width, height;
+
+    if (!gst_mpeg_video_parse_sequence_extension(seq_ext, buf, buf_size, 4)) {
+        GST_ERROR("failed to parse sequence-extension");
+        return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+    }
+    priv->has_seq_ext = TRUE;
+    priv->progressive_sequence = seq_ext->progressive;
+    gst_vaapi_decoder_set_interlaced(base_decoder, !priv->progressive_sequence);
+
+    width  = (priv->width  & 0x0fff) | ((guint32)seq_ext->horiz_size_ext << 12);
+    height = (priv->height & 0x0fff) | ((guint32)seq_ext->vert_size_ext  << 12);
+    GST_DEBUG("video resolution %ux%u", width, height);
+
+    if (seq_ext->fps_n_ext && seq_ext->fps_d_ext) {
+        priv->fps_n *= seq_ext->fps_n_ext + 1;
+        priv->fps_d *= seq_ext->fps_d_ext + 1;
+        pts_set_framerate(&priv->tsg, priv->fps_n, priv->fps_d);
+        gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
+    }
+
+    if (priv->width != width) {
+        priv->width = width;
+        priv->size_changed = TRUE;
+    }
+
+    if (priv->height != height) {
+        priv->height = height;
+        priv->size_changed = TRUE;
+    }
+
+    switch (seq_ext->profile) {
+    case GST_MPEG_VIDEO_PROFILE_SIMPLE:
+        profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
+        break;
+    case GST_MPEG_VIDEO_PROFILE_MAIN:
+        profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
+        break;
+    case GST_MPEG_VIDEO_PROFILE_HIGH:
+        profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
+        break;
+    default:
+        GST_ERROR("unsupported profile %d", seq_ext->profile);
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
+    }
+    if (priv->profile != profile) {
+        priv->profile = profile;
+        priv->profile_changed = TRUE;
+    }
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_sequence_end(GstVaapiDecoderMpeg2 *decoder)
+{
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+
+    if (priv->current_picture && !decode_current_picture(decoder))
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+
+    gst_vaapi_dpb_flush(priv->dpb);
+    return GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
+}
+
+static GstVaapiDecoderStatus
+decode_quant_matrix_ext(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
+{
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+    GstMpegVideoQuantMatrixExt * const quant_matrix_ext = &priv->quant_matrix_ext;
+
+    if (!gst_mpeg_video_parse_quant_matrix_extension(quant_matrix_ext, buf, buf_size, 4)) {
+        GST_ERROR("failed to parse quant-matrix-extension");
+        return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+    }
+    priv->has_quant_matrix_ext = TRUE;
+    priv->quant_matrix_changed = TRUE;
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_gop(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
+{
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+    GstMpegVideoGop gop;
+    GstClockTime pts;
+
+    if (!gst_mpeg_video_parse_gop(&gop, buf, buf_size, 4)) {
+        GST_ERROR("failed to parse GOP");
+        return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+    }
+
+    priv->closed_gop  = gop.closed_gop;
+    priv->broken_link = gop.broken_link;
+
+    GST_DEBUG("GOP %02u:%02u:%02u:%02u (closed_gop %d, broken_link %d)",
+              gop.hour, gop.minute, gop.second, gop.frame,
+              priv->closed_gop, priv->broken_link);
+
+    pts = gst_adapter_prev_timestamp(priv->adapter, NULL);
+    pts_sync(&priv->tsg, pts);
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_picture(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
+{
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+    GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr;
+    GstVaapiPicture *picture;
+    GstVaapiDecoderStatus status;
+    GstClockTime pts;
+
+    status = ensure_context(decoder);
+    if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
+        GST_ERROR("failed to reset context");
+        return status;
+    }
+
+    if (priv->current_picture && !decode_current_picture(decoder))
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+
+    if (priv->current_picture) {
+        /* Re-use current picture where the first field was decoded */
+        picture = gst_vaapi_picture_new_field(priv->current_picture);
+        if (!picture) {
+            GST_ERROR("failed to allocate field picture");
+            return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+        }
+    }
+    else {
+        /* Create new picture */
+        picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
+        if (!picture) {
+            GST_ERROR("failed to allocate picture");
+            return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+        }
+    }
+    gst_vaapi_picture_replace(&priv->current_picture, picture);
+    gst_vaapi_picture_unref(picture);
+
+    status = ensure_quant_matrix(decoder, picture);
+    if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
+        GST_ERROR("failed to reset quantizer matrix");
+        return status;
+    }
+
+    if (!gst_mpeg_video_parse_picture_header(pic_hdr, buf, buf_size, 4)) {
+        GST_ERROR("failed to parse picture header");
+        return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+    }
+    priv->has_pic_ext = FALSE;
+
+    switch (pic_hdr->pic_type) {
+    case GST_MPEG_VIDEO_PICTURE_TYPE_I:
+        GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
+        picture->type = GST_VAAPI_PICTURE_TYPE_I;
+        break;
+    case GST_MPEG_VIDEO_PICTURE_TYPE_P:
+        GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
+        picture->type = GST_VAAPI_PICTURE_TYPE_P;
+        break;
+    case GST_MPEG_VIDEO_PICTURE_TYPE_B:
+        picture->type = GST_VAAPI_PICTURE_TYPE_B;
+        break;
+    default:
+        GST_ERROR("unsupported picture type %d", pic_hdr->pic_type);
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+    }
+
+    /* Update presentation time */
+    pts = gst_adapter_prev_timestamp(priv->adapter, NULL);
+    picture->pts = pts_eval(&priv->tsg, pts, pic_hdr->tsn);
+    picture->poc = pts_get_poc(&priv->tsg);
+    return status;
+}
+
+static GstVaapiDecoderStatus
+decode_picture_ext(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
+{
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+    GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext;
+    GstVaapiPicture * const picture = priv->current_picture;
+
+    if (!gst_mpeg_video_parse_picture_extension(pic_ext, buf, buf_size, 4)) {
+        GST_ERROR("failed to parse picture-extension");
+        return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+    }
+    priv->has_pic_ext = TRUE;
+
+    if (priv->progressive_sequence && !pic_ext->progressive_frame) {
+        GST_WARNING("invalid interlaced frame in progressive sequence, fixing");
+        pic_ext->progressive_frame = 1;
+    }
+
+    if (pic_ext->picture_structure == 0 ||
+        (pic_ext->progressive_frame &&
+         pic_ext->picture_structure != GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME)) {
+        GST_WARNING("invalid picture_structure %d, replacing with \"frame\"",
+                    pic_ext->picture_structure);
+        pic_ext->picture_structure = GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME;
+    }
+
+    if (!priv->progressive_sequence && !pic_ext->progressive_frame) {
+        GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_INTERLACED);
+        if (pic_ext->top_field_first)
+            GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_TFF);
+    }
+
+    switch (pic_ext->picture_structure) {
+    case GST_MPEG_VIDEO_PICTURE_STRUCTURE_TOP_FIELD:
+        picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
+        break;
+    case GST_MPEG_VIDEO_PICTURE_STRUCTURE_BOTTOM_FIELD:
+        picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
+        break;
+    case GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME:
+        picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
+        break;
+    }
+
+    /* Allocate dummy picture for first field based I-frame */
+    if (picture->type == GST_VAAPI_PICTURE_TYPE_I &&
+        !GST_VAAPI_PICTURE_IS_FRAME(picture) &&
+        gst_vaapi_dpb_size(priv->dpb) == 0) {
+        GstVaapiPicture *dummy_picture;
+        gboolean success;
+
+        dummy_picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder);
+        if (!dummy_picture) {
+            GST_ERROR("failed to allocate dummy picture");
+            return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+        }
+
+        dummy_picture->type      = GST_VAAPI_PICTURE_TYPE_I;
+        dummy_picture->pts       = GST_CLOCK_TIME_NONE;
+        dummy_picture->poc       = -1;
+        dummy_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
+
+        GST_VAAPI_PICTURE_FLAG_SET(
+            dummy_picture,
+            (GST_VAAPI_PICTURE_FLAG_SKIPPED |
+             GST_VAAPI_PICTURE_FLAG_REFERENCE)
+        );
+
+        success = gst_vaapi_dpb_add(priv->dpb, dummy_picture);
+        gst_vaapi_picture_unref(dummy_picture);
+        if (!success) {
+            GST_ERROR("failed to add dummy picture into DPB");
+            return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+        }
+        GST_INFO("allocated dummy picture for first field based I-frame");
+    }
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static inline guint32
+pack_f_code(guint8 f_code[2][2])
+{
+    return (((guint32)f_code[0][0] << 12) |
+            ((guint32)f_code[0][1] <<  8) |
+            ((guint32)f_code[1][0] <<  4) |
+            (         f_code[1][1]      ));
+}
+
+static gboolean
+fill_picture(GstVaapiDecoderMpeg2 *decoder, GstVaapiPicture *picture)
+{
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+    VAPictureParameterBufferMPEG2 * const pic_param = picture->param;
+    GstMpegVideoPictureHdr * const pic_hdr = &priv->pic_hdr;
+    GstMpegVideoPictureExt * const pic_ext = &priv->pic_ext;
+    GstVaapiPicture *prev_picture, *next_picture;
+
+    if (!priv->has_pic_ext)
+        return FALSE;
+
+    /* Fill in VAPictureParameterBufferMPEG2 */
+    pic_param->horizontal_size                                          = priv->width;
+    pic_param->vertical_size                                            = priv->height;
+    pic_param->forward_reference_picture                                = VA_INVALID_ID;
+    pic_param->backward_reference_picture                               = VA_INVALID_ID;
+    pic_param->picture_coding_type                                      = pic_hdr->pic_type;
+    pic_param->f_code                                                   = pack_f_code(pic_ext->f_code);
+
+#define COPY_FIELD(a, b, f) \
+    pic_param->a.b.f = pic_ext->f
+    pic_param->picture_coding_extension.value                           = 0;
+    pic_param->picture_coding_extension.bits.is_first_field             = GST_VAAPI_PICTURE_IS_FIRST_FIELD(picture);
+    COPY_FIELD(picture_coding_extension, bits, intra_dc_precision);
+    COPY_FIELD(picture_coding_extension, bits, picture_structure);
+    COPY_FIELD(picture_coding_extension, bits, top_field_first);
+    COPY_FIELD(picture_coding_extension, bits, frame_pred_frame_dct);
+    COPY_FIELD(picture_coding_extension, bits, concealment_motion_vectors);
+    COPY_FIELD(picture_coding_extension, bits, q_scale_type);
+    COPY_FIELD(picture_coding_extension, bits, intra_vlc_format);
+    COPY_FIELD(picture_coding_extension, bits, alternate_scan);
+    COPY_FIELD(picture_coding_extension, bits, repeat_first_field);
+    COPY_FIELD(picture_coding_extension, bits, progressive_frame);
+
+    gst_vaapi_dpb_mpeg2_get_references(
+        priv->dpb,
+        picture,
+        &prev_picture,
+        &next_picture
+    );
+
+    switch (pic_hdr->pic_type) {
+    case GST_MPEG_VIDEO_PICTURE_TYPE_B:
+        if (next_picture)
+            pic_param->backward_reference_picture = next_picture->surface_id;
+        if (prev_picture)
+            pic_param->forward_reference_picture = prev_picture->surface_id;
+        else if (!priv->closed_gop)
+            GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_SKIPPED);
+        break;
+    case GST_MPEG_VIDEO_PICTURE_TYPE_P:
+        if (prev_picture)
+            pic_param->forward_reference_picture = prev_picture->surface_id;
+        break;
+    }
+    return TRUE;
+}
+
+static GstVaapiDecoderStatus
+decode_slice(
+    GstVaapiDecoderMpeg2 *decoder,
+    int                   slice_no,
+    guchar               *buf,
+    guint                 buf_size
+)
+{
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+    GstVaapiPicture * const picture = priv->current_picture;
+    GstVaapiSlice *slice;
+    VASliceParameterBufferMPEG2 *slice_param;
+    GstBitReader br;
+    gint mb_x, mb_y, mb_inc;
+    guint macroblock_offset;
+    guint8 slice_vertical_position_extension;
+    guint8 quantiser_scale_code;
+    guint8 intra_slice = 0;
+    guint8 extra_bit_slice, junk8;
+
+    GST_DEBUG("slice %d @ %p, %u bytes)", slice_no, buf, buf_size);
+
+    if (picture->slices->len == 0 && !fill_picture(decoder, picture))
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+
+    slice = GST_VAAPI_SLICE_NEW(MPEG2, decoder, buf, buf_size);
+    if (!slice) {
+        GST_ERROR("failed to allocate slice");
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+    gst_vaapi_picture_add_slice(picture, slice);
+
+    /* Parse slice */
+    gst_bit_reader_init(&br, buf, buf_size);
+    SKIP(&br, 32); /* slice_start_code */
+    if (priv->height > 2800)
+        READ_UINT8(&br, slice_vertical_position_extension, 3);
+    if (priv->has_seq_scalable_ext) {
+        GST_ERROR("failed to parse slice %d. Unsupported sequence_scalable_extension()", slice_no);
+        return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+    }
+    READ_UINT8(&br, quantiser_scale_code, 5);
+    READ_UINT8(&br, extra_bit_slice, 1);
+    if (extra_bit_slice == 1) {
+        READ_UINT8(&br, intra_slice, 1);
+        READ_UINT8(&br, junk8, 7);
+        READ_UINT8(&br, extra_bit_slice, 1);
+        while (extra_bit_slice == 1) {
+            READ_UINT8(&br, junk8, 8);
+            READ_UINT8(&br, extra_bit_slice, 1);
+        }
+    }
+    macroblock_offset = gst_bit_reader_get_pos(&br);
+
+    mb_y = slice_no;
+    mb_x = -1;
+    do {
+        if (!decode_vlc(&br, &mb_inc, mpeg2_mbaddr_vlc_table,
+                        G_N_ELEMENTS(mpeg2_mbaddr_vlc_table))) {
+            GST_WARNING("failed to decode first macroblock_address_increment");
+            goto failed;
+        }
+        mb_x += mb_inc == GST_MPEG_VIDEO_MACROBLOCK_ESCAPE ? 33 : mb_inc;
+    } while (mb_inc == GST_MPEG_VIDEO_MACROBLOCK_ESCAPE);
+
+    /* Fill in VASliceParameterBufferMPEG2 */
+    slice_param                            = slice->param;
+    slice_param->macroblock_offset         = macroblock_offset;
+    slice_param->slice_horizontal_position = mb_x;
+    slice_param->slice_vertical_position   = mb_y;
+    slice_param->quantiser_scale_code      = quantiser_scale_code;
+    slice_param->intra_slice_flag          = intra_slice;
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+
+failed:
+    return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+}
+
+static inline gint
+scan_for_start_code(GstAdapter *adapter, guint ofs, guint size, guint32 *scp)
+{
+    return (gint)gst_adapter_masked_scan_uint32_peek(adapter,
+                                                     0xffffff00, 0x00000100,
+                                                     ofs, size,
+                                                     scp);
+}
+
+static GstVaapiDecoderStatus
+decode_buffer(GstVaapiDecoderMpeg2 *decoder, GstBuffer *buffer)
+{
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+    GstVaapiDecoderStatus status;
+    guchar *buf;
+    guint buf_size, size;
+    guint32 start_code;
+    guint8 type;
+    gint ofs;
+
+    buf      = GST_BUFFER_DATA(buffer);
+    buf_size = GST_BUFFER_SIZE(buffer);
+    if (!buf && buf_size == 0)
+        return decode_sequence_end(decoder);
+
+    gst_adapter_push(priv->adapter, gst_buffer_ref(buffer));
+
+    size   = gst_adapter_available(priv->adapter);
+    status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+    do {
+        if (size < 8)
+            break;
+        ofs = scan_for_start_code(priv->adapter, 0, size, &start_code);
+        if (ofs < 0)
+            break;
+        gst_adapter_flush(priv->adapter, ofs);
+        size -= ofs;
+
+        status = gst_vaapi_decoder_check_status(GST_VAAPI_DECODER(decoder));
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            break;
+
+        if (size < 8)
+            break;
+        ofs = scan_for_start_code(priv->adapter, 4, size - 4, NULL);
+        if (ofs < 0)
+            break;
+        buffer = gst_adapter_take_buffer(priv->adapter, ofs);
+        size -= ofs;
+
+        if (ofs == 4) {
+            // Ignore empty user-data packets
+            if ((start_code & 0xff) == GST_MPEG_VIDEO_PACKET_USER_DATA)
+                continue;
+            GST_ERROR("failed to get a valid packet (SC: 0x%08x)", start_code);
+            status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+            break;
+        }
+
+        buf      = GST_BUFFER_DATA(buffer);
+        buf_size = GST_BUFFER_SIZE(buffer);
+
+        type = start_code & 0xff;
+        switch (type) {
+        case GST_MPEG_VIDEO_PACKET_PICTURE:
+            if (!priv->width || !priv->height)
+                break;
+            status = decode_picture(decoder, buf, buf_size);
+            break;
+        case GST_MPEG_VIDEO_PACKET_SEQUENCE:
+            status = decode_sequence(decoder, buf, buf_size);
+            break;
+        case GST_MPEG_VIDEO_PACKET_EXTENSION: {
+            const guchar id = buf[4] >> 4;
+            switch (id) {
+            case GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE:
+                status = decode_sequence_ext(decoder, buf, buf_size);
+                break;
+            case GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX:
+                status = decode_quant_matrix_ext(decoder, buf, buf_size);
+                break;
+            case GST_MPEG_VIDEO_PACKET_EXT_PICTURE:
+                if (!priv->width || !priv->height)
+                    break;
+                status = decode_picture_ext(decoder, buf, buf_size);
+                break;
+            default:
+                // Ignore unknown extensions
+                GST_WARNING("unsupported start-code extension (0x%02x)", id);
+                break;
+            }
+            break;
+        }
+        case GST_MPEG_VIDEO_PACKET_SEQUENCE_END:
+            status = decode_sequence_end(decoder);
+            break;
+        case GST_MPEG_VIDEO_PACKET_GOP:
+            status = decode_gop(decoder, buf, buf_size);
+            break;
+        case GST_MPEG_VIDEO_PACKET_USER_DATA:
+            // Ignore user-data packets
+            status = GST_VAAPI_DECODER_STATUS_SUCCESS;
+            break;
+        default:
+            if (type >= GST_MPEG_VIDEO_PACKET_SLICE_MIN &&
+                type <= GST_MPEG_VIDEO_PACKET_SLICE_MAX) {
+                if (!priv->current_picture)
+                    break;
+                status = decode_slice(
+                    decoder,
+                    type - GST_MPEG_VIDEO_PACKET_SLICE_MIN,
+                    buf, buf_size
+                );
+                break;
+            }
+            else if (type >= 0xb9 && type <= 0xff) {
+                // Ignore system start codes (PES headers)
+                status = GST_VAAPI_DECODER_STATUS_SUCCESS;
+                break;
+            }
+            GST_WARNING("unsupported start code (0x%02x)", type);
+            status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+            break;
+        }
+        gst_buffer_unref(buffer);
+    } while (status == GST_VAAPI_DECODER_STATUS_SUCCESS);
+    return status;
+}
+
+GstVaapiDecoderStatus
+gst_vaapi_decoder_mpeg2_decode(GstVaapiDecoder *base, GstBuffer *buffer)
+{
+    GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2(base);
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+
+    g_return_val_if_fail(priv->is_constructed,
+                         GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED);
+
+    if (!priv->is_opened) {
+        priv->is_opened = gst_vaapi_decoder_mpeg2_open(decoder, buffer);
+        if (!priv->is_opened)
+            return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
+    }
+    return decode_buffer(decoder, buffer);
+}
+
+static void
+gst_vaapi_decoder_mpeg2_finalize(GObject *object)
+{
+    GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2(object);
+
+    gst_vaapi_decoder_mpeg2_destroy(decoder);
+
+    G_OBJECT_CLASS(gst_vaapi_decoder_mpeg2_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_decoder_mpeg2_constructed(GObject *object)
+{
+    GstVaapiDecoderMpeg2 * const decoder = GST_VAAPI_DECODER_MPEG2(object);
+    GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
+    GObjectClass *parent_class;
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_decoder_mpeg2_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+
+    priv->is_constructed = gst_vaapi_decoder_mpeg2_create(decoder);
+}
+
+static void
+gst_vaapi_decoder_mpeg2_class_init(GstVaapiDecoderMpeg2Class *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiDecoderMpeg2Private));
+
+    object_class->finalize      = gst_vaapi_decoder_mpeg2_finalize;
+    object_class->constructed   = gst_vaapi_decoder_mpeg2_constructed;
+
+    decoder_class->decode       = gst_vaapi_decoder_mpeg2_decode;
+    decoder_class->clear_buffer = gst_vaapi_decoder_mpeg2_clear_buffer;
+}
+
+static void
+gst_vaapi_decoder_mpeg2_init(GstVaapiDecoderMpeg2 *decoder)
+{
+    GstVaapiDecoderMpeg2Private *priv;
+
+    priv                        = GST_VAAPI_DECODER_MPEG2_GET_PRIVATE(decoder);
+    decoder->priv               = priv;
+    priv->width                 = 0;
+    priv->height                = 0;
+    priv->fps_n                 = 0;
+    priv->fps_d                 = 0;
+    priv->hw_profile            = GST_VAAPI_PROFILE_UNKNOWN;
+    priv->profile               = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
+    priv->current_picture       = NULL;
+    priv->adapter               = NULL;
+    priv->is_constructed        = FALSE;
+    priv->is_opened             = FALSE;
+    priv->has_seq_ext           = FALSE;
+    priv->has_seq_scalable_ext  = FALSE;
+    priv->has_pic_ext           = FALSE;
+    priv->has_quant_matrix_ext  = FALSE;
+    priv->size_changed          = FALSE;
+    priv->profile_changed       = TRUE; /* Allow fallbacks to work */
+    priv->quant_matrix_changed  = FALSE;
+    priv->progressive_sequence  = FALSE;
+    priv->closed_gop            = FALSE;
+    priv->broken_link           = FALSE;
+}
+
+/**
+ * gst_vaapi_decoder_mpeg2_new:
+ * @display: a #GstVaapiDisplay
+ * @caps: a #GstCaps holding codec information
+ *
+ * Creates a new #GstVaapiDecoder for MPEG-2 decoding.  The @caps can
+ * hold extra information like codec-data and pictured coded size.
+ *
+ * Return value: the newly allocated #GstVaapiDecoder object
+ */
+GstVaapiDecoder *
+gst_vaapi_decoder_mpeg2_new(GstVaapiDisplay *display, GstCaps *caps)
+{
+    GstVaapiDecoderMpeg2 *decoder;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+    g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
+
+    decoder = g_object_new(
+        GST_VAAPI_TYPE_DECODER_MPEG2,
+        "display",      display,
+        "caps",         caps,
+        NULL
+    );
+    if (!decoder->priv->is_constructed) {
+        g_object_unref(decoder);
+        return NULL;
+    }
+    return GST_VAAPI_DECODER_CAST(decoder);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_mpeg2.h b/gst-libs/gst/vaapi/gstvaapidecoder_mpeg2.h
new file mode 100644 (file)
index 0000000..e438c39
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ *  gstvaapidecoder_mpeg2.h - MPEG-2 decoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DECODER_MPEG2_H
+#define GST_VAAPI_DECODER_MPEG2_H
+
+#include <gst/vaapi/gstvaapidecoder.h>
+#include <gst/base/gstadapter.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_DECODER_MPEG2 \
+    (gst_vaapi_decoder_mpeg2_get_type())
+
+#define GST_VAAPI_DECODER_MPEG2(obj)                            \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_DECODER_MPEG2,   \
+                                GstVaapiDecoderMpeg2))
+
+#define GST_VAAPI_DECODER_MPEG2_CLASS(klass)                    \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_DECODER_MPEG2,      \
+                             GstVaapiDecoderMpeg2Class))
+
+#define GST_VAAPI_IS_DECODER_MPEG2(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_DECODER_MPEG2))
+
+#define GST_VAAPI_IS_DECODER_MPEG2_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_DECODER_MPEG2))
+
+#define GST_VAAPI_DECODER_MPEG2_GET_CLASS(obj)                  \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_DECODER_MPEG2,    \
+                               GstVaapiDecoderMpeg2Class))
+
+typedef struct _GstVaapiDecoderMpeg2            GstVaapiDecoderMpeg2;
+typedef struct _GstVaapiDecoderMpeg2Private     GstVaapiDecoderMpeg2Private;
+typedef struct _GstVaapiDecoderMpeg2Class       GstVaapiDecoderMpeg2Class;
+
+/**
+ * GstVaapiDecoderMpeg2:
+ *
+ * A decoder based on Mpeg2.
+ */
+struct _GstVaapiDecoderMpeg2 {
+    /*< private >*/
+    GstVaapiDecoder parent_instance;
+
+    GstVaapiDecoderMpeg2Private *priv;
+};
+
+/**
+ * GstVaapiDecoderMpeg2Class:
+ *
+ * A decoder class based on Mpeg2.
+ */
+struct _GstVaapiDecoderMpeg2Class {
+    /*< private >*/
+    GstVaapiDecoderClass parent_class;
+};
+
+GType
+gst_vaapi_decoder_mpeg2_get_type(void) G_GNUC_CONST;
+
+GstVaapiDecoder *
+gst_vaapi_decoder_mpeg2_new(GstVaapiDisplay *display, GstCaps *caps);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DECODER_MPEG2_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_mpeg4.c b/gst-libs/gst/vaapi/gstvaapidecoder_mpeg4.c
new file mode 100644 (file)
index 0000000..4b4279b
--- /dev/null
@@ -0,0 +1,1205 @@
+/*
+ *  gstvaapidecoder_mpeg4.c - MPEG-4 decoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapidecoder_mpeg4
+ * @short_description: MPEG-4 decoder, include h263/divx/xvid support
+ */
+
+#include "sysdeps.h"
+#include <string.h>
+#include <stdlib.h>
+#include <gst/base/gstbitreader.h>
+#include <gst/codecparsers/gstmpeg4parser.h>
+#include "gstvaapidecoder_mpeg4.h"
+#include "gstvaapidecoder_objects.h"
+#include "gstvaapidecoder_priv.h"
+#include "gstvaapidisplay_priv.h"
+#include "gstvaapiobject_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiDecoderMpeg4,
+              gst_vaapi_decoder_mpeg4,
+              GST_VAAPI_TYPE_DECODER);
+
+#define GST_VAAPI_DECODER_MPEG4_GET_PRIVATE(obj)                \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_DECODER_MPEG4,  \
+                                 GstVaapiDecoderMpeg4Private))
+
+struct _GstVaapiDecoderMpeg4Private {
+    GstVaapiProfile                 profile;
+    guint                           level; 
+    guint                           width; 
+    guint                           height;
+    guint                           fps_n;
+    guint                           fps_d; 
+    guint                           coding_type;
+    GstMpeg4VisualObjectSequence    vos_hdr;
+    GstMpeg4VisualObject            vo_hdr;
+    GstMpeg4VideoSignalType         signal_type;
+    GstMpeg4VideoObjectLayer        vol_hdr;
+    GstMpeg4VideoObjectPlane        vop_hdr;
+    GstMpeg4VideoPlaneShortHdr      svh_hdr;
+    GstMpeg4VideoPacketHdr          packet_hdr;
+    GstMpeg4SpriteTrajectory        sprite_trajectory;
+    VAIQMatrixBufferMPEG4           iq_matrix;
+    GstVaapiPicture                *curr_picture;
+    // forward reference pic
+    GstVaapiPicture                *next_picture;
+    // backward reference pic
+    GstVaapiPicture                *prev_picture;
+    GstAdapter                     *adapter;
+    GstBuffer                      *sub_buffer;
+    GstClockTime                    seq_pts;
+    GstClockTime                    gop_pts;
+    GstClockTime                    pts_diff;
+    GstClockTime                    max_pts;
+    // anchor sync time base for any picture type, 
+    // it is time base of backward reference frame
+    GstClockTime                    last_sync_time; 
+    // time base for recent I/P/S frame, 
+    // it is time base of forward reference frame for B frame
+    GstClockTime                    sync_time; 
+
+    /* last non-b-frame time by resolution */
+    GstClockTime                    last_non_b_scale_time;
+    GstClockTime                    non_b_scale_time;
+    GstClockTime                    trb;
+    GstClockTime                    trd;
+    // temporal_reference of previous frame of svh
+    guint8                          prev_t_ref;
+    guint                           is_constructed          : 1;
+    guint                           is_opened               : 1;
+    guint                           is_first_field          : 1;
+    guint                           size_changed            : 1;
+    guint                           profile_changed         : 1;
+    guint                           progressive_sequence    : 1;
+    guint                           closed_gop              : 1;
+    guint                           broken_link             : 1;
+    guint                           calculate_pts_diff      : 1;
+    guint                           is_svh                  : 1;
+};
+
+static void
+gst_vaapi_decoder_mpeg4_clear_buffer(GstVaapiDecoder *base)
+{
+    GstVaapiDecoderMpeg4* const decoder = GST_VAAPI_DECODER_MPEG4(base);
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+
+    priv->seq_pts               = GST_CLOCK_TIME_NONE;
+    priv->gop_pts               = GST_CLOCK_TIME_NONE;
+    priv->max_pts               = GST_CLOCK_TIME_NONE;
+    priv->pts_diff              = 0;
+    priv->prev_t_ref            = -1;
+    priv->calculate_pts_diff    = TRUE;
+    priv->is_first_field        = FALSE;
+    priv->closed_gop            = FALSE;
+    priv->broken_link           = FALSE;
+    priv->last_non_b_scale_time = 0;
+    priv->non_b_scale_time      = 0;
+    priv->trb                   = 0;
+    priv->trd                   = 0;
+
+    gst_vaapi_picture_replace(&priv->curr_picture, NULL);
+    gst_vaapi_picture_replace(&priv->next_picture, NULL);
+    gst_vaapi_picture_replace(&priv->prev_picture, NULL);
+
+    if (priv->sub_buffer) {
+        gst_buffer_unref(priv->sub_buffer);
+        priv->sub_buffer = NULL;
+    }
+
+    if (priv->adapter) {
+        gst_adapter_clear(priv->adapter);
+    }
+}
+
+static void
+gst_vaapi_decoder_mpeg4_close(GstVaapiDecoderMpeg4 *decoder)
+{
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+
+    gst_vaapi_decoder_mpeg4_clear_buffer(GST_VAAPI_DECODER_CAST(decoder));
+
+    if (priv->adapter) {
+        g_object_unref(priv->adapter);
+        priv->adapter = NULL;
+    }
+}
+
+static gboolean
+gst_vaapi_decoder_mpeg4_open(GstVaapiDecoderMpeg4 *decoder, GstBuffer *buffer)
+{
+    GstVaapiDecoder *const base_decoder = GST_VAAPI_DECODER(decoder);
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+    GstCaps *caps = NULL;
+    GstStructure *structure = NULL;
+
+    gst_vaapi_decoder_mpeg4_close(decoder);
+
+    priv->adapter = gst_adapter_new();
+    if (!priv->adapter)
+        return FALSE;
+
+    priv->is_svh = 0;
+    caps = gst_vaapi_decoder_get_caps(base_decoder);
+    if (caps) {
+        structure = gst_caps_get_structure(caps, 0);
+        if (structure) {
+            if (gst_structure_has_name(structure, "video/x-h263")) {
+                priv->is_svh = 1;
+                priv->profile = GST_VAAPI_PROFILE_MPEG4_SIMPLE;
+                priv->prev_t_ref = -1;
+            }
+        }
+    }
+    return TRUE;
+}
+
+static void
+gst_vaapi_decoder_mpeg4_destroy(GstVaapiDecoderMpeg4 *decoder)
+{
+    gst_vaapi_decoder_mpeg4_close(decoder);
+}
+
+static gboolean
+gst_vaapi_decoder_mpeg4_create(GstVaapiDecoderMpeg4 *decoder)
+{
+    if (!GST_VAAPI_DECODER_CODEC(decoder))
+        return FALSE;
+    return TRUE;
+}
+
+static inline void
+copy_quant_matrix(guint8 dst[64], const guint8 src[64])
+{
+    memcpy(dst, src, 64);
+}
+
+static GstVaapiDecoderStatus
+ensure_context(GstVaapiDecoderMpeg4 *decoder)
+{
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+    GstVaapiProfile profiles[2];
+    GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
+    guint i, n_profiles = 0;
+    gboolean reset_context = FALSE;
+
+    if (priv->profile_changed) {
+        GST_DEBUG("profile changed");
+        priv->profile_changed = FALSE;
+        reset_context         = TRUE;
+
+        profiles[n_profiles++] = priv->profile;
+        if (priv->profile == GST_VAAPI_PROFILE_MPEG4_SIMPLE)
+            profiles[n_profiles++] = GST_VAAPI_PROFILE_MPEG4_ADVANCED_SIMPLE;
+
+        for (i = 0; i < n_profiles; i++) {
+            if (gst_vaapi_display_has_decoder(GST_VAAPI_DECODER_DISPLAY(decoder),
+                                              profiles[i], entrypoint))
+                break;
+        }
+        if (i == n_profiles)
+            return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
+        priv->profile = profiles[i];
+    }
+
+    if (priv->size_changed) {
+        GST_DEBUG("size changed");
+        priv->size_changed = FALSE;
+        reset_context      = TRUE;
+    }
+
+    if (reset_context) {
+        reset_context = gst_vaapi_decoder_ensure_context(
+            GST_VAAPI_DECODER(decoder),
+            priv->profile,
+            entrypoint,
+            priv->width,
+            priv->height,
+            GST_DECODER_DEFAULT_SURFACES_COUNT
+        );
+        if (!reset_context)
+            return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+    }
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+ensure_quant_matrix(GstVaapiDecoderMpeg4 *decoder, GstVaapiPicture *picture)
+{
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+    VAIQMatrixBufferMPEG4 *iq_matrix;
+
+    if (!priv->vol_hdr.load_intra_quant_mat && !priv->vol_hdr.load_non_intra_quant_mat) {
+            return GST_VAAPI_DECODER_STATUS_SUCCESS;
+    }
+
+    picture->iq_matrix = GST_VAAPI_IQ_MATRIX_NEW(MPEG4, decoder);
+    if (!picture->iq_matrix) {
+        GST_DEBUG("failed to allocate IQ matrix");
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+    iq_matrix = picture->iq_matrix->param;
+
+    if (priv->vol_hdr.load_intra_quant_mat) {
+        iq_matrix->load_intra_quant_mat = 1;
+        copy_quant_matrix(iq_matrix->intra_quant_mat,
+                          priv->vol_hdr.intra_quant_mat);
+    }
+    else
+        iq_matrix->load_intra_quant_mat = 0;
+
+    if (priv->vol_hdr.load_non_intra_quant_mat) {
+        iq_matrix->load_non_intra_quant_mat = 1;
+        copy_quant_matrix(iq_matrix->non_intra_quant_mat,
+                      priv->vol_hdr.non_intra_quant_mat);
+    }
+    else
+        iq_matrix->load_non_intra_quant_mat = 0;
+    
+
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static inline GstVaapiDecoderStatus
+render_picture(GstVaapiDecoderMpeg4 *decoder, GstVaapiPicture *picture)
+{
+    if (!gst_vaapi_picture_output(picture))
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+/* decode_picture() start to decode a frame/picture
+ * decode_current_picture() finishe decoding a frame/picture 
+ * (commit buffer to driver for decoding)
+ */
+static GstVaapiDecoderStatus
+decode_current_picture(GstVaapiDecoderMpeg4 *decoder)
+{
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+    GstVaapiPicture * const picture = priv->curr_picture;
+    GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_SUCCESS;
+
+    if (picture) {
+        if (!gst_vaapi_picture_decode(picture))
+            status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+        if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture)) {
+            if ((priv->prev_picture && priv->next_picture) ||
+                (priv->closed_gop && priv->next_picture))
+                status = render_picture(decoder, picture);
+        }
+        gst_vaapi_picture_replace(&priv->curr_picture, NULL);
+    }
+    return status;
+}
+
+static GstVaapiDecoderStatus
+decode_sequence(GstVaapiDecoderMpeg4 *decoder, const guint8 *buf, guint buf_size)
+{
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+    GstMpeg4VisualObjectSequence * const vos_hdr = &priv->vos_hdr;
+    GstVaapiProfile profile;
+
+    if (gst_mpeg4_parse_visual_object_sequence(vos_hdr, buf, buf_size) != GST_MPEG4_PARSER_OK) {
+        GST_DEBUG("failed to parse sequence header");
+        return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+    }
+
+    priv->level = vos_hdr->level;
+    switch (vos_hdr->profile) {
+    case GST_MPEG4_PROFILE_SIMPLE:
+        profile = GST_VAAPI_PROFILE_MPEG4_SIMPLE;
+        break;
+    case GST_MPEG4_PROFILE_ADVANCED_SIMPLE:
+    case GST_MPEG4_PROFILE_SIMPLE_SCALABLE: /* shared profile with ADVANCED_SIMPLE */
+        profile = GST_VAAPI_PROFILE_MPEG4_ADVANCED_SIMPLE;
+        break;
+    default:
+        GST_DEBUG("unsupported profile %d", profile);
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
+    }
+    if (priv->profile != profile) {
+        priv->profile = profile;
+        priv->profile_changed = TRUE;
+    }
+    priv->seq_pts = gst_adapter_prev_timestamp(priv->adapter, NULL);
+    priv->size_changed          = TRUE;
+
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_sequence_end(GstVaapiDecoderMpeg4 *decoder)
+{
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+    GstVaapiDecoderStatus status;
+
+    if (priv->curr_picture) {
+        status = decode_current_picture(decoder);
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            return status;
+        status = render_picture(decoder, priv->curr_picture);
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            return status;
+    }
+
+    if (priv->next_picture) {
+        status = render_picture(decoder, priv->next_picture);
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            return status;
+    }
+    return GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
+}
+
+static GstVaapiDecoderStatus
+decode_visual_object(GstVaapiDecoderMpeg4 *decoder, const guint8 *buf, guint buf_size)
+{
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+    GstMpeg4VisualObject * vo_hdr = &priv->vo_hdr;
+    GstMpeg4VideoSignalType * signal_type = &priv->signal_type;
+
+    if (gst_mpeg4_parse_visual_object (vo_hdr, signal_type, buf, buf_size) != GST_MPEG4_PARSER_OK) {
+        GST_DEBUG("failed to parse visual object");
+        return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+    }
+
+    /* XXX: video_signal_type isn't used for decoding */
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_video_object_layer(GstVaapiDecoderMpeg4 *decoder, const guint8 *buf, guint buf_size)
+{
+    GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+    GstMpeg4VisualObject * vo_hdr = &priv->vo_hdr;
+    GstMpeg4VideoObjectLayer * vol_hdr = &priv->vol_hdr;
+
+    if (gst_mpeg4_parse_video_object_layer (vol_hdr, vo_hdr, buf, buf_size) != GST_MPEG4_PARSER_OK) {
+        GST_DEBUG("failed to parse video object layer");
+        return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+    }
+
+    priv->width  = vol_hdr->width;
+    priv->height = vol_hdr->height;
+
+    priv->progressive_sequence  = !vol_hdr->interlaced;
+
+    if (vol_hdr->fixed_vop_rate) {
+        priv->fps_n = vol_hdr->vop_time_increment_resolution;
+        priv->fps_d = vol_hdr->fixed_vop_time_increment;
+        gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);    
+    }
+
+    gst_vaapi_decoder_set_pixel_aspect_ratio(base_decoder, priv->vol_hdr.par_width, priv->vol_hdr.par_height);
+    gst_vaapi_decoder_set_picture_size(base_decoder, priv->width, priv->height);
+
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_gop(GstVaapiDecoderMpeg4 *decoder, const guint8 *buf, guint buf_size)
+{
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+    GstMpeg4GroupOfVOP gop;
+    GstClockTime gop_time;
+
+    if (buf_size >4) {
+        if (gst_mpeg4_parse_group_of_vop(&gop, buf, buf_size) != GST_MPEG4_PARSER_OK) {
+        GST_DEBUG("failed to parse GOP");
+        return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+        }
+    }
+    else {
+        gop.closed          = 1;
+        gop.broken_link     = 0;
+        gop.hours           = 0;
+        gop.minutes         = 0;
+        gop.seconds         = 0;
+    }
+
+    priv->closed_gop  = gop.closed;
+    priv->broken_link = gop.broken_link;
+
+    GST_DEBUG("GOP %02u:%02u:%02u (closed_gop %d, broken_link %d)",
+              gop.hours, gop.minutes, gop.seconds,
+              priv->closed_gop, priv->broken_link);
+
+    gop_time             = gop.hours * 3600 + gop.minutes * 60 + gop.seconds;
+    priv->last_sync_time = gop_time;
+    priv->sync_time      = gop_time;
+    
+    if (priv->gop_pts != GST_CLOCK_TIME_NONE)
+        priv->pts_diff += gop_time * GST_SECOND - priv->gop_pts;
+    priv->gop_pts = gop_time * GST_SECOND;
+    priv->calculate_pts_diff = TRUE;
+    priv->is_first_field = TRUE;
+
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+void
+calculate_pts_diff(GstVaapiDecoderMpeg4 *decoder,
+                      GstMpeg4VideoObjectLayer *vol_hdr,
+                      GstMpeg4VideoObjectPlane *vop_hdr)
+{
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+    GstClockTime frame_timestamp;
+
+    frame_timestamp = gst_adapter_prev_timestamp(priv->adapter, NULL);
+    if (frame_timestamp && frame_timestamp != GST_CLOCK_TIME_NONE) {
+        /* Buffer with timestamp */
+        if (priv->max_pts != GST_CLOCK_TIME_NONE &&
+            frame_timestamp < priv->max_pts) {
+            frame_timestamp = priv->max_pts +
+                gst_util_uint64_scale((vol_hdr->fixed_vop_rate ?
+                                       vol_hdr->fixed_vop_time_increment : 1),
+                                      GST_SECOND,
+                                      vol_hdr->vop_time_increment_resolution);
+        }
+    } else {
+        /* Buffer without timestamp set */
+        if (priv->max_pts == GST_CLOCK_TIME_NONE) /* first buffer */
+            frame_timestamp = 0;
+        else {
+            GstClockTime tmp_pts;
+            tmp_pts = priv->pts_diff + priv->gop_pts +
+                vop_hdr->modulo_time_base * GST_SECOND +
+                gst_util_uint64_scale(vop_hdr->time_increment,
+                                      GST_SECOND,
+                                      vol_hdr->vop_time_increment_resolution);
+            if (tmp_pts > priv->max_pts)
+                frame_timestamp = tmp_pts;
+            else
+                frame_timestamp = priv->max_pts +
+                    gst_util_uint64_scale((vol_hdr->fixed_vop_rate ?
+                                           vol_hdr->fixed_vop_time_increment : 1),
+                                           GST_SECOND,
+                                          vol_hdr->vop_time_increment_resolution);
+        }
+    }
+
+    priv->pts_diff = frame_timestamp -
+        (priv->gop_pts + vop_hdr->modulo_time_base * GST_SECOND +
+         gst_util_uint64_scale(vop_hdr->time_increment, GST_SECOND,
+                               vol_hdr->vop_time_increment_resolution));
+}
+static GstVaapiDecoderStatus
+decode_picture(GstVaapiDecoderMpeg4 *decoder, const guint8 *buf, guint buf_size)
+{
+    GstMpeg4ParseResult parser_result = GST_MPEG4_PARSER_OK;
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+    GstMpeg4VideoObjectPlane * const vop_hdr = &priv->vop_hdr;
+    GstMpeg4VideoObjectLayer * const vol_hdr = &priv->vol_hdr;
+    GstMpeg4SpriteTrajectory * const sprite_trajectory = &priv->sprite_trajectory;
+    GstVaapiPicture *picture;
+    GstVaapiDecoderStatus status;
+    GstClockTime pts;
+
+    // context depends on priv->width and priv->height, so we move parse_vop a little earlier
+    if (priv->is_svh) {
+        parser_result = gst_mpeg4_parse_video_plane_short_header(&priv->svh_hdr, buf, buf_size);
+
+    }
+    else {
+        parser_result = gst_mpeg4_parse_video_object_plane(vop_hdr, sprite_trajectory, vol_hdr, buf, buf_size);
+        /* Need to skip this frame if VOP was not coded */
+        if (GST_MPEG4_PARSER_OK == parser_result && !vop_hdr->coded)
+            return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+    }
+
+    if (parser_result != GST_MPEG4_PARSER_OK) {
+        GST_DEBUG("failed to parse picture header");
+        return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+    }
+
+    if (priv->is_svh) {
+        priv->width = priv->svh_hdr.vop_width;
+        priv->height = priv->svh_hdr.vop_height;
+    }
+    else {
+        if (!vop_hdr->width && !vop_hdr->height) {
+            vop_hdr->width = vol_hdr->width;
+            vop_hdr->height = vol_hdr->height;
+        }
+        priv->width = vop_hdr->width;
+        priv->height = vop_hdr->height;
+    }
+
+    status = ensure_context(decoder);
+    if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
+        GST_DEBUG("failed to reset context");
+        return status;
+    }
+
+    if (priv->curr_picture) {
+        status = decode_current_picture(decoder);
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            return status;
+    }
+
+    priv->curr_picture = GST_VAAPI_PICTURE_NEW(MPEG4, decoder);
+    if (!priv->curr_picture) {
+        GST_DEBUG("failed to allocate picture");
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+    picture = priv->curr_picture;
+
+    status = ensure_quant_matrix(decoder, picture);
+    if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
+        GST_DEBUG("failed to reset quantizer matrix");
+        return status;
+    }
+
+    /* 7.6.7 Temporal prediction structure
+     * forward reference frame     B B B B B B      backward reference frame
+     *            |                                              |
+     *  nearest I/P/S in the past with vop_coded ==1             |
+     *                         nearest I/P/S in the future with any vop_coded
+     * fixme, it said that B frame shouldn't use backward reference frame 
+     *        when backward reference frame coded is 0
+     */
+    if (priv->is_svh) {
+        priv->coding_type = priv->svh_hdr.picture_coding_type;
+    }
+    else {
+        priv->coding_type = priv->vop_hdr.coding_type;
+    }
+    switch (priv->coding_type) {
+    case GST_MPEG4_I_VOP:
+        picture->type = GST_VAAPI_PICTURE_TYPE_I;
+        if (priv->is_svh || vop_hdr->coded) 
+            GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
+        break;
+    case GST_MPEG4_P_VOP:
+        picture->type = GST_VAAPI_PICTURE_TYPE_P;
+        if (priv->is_svh || vop_hdr->coded) 
+            GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
+        break;
+    case GST_MPEG4_B_VOP:
+        picture->type = GST_VAAPI_PICTURE_TYPE_B;
+        break;
+    case GST_MPEG4_S_VOP:
+        picture->type = GST_VAAPI_PICTURE_TYPE_S;
+        // see 3.175 reference VOP
+        if (vop_hdr->coded) 
+            GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
+        break;
+    default:
+        GST_DEBUG("unsupported picture type %d", priv->coding_type);
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+    }
+
+    if (!priv->is_svh && !vop_hdr->coded) {
+        status = render_picture(decoder, priv->prev_picture);
+        return status;
+    }
+
+    if (priv->is_svh) {
+        if (priv->calculate_pts_diff) {
+            priv->prev_t_ref = priv->svh_hdr.temporal_reference;
+            priv->sync_time = gst_adapter_prev_timestamp(priv->adapter, NULL);
+            if (priv->sync_time == GST_CLOCK_TIME_NONE)
+                priv->sync_time = 0;
+            priv->calculate_pts_diff = FALSE;
+        }
+
+        pts = gst_adapter_prev_timestamp(priv->adapter, NULL);
+        if (pts == GST_CLOCK_TIME_NONE) { /* Buffer without timestamp set*/
+            guint temp_ref = priv->svh_hdr.temporal_reference;
+            if (temp_ref < priv->prev_t_ref) {
+                temp_ref += 256;
+            }
+            guint delta_ref = temp_ref - priv->prev_t_ref;
+
+            pts = priv->sync_time;
+            // see temporal_reference definition in spec, 30000/1001Hz
+            pts += gst_util_uint64_scale(delta_ref, GST_SECOND*1001, 30000);
+        }
+        priv->sync_time = pts;
+        priv->prev_t_ref = priv->svh_hdr.temporal_reference;
+    }
+    else {
+        /* Update priv->pts_diff */
+        if (priv->calculate_pts_diff) {
+            calculate_pts_diff(decoder, vol_hdr, vop_hdr);
+            priv->calculate_pts_diff = FALSE;
+        }
+
+        /* Update presentation time, 6.3.5 */
+        if(vop_hdr->coding_type != GST_MPEG4_B_VOP) {
+            // increment basing on decoding order
+            priv->last_sync_time = priv->sync_time;
+            priv->sync_time = priv->last_sync_time + vop_hdr->modulo_time_base;
+            pts = priv->sync_time * GST_SECOND;
+            pts += gst_util_uint64_scale(vop_hdr->time_increment, GST_SECOND, vol_hdr->vop_time_increment_resolution);
+            priv->last_non_b_scale_time = priv->non_b_scale_time;
+            priv->non_b_scale_time = priv->sync_time * vol_hdr->vop_time_increment_resolution + vop_hdr->time_increment;
+            priv->trd  = priv->non_b_scale_time - priv->last_non_b_scale_time;
+        }
+        else {
+            // increment basing on display oder
+            pts = (priv->last_sync_time + vop_hdr->modulo_time_base) * GST_SECOND;
+            pts += gst_util_uint64_scale(vop_hdr->time_increment, GST_SECOND, vol_hdr->vop_time_increment_resolution);
+            priv->trb = (priv->last_sync_time + vop_hdr->modulo_time_base) * vol_hdr->vop_time_increment_resolution +
+                vop_hdr->time_increment - priv->last_non_b_scale_time;
+        }
+    }
+    picture->pts = pts + priv->pts_diff;
+    if (priv->max_pts == GST_CLOCK_TIME_NONE || priv->max_pts < picture->pts)
+        priv->max_pts = picture->pts;
+
+    /* Update reference pictures */
+    /* XXX: consider priv->vol_hdr.low_delay, consider packed video frames for DivX/XviD */
+    if (GST_VAAPI_PICTURE_IS_REFERENCE(picture)) {
+        if (priv->next_picture)
+            status = render_picture(decoder, priv->next_picture);
+        gst_vaapi_picture_replace(&priv->prev_picture, priv->next_picture);
+        gst_vaapi_picture_replace(&priv->next_picture, picture);
+    }
+    return status;
+}
+
+static inline guint
+get_vop_coding_type(GstVaapiPicture *picture)
+{
+    return picture->type - GST_VAAPI_PICTURE_TYPE_I;
+}
+
+static gboolean
+fill_picture(GstVaapiDecoderMpeg4 *decoder, GstVaapiPicture *picture)
+{
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+    VAPictureParameterBufferMPEG4 * const pic_param = picture->param;
+    GstMpeg4VideoObjectPlane * const vop_hdr = &priv->vop_hdr;
+
+    /* Fill in VAPictureParameterBufferMPEG4 */
+    pic_param->forward_reference_picture                        = VA_INVALID_ID;
+    pic_param->backward_reference_picture                       = VA_INVALID_ID;
+
+    pic_param->vol_fields.value                                 = 0;
+    pic_param->vop_fields.value                                 = 0;
+    if(priv->is_svh) {
+        // vol_hdr Parameters
+        pic_param->vol_fields.bits.short_video_header           = 1; 
+        // does the following vol_hdr parameters matter for short video header?
+        pic_param->vol_fields.bits.chroma_format                = 1; // I420, see table 6-15. 
+        pic_param->vol_fields.bits.interlaced                   = 0; 
+        pic_param->vol_fields.bits.obmc_disable                 = 1;
+        pic_param->vol_fields.bits.sprite_enable                = 0;
+        pic_param->vol_fields.bits.sprite_warping_accuracy      = 0;
+        pic_param->vol_fields.bits.quant_type                   = 0; //method 1; $7.4.4
+        pic_param->vol_fields.bits.quarter_sample               = 0; 
+        pic_param->vol_fields.bits.data_partitioned             = 0; 
+        pic_param->vol_fields.bits.reversible_vlc               = 0; 
+        pic_param->vol_fields.bits.resync_marker_disable        = 1; 
+        pic_param->no_of_sprite_warping_points                  = 0; 
+        pic_param->quant_precision                              = 5;
+        // VOP parameters    
+        pic_param->vop_width                                    = priv->svh_hdr.vop_width;
+        pic_param->vop_height                                   = priv->svh_hdr.vop_height;
+        pic_param->vop_fields.bits.vop_coding_type              = priv->svh_hdr.picture_coding_type;
+        pic_param->vop_time_increment_resolution                = priv->vol_hdr.vop_time_increment_resolution; 
+        
+        pic_param->num_gobs_in_vop                              = priv->svh_hdr.num_gobs_in_vop;
+        pic_param->num_macroblocks_in_gob                       = priv->svh_hdr.num_macroblocks_in_gob;
+    }
+    else {
+        // VOL parameters
+        pic_param->vol_fields.bits.short_video_header           = 0; 
+        pic_param->vol_fields.bits.chroma_format                = priv->vol_hdr.chroma_format;
+        pic_param->vol_fields.bits.interlaced                   = priv->vol_hdr.interlaced;
+        pic_param->vol_fields.bits.obmc_disable                 = priv->vol_hdr.obmc_disable;
+        pic_param->vol_fields.bits.sprite_enable                = priv->vol_hdr.sprite_enable;
+        pic_param->vol_fields.bits.sprite_warping_accuracy      = priv->vol_hdr.sprite_warping_accuracy; 
+        pic_param->vol_fields.bits.quant_type                   = priv->vol_hdr.quant_type;
+        pic_param->vol_fields.bits.quarter_sample               = priv->vol_hdr.quarter_sample;
+        pic_param->vol_fields.bits.data_partitioned             = priv->vol_hdr.data_partitioned;
+        pic_param->vol_fields.bits.reversible_vlc               = priv->vol_hdr.reversible_vlc;
+        pic_param->vol_fields.bits.resync_marker_disable        = priv->vol_hdr.resync_marker_disable;
+        pic_param->no_of_sprite_warping_points                  = priv->vol_hdr.no_of_sprite_warping_points;
+        int i =0;
+        for (i=0; i<3 && i<priv->vol_hdr.no_of_sprite_warping_points ; i++) {
+            pic_param->sprite_trajectory_du[i]                  = priv->sprite_trajectory.vop_ref_points[i];
+            pic_param->sprite_trajectory_dv[i]                  = priv->sprite_trajectory.sprite_ref_points[i];
+        }
+        pic_param->quant_precision                              = priv->vol_hdr.quant_precision;
+        
+        // VOP parameters    
+        pic_param->vop_width                                    = vop_hdr->width;
+        pic_param->vop_height                                   = vop_hdr->height;
+        pic_param->vop_fields.bits.vop_coding_type              = vop_hdr->coding_type;
+        pic_param->vop_fields.bits.vop_rounding_type            = vop_hdr->rounding_type;
+        pic_param->vop_fields.bits.intra_dc_vlc_thr             = vop_hdr->intra_dc_vlc_thr;
+        pic_param->vop_fields.bits.top_field_first              = vop_hdr->top_field_first;
+        pic_param->vop_fields.bits.alternate_vertical_scan_flag = vop_hdr->alternate_vertical_scan_flag;
+
+        pic_param->vop_fcode_forward                            = vop_hdr->fcode_forward;
+        pic_param->vop_fcode_backward                           = vop_hdr->fcode_backward;
+        pic_param->vop_time_increment_resolution                = priv->vol_hdr.vop_time_increment_resolution;
+    }    
+
+    pic_param->TRB = 0;
+    pic_param->TRD = 0;
+    switch (priv->coding_type) {
+    case GST_MPEG4_B_VOP:
+        pic_param->TRB                                          = priv->trb;
+        pic_param->backward_reference_picture                   = priv->next_picture->surface_id;
+        pic_param->vop_fields.bits.backward_reference_vop_coding_type = get_vop_coding_type(priv->next_picture);
+        // fall-through
+    case GST_MPEG4_P_VOP:
+        pic_param->TRD                                          = priv->trd;
+        if (priv->prev_picture)
+            pic_param->forward_reference_picture                = priv->prev_picture->surface_id;
+        break;
+    }
+
+    if (priv->vol_hdr.interlaced) {
+        priv->is_first_field ^= 1;
+    }
+    return TRUE;
+}
+
+static GstVaapiDecoderStatus
+decode_slice(
+    GstVaapiDecoderMpeg4 *decoder,
+    const guint8          *buf,
+    guint                 buf_size,
+    gboolean              has_packet_header
+)
+{
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+    GstVaapiPicture * const picture = priv->curr_picture;
+    GstVaapiSlice *slice;
+    VASliceParameterBufferMPEG4 *slice_param;
+
+    GST_DEBUG("decoder silce: %p, %u bytes)", buf, buf_size);
+
+    // has_packet_header is ture for the 2+ slice
+    if (!has_packet_header && !fill_picture(decoder, picture))
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+
+    slice = GST_VAAPI_SLICE_NEW(MPEG4, decoder, buf, buf_size);
+    if (!slice) {
+        GST_DEBUG("failed to allocate slice");
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+    gst_vaapi_picture_add_slice(picture, slice);
+
+    /* Fill in VASliceParameterBufferMPEG4 */
+    slice_param = slice->param;
+    if (priv->is_svh) {
+        slice_param->macroblock_offset         = (priv->svh_hdr.size)%8;
+        slice_param->macroblock_number         = 0; 
+        // the header of first gob_layer is empty (gob_header_empty=1), use vop_quant
+        slice_param->quant_scale               = priv->svh_hdr.vop_quant; 
+    }
+    else {
+        if (has_packet_header) {
+            slice_param->macroblock_offset     = priv->packet_hdr.size % 8;
+            slice_param->macroblock_number     = priv->packet_hdr.macroblock_number;
+            slice_param->quant_scale           = priv->packet_hdr.quant_scale;
+       }    
+        else {
+            slice_param->macroblock_offset     = priv->vop_hdr.size % 8;
+            slice_param->macroblock_number     = 0;
+            slice_param->quant_scale           = priv->vop_hdr.quant;
+        }
+    }
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_packet(GstVaapiDecoderMpeg4 *decoder, GstMpeg4Packet packet)
+{
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+    GstMpeg4Packet *tos = &packet;
+    GstVaapiDecoderStatus status;
+
+    if (tos->size < 0)
+        return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+
+    status = gst_vaapi_decoder_check_status(GST_VAAPI_DECODER(decoder));
+    if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+        return status;
+
+    // packet.size is the size from current marker to the next.
+    if (tos->type == GST_MPEG4_VISUAL_OBJ_SEQ_START) {
+        status = decode_sequence(decoder, packet.data + packet.offset, packet.size);
+    }
+    else if (tos->type == GST_MPEG4_VISUAL_OBJ_SEQ_END) {
+        status = decode_sequence_end(decoder);
+    }
+    else if (tos->type == GST_MPEG4_VISUAL_OBJ) {
+        status = decode_visual_object(decoder, packet.data + packet.offset, packet.size);
+    }
+    else if (tos->type >= GST_MPEG4_VIDEO_OBJ_FIRST && tos->type <= GST_MPEG4_VIDEO_OBJ_LAST) {
+        GST_WARNING("unexpected marker: (GST_MPEG4_VIDEO_OBJ_FIRST, GST_MPEG4_VIDEO_OBJ_LAST)");
+        status = GST_VAAPI_DECODER_STATUS_SUCCESS;
+    }
+    else if (tos->type >= GST_MPEG4_VIDEO_LAYER_FIRST && tos->type <= GST_MPEG4_VIDEO_LAYER_LAST) {
+        status = decode_video_object_layer(decoder, packet.data + packet.offset, packet.size);
+    }
+    else if (tos->type == GST_MPEG4_GROUP_OF_VOP) {
+        status = decode_gop(decoder, packet.data + packet.offset, packet.size);
+    }
+    else if (tos->type == GST_MPEG4_VIDEO_OBJ_PLANE) {
+        status = decode_picture(decoder, packet.data + packet.offset, packet.size);
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            return status;
+
+        /* decode slice
+         * A resync marker shall only be located immediately before a macroblock 
+         * (or video packet header if exists) and aligned with a byte
+         * either start_code or resync_marker are scaned/measured by byte, 
+         * while the header itself are parsed/measured in bit
+         * it means: resync_marker(video_packet_header) start from byte boundary, 
+         * while MB doesn't start from byte boundary -- it is what 'macroblock_offset' 
+         * in slice refer to
+         */
+        const guint8 *_data = packet.data + packet.offset + priv->vop_hdr.size/8; 
+        gint  _data_size = packet.size - (priv->vop_hdr.size/8); 
+        GstMpeg4Packet video_packet;
+        
+        if (priv->vol_hdr.resync_marker_disable) {
+            status = decode_slice(decoder, _data, _data_size, FALSE);
+            if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+                return status;
+        }
+        else {
+            // next start_code is required to determine the end of last slice
+            _data_size += 4;
+            GstMpeg4ParseResult ret = GST_MPEG4_PARSER_OK;
+
+            gboolean first_slice = TRUE;
+            while (_data_size > 0) {
+                // we can skip user data here
+                ret = gst_mpeg4_parse(&video_packet, TRUE, &priv->vop_hdr, _data, 0,  _data_size);
+                if(ret != GST_MPEG4_PARSER_OK) {
+                    break;
+                }
+
+                if (first_slice) {
+                    status = decode_slice(decoder, _data, video_packet.size, FALSE);
+                    first_slice = FALSE;
+                }
+                else {
+                    _data += video_packet.offset;
+                    _data_size -= video_packet.offset;
+
+                    ret = gst_mpeg4_parse_video_packet_header (&priv->packet_hdr, &priv->vol_hdr, &priv->vop_hdr, &priv->sprite_trajectory, _data, _data_size);
+                    status = decode_slice(decoder,_data + priv->packet_hdr.size/8, video_packet.size - priv->packet_hdr.size/8, TRUE); 
+                }
+
+                _data += video_packet.size;
+                _data_size -= video_packet.size;
+            }
+        }
+        status = decode_current_picture(decoder);
+    }
+    else if (tos->type == GST_MPEG4_USER_DATA
+          || tos->type == GST_MPEG4_VIDEO_SESSION_ERR 
+          || tos->type == GST_MPEG4_FBA 
+          || tos->type == GST_MPEG4_FBA_PLAN 
+          || tos->type == GST_MPEG4_MESH 
+          || tos->type == GST_MPEG4_MESH_PLAN 
+          || tos->type == GST_MPEG4_STILL_TEXTURE_OBJ 
+          || tos->type == GST_MPEG4_TEXTURE_SPATIAL 
+          || tos->type == GST_MPEG4_TEXTURE_SNR_LAYER 
+          || tos->type == GST_MPEG4_TEXTURE_TILE 
+          || tos->type == GST_MPEG4_SHAPE_LAYER 
+          || tos->type == GST_MPEG4_STUFFING 
+          || tos->type == GST_MPEG4_SYSTEM_FIRST 
+          || tos->type == GST_MPEG4_SYSTEM_LAST) {
+        GST_WARNING("Ignore marker: %x\n", tos->type);
+        status = GST_VAAPI_DECODER_STATUS_SUCCESS;
+    }
+    
+    return status;
+}
+
+static GstVaapiDecoderStatus
+decode_buffer(GstVaapiDecoderMpeg4 *decoder, GstBuffer *buffer)
+{
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+    GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+    guchar *buf;
+    guint pos, buf_size;
+
+    buf      = GST_BUFFER_DATA(buffer);
+    buf_size = GST_BUFFER_SIZE(buffer);
+
+    // visual object sequence end
+    if (!buf && buf_size == 0)
+        return decode_sequence_end(decoder);
+
+    gst_buffer_ref(buffer);
+    gst_adapter_push(priv->adapter, buffer);
+
+    if (priv->sub_buffer) {
+        buffer = gst_buffer_merge(priv->sub_buffer, buffer);
+        if (!buffer)
+            return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+        gst_buffer_unref(priv->sub_buffer);
+        priv->sub_buffer = NULL;
+    }
+
+    buf      = GST_BUFFER_DATA(buffer);
+    buf_size = GST_BUFFER_SIZE(buffer);
+    pos = 0;
+
+    GstMpeg4Packet packet;
+    GstMpeg4ParseResult result = GST_MPEG4_PARSER_OK;
+    guint consumed_size = 0;
+
+    if (priv->is_svh) {
+        while (result == GST_MPEG4_PARSER_OK && pos < buf_size) {
+            result = gst_h263_parse (&packet,buf, pos, buf_size);
+            if (result != GST_MPEG4_PARSER_OK) {
+                break;
+            }
+            status = decode_picture(decoder, packet.data+packet.offset, packet.size);
+            if (GST_VAAPI_DECODER_STATUS_SUCCESS == status) {
+                // MBs are not byte aligned, so we set the start address with byte aligned 
+                // and mb offset with (priv->svh_hdr.size)%8
+                status = decode_slice(decoder, packet.data+packet.offset+(priv->svh_hdr.size)/8, 
+                        packet.size - (priv->svh_hdr.size)/8, FALSE);
+                status = decode_current_picture(decoder);
+
+                consumed_size = packet.offset + packet.size; 
+                pos += consumed_size; 
+                if (gst_adapter_available(priv->adapter) >= consumed_size)
+                    gst_adapter_flush(priv->adapter, consumed_size);
+            }
+            else {
+                GST_WARNING("decode h263 packet failed\n");
+                break;
+            }
+        }
+    }
+    else {
+        while (pos < buf_size) {
+            // don't skip user data, we need the size to pop tsb buffer
+            result = gst_mpeg4_parse(&packet, FALSE, NULL, buf, pos, buf_size);
+            if (result != GST_MPEG4_PARSER_OK) {
+                break;
+            }
+            status = decode_packet(decoder, packet);
+            if (GST_VAAPI_DECODER_STATUS_SUCCESS == status ||
+                GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA == status) {
+                consumed_size = packet.offset + packet.size - pos; 
+                pos = packet.offset + packet.size; 
+                if (gst_adapter_available(priv->adapter) >= consumed_size)
+                    gst_adapter_flush(priv->adapter, consumed_size);
+            }
+            else {
+                GST_WARNING("decode mp4 packet failed\n");
+                break;
+            }
+        }
+    }
+
+    if ((result == GST_MPEG4_PARSER_NO_PACKET ||
+         result == GST_MPEG4_PARSER_NO_PACKET_END ||
+         status == GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE) &&
+        pos < buf_size) {
+        priv->sub_buffer = gst_buffer_create_sub(buffer, pos, buf_size-pos);
+        status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+    }
+    return status;
+}
+
+static GstVaapiDecoderStatus
+decode_codec_data(GstVaapiDecoderMpeg4 *decoder, GstBuffer *buffer)
+{
+    GstVaapiDecoderStatus status;
+    guchar *buf, *_buf;
+    guint pos, buf_size, _buf_size;
+
+    _buf      = GST_BUFFER_DATA(buffer);
+    _buf_size = GST_BUFFER_SIZE(buffer);
+    // add additional 0x000001b2 to enclose the last header
+    buf_size = _buf_size + 4;
+    buf = malloc(buf_size);
+    memcpy(buf, _buf, buf_size);
+    buf[buf_size-4] = 0;
+    buf[buf_size-3] = 0;
+    buf[buf_size-2] = 1;
+    buf[buf_size-1] = 0xb2;
+
+    pos = 0;
+    GstMpeg4Packet packet;
+    GstMpeg4ParseResult result = GST_MPEG4_PARSER_OK;
+
+    while (result == GST_MPEG4_PARSER_OK && pos < buf_size) {
+        result = gst_mpeg4_parse(&packet, FALSE, NULL, buf, pos, buf_size);
+        if (result != GST_MPEG4_PARSER_OK) {
+            break;
+        }
+        status = decode_packet(decoder, packet);
+        if (GST_VAAPI_DECODER_STATUS_SUCCESS == status) {
+            pos = packet.offset + packet.size; 
+        }
+        else {
+            GST_WARNING("decode mp4 packet failed when decoding codec data\n");
+            break;
+        }
+    }
+    free(buf);
+    return status;
+}
+
+GstVaapiDecoderStatus
+gst_vaapi_decoder_mpeg4_decode(GstVaapiDecoder *base, GstBuffer *buffer)
+{
+    GstVaapiDecoderMpeg4 * const decoder = GST_VAAPI_DECODER_MPEG4(base);
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+    GstBuffer *codec_data = NULL;
+    GstVaapiDecoderStatus status;
+
+    g_return_val_if_fail(priv->is_constructed,
+                         GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED);
+
+    if (!priv->is_opened) {
+        priv->is_opened = gst_vaapi_decoder_mpeg4_open(decoder, buffer);
+        if (!priv->is_opened)
+            return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
+
+        codec_data = GST_VAAPI_DECODER_CODEC_DATA(decoder);
+        if (codec_data) {
+            status = decode_codec_data(decoder, codec_data);
+            if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+                return status;
+        }
+    }
+    return decode_buffer(decoder, buffer);
+}
+
+static void
+gst_vaapi_decoder_mpeg4_finalize(GObject *object)
+{
+    GstVaapiDecoderMpeg4 * const decoder = GST_VAAPI_DECODER_MPEG4(object);
+
+    gst_vaapi_decoder_mpeg4_destroy(decoder);
+
+    G_OBJECT_CLASS(gst_vaapi_decoder_mpeg4_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_decoder_mpeg4_constructed(GObject *object)
+{
+    GstVaapiDecoderMpeg4 * const decoder = GST_VAAPI_DECODER_MPEG4(object);
+    GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
+    GObjectClass *parent_class;
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_decoder_mpeg4_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+
+    priv->is_constructed = gst_vaapi_decoder_mpeg4_create(decoder);
+}
+
+static void
+gst_vaapi_decoder_mpeg4_class_init(GstVaapiDecoderMpeg4Class *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiDecoderMpeg4Private));
+
+    object_class->finalize      = gst_vaapi_decoder_mpeg4_finalize;
+    object_class->constructed   = gst_vaapi_decoder_mpeg4_constructed;
+
+    decoder_class->decode       = gst_vaapi_decoder_mpeg4_decode;
+    decoder_class->clear_buffer = gst_vaapi_decoder_mpeg4_clear_buffer;
+}
+
+static void
+gst_vaapi_decoder_mpeg4_init(GstVaapiDecoderMpeg4 *decoder)
+{
+    GstVaapiDecoderMpeg4Private *priv;
+
+    priv                        = GST_VAAPI_DECODER_MPEG4_GET_PRIVATE(decoder);
+    decoder->priv               = priv;
+    priv->width                 = 0;
+    priv->height                = 0;
+    priv->fps_n                 = 0;
+    priv->fps_d                 = 0;
+    priv->profile               = GST_VAAPI_PROFILE_MPEG4_SIMPLE;
+    priv->curr_picture          = NULL;
+    priv->next_picture          = NULL;
+    priv->prev_picture          = NULL;
+    priv->adapter               = NULL;
+    priv->sub_buffer            = NULL;
+    priv->seq_pts               = GST_CLOCK_TIME_NONE;
+    priv->gop_pts               = GST_CLOCK_TIME_NONE;
+    priv->max_pts               = GST_CLOCK_TIME_NONE;
+    priv->pts_diff              = 0;
+    priv->calculate_pts_diff    = TRUE;
+    priv->is_constructed        = FALSE;
+    priv->is_opened             = FALSE;
+    priv->is_first_field        = FALSE;
+    priv->size_changed          = TRUE;
+    priv->profile_changed       = TRUE;
+    priv->progressive_sequence  = FALSE;
+    priv->closed_gop            = FALSE;
+    priv->broken_link           = FALSE;
+    priv->last_non_b_scale_time = 0;
+    priv->non_b_scale_time      = 0;
+    priv->trb                   = 0;
+    priv->trd                   = 0;
+}
+
+/**
+ * gst_vaapi_decoder_mpeg4_new:
+ * @display: a #GstVaapiDisplay
+ * @caps: a #GstCaps holding codec information
+ *
+ * Creates a new #GstVaapiDecoder for MPEG-2 decoding.  The @caps can
+ * hold extra information like codec-data and pictured coded size.
+ *
+ * Return value: the newly allocated #GstVaapiDecoder object
+ */
+GstVaapiDecoder *
+gst_vaapi_decoder_mpeg4_new(GstVaapiDisplay *display, GstCaps *caps)
+{
+    GstVaapiDecoderMpeg4 *decoder;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+    g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
+
+    decoder = g_object_new(
+        GST_VAAPI_TYPE_DECODER_MPEG4,
+        "display",      display,
+        "caps",         caps,
+        NULL
+    );
+    if (!decoder->priv->is_constructed) {
+        g_object_unref(decoder);
+        return NULL;
+    }
+    return GST_VAAPI_DECODER_CAST(decoder);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_mpeg4.h b/gst-libs/gst/vaapi/gstvaapidecoder_mpeg4.h
new file mode 100644 (file)
index 0000000..4c877bb
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ *  gstvaapidecoder_mpeg4.h - MPEG-4 decoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DECODER_MPEG4_H
+#define GST_VAAPI_DECODER_MPEG4_H
+
+#include <gst/vaapi/gstvaapidecoder.h>
+#include <gst/base/gstadapter.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_DECODER_MPEG4 \
+    (gst_vaapi_decoder_mpeg4_get_type())
+
+#define GST_VAAPI_DECODER_MPEG4(obj)                            \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_DECODER_MPEG4,   \
+                                GstVaapiDecoderMpeg4))
+
+#define GST_VAAPI_DECODER_MPEG4_CLASS(klass)                    \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_DECODER_MPEG4,      \
+                             GstVaapiDecoderMpeg4Class))
+
+#define GST_VAAPI_IS_DECODER_MPEG4(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_DECODER_MPEG4))
+
+#define GST_VAAPI_IS_DECODER_MPEG4_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_DECODER_MPEG4))
+
+#define GST_VAAPI_DECODER_MPEG4_GET_CLASS(obj)                  \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_DECODER_MPEG4,    \
+                               GstVaapiDecoderMpeg4Class))
+
+typedef struct _GstVaapiDecoderMpeg4            GstVaapiDecoderMpeg4;
+typedef struct _GstVaapiDecoderMpeg4Private     GstVaapiDecoderMpeg4Private;
+typedef struct _GstVaapiDecoderMpeg4Class       GstVaapiDecoderMpeg4Class;
+
+/**
+ * GstVaapiDecoderMpeg4:
+ *
+ * A decoder based on Mpeg4.
+ */
+struct _GstVaapiDecoderMpeg4 {
+    /*< private >*/
+    GstVaapiDecoder parent_instance;
+
+    GstVaapiDecoderMpeg4Private *priv;
+};
+
+/**
+ * GstVaapiDecoderMpeg4Class:
+ *
+ * A decoder class based on Mpeg4.
+ */
+struct _GstVaapiDecoderMpeg4Class {
+    /*< private >*/
+    GstVaapiDecoderClass parent_class;
+};
+
+GType
+gst_vaapi_decoder_mpeg4_get_type(void) G_GNUC_CONST;
+
+GstVaapiDecoder *
+gst_vaapi_decoder_mpeg4_new(GstVaapiDisplay *display, GstCaps *caps);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DECODER_MPEG4_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_objects.c b/gst-libs/gst/vaapi/gstvaapidecoder_objects.c
new file mode 100644 (file)
index 0000000..5f90fb0
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ *  gstvaapidecoder_objects.c - VA decoder objects helpers
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "sysdeps.h"
+#include <string.h>
+#include <gst/vaapi/gstvaapicontext.h>
+#include "gstvaapidecoder_objects.h"
+#include "gstvaapidecoder_priv.h"
+#include "gstvaapicompat.h"
+#include "gstvaapiutils.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+#define GET_DECODER(obj)    GST_VAAPI_DECODER_CAST((obj)->parent_instance.codec)
+#define GET_CONTEXT(obj)    GET_DECODER(obj)->priv->context
+#define GET_VA_DISPLAY(obj) GET_DECODER(obj)->priv->va_display
+#define GET_VA_CONTEXT(obj) GET_DECODER(obj)->priv->va_context
+
+/* ------------------------------------------------------------------------- */
+/* --- Pictures                                                          --- */
+/* ------------------------------------------------------------------------- */
+
+GST_VAAPI_CODEC_DEFINE_TYPE(GstVaapiPicture,
+                            gst_vaapi_picture,
+                            GST_VAAPI_TYPE_CODEC_OBJECT)
+
+enum {
+    GST_VAAPI_CREATE_PICTURE_FLAG_CLONE = 1 << 0,
+    GST_VAAPI_CREATE_PICTURE_FLAG_FIELD = 1 << 1,
+};
+
+static void
+destroy_slice_cb(gpointer data, gpointer user_data)
+{
+    GstMiniObject * const object = data;
+
+    gst_mini_object_unref(object);
+}
+
+static void
+gst_vaapi_picture_destroy(GstVaapiPicture *picture)
+{
+    if (picture->slices) {
+        g_ptr_array_foreach(picture->slices, destroy_slice_cb, NULL);
+        g_ptr_array_free(picture->slices, TRUE);
+        picture->slices = NULL;
+    }
+
+    if (picture->iq_matrix) {
+        gst_mini_object_unref(GST_MINI_OBJECT(picture->iq_matrix));
+        picture->iq_matrix = NULL;
+    }
+
+    if (picture->huf_table) {
+        gst_mini_object_unref(GST_MINI_OBJECT(picture->huf_table));
+        picture->huf_table = NULL;
+    }
+
+    if (picture->bitplane) {
+        gst_mini_object_unref(GST_MINI_OBJECT(picture->bitplane));
+        picture->bitplane = NULL;
+    }
+
+    if (picture->proxy) {
+        g_object_unref(picture->proxy);
+        picture->proxy = NULL;
+    }
+    else if (picture->surface) {
+        /* Explicitly release any surface that was not bound to a proxy */
+        gst_vaapi_context_put_surface(GET_CONTEXT(picture), picture->surface);
+    }
+    picture->surface_id = VA_INVALID_ID;
+    picture->surface = NULL;
+
+    vaapi_destroy_buffer(GET_VA_DISPLAY(picture), &picture->param_id);
+    picture->param = NULL;
+}
+
+static gboolean
+gst_vaapi_picture_create(
+    GstVaapiPicture                          *picture,
+    const GstVaapiCodecObjectConstructorArgs *args
+)
+{
+    gboolean success;
+
+    if (args->flags & GST_VAAPI_CREATE_PICTURE_FLAG_CLONE) {
+        GstVaapiPicture * const parent_picture = GST_VAAPI_PICTURE(args->data);
+
+        picture->proxy   = g_object_ref(parent_picture->proxy);
+        picture->surface = gst_vaapi_surface_proxy_get_surface(picture->proxy);
+        picture->type    = parent_picture->type;
+        picture->pts     = parent_picture->pts;
+        picture->poc     = parent_picture->poc;
+
+        // Copy all picture flags but "output"
+        GST_VAAPI_PICTURE_FLAG_SET(
+            picture,
+            GST_VAAPI_PICTURE_FLAGS(parent_picture) &
+            (GST_VAAPI_PICTURE_FLAG_SKIPPED     |
+             GST_VAAPI_PICTURE_FLAG_REFERENCE   |
+             GST_VAAPI_PICTURE_FLAG_INTERLACED  |
+             GST_VAAPI_PICTURE_FLAG_FF          |
+             GST_VAAPI_PICTURE_FLAG_TFF)
+        );
+
+        picture->structure = parent_picture->structure;
+        if ((args->flags & GST_VAAPI_CREATE_PICTURE_FLAG_FIELD) &&
+            GST_VAAPI_PICTURE_IS_INTERLACED(picture)) {
+            switch (picture->structure) {
+            case GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD:
+                picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
+                break;
+            case GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD:
+                picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
+                break;
+            }
+            GST_VAAPI_PICTURE_FLAG_UNSET(picture, GST_VAAPI_PICTURE_FLAG_FF);
+        }
+    }
+    else {
+        picture->surface = gst_vaapi_context_get_surface(GET_CONTEXT(picture));
+        if (!picture->surface)
+            return FALSE;
+
+        picture->proxy =
+            gst_vaapi_surface_proxy_new(GET_CONTEXT(picture), picture->surface);
+        if (!picture->proxy)
+            return FALSE;
+
+        picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
+        GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_FF);
+    }
+    picture->surface_id = gst_vaapi_surface_get_id(picture->surface);
+
+    success = vaapi_create_buffer(
+        GET_VA_DISPLAY(picture),
+        GET_VA_CONTEXT(picture),
+        VAPictureParameterBufferType,
+        args->param_size,
+        args->param,
+        &picture->param_id,
+        &picture->param
+    );
+    if (!success)
+        return FALSE;
+    picture->param_size = args->param_size;
+
+    picture->slices = g_ptr_array_new();
+    if (!picture->slices)
+        return FALSE;
+    return TRUE;
+}
+
+static void
+gst_vaapi_picture_init(GstVaapiPicture *picture)
+{
+    picture->type       = GST_VAAPI_PICTURE_TYPE_NONE;
+    picture->surface    = NULL;
+    picture->proxy      = NULL;
+    picture->surface_id = VA_INVALID_ID;
+    picture->param      = NULL;
+    picture->param_id   = VA_INVALID_ID;
+    picture->param_size = 0;
+    picture->slices     = NULL;
+    picture->iq_matrix  = NULL;
+    picture->huf_table  = NULL;
+    picture->bitplane   = NULL;
+    picture->pts        = GST_CLOCK_TIME_NONE;
+    picture->poc        = 0;
+}
+
+GstVaapiPicture *
+gst_vaapi_picture_new(
+    GstVaapiDecoder *decoder,
+    gconstpointer    param,
+    guint            param_size
+)
+{
+    GstVaapiCodecObject *object;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), NULL);
+
+    object = gst_vaapi_codec_object_new(
+        GST_VAAPI_TYPE_PICTURE,
+        GST_VAAPI_CODEC_BASE(decoder),
+        param, param_size,
+        NULL, 0
+    );
+    if (!object)
+        return NULL;
+    return GST_VAAPI_PICTURE_CAST(object);
+}
+
+GstVaapiPicture *
+gst_vaapi_picture_new_field(GstVaapiPicture *picture)
+{
+    GstMiniObject *obj;
+    GstVaapiCodecObject *va_obj;
+    GstVaapiCodecObjectConstructorArgs args;
+
+    g_return_val_if_fail(GST_VAAPI_IS_PICTURE(picture), NULL);
+
+    obj = gst_mini_object_new(GST_VAAPI_TYPE_PICTURE);
+    if (!obj)
+        return NULL;
+
+    va_obj = GST_VAAPI_CODEC_OBJECT(obj);
+    args.codec      = GST_VAAPI_CODEC_BASE(GET_DECODER(picture));
+    args.param      = NULL;
+    args.param_size = picture->param_size;
+    args.data       = picture;
+    args.data_size  = 0;
+    args.flags      = (GST_VAAPI_CREATE_PICTURE_FLAG_CLONE|
+                       GST_VAAPI_CREATE_PICTURE_FLAG_FIELD);
+    if (gst_vaapi_codec_object_construct(va_obj, &args))
+        return GST_VAAPI_PICTURE_CAST(va_obj);
+
+    gst_mini_object_unref(obj);
+    return NULL;
+}
+
+void
+gst_vaapi_picture_add_slice(GstVaapiPicture *picture, GstVaapiSlice *slice)
+{
+    g_return_if_fail(GST_VAAPI_IS_PICTURE(picture));
+    g_return_if_fail(GST_VAAPI_IS_SLICE(slice));
+
+    g_ptr_array_add(picture->slices, slice);
+}
+
+static gboolean
+do_decode(VADisplay dpy, VAContextID ctx, VABufferID *buf_id, void **buf_ptr)
+{
+    VAStatus status;
+
+    vaapi_unmap_buffer(dpy, *buf_id, buf_ptr);
+
+    status = vaRenderPicture(dpy, ctx, buf_id, 1);
+    if (!vaapi_check_status(status, "vaRenderPicture()"))
+        return FALSE;
+
+    /* XXX: vaRenderPicture() is meant to destroy the VA buffer implicitly */
+    vaapi_destroy_buffer(dpy, buf_id);
+    return TRUE;
+}
+
+gboolean
+gst_vaapi_picture_decode(GstVaapiPicture *picture)
+{
+    GstVaapiIqMatrix *iq_matrix;
+    GstVaapiBitPlane *bitplane;
+    GstVaapiHuffmanTable *huf_table;
+    VADisplay va_display;
+    VAContextID va_context;
+    VAStatus status;
+    guint i;
+
+    g_return_val_if_fail(GST_VAAPI_IS_PICTURE(picture), FALSE);
+
+    va_display = GET_VA_DISPLAY(picture);
+    va_context = GET_VA_CONTEXT(picture);
+
+    GST_DEBUG("decode picture 0x%08x", picture->surface_id);
+
+    status = vaBeginPicture(va_display, va_context, picture->surface_id);
+    if (!vaapi_check_status(status, "vaBeginPicture()"))
+        return FALSE;
+
+    if (!do_decode(va_display, va_context, &picture->param_id, &picture->param))
+        return FALSE;
+
+    iq_matrix = picture->iq_matrix;
+    if (iq_matrix && !do_decode(va_display, va_context,
+                                &iq_matrix->param_id, &iq_matrix->param))
+        return FALSE;
+
+    bitplane = picture->bitplane;
+    if (bitplane && !do_decode(va_display, va_context,
+                               &bitplane->data_id, (void **)&bitplane->data))
+        return FALSE;
+
+    huf_table = picture->huf_table;
+    if (huf_table && !do_decode(va_display, va_context,
+                                &huf_table->param_id,
+                                (void **)&huf_table->param))
+        return FALSE;
+
+    for (i = 0; i < picture->slices->len; i++) {
+        GstVaapiSlice * const slice = g_ptr_array_index(picture->slices, i);
+        VABufferID va_buffers[2];
+
+        vaapi_unmap_buffer(va_display, slice->param_id, NULL);
+        va_buffers[0] = slice->param_id;
+        va_buffers[1] = slice->data_id;
+
+        status = vaRenderPicture(va_display, va_context, va_buffers, 2);
+        if (!vaapi_check_status(status, "vaRenderPicture()"))
+            return FALSE;
+
+        vaapi_destroy_buffer(va_display, &slice->param_id);
+        vaapi_destroy_buffer(va_display, &slice->data_id);
+    }
+
+    status = vaEndPicture(va_display, va_context);
+    if (!vaapi_check_status(status, "vaEndPicture()"))
+        return FALSE;
+    return TRUE;
+}
+
+gboolean
+gst_vaapi_picture_output(GstVaapiPicture *picture)
+{
+    GstVaapiSurfaceProxy *proxy;
+
+    g_return_val_if_fail(GST_VAAPI_IS_PICTURE(picture), FALSE);
+
+    if (!picture->proxy)
+        return FALSE;
+
+    if (!GST_VAAPI_PICTURE_IS_SKIPPED(picture)) {
+        proxy = g_object_ref(picture->proxy);
+        gst_vaapi_surface_proxy_set_timestamp(proxy, picture->pts);
+        if (GST_VAAPI_PICTURE_IS_INTERLACED(picture))
+            gst_vaapi_surface_proxy_set_interlaced(proxy, TRUE);
+        if (GST_VAAPI_PICTURE_IS_TFF(picture))
+            gst_vaapi_surface_proxy_set_tff(proxy, TRUE);
+        gst_vaapi_decoder_push_surface_proxy(GET_DECODER(picture), proxy);
+    }
+    GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_OUTPUT);
+    return TRUE;
+}
+
+/* ------------------------------------------------------------------------- */
+/* --- Slices                                                            --- */
+/* ------------------------------------------------------------------------- */
+
+GST_VAAPI_CODEC_DEFINE_TYPE(GstVaapiSlice,
+                            gst_vaapi_slice,
+                            GST_VAAPI_TYPE_CODEC_OBJECT)
+
+static void
+gst_vaapi_slice_destroy(GstVaapiSlice *slice)
+{
+    VADisplay const va_display = GET_VA_DISPLAY(slice);
+
+    vaapi_destroy_buffer(va_display, &slice->data_id);
+    vaapi_destroy_buffer(va_display, &slice->param_id);
+    slice->param = NULL;
+}
+
+static gboolean
+gst_vaapi_slice_create(
+    GstVaapiSlice                            *slice,
+    const GstVaapiCodecObjectConstructorArgs *args
+)
+{
+    VASliceParameterBufferBase *slice_param;
+    gboolean success;
+
+    success = vaapi_create_buffer(
+        GET_VA_DISPLAY(slice),
+        GET_VA_CONTEXT(slice),
+        VASliceDataBufferType,
+        args->data_size,
+        args->data,
+        &slice->data_id,
+        NULL
+    );
+    if (!success)
+        return FALSE;
+
+    success = vaapi_create_buffer(
+        GET_VA_DISPLAY(slice),
+        GET_VA_CONTEXT(slice),
+        VASliceParameterBufferType,
+        args->param_size,
+        args->param,
+        &slice->param_id,
+        &slice->param
+    );
+    if (!success)
+        return FALSE;
+
+    slice_param                    = slice->param;
+    slice_param->slice_data_size   = args->data_size;
+    slice_param->slice_data_offset = 0;
+    slice_param->slice_data_flag   = VA_SLICE_DATA_FLAG_ALL;
+    return TRUE;
+}
+
+static void
+gst_vaapi_slice_init(GstVaapiSlice *slice)
+{
+    slice->param        = NULL;
+    slice->param_id     = VA_INVALID_ID;
+    slice->data_id      = VA_INVALID_ID;
+}
+
+GstVaapiSlice *
+gst_vaapi_slice_new(
+    GstVaapiDecoder *decoder,
+    gconstpointer    param,
+    guint            param_size,
+    const guchar    *data,
+    guint            data_size
+)
+{
+    GstVaapiCodecObject *object;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), NULL);
+
+    object = gst_vaapi_codec_object_new(
+        GST_VAAPI_TYPE_SLICE,
+        GST_VAAPI_CODEC_BASE(decoder),
+        param, param_size,
+        data, data_size
+    );
+    return GST_VAAPI_SLICE_CAST(object);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_objects.h b/gst-libs/gst/vaapi/gstvaapidecoder_objects.h
new file mode 100644 (file)
index 0000000..f7a7ea6
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ *  gstvaapidecoder_objects.h - VA decoder objects
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DECODER_OBJECTS_H
+#define GST_VAAPI_DECODER_OBJECTS_H
+
+#include <gst/vaapi/gstvaapicodec_objects.h>
+
+G_BEGIN_DECLS
+
+typedef enum _GstVaapiPictureType       GstVaapiPictureType;
+typedef struct _GstVaapiPicture         GstVaapiPicture;
+typedef struct _GstVaapiPictureClass    GstVaapiPictureClass;
+typedef struct _GstVaapiSlice           GstVaapiSlice;
+typedef struct _GstVaapiSliceClass      GstVaapiSliceClass;
+
+/* ------------------------------------------------------------------------- */
+/* --- Pictures                                                          --- */
+/* ------------------------------------------------------------------------- */
+
+#define GST_VAAPI_TYPE_PICTURE \
+    (gst_vaapi_picture_get_type())
+
+#define GST_VAAPI_PICTURE_CAST(obj) \
+    ((GstVaapiPicture *)(obj))
+
+#define GST_VAAPI_PICTURE(obj)                          \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                  \
+                                GST_VAAPI_TYPE_PICTURE, \
+                                GstVaapiPicture))
+
+#define GST_VAAPI_PICTURE_CLASS(klass)                  \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                   \
+                             GST_VAAPI_TYPE_PICTURE,    \
+                             GstVaapiPictureClass))
+
+#define GST_VAAPI_IS_PICTURE(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_PICTURE))
+
+#define GST_VAAPI_IS_PICTURE_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_PICTURE))
+
+#define GST_VAAPI_PICTURE_GET_CLASS(obj)                \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                   \
+                               GST_VAAPI_TYPE_PICTURE,  \
+                               GstVaapiPictureClass))
+
+enum _GstVaapiPictureType {
+    GST_VAAPI_PICTURE_TYPE_NONE = 0,        // Undefined
+    GST_VAAPI_PICTURE_TYPE_I,               // Intra
+    GST_VAAPI_PICTURE_TYPE_P,               // Predicted
+    GST_VAAPI_PICTURE_TYPE_B,               // Bi-directional predicted
+    GST_VAAPI_PICTURE_TYPE_S,               // S(GMC)-VOP (MPEG-4)
+    GST_VAAPI_PICTURE_TYPE_SI,              // Switching Intra
+    GST_VAAPI_PICTURE_TYPE_SP,              // Switching Predicted
+    GST_VAAPI_PICTURE_TYPE_BI,              // BI type (VC-1)
+};
+
+/**
+ * Picture flags:
+ * @GST_VAAPI_PICTURE_FLAG_SKIPPED: skipped frame
+ * @GST_VAAPI_PICTURE_FLAG_REFERENCE: reference frame
+ * @GST_VAAPI_PICTURE_FLAG_OUTPUT: frame was output
+ * @GST_VAAPI_PICTURE_FLAG_INTERLACED: interlaced frame
+ * @GST_VAAPI_PICTURE_FLAG_FF: first-field
+ * @GST_VAAPI_PICTURE_FLAG_TFF: top-field-first
+ * @GST_VAAPI_PICTURE_FLAG_LAST: first flag that can be used by subclasses
+ *
+ * Enum values used for #GstVaapiPicture flags.
+ */
+enum {
+    GST_VAAPI_PICTURE_FLAG_SKIPPED    = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 0),
+    GST_VAAPI_PICTURE_FLAG_REFERENCE  = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 1),
+    GST_VAAPI_PICTURE_FLAG_OUTPUT     = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 2),
+    GST_VAAPI_PICTURE_FLAG_INTERLACED = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 3),
+    GST_VAAPI_PICTURE_FLAG_FF         = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 4),
+    GST_VAAPI_PICTURE_FLAG_TFF        = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 5),
+    GST_VAAPI_PICTURE_FLAG_LAST       = (GST_VAAPI_CODEC_OBJECT_FLAG_LAST << 6),
+};
+
+#define GST_VAAPI_PICTURE_FLAGS         GST_MINI_OBJECT_FLAGS
+#define GST_VAAPI_PICTURE_FLAG_IS_SET   GST_MINI_OBJECT_FLAG_IS_SET
+#define GST_VAAPI_PICTURE_FLAG_SET      GST_MINI_OBJECT_FLAG_SET
+#define GST_VAAPI_PICTURE_FLAG_UNSET    GST_MINI_OBJECT_FLAG_UNSET
+
+#define GST_VAAPI_PICTURE_IS_SKIPPED(picture) \
+    GST_VAAPI_PICTURE_FLAG_IS_SET(picture, GST_VAAPI_PICTURE_FLAG_SKIPPED)
+
+#define GST_VAAPI_PICTURE_IS_REFERENCE(picture) \
+    GST_VAAPI_PICTURE_FLAG_IS_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE)
+
+#define GST_VAAPI_PICTURE_IS_OUTPUT(picture) \
+    GST_VAAPI_PICTURE_FLAG_IS_SET(picture, GST_VAAPI_PICTURE_FLAG_OUTPUT)
+
+#define GST_VAAPI_PICTURE_IS_INTERLACED(picture) \
+    GST_VAAPI_PICTURE_FLAG_IS_SET(picture, GST_VAAPI_PICTURE_FLAG_INTERLACED)
+
+#define GST_VAAPI_PICTURE_IS_FIRST_FIELD(picture) \
+    GST_VAAPI_PICTURE_FLAG_IS_SET(picture, GST_VAAPI_PICTURE_FLAG_FF)
+
+#define GST_VAAPI_PICTURE_IS_TFF(picture) \
+    GST_VAAPI_PICTURE_FLAG_IS_SET(picture, GST_VAAPI_PICTURE_FLAG_TFF)
+
+#define GST_VAAPI_PICTURE_IS_FRAME(picture) \
+    (GST_VAAPI_PICTURE(picture)->structure == GST_VAAPI_PICTURE_STRUCTURE_FRAME)
+
+#define GST_VAAPI_PICTURE_IS_COMPLETE(picture)          \
+    (GST_VAAPI_PICTURE_IS_FRAME(picture) ||             \
+     !GST_VAAPI_PICTURE_IS_FIRST_FIELD(picture))
+
+/**
+ * GstVaapiPicture:
+ *
+ * A #GstVaapiCodecObject holding a picture parameter.
+ */
+struct _GstVaapiPicture {
+    /*< private >*/
+    GstVaapiCodecObject         parent_instance;
+    GstVaapiSurface            *surface;
+    GstVaapiSurfaceProxy       *proxy;
+    VABufferID                  param_id;
+    guint                       param_size;
+
+    /*< public >*/
+    GstVaapiPictureType         type;
+    VASurfaceID                 surface_id;
+    gpointer                    param;
+    GPtrArray                  *slices;
+    GstVaapiIqMatrix           *iq_matrix;
+    GstVaapiHuffmanTable       *huf_table;
+    GstVaapiBitPlane           *bitplane;
+    GstClockTime                pts;
+    gint32                      poc;
+    guint                       structure;
+};
+
+/**
+ * GstVaapiPictureClass:
+ *
+ * The #GstVaapiPicture base class.
+ */
+struct _GstVaapiPictureClass {
+    /*< private >*/
+    GstVaapiCodecObjectClass    parent_class;
+};
+
+G_GNUC_INTERNAL
+GType
+gst_vaapi_picture_get_type(void) G_GNUC_CONST;
+
+G_GNUC_INTERNAL
+GstVaapiPicture *
+gst_vaapi_picture_new(
+    GstVaapiDecoder *decoder,
+    gconstpointer    param,
+    guint            param_size
+);
+
+G_GNUC_INTERNAL
+GstVaapiPicture *
+gst_vaapi_picture_new_field(GstVaapiPicture *picture);
+
+G_GNUC_INTERNAL
+void
+gst_vaapi_picture_add_slice(GstVaapiPicture *picture, GstVaapiSlice *slice);
+
+G_GNUC_INTERNAL
+gboolean
+gst_vaapi_picture_decode(GstVaapiPicture *picture);
+
+G_GNUC_INTERNAL
+gboolean
+gst_vaapi_picture_output(GstVaapiPicture *picture);
+
+static inline gpointer
+gst_vaapi_picture_ref(gpointer ptr)
+{
+    return gst_mini_object_ref(GST_MINI_OBJECT(ptr));
+}
+
+static inline void
+gst_vaapi_picture_unref(gpointer ptr)
+{
+    gst_mini_object_unref(GST_MINI_OBJECT(ptr));
+}
+
+#define gst_vaapi_picture_replace(old_picture_p, new_picture)   \
+    gst_mini_object_replace((GstMiniObject **)(old_picture_p),  \
+                            (GstMiniObject *)(new_picture))
+
+/* ------------------------------------------------------------------------- */
+/* --- Slices                                                            --- */
+/* ------------------------------------------------------------------------- */
+
+#define GST_VAAPI_TYPE_SLICE \
+    (gst_vaapi_slice_get_type())
+
+#define GST_VAAPI_SLICE_CAST(obj) \
+    ((GstVaapiSlice *)(obj))
+
+#define GST_VAAPI_SLICE(obj)                            \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                  \
+                                GST_VAAPI_TYPE_SLICE,   \
+                                GstVaapiSlice))
+
+#define GST_VAAPI_SLICE_CLASS(klass)                    \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                   \
+                             GST_VAAPI_TYPE_SLICE,      \
+                             GstVaapiSliceClass))
+
+#define GST_VAAPI_IS_SLICE(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_SLICE))
+
+#define GST_VAAPI_IS_SLICE_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_SLICE))
+
+#define GST_VAAPI_SLICE_GET_CLASS(obj)                  \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                   \
+                               GST_VAAPI_TYPE_SLICE,    \
+                               GstVaapiSliceClass))
+
+/**
+ * GstVaapiSlice:
+ *
+ * A #GstVaapiCodecObject holding a slice parameter.
+ */
+struct _GstVaapiSlice {
+    /*< private >*/
+    GstVaapiCodecObject         parent_instance;
+
+    /*< public >*/
+    VABufferID                  param_id;
+    VABufferID                  data_id;
+    gpointer                    param;
+};
+
+/**
+ * GstVaapiSliceClass:
+ *
+ * The #GstVaapiSlice base class.
+ */
+struct _GstVaapiSliceClass {
+    /*< private >*/
+    GstVaapiCodecObjectClass    parent_class;
+};
+
+G_GNUC_INTERNAL
+GType
+gst_vaapi_slice_get_type(void) G_GNUC_CONST;
+
+G_GNUC_INTERNAL
+GstVaapiSlice *
+gst_vaapi_slice_new(
+    GstVaapiDecoder *decoder,
+    gconstpointer    param,
+    guint            param_size,
+    const guchar    *data,
+    guint            data_size
+);
+
+/* ------------------------------------------------------------------------- */
+/* --- Helpers to create codec-dependent objects                         --- */
+/* ------------------------------------------------------------------------- */
+
+#define GST_VAAPI_PICTURE_NEW(codec, decoder)                           \
+    gst_vaapi_picture_new(GST_VAAPI_DECODER_CAST(decoder),              \
+                          NULL, sizeof(VAPictureParameterBuffer##codec))
+
+#define GST_VAAPI_SLICE_NEW(codec, decoder, buf, buf_size)              \
+    gst_vaapi_slice_new(GST_VAAPI_DECODER_CAST(decoder),                \
+                        NULL, sizeof(VASliceParameterBuffer##codec),    \
+                        buf, buf_size)
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DECODER_OBJECTS_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_priv.h b/gst-libs/gst/vaapi/gstvaapidecoder_priv.h
new file mode 100644 (file)
index 0000000..686a16b
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ *  gstvaapidecoder_priv.h - VA decoder abstraction (private definitions)
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DECODER_PRIV_H
+#define GST_VAAPI_DECODER_PRIV_H
+
+#include <glib.h>
+#include <gst/vaapi/gstvaapidecoder.h>
+#include <gst/vaapi/gstvaapicontext.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_DECODER_CAST(decoder) ((GstVaapiDecoder *)(decoder))
+
+/**
+ * GST_VAAPI_DECODER_DISPLAY:
+ * @decoder: a #GstVaapiDecoder
+ *
+ * Macro that evaluates to the #GstVaapiDisplay of @decoder.
+ * This is an internal macro that does not do any run-time type check.
+ */
+#undef  GST_VAAPI_DECODER_DISPLAY
+#define GST_VAAPI_DECODER_DISPLAY(decoder) \
+    GST_VAAPI_DECODER_CAST(decoder)->priv->display
+
+/**
+ * GST_VAAPI_DECODER_CONTEXT:
+ * @decoder: a #GstVaapiDecoder
+ *
+ * Macro that evaluates to the #GstVaapiContext of @decoder.
+ * This is an internal macro that does not do any run-time type check.
+ */
+#undef  GST_VAAPI_DECODER_CONTEXT
+#define GST_VAAPI_DECODER_CONTEXT(decoder) \
+    GST_VAAPI_DECODER_CAST(decoder)->priv->context
+
+/**
+ * GST_VAAPI_DECODER_CODEC:
+ * @decoder: a #GstVaapiDecoder
+ *
+ * Macro that evaluates to the #GstVaapiCodec of @decoder.
+ * This is an internal macro that does not do any run-time type check.
+ */
+#undef  GST_VAAPI_DECODER_CODEC
+#define GST_VAAPI_DECODER_CODEC(decoder) \
+    GST_VAAPI_DECODER_CAST(decoder)->priv->codec
+
+/**
+ * GST_VAAPI_DECODER_CODEC_DATA:
+ * @decoder: a #GstVaapiDecoder
+ *
+ * Macro that evaluates to the #GstBuffer holding optional codec data
+ * for @decoder.
+ * This is an internal macro that does not do any run-time type check.
+ */
+#undef  GST_VAAPI_DECODER_CODEC_DATA
+#define GST_VAAPI_DECODER_CODEC_DATA(decoder) \
+    GST_VAAPI_DECODER_CAST(decoder)->priv->codec_data
+
+/**
+ * GST_VAAPI_DECODER_WIDTH:
+ * @decoder: a #GstVaapiDecoder
+ *
+ * Macro that evaluates to the coded width of the picture
+ * This is an internal macro that does not do any run-time type check.
+ */
+#undef  GST_VAAPI_DECODER_WIDTH
+#define GST_VAAPI_DECODER_WIDTH(decoder) \
+    GST_VAAPI_DECODER_CAST(decoder)->priv->width
+
+/**
+ * GST_VAAPI_DECODER_HEIGHT:
+ * @decoder: a #GstVaapiDecoder
+ *
+ * Macro that evaluates to the coded height of the picture
+ * This is an internal macro that does not do any run-time type check.
+ */
+#undef  GST_VAAPI_DECODER_HEIGHT
+#define GST_VAAPI_DECODER_HEIGHT(decoder) \
+    GST_VAAPI_DECODER_CAST(decoder)->priv->height
+
+/* End-of-Stream buffer */
+#define GST_BUFFER_FLAG_EOS (GST_BUFFER_FLAG_LAST + 0)
+
+#define GST_BUFFER_IS_EOS(buffer) \
+    GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_EOS)
+
+#define GST_VAAPI_DECODER_GET_PRIVATE(obj)                      \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_DECODER,        \
+                                 GstVaapiDecoderPrivate))
+
+/* Number of scratch surfaces beyond those used as reference */
+/* 5 = 2 + 4; 2 for reference, 4  for scratch*/
+#define GST_DECODER_DEFAULT_SURFACES_COUNT 6
+
+struct _GstVaapiDecoderPrivate {
+    GstVaapiDisplay    *display;
+    VADisplay           va_display;
+    GstVaapiContext    *context;
+    VAContextID         va_context;
+    GstCaps            *caps;
+    GstVaapiCodec       codec;
+    GstBuffer          *codec_data;
+    guint               width;
+    guint               height;
+    guint               fps_n;
+    guint               fps_d;
+    guint               par_n;
+    guint               par_d;
+    GQueue             *buffers;
+    GQueue             *surfaces;
+    guint               is_interlaced   : 1;
+};
+
+G_GNUC_INTERNAL
+void
+gst_vaapi_decoder_set_picture_size(
+    GstVaapiDecoder    *decoder,
+    guint               width,
+    guint               height
+);
+
+G_GNUC_INTERNAL
+void
+gst_vaapi_decoder_set_framerate(
+    GstVaapiDecoder    *decoder,
+    guint               fps_n,
+    guint               fps_d
+);
+
+G_GNUC_INTERNAL
+void
+gst_vaapi_decoder_set_pixel_aspect_ratio(
+    GstVaapiDecoder    *decoder,
+    guint               par_n,
+    guint               par_d
+);
+
+G_GNUC_INTERNAL
+void
+gst_vaapi_decoder_set_interlaced(GstVaapiDecoder *decoder, gboolean interlaced);
+
+G_GNUC_INTERNAL
+gboolean
+gst_vaapi_decoder_ensure_context(
+    GstVaapiDecoder    *decoder,
+    GstVaapiProfile     profile,
+    GstVaapiEntrypoint  entrypoint,
+    guint               width,
+    guint               height,
+    guint               surface_num
+);
+
+G_GNUC_INTERNAL
+gboolean
+gst_vaapi_decoder_push_buffer_sub(
+    GstVaapiDecoder *decoder,
+    GstBuffer       *buffer,
+    guint            offset,
+    guint            size
+);
+
+G_GNUC_INTERNAL
+void
+gst_vaapi_decoder_push_surface_proxy(
+    GstVaapiDecoder      *decoder,
+    GstVaapiSurfaceProxy *proxy
+);
+
+G_GNUC_INTERNAL
+GstVaapiDecoderStatus
+gst_vaapi_decoder_check_status(GstVaapiDecoder *decoder);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DECODER_PRIV_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_vc1.c b/gst-libs/gst/vaapi/gstvaapidecoder_vc1.c
new file mode 100644 (file)
index 0000000..f91a6d5
--- /dev/null
@@ -0,0 +1,1344 @@
+/*
+ *  gstvaapidecoder_vc1.c - VC-1 decoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapidecoder_vc1
+ * @short_description: VC-1 decoder
+ */
+
+#include "sysdeps.h"
+#include <string.h>
+#include <gst/codecparsers/gstvc1parser.h>
+#include "gstvaapidecoder_vc1.h"
+#include "gstvaapidecoder_objects.h"
+#include "gstvaapidecoder_priv.h"
+#include "gstvaapidisplay_priv.h"
+#include "gstvaapiobject_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiDecoderVC1,
+              gst_vaapi_decoder_vc1,
+              GST_VAAPI_TYPE_DECODER);
+
+#define GST_VAAPI_DECODER_VC1_GET_PRIVATE(obj)                  \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_DECODER_VC1,    \
+                                 GstVaapiDecoderVC1Private))
+
+struct _GstVaapiDecoderVC1Private {
+    GstVaapiProfile             profile;
+    guint                       width;
+    guint                       height;
+    guint                       fps_n;
+    guint                       fps_d;
+    GstVC1SeqHdr                seq_hdr;
+    GstVC1EntryPointHdr         entrypoint_hdr;
+    GstVC1FrameHdr              frame_hdr;
+    GstVC1BitPlanes            *bitplanes;
+    GstVaapiPicture            *current_picture;
+    GstVaapiPicture            *next_picture;
+    GstVaapiPicture            *prev_picture;
+    GstAdapter                 *adapter;
+    GstBuffer                  *sub_buffer;
+    guint8                     *rbdu_buffer;
+    guint                       rbdu_buffer_size;
+    guint                       is_constructed          : 1;
+    guint                       is_opened               : 1;
+    guint                       is_first_field          : 1;
+    guint                       has_entrypoint          : 1;
+    guint                       size_changed            : 1;
+    guint                       profile_changed         : 1;
+    guint                       closed_entry            : 1;
+    guint                       broken_link             : 1;
+};
+
+static GstVaapiDecoderStatus
+get_status(GstVC1ParserResult result)
+{
+    GstVaapiDecoderStatus status;
+
+    switch (result) {
+    case GST_VC1_PARSER_OK:
+        status = GST_VAAPI_DECODER_STATUS_SUCCESS;
+        break;
+    case GST_VC1_PARSER_NO_BDU_END:
+        status = GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+        break;
+    case GST_VC1_PARSER_ERROR:
+        status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+        break;
+    default:
+        status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+        break;
+    }
+    return status;
+}
+
+static void
+gst_vaapi_decoder_vc1_close(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+
+    gst_vaapi_picture_replace(&priv->current_picture, NULL);
+    gst_vaapi_picture_replace(&priv->next_picture,    NULL);
+    gst_vaapi_picture_replace(&priv->prev_picture,    NULL);
+
+    if (priv->sub_buffer) {
+        gst_buffer_unref(priv->sub_buffer);
+        priv->sub_buffer = NULL;
+    }
+
+    if (priv->bitplanes) {
+        gst_vc1_bitplanes_free(priv->bitplanes);
+        priv->bitplanes = NULL;
+    }
+
+    if (priv->adapter) {
+        gst_adapter_clear(priv->adapter);
+        g_object_unref(priv->adapter);
+        priv->adapter = NULL;
+    }
+}
+
+static gboolean
+gst_vaapi_decoder_vc1_open(GstVaapiDecoderVC1 *decoder, GstBuffer *buffer)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+
+    gst_vaapi_decoder_vc1_close(decoder);
+
+    priv->adapter = gst_adapter_new();
+    if (!priv->adapter)
+        return FALSE;
+
+    priv->bitplanes = gst_vc1_bitplanes_new();
+    if (!priv->bitplanes)
+        return FALSE;
+    return TRUE;
+}
+
+static void
+gst_vaapi_decoder_vc1_destroy(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+
+    gst_vaapi_decoder_vc1_close(decoder);
+
+    if (priv->rbdu_buffer) {
+        g_free(priv->rbdu_buffer);
+        priv->rbdu_buffer = NULL;
+        priv->rbdu_buffer_size = 0;
+    }
+}
+
+static gboolean
+gst_vaapi_decoder_vc1_create(GstVaapiDecoderVC1 *decoder)
+{
+    if (!GST_VAAPI_DECODER_CODEC(decoder))
+        return FALSE;
+    return TRUE;
+}
+
+static GstVaapiDecoderStatus
+ensure_context(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVaapiProfile profiles[2];
+    GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
+    guint i, n_profiles = 0;
+    gboolean reset_context = FALSE;
+
+    if (priv->profile_changed) {
+        GST_DEBUG("profile changed");
+        priv->profile_changed = FALSE;
+        reset_context         = TRUE;
+
+        profiles[n_profiles++] = priv->profile;
+        if (priv->profile == GST_VAAPI_PROFILE_VC1_SIMPLE)
+            profiles[n_profiles++] = GST_VAAPI_PROFILE_VC1_MAIN;
+
+        for (i = 0; i < n_profiles; i++) {
+            if (gst_vaapi_display_has_decoder(GST_VAAPI_DECODER_DISPLAY(decoder),
+                                              profiles[i], entrypoint))
+                break;
+        }
+        if (i == n_profiles)
+            return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
+        priv->profile = profiles[i];
+    }
+
+    if (priv->size_changed) {
+        GST_DEBUG("size changed");
+        priv->size_changed = FALSE;
+        reset_context      = TRUE;
+    }
+
+    if (reset_context) {
+        reset_context = gst_vaapi_decoder_ensure_context(
+            GST_VAAPI_DECODER(decoder),
+            priv->profile,
+            entrypoint,
+            priv->width,
+            priv->height,
+            GST_DECODER_DEFAULT_SURFACES_COUNT
+        );
+        if (!reset_context)
+            return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+    }
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static inline GstVaapiDecoderStatus
+render_picture(GstVaapiDecoderVC1 *decoder, GstVaapiPicture *picture)
+{
+    if (!gst_vaapi_picture_output(picture))
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_current_picture(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVaapiPicture * const picture = priv->current_picture;
+    GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_SUCCESS;
+
+    if (picture) {
+        if (!gst_vaapi_picture_decode(picture))
+            status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+        if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture)) {
+            if (priv->prev_picture && priv->next_picture)
+                status = render_picture(decoder, picture);
+        }
+        gst_vaapi_picture_replace(&priv->current_picture, NULL);
+    }
+    return status;
+}
+
+static GstVaapiDecoderStatus
+decode_sequence(GstVaapiDecoderVC1 *decoder, GstVC1BDU *rbdu, GstVC1BDU *ebdu)
+{
+    GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVC1AdvancedSeqHdr * const adv_hdr = &seq_hdr->advanced;
+    GstVC1SeqStructC * const structc = &seq_hdr->struct_c;
+    GstVC1ParserResult result;
+    GstVaapiProfile profile;
+    guint width, height, fps_n, fps_d;
+
+    result = gst_vc1_parse_sequence_header(
+        rbdu->data + rbdu->offset,
+        rbdu->size,
+        seq_hdr
+    );
+    if (result != GST_VC1_PARSER_OK) {
+        GST_DEBUG("failed to parse sequence layer");
+        return get_status(result);
+    }
+
+    priv->has_entrypoint = FALSE;
+
+    /* Validate profile */
+    switch (seq_hdr->profile) {
+    case GST_VC1_PROFILE_SIMPLE:
+    case GST_VC1_PROFILE_MAIN:
+    case GST_VC1_PROFILE_ADVANCED:
+        break;
+    default:
+        GST_DEBUG("unsupported profile %d", seq_hdr->profile);
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
+    }
+
+    fps_n = 0;
+    fps_d = 0;
+    switch (seq_hdr->profile) {
+    case GST_VC1_PROFILE_SIMPLE:
+    case GST_VC1_PROFILE_MAIN:
+        if (structc->wmvp) {
+            fps_n = structc->framerate;
+            fps_d = 1;
+        }
+        break;
+    case GST_VC1_PROFILE_ADVANCED:
+        if (adv_hdr->display_ext && adv_hdr->framerate_flag) {
+            if (adv_hdr->framerateind) {
+                // 6.1.14.4.4 - Frame Rate Explicit
+                fps_n = adv_hdr->framerateexp + 1;
+                fps_d = 32;
+            }
+            else {
+                // 6.1.14.4.2 - Frame Rate Numerator
+                static const guint frameratenr_table[] = {
+                    [1] = 24000,
+                    [2] = 25000,
+                    [3] = 30000,
+                    [4] = 50000,
+                    [5] = 60000,
+                    [6] = 48000,
+                    [7] = 72000
+                };
+
+                // 6.1.14.4.3 - Frame Rate Denominator
+                static const guint frameratedr_table[] = {
+                    [1] = 1000,
+                    [2] = 1001
+                };
+
+                if (adv_hdr->frameratenr < 1 || adv_hdr->frameratenr > 7) {
+                    GST_DEBUG("unsupported FRAMERATENR value");
+                    return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+                }
+                fps_n = frameratenr_table[adv_hdr->frameratenr];
+
+                if (adv_hdr->frameratedr < 1 || adv_hdr->frameratedr > 2) {
+                    GST_DEBUG("unsupported FRAMERATEDR value");
+                    return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+                }
+                fps_d = frameratedr_table[adv_hdr->frameratedr];
+            }
+        }
+        break;
+    default:
+        g_assert(0 && "XXX: we already validated the profile above");
+        break;
+    }
+    if (fps_n && fps_d) {
+        priv->fps_n = fps_n;
+        priv->fps_d = fps_d;
+        gst_vaapi_decoder_set_framerate(base_decoder, priv->fps_n, priv->fps_d);
+    }
+
+    switch (seq_hdr->profile) {
+    case GST_VC1_PROFILE_SIMPLE:
+    case GST_VC1_PROFILE_MAIN:
+        width  = seq_hdr->struct_c.coded_width;
+        height = seq_hdr->struct_c.coded_height;
+        break;
+    case GST_VC1_PROFILE_ADVANCED:
+        width  = seq_hdr->advanced.max_coded_width;
+        height = seq_hdr->advanced.max_coded_height;
+        break;
+    default:
+        g_assert(0 && "XXX: we already validated the profile above");
+        break;
+    }
+
+    if (priv->width != width) {
+        priv->width = width;
+        priv->size_changed = TRUE;
+    }
+
+    if (priv->height != height) {
+        priv->height = height;
+        priv->size_changed = TRUE;
+    }
+
+    switch (seq_hdr->profile) {
+    case GST_VC1_PROFILE_SIMPLE:
+        profile = GST_VAAPI_PROFILE_VC1_SIMPLE;
+        break;
+    case GST_VC1_PROFILE_MAIN:
+        profile = GST_VAAPI_PROFILE_VC1_MAIN;
+        break;
+    case GST_VC1_PROFILE_ADVANCED:
+        profile = GST_VAAPI_PROFILE_VC1_ADVANCED;
+        break;
+    default:
+        g_assert(0 && "XXX: we already validated the profile above");
+        break;
+    }
+    if (priv->profile != profile) {
+        priv->profile = profile;
+        priv->profile_changed = TRUE;
+    }
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+static GstVaapiDecoderStatus
+decode_sequence_end(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVaapiDecoderStatus status;
+
+    if (priv->current_picture) {
+        status = decode_current_picture(decoder);
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            return status;
+        status = render_picture(decoder, priv->current_picture);
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            return status;
+    }
+
+    if (priv->next_picture) {
+        status = render_picture(decoder, priv->next_picture);
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            return status;
+    }
+    return GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
+}
+
+static GstVaapiDecoderStatus
+decode_entry_point(GstVaapiDecoderVC1 *decoder, GstVC1BDU *rbdu, GstVC1BDU *ebdu)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVC1EntryPointHdr * const entrypoint_hdr = &priv->entrypoint_hdr;
+    GstVC1ParserResult result;
+
+    result = gst_vc1_parse_entry_point_header(
+        rbdu->data + rbdu->offset,
+        rbdu->size,
+        entrypoint_hdr,
+        seq_hdr
+    );
+    if (result != GST_VC1_PARSER_OK) {
+        GST_DEBUG("failed to parse entrypoint layer");
+        return get_status(result);
+    }
+
+    if (entrypoint_hdr->coded_size_flag) {
+        priv->width        = entrypoint_hdr->coded_width;
+        priv->height       = entrypoint_hdr->coded_height;
+        priv->size_changed = TRUE;
+    }
+
+    priv->has_entrypoint = TRUE;
+    priv->closed_entry   = entrypoint_hdr->closed_entry;
+    priv->broken_link    = entrypoint_hdr->broken_link;
+    return GST_VAAPI_DECODER_STATUS_SUCCESS;
+}
+
+/* Reconstruct bitstream PTYPE (7.1.1.4, index into Table-35) */
+static guint
+get_PTYPE(guint ptype)
+{
+    switch (ptype) {
+    case GST_VC1_PICTURE_TYPE_I:  return 0;
+    case GST_VC1_PICTURE_TYPE_P:  return 1;
+    case GST_VC1_PICTURE_TYPE_B:  return 2;
+    case GST_VC1_PICTURE_TYPE_BI: return 3;
+    }
+    return 4; /* skipped P-frame */
+}
+
+/* Reconstruct bitstream BFRACTION (7.1.1.14, index into Table-40) */
+static guint
+get_BFRACTION(guint bfraction)
+{
+    guint i;
+
+    static const struct {
+        guint16 index;
+        guint16 value;
+    }
+    bfraction_map[] = {
+        {  0,  GST_VC1_BFRACTION_BASIS      / 2 },
+        {  1,  GST_VC1_BFRACTION_BASIS      / 3 },
+        {  2, (GST_VC1_BFRACTION_BASIS * 2) / 3 },
+        {  3,  GST_VC1_BFRACTION_BASIS      / 4 },
+        {  4, (GST_VC1_BFRACTION_BASIS * 3) / 4 },
+        {  5,  GST_VC1_BFRACTION_BASIS      / 5 },
+        {  6, (GST_VC1_BFRACTION_BASIS * 2) / 5 },
+        {  7, (GST_VC1_BFRACTION_BASIS * 3) / 5 },
+        {  8, (GST_VC1_BFRACTION_BASIS * 4) / 5 },
+        {  9,  GST_VC1_BFRACTION_BASIS      / 6 },
+        { 10, (GST_VC1_BFRACTION_BASIS * 5) / 6 },
+        { 11,  GST_VC1_BFRACTION_BASIS      / 7 },
+        { 12, (GST_VC1_BFRACTION_BASIS * 2) / 7 },
+        { 13, (GST_VC1_BFRACTION_BASIS * 3) / 7 },
+        { 14, (GST_VC1_BFRACTION_BASIS * 4) / 7 },
+        { 15, (GST_VC1_BFRACTION_BASIS * 5) / 7 },
+        { 16, (GST_VC1_BFRACTION_BASIS * 6) / 7 },
+        { 17,  GST_VC1_BFRACTION_BASIS      / 8 },
+        { 18, (GST_VC1_BFRACTION_BASIS * 3) / 8 },
+        { 19, (GST_VC1_BFRACTION_BASIS * 5) / 8 },
+        { 20, (GST_VC1_BFRACTION_BASIS * 7) / 8 },
+        { 21,  GST_VC1_BFRACTION_RESERVED },
+        { 22,  GST_VC1_BFRACTION_PTYPE_BI }
+    };
+
+    if (!bfraction)
+        return 0;
+
+    for (i = 0; i < G_N_ELEMENTS(bfraction_map); i++) {
+        if (bfraction_map[i].value == bfraction)
+            return bfraction_map[i].index;
+    }
+    return 21; /* RESERVED */
+}
+
+/* Translate GStreamer MV modes to VA-API */
+static guint
+get_VAMvModeVC1(guint mvmode)
+{
+    switch (mvmode) {
+    case GST_VC1_MVMODE_1MV_HPEL_BILINEAR: return VAMvMode1MvHalfPelBilinear;
+    case GST_VC1_MVMODE_1MV:               return VAMvMode1Mv;
+    case GST_VC1_MVMODE_1MV_HPEL:          return VAMvMode1MvHalfPel;
+    case GST_VC1_MVMODE_MIXED_MV:          return VAMvModeMixedMv;
+    case GST_VC1_MVMODE_INTENSITY_COMP:    return VAMvModeIntensityCompensation;
+    }
+    return 0;
+}
+
+/* Reconstruct bitstream MVMODE (7.1.1.32) */
+static guint
+get_MVMODE(GstVC1FrameHdr *frame_hdr)
+{
+    guint mvmode;
+
+    if (frame_hdr->profile == GST_VC1_PROFILE_ADVANCED)
+        mvmode = frame_hdr->pic.advanced.mvmode;
+    else
+        mvmode = frame_hdr->pic.simple.mvmode;
+
+    if (frame_hdr->ptype == GST_VC1_PICTURE_TYPE_P ||
+        frame_hdr->ptype == GST_VC1_PICTURE_TYPE_B)
+        return get_VAMvModeVC1(mvmode);
+    return 0;
+}
+
+/* Reconstruct bitstream MVMODE2 (7.1.1.33) */
+static guint
+get_MVMODE2(GstVC1FrameHdr *frame_hdr)
+{
+    guint mvmode, mvmode2;
+
+    if (frame_hdr->profile == GST_VC1_PROFILE_ADVANCED) {
+        mvmode  = frame_hdr->pic.advanced.mvmode;
+        mvmode2 = frame_hdr->pic.advanced.mvmode2;
+    }
+    else {
+        mvmode  = frame_hdr->pic.simple.mvmode;
+        mvmode2 = frame_hdr->pic.simple.mvmode2;
+    }
+
+    if (frame_hdr->ptype == GST_VC1_PICTURE_TYPE_P &&
+        mvmode == GST_VC1_MVMODE_INTENSITY_COMP)
+        return get_VAMvModeVC1(mvmode2);
+    return 0;
+}
+
+static inline int
+has_MVTYPEMB_bitplane(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
+    guint mvmode, mvmode2;
+
+    if (seq_hdr->profile == GST_VC1_PROFILE_ADVANCED) {
+        GstVC1PicAdvanced * const pic = &frame_hdr->pic.advanced;
+        if (pic->mvtypemb)
+            return 0;
+        mvmode  = pic->mvmode;
+        mvmode2 = pic->mvmode2;
+    }
+    else {
+        GstVC1PicSimpleMain * const pic = &frame_hdr->pic.simple;
+        if (pic->mvtypemb)
+            return 0;
+        mvmode  = pic->mvmode;
+        mvmode2 = pic->mvmode2;
+    }
+    return (frame_hdr->ptype == GST_VC1_PICTURE_TYPE_P &&
+            (mvmode == GST_VC1_MVMODE_MIXED_MV ||
+             (mvmode == GST_VC1_MVMODE_INTENSITY_COMP &&
+              mvmode2 == GST_VC1_MVMODE_MIXED_MV)));
+}
+
+static inline int
+has_SKIPMB_bitplane(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
+
+    if (seq_hdr->profile == GST_VC1_PROFILE_ADVANCED) {
+        GstVC1PicAdvanced * const pic = &frame_hdr->pic.advanced;
+        if (pic->skipmb)
+            return 0;
+    }
+    else {
+        GstVC1PicSimpleMain * const pic = &frame_hdr->pic.simple;
+        if (pic->skipmb)
+            return 0;
+    }
+    return (frame_hdr->ptype == GST_VC1_PICTURE_TYPE_P ||
+            frame_hdr->ptype == GST_VC1_PICTURE_TYPE_B);
+}
+
+static inline int
+has_DIRECTMB_bitplane(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
+
+    if (seq_hdr->profile == GST_VC1_PROFILE_ADVANCED) {
+        GstVC1PicAdvanced * const pic = &frame_hdr->pic.advanced;
+        if (pic->directmb)
+            return 0;
+    }
+    else {
+        GstVC1PicSimpleMain * const pic = &frame_hdr->pic.simple;
+        if (pic->directmb)
+            return 0;
+    }
+    return frame_hdr->ptype == GST_VC1_PICTURE_TYPE_B;
+}
+
+static inline int
+has_ACPRED_bitplane(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
+    GstVC1PicAdvanced * const pic = &frame_hdr->pic.advanced;
+
+    if (seq_hdr->profile != GST_VC1_PROFILE_ADVANCED)
+        return 0;
+    if (pic->acpred)
+        return 0;
+    return (frame_hdr->ptype == GST_VC1_PICTURE_TYPE_I ||
+            frame_hdr->ptype == GST_VC1_PICTURE_TYPE_BI);
+}
+
+static inline int
+has_OVERFLAGS_bitplane(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVC1EntryPointHdr * const entrypoint_hdr = &priv->entrypoint_hdr;
+    GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
+    GstVC1PicAdvanced * const pic = &frame_hdr->pic.advanced;
+
+    if (seq_hdr->profile != GST_VC1_PROFILE_ADVANCED)
+        return 0;
+    if (pic->overflags)
+        return 0;
+    return ((frame_hdr->ptype == GST_VC1_PICTURE_TYPE_I ||
+             frame_hdr->ptype == GST_VC1_PICTURE_TYPE_BI) &&
+            (entrypoint_hdr->overlap && frame_hdr->pquant <= 8) &&
+            pic->condover == GST_VC1_CONDOVER_SELECT);
+}
+
+static inline void
+pack_bitplanes(GstVaapiBitPlane *bitplane, guint n, const guint8 *bitplanes[3], guint x, guint y, guint stride)
+{
+    const guint dst_index = n / 2;
+    const guint src_index = y * stride + x;
+    guint8 v = 0;
+
+    if (bitplanes[0])
+        v |= bitplanes[0][src_index];
+    if (bitplanes[1])
+        v |= bitplanes[1][src_index] << 1;
+    if (bitplanes[2])
+        v |= bitplanes[2][src_index] << 2;
+    bitplane->data[dst_index] = (bitplane->data[dst_index] << 4) | v;
+}
+
+static gboolean
+fill_picture_structc(GstVaapiDecoderVC1 *decoder, GstVaapiPicture *picture)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    VAPictureParameterBufferVC1 * const pic_param = picture->param;
+    GstVC1SeqStructC * const structc = &priv->seq_hdr.struct_c;
+    GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
+    GstVC1PicSimpleMain * const pic = &frame_hdr->pic.simple;
+
+    /* Fill in VAPictureParameterBufferVC1 (simple/main profile bits) */
+    pic_param->sequence_fields.bits.finterpflag                     = structc->finterpflag;
+    pic_param->sequence_fields.bits.multires                        = structc->multires;
+    pic_param->sequence_fields.bits.overlap                         = structc->overlap;
+    pic_param->sequence_fields.bits.syncmarker                      = structc->syncmarker;
+    pic_param->sequence_fields.bits.rangered                        = structc->rangered;
+    pic_param->sequence_fields.bits.max_b_frames                    = structc->maxbframes;
+    pic_param->conditional_overlap_flag                             = 0; /* advanced profile only */
+    pic_param->fast_uvmc_flag                                       = structc->fastuvmc;
+    pic_param->b_picture_fraction                                   = get_BFRACTION(pic->bfraction);
+    pic_param->cbp_table                                            = pic->cbptab;
+    pic_param->mb_mode_table                                        = 0; /* XXX: interlaced frame */
+    pic_param->range_reduction_frame                                = pic->rangeredfrm;
+    pic_param->rounding_control                                     = 0; /* advanced profile only */
+    pic_param->post_processing                                      = 0; /* advanced profile only */
+    pic_param->picture_resolution_index                             = pic->respic;
+    pic_param->luma_scale                                           = pic->lumscale;
+    pic_param->luma_shift                                           = pic->lumshift;
+    pic_param->raw_coding.flags.mv_type_mb                          = pic->mvtypemb;
+    pic_param->raw_coding.flags.direct_mb                           = pic->directmb;
+    pic_param->raw_coding.flags.skip_mb                             = pic->skipmb;
+    pic_param->bitplane_present.flags.bp_mv_type_mb                 = has_MVTYPEMB_bitplane(decoder);
+    pic_param->bitplane_present.flags.bp_direct_mb                  = has_DIRECTMB_bitplane(decoder);
+    pic_param->bitplane_present.flags.bp_skip_mb                    = has_SKIPMB_bitplane(decoder);
+    pic_param->mv_fields.bits.mv_table                              = pic->mvtab;
+    pic_param->mv_fields.bits.extended_mv_flag                      = structc->extended_mv;
+    pic_param->mv_fields.bits.extended_mv_range                     = pic->mvrange;
+    pic_param->transform_fields.bits.variable_sized_transform_flag  = structc->vstransform;
+    pic_param->transform_fields.bits.mb_level_transform_type_flag   = pic->ttmbf;
+    pic_param->transform_fields.bits.frame_level_transform_type     = pic->ttfrm;
+    pic_param->transform_fields.bits.transform_ac_codingset_idx2    = pic->transacfrm2;
+    return TRUE;
+}
+
+static gboolean
+fill_picture_advanced(GstVaapiDecoderVC1 *decoder, GstVaapiPicture *picture)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    VAPictureParameterBufferVC1 * const pic_param = picture->param;
+    GstVC1AdvancedSeqHdr * const adv_hdr = &priv->seq_hdr.advanced;
+    GstVC1EntryPointHdr * const entrypoint_hdr = &priv->entrypoint_hdr;
+    GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
+    GstVC1PicAdvanced * const pic = &frame_hdr->pic.advanced;
+
+    if (!priv->has_entrypoint)
+        return FALSE;
+
+    /* Fill in VAPictureParameterBufferVC1 (advanced profile bits) */
+    pic_param->sequence_fields.bits.pulldown                        = adv_hdr->pulldown;
+    pic_param->sequence_fields.bits.interlace                       = adv_hdr->interlace;
+    pic_param->sequence_fields.bits.tfcntrflag                      = adv_hdr->tfcntrflag;
+    pic_param->sequence_fields.bits.finterpflag                     = adv_hdr->finterpflag;
+    pic_param->sequence_fields.bits.psf                             = adv_hdr->psf;
+    pic_param->sequence_fields.bits.overlap                         = entrypoint_hdr->overlap;
+    pic_param->entrypoint_fields.bits.broken_link                   = entrypoint_hdr->broken_link;
+    pic_param->entrypoint_fields.bits.closed_entry                  = entrypoint_hdr->closed_entry;
+    pic_param->entrypoint_fields.bits.panscan_flag                  = entrypoint_hdr->panscan_flag;
+    pic_param->entrypoint_fields.bits.loopfilter                    = entrypoint_hdr->loopfilter;
+    pic_param->conditional_overlap_flag                             = pic->condover;
+    pic_param->fast_uvmc_flag                                       = entrypoint_hdr->fastuvmc;
+    pic_param->range_mapping_fields.bits.luma_flag                  = entrypoint_hdr->range_mapy_flag;
+    pic_param->range_mapping_fields.bits.luma                       = entrypoint_hdr->range_mapy;
+    pic_param->range_mapping_fields.bits.chroma_flag                = entrypoint_hdr->range_mapuv_flag;
+    pic_param->range_mapping_fields.bits.chroma                     = entrypoint_hdr->range_mapuv;
+    pic_param->b_picture_fraction                                   = get_BFRACTION(pic->bfraction);
+    pic_param->cbp_table                                            = pic->cbptab;
+    pic_param->mb_mode_table                                        = 0; /* XXX: interlaced frame */
+    pic_param->range_reduction_frame                                = 0; /* simple/main profile only */
+    pic_param->rounding_control                                     = pic->rndctrl;
+    pic_param->post_processing                                      = pic->postproc;
+    pic_param->picture_resolution_index                             = 0; /* simple/main profile only */
+    pic_param->luma_scale                                           = pic->lumscale;
+    pic_param->luma_shift                                           = pic->lumshift;
+    pic_param->picture_fields.bits.frame_coding_mode                = pic->fcm;
+    pic_param->picture_fields.bits.top_field_first                  = pic->tff;
+    pic_param->picture_fields.bits.is_first_field                   = pic->fcm == 0; /* XXX: interlaced frame */
+    pic_param->picture_fields.bits.intensity_compensation           = pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP;
+    pic_param->raw_coding.flags.mv_type_mb                          = pic->mvtypemb;
+    pic_param->raw_coding.flags.direct_mb                           = pic->directmb;
+    pic_param->raw_coding.flags.skip_mb                             = pic->skipmb;
+    pic_param->raw_coding.flags.ac_pred                             = pic->acpred;
+    pic_param->raw_coding.flags.overflags                           = pic->overflags;
+    pic_param->bitplane_present.flags.bp_mv_type_mb                 = has_MVTYPEMB_bitplane(decoder);
+    pic_param->bitplane_present.flags.bp_direct_mb                  = has_DIRECTMB_bitplane(decoder);
+    pic_param->bitplane_present.flags.bp_skip_mb                    = has_SKIPMB_bitplane(decoder);
+    pic_param->bitplane_present.flags.bp_ac_pred                    = has_ACPRED_bitplane(decoder);
+    pic_param->bitplane_present.flags.bp_overflags                  = has_OVERFLAGS_bitplane(decoder);
+    pic_param->reference_fields.bits.reference_distance_flag        = entrypoint_hdr->refdist_flag;
+    pic_param->mv_fields.bits.mv_table                              = pic->mvtab;
+    pic_param->mv_fields.bits.extended_mv_flag                      = entrypoint_hdr->extended_mv;
+    pic_param->mv_fields.bits.extended_mv_range                     = pic->mvrange;
+    pic_param->mv_fields.bits.extended_dmv_flag                     = entrypoint_hdr->extended_dmv;
+    pic_param->pic_quantizer_fields.bits.dquant                     = entrypoint_hdr->dquant;
+    pic_param->pic_quantizer_fields.bits.quantizer                  = entrypoint_hdr->quantizer;
+    pic_param->transform_fields.bits.variable_sized_transform_flag  = entrypoint_hdr->vstransform;
+    pic_param->transform_fields.bits.mb_level_transform_type_flag   = pic->ttmbf;
+    pic_param->transform_fields.bits.frame_level_transform_type     = pic->ttfrm;
+    pic_param->transform_fields.bits.transform_ac_codingset_idx2    = pic->transacfrm2;
+    return TRUE;
+}
+
+static gboolean
+fill_picture(GstVaapiDecoderVC1 *decoder, GstVaapiPicture *picture)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    VAPictureParameterBufferVC1 * const pic_param = picture->param;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
+
+    /* Fill in VAPictureParameterBufferVC1 (common fields) */
+    pic_param->forward_reference_picture                            = VA_INVALID_ID;
+    pic_param->backward_reference_picture                           = VA_INVALID_ID;
+    pic_param->inloop_decoded_picture                               = VA_INVALID_ID;
+    pic_param->sequence_fields.value                                = 0;
+#if VA_CHECK_VERSION(0,32,0)
+    pic_param->sequence_fields.bits.profile                         = seq_hdr->profile;
+#endif
+    pic_param->coded_width                                          = priv->width;
+    pic_param->coded_height                                         = priv->height;
+    pic_param->entrypoint_fields.value                              = 0;
+    pic_param->range_mapping_fields.value                           = 0;
+    pic_param->picture_fields.value                                 = 0;
+    pic_param->picture_fields.bits.picture_type                     = get_PTYPE(frame_hdr->ptype);
+    pic_param->raw_coding.value                                     = 0;
+    pic_param->bitplane_present.value                               = 0;
+    pic_param->reference_fields.value                               = 0;
+    pic_param->mv_fields.value                                      = 0;
+    pic_param->mv_fields.bits.mv_mode                               = get_MVMODE(frame_hdr);
+    pic_param->mv_fields.bits.mv_mode2                              = get_MVMODE2(frame_hdr);
+    pic_param->pic_quantizer_fields.value                           = 0;
+    pic_param->pic_quantizer_fields.bits.half_qp                    = frame_hdr->halfqp;
+    pic_param->pic_quantizer_fields.bits.pic_quantizer_scale        = frame_hdr->pquant;
+    pic_param->pic_quantizer_fields.bits.pic_quantizer_type         = frame_hdr->pquantizer;
+    pic_param->pic_quantizer_fields.bits.dq_frame                   = frame_hdr->vopdquant.dquantfrm;
+    pic_param->pic_quantizer_fields.bits.dq_profile                 = frame_hdr->vopdquant.dqprofile;
+    pic_param->pic_quantizer_fields.bits.dq_sb_edge                 = frame_hdr->vopdquant.dqsbedge;
+    pic_param->pic_quantizer_fields.bits.dq_db_edge                 = frame_hdr->vopdquant.dqsbedge;
+    pic_param->pic_quantizer_fields.bits.dq_binary_level            = frame_hdr->vopdquant.dqbilevel;
+    pic_param->pic_quantizer_fields.bits.alt_pic_quantizer          = frame_hdr->vopdquant.altpquant;
+    pic_param->transform_fields.value                               = 0;
+    pic_param->transform_fields.bits.transform_ac_codingset_idx1    = frame_hdr->transacfrm;
+    pic_param->transform_fields.bits.intra_transform_dc_table       = frame_hdr->transdctab;
+
+    if (seq_hdr->profile == GST_VC1_PROFILE_ADVANCED) {
+        if (!fill_picture_advanced(decoder, picture))
+            return FALSE;
+    }
+    else {
+        if (!fill_picture_structc(decoder, picture))
+            return FALSE;
+    }
+
+    switch (picture->type) {
+    case GST_VAAPI_PICTURE_TYPE_B:
+        if (priv->next_picture)
+            pic_param->backward_reference_picture = priv->next_picture->surface_id;
+        // fall-through
+    case GST_VAAPI_PICTURE_TYPE_P:
+        if (priv->prev_picture)
+            pic_param->forward_reference_picture = priv->prev_picture->surface_id;
+        break;
+    default:
+        break;
+    }
+
+    if (pic_param->bitplane_present.value) {
+        const guint8 *bitplanes[3];
+        guint x, y, n;
+
+        switch (picture->type) {
+        case GST_VAAPI_PICTURE_TYPE_P:
+            bitplanes[0] = pic_param->bitplane_present.flags.bp_direct_mb  ? priv->bitplanes->directmb  : NULL;
+            bitplanes[1] = pic_param->bitplane_present.flags.bp_skip_mb    ? priv->bitplanes->skipmb    : NULL;
+            bitplanes[2] = pic_param->bitplane_present.flags.bp_mv_type_mb ? priv->bitplanes->mvtypemb  : NULL;
+            break;
+        case GST_VAAPI_PICTURE_TYPE_B:
+            bitplanes[0] = pic_param->bitplane_present.flags.bp_direct_mb  ? priv->bitplanes->directmb  : NULL;
+            bitplanes[1] = pic_param->bitplane_present.flags.bp_skip_mb    ? priv->bitplanes->skipmb    : NULL;
+            bitplanes[2] = NULL; /* XXX: interlaced frame (FORWARD plane) */
+            break;
+        case GST_VAAPI_PICTURE_TYPE_BI:
+        case GST_VAAPI_PICTURE_TYPE_I:
+            bitplanes[0] = NULL; /* XXX: interlaced frame (FIELDTX plane) */
+            bitplanes[1] = pic_param->bitplane_present.flags.bp_ac_pred    ? priv->bitplanes->acpred    : NULL;
+            bitplanes[2] = pic_param->bitplane_present.flags.bp_overflags  ? priv->bitplanes->overflags : NULL;
+            break;
+        default:
+            bitplanes[0] = NULL;
+            bitplanes[1] = NULL;
+            bitplanes[2] = NULL;
+            break;
+        }
+
+        picture->bitplane = GST_VAAPI_BITPLANE_NEW(
+            decoder,
+            (seq_hdr->mb_width * seq_hdr->mb_height + 1) / 2
+        );
+        if (!picture->bitplane)
+            return FALSE;
+
+        n = 0;
+        for (y = 0; y < seq_hdr->mb_height; y++)
+            for (x = 0; x < seq_hdr->mb_width; x++, n++)
+                pack_bitplanes(picture->bitplane, n, bitplanes, x, y, seq_hdr->mb_stride);
+        if (n & 1) /* move last nibble to the high order */
+            picture->bitplane->data[n/2] <<= 4;
+    }
+    return TRUE;
+}
+
+static GstVaapiDecoderStatus
+decode_frame(GstVaapiDecoderVC1 *decoder, GstVC1BDU *rbdu, GstVC1BDU *ebdu)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
+    GstVC1ParserResult result;
+    GstVaapiPicture *picture;
+    GstVaapiSlice *slice;
+    GstVaapiDecoderStatus status;
+    VASliceParameterBufferVC1 *slice_param;
+    GstClockTime pts;
+
+    status = ensure_context(decoder);
+    if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
+        GST_DEBUG("failed to reset context");
+        return status;
+    }
+
+    if (priv->current_picture) {
+        status = decode_current_picture(decoder);
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            return status;
+    }
+
+    priv->current_picture = GST_VAAPI_PICTURE_NEW(VC1, decoder);
+    if (!priv->current_picture) {
+        GST_DEBUG("failed to allocate picture");
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+    picture = priv->current_picture;
+
+    if (!gst_vc1_bitplanes_ensure_size(priv->bitplanes, seq_hdr)) {
+        GST_DEBUG("failed to allocate bitplanes");
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+
+    memset(frame_hdr, 0, sizeof(*frame_hdr));
+    result = gst_vc1_parse_frame_header(
+        rbdu->data + rbdu->offset,
+        rbdu->size,
+        frame_hdr,
+        seq_hdr,
+        priv->bitplanes
+    );
+    if (result != GST_VC1_PARSER_OK) {
+        GST_DEBUG("failed to parse frame layer");
+        return get_status(result);
+    }
+
+    switch (frame_hdr->ptype) {
+    case GST_VC1_PICTURE_TYPE_I:
+        picture->type   = GST_VAAPI_PICTURE_TYPE_I;
+        GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
+        break;
+    case GST_VC1_PICTURE_TYPE_SKIPPED:
+    case GST_VC1_PICTURE_TYPE_P:
+        picture->type   = GST_VAAPI_PICTURE_TYPE_P;
+        GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_REFERENCE);
+        break;
+    case GST_VC1_PICTURE_TYPE_B:
+        picture->type   = GST_VAAPI_PICTURE_TYPE_B;
+        break;
+    case GST_VC1_PICTURE_TYPE_BI:
+        picture->type   = GST_VAAPI_PICTURE_TYPE_BI;
+        break;
+    default:
+        GST_DEBUG("unsupported picture type %d", frame_hdr->ptype);
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+    }
+
+    /* Update presentation time */
+    pts = gst_adapter_prev_timestamp(priv->adapter, NULL);
+    picture->pts = pts;
+
+    /* Update reference pictures */
+    if (GST_VAAPI_PICTURE_IS_REFERENCE(picture)) {
+        if (priv->next_picture)
+            status = render_picture(decoder, priv->next_picture);
+        gst_vaapi_picture_replace(&priv->prev_picture, priv->next_picture);
+        gst_vaapi_picture_replace(&priv->next_picture, picture);
+    }
+
+    if (!fill_picture(decoder, picture))
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+
+    slice = GST_VAAPI_SLICE_NEW(
+        VC1,
+        decoder,
+        ebdu->data + ebdu->sc_offset,
+        ebdu->size + ebdu->offset - ebdu->sc_offset
+    );
+    if (!slice) {
+        GST_DEBUG("failed to allocate slice");
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+    gst_vaapi_picture_add_slice(picture, slice);
+
+    /* Fill in VASliceParameterBufferVC1 */
+    slice_param                            = slice->param;
+    slice_param->macroblock_offset         = 8 * (ebdu->offset - ebdu->sc_offset) + frame_hdr->header_size;
+    slice_param->slice_vertical_position   = 0;
+
+    /* Decode picture right away, we got the full frame */
+    return decode_current_picture(decoder);
+}
+
+static gboolean
+decode_rbdu(GstVaapiDecoderVC1 *decoder, GstVC1BDU *rbdu, GstVC1BDU *ebdu)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    guint8 *rbdu_buffer;
+    guint i, j, rbdu_buffer_size;
+
+    /* BDU are encapsulated in advanced profile mode only */
+    if (priv->profile != GST_VAAPI_PROFILE_VC1_ADVANCED) {
+        memcpy(rbdu, ebdu, sizeof(*rbdu));
+        return TRUE;
+    }
+
+    /* Reallocate unescaped bitstream buffer */
+    rbdu_buffer = priv->rbdu_buffer;
+    if (!rbdu_buffer || ebdu->size > priv->rbdu_buffer_size) {
+        rbdu_buffer = g_realloc(priv->rbdu_buffer, ebdu->size);
+        if (!rbdu_buffer)
+            return FALSE;
+        priv->rbdu_buffer = rbdu_buffer;
+        priv->rbdu_buffer_size = ebdu->size;
+    }
+
+    /* Unescape bitstream buffer */
+    if (ebdu->size < 4) {
+        memcpy(rbdu_buffer, ebdu->data + ebdu->offset, ebdu->size);
+        rbdu_buffer_size = ebdu->size;
+    }
+    else {
+        guint8 * const bdu_buffer = ebdu->data + ebdu->offset;
+        for (i = 0, j = 0; i < ebdu->size; i++) {
+            if (i >= 2 && i < ebdu->size - 1 &&
+                bdu_buffer[i - 1] == 0x00   &&
+                bdu_buffer[i - 2] == 0x00   &&
+                bdu_buffer[i    ] == 0x03   &&
+                bdu_buffer[i + 1] <= 0x03)
+                i++;
+            rbdu_buffer[j++] = bdu_buffer[i];
+        }
+        rbdu_buffer_size = j;
+    }
+
+    /* Reconstruct RBDU */
+    rbdu->type      = ebdu->type;
+    rbdu->size      = rbdu_buffer_size;
+    rbdu->sc_offset = 0;
+    rbdu->offset    = 0;
+    rbdu->data      = rbdu_buffer;
+    return TRUE;
+}
+
+static GstVaapiDecoderStatus
+decode_ebdu(GstVaapiDecoderVC1 *decoder, GstVC1BDU *ebdu)
+{
+    GstVaapiDecoderStatus status;
+    GstVC1BDU rbdu;
+
+    if (!decode_rbdu(decoder, &rbdu, ebdu))
+        return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+
+    switch (ebdu->type) {
+    case GST_VC1_SEQUENCE:
+        status = decode_sequence(decoder, &rbdu, ebdu);
+        break;
+    case GST_VC1_ENTRYPOINT:
+        status = decode_entry_point(decoder, &rbdu, ebdu);
+        break;
+    case GST_VC1_FRAME:
+        status = decode_frame(decoder, &rbdu, ebdu);
+        break;
+    case GST_VC1_SLICE:
+        GST_DEBUG("decode slice");
+        status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+        break;
+    case GST_VC1_END_OF_SEQ:
+        status = decode_sequence_end(decoder);
+        break;
+    default:
+        GST_DEBUG("unsupported BDU type %d", ebdu->type);
+        status = GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
+        break;
+    }
+    return status;
+}
+
+static GstVaapiDecoderStatus
+decode_buffer(GstVaapiDecoderVC1 *decoder, GstBuffer *buffer)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVaapiDecoderStatus status;
+    GstVC1ParserResult result;
+    GstVC1BDU ebdu;
+    GstBuffer *codec_data;
+    guchar *buf;
+    guint buf_size, ofs;
+
+    buf      = GST_BUFFER_DATA(buffer);
+    buf_size = GST_BUFFER_SIZE(buffer);
+    if (!buf && buf_size == 0)
+        return decode_sequence_end(decoder);
+
+    gst_buffer_ref(buffer);
+    gst_adapter_push(priv->adapter, buffer);
+
+    /* Assume demuxer sends out plain frames if codec-data */
+    codec_data = GST_VAAPI_DECODER_CODEC_DATA(decoder);
+    if (codec_data && codec_data != buffer) {
+        ebdu.type      = GST_VC1_FRAME;
+        ebdu.size      = buf_size;
+        ebdu.sc_offset = 0;
+        ebdu.offset    = 0;
+        ebdu.data      = buf;
+        status = decode_ebdu(decoder, &ebdu);
+
+        if (gst_adapter_available(priv->adapter) >= buf_size)
+            gst_adapter_flush(priv->adapter, buf_size);
+        return status;
+    }
+
+    if (priv->sub_buffer) {
+        buffer = gst_buffer_merge(priv->sub_buffer, buffer);
+        if (!buffer)
+            return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+        gst_buffer_unref(priv->sub_buffer);
+        priv->sub_buffer = NULL;
+    }
+
+    buf      = GST_BUFFER_DATA(buffer);
+    buf_size = GST_BUFFER_SIZE(buffer);
+    ofs      = 0;
+    do {
+        result = gst_vc1_identify_next_bdu(
+            buf + ofs,
+            buf_size - ofs,
+            &ebdu
+        );
+        status = get_status(result);
+
+        if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA) {
+            priv->sub_buffer = gst_buffer_create_sub(buffer, ofs, buf_size - ofs);
+            break;
+        }
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+            break;
+
+        ofs += ebdu.offset + ebdu.size;
+        if (gst_adapter_available(priv->adapter) >= ebdu.offset)
+            gst_adapter_flush(priv->adapter, ebdu.offset);
+
+        status = decode_ebdu(decoder, &ebdu);
+        if (gst_adapter_available(priv->adapter) >= ebdu.size)
+            gst_adapter_flush(priv->adapter, ebdu.size);
+    } while (status == GST_VAAPI_DECODER_STATUS_SUCCESS);
+    return status;
+}
+
+static GstVaapiDecoderStatus
+decode_codec_data(GstVaapiDecoderVC1 *decoder, GstBuffer *buffer)
+{
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
+    GstVaapiDecoderStatus status;
+    GstVC1ParserResult result;
+    GstVC1BDU ebdu;
+    GstCaps *caps;
+    GstStructure *structure;
+    guchar *buf;
+    guint buf_size, ofs;
+    gint width, height;
+    guint32 format;
+
+    buf      = GST_BUFFER_DATA(buffer);
+    buf_size = GST_BUFFER_SIZE(buffer);
+    if (!buf || buf_size == 0)
+        return GST_VAAPI_DECODER_STATUS_SUCCESS;
+
+    caps      = GST_VAAPI_DECODER_CAST(decoder)->priv->caps;
+    structure = gst_caps_get_structure(caps, 0);
+
+    if (!gst_structure_get_int(structure, "width", &width) ||
+        !gst_structure_get_int(structure, "height", &height)) {
+        GST_DEBUG("failed to parse size from codec-data");
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
+    }
+
+    if (!gst_structure_get_fourcc(structure, "format", &format)) {
+        GST_DEBUG("failed to parse profile from codec-data");
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
+    }
+
+    /* WMV3 -- expecting sequence header */
+    if (format == GST_MAKE_FOURCC('W','M','V','3')) {
+        seq_hdr->struct_c.coded_width  = width;
+        seq_hdr->struct_c.coded_height = height;
+        ebdu.type      = GST_VC1_SEQUENCE;
+        ebdu.size      = buf_size;
+        ebdu.sc_offset = 0;
+        ebdu.offset    = 0;
+        ebdu.data      = buf;
+        return decode_ebdu(decoder, &ebdu);
+    }
+
+    /* WVC1 -- expecting bitstream data units */
+    if (format != GST_MAKE_FOURCC('W','V','C','1'))
+        return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
+    seq_hdr->advanced.max_coded_width  = width;
+    seq_hdr->advanced.max_coded_height = height;
+
+    ofs = 0;
+    do {
+        result = gst_vc1_identify_next_bdu(
+            buf + ofs,
+            buf_size - ofs,
+            &ebdu
+        );
+
+        switch (result) {
+        case GST_VC1_PARSER_NO_BDU_END:
+            /* Assume the EBDU is complete within codec-data bounds */
+            ebdu.size = buf_size - ofs - (ebdu.offset - ebdu.sc_offset);
+            // fall-through
+        case GST_VC1_PARSER_OK:
+            status = decode_ebdu(decoder, &ebdu);
+            ofs += ebdu.offset + ebdu.size;
+            break;
+        default:
+            status = get_status(result);
+            break;
+        }
+    } while (status == GST_VAAPI_DECODER_STATUS_SUCCESS && ofs < buf_size);
+    return status;
+}
+
+GstVaapiDecoderStatus
+gst_vaapi_decoder_vc1_decode(GstVaapiDecoder *base, GstBuffer *buffer)
+{
+    GstVaapiDecoderVC1 * const decoder = GST_VAAPI_DECODER_VC1(base);
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GstVaapiDecoderStatus status;
+    GstBuffer *codec_data;
+
+    g_return_val_if_fail(priv->is_constructed,
+                         GST_VAAPI_DECODER_STATUS_ERROR_INIT_FAILED);
+
+    if (!priv->is_opened) {
+        priv->is_opened = gst_vaapi_decoder_vc1_open(decoder, buffer);
+        if (!priv->is_opened)
+            return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC;
+
+        codec_data = GST_VAAPI_DECODER_CODEC_DATA(decoder);
+        if (codec_data) {
+            status = decode_codec_data(decoder, codec_data);
+            if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
+                return status;
+        }
+    }
+    return decode_buffer(decoder, buffer);
+}
+
+static void
+gst_vaapi_decoder_vc1_finalize(GObject *object)
+{
+    GstVaapiDecoderVC1 * const decoder = GST_VAAPI_DECODER_VC1(object);
+
+    gst_vaapi_decoder_vc1_destroy(decoder);
+
+    G_OBJECT_CLASS(gst_vaapi_decoder_vc1_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_decoder_vc1_constructed(GObject *object)
+{
+    GstVaapiDecoderVC1 * const decoder = GST_VAAPI_DECODER_VC1(object);
+    GstVaapiDecoderVC1Private * const priv = decoder->priv;
+    GObjectClass *parent_class;
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_decoder_vc1_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+
+    priv->is_constructed = gst_vaapi_decoder_vc1_create(decoder);
+}
+
+static void
+gst_vaapi_decoder_vc1_class_init(GstVaapiDecoderVC1Class *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstVaapiDecoderClass * const decoder_class = GST_VAAPI_DECODER_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiDecoderVC1Private));
+
+    object_class->finalize      = gst_vaapi_decoder_vc1_finalize;
+    object_class->constructed   = gst_vaapi_decoder_vc1_constructed;
+
+    decoder_class->decode       = gst_vaapi_decoder_vc1_decode;
+}
+
+static void
+gst_vaapi_decoder_vc1_init(GstVaapiDecoderVC1 *decoder)
+{
+    GstVaapiDecoderVC1Private *priv;
+
+    priv                        = GST_VAAPI_DECODER_VC1_GET_PRIVATE(decoder);
+    decoder->priv               = priv;
+    priv->width                 = 0;
+    priv->height                = 0;
+    priv->fps_n                 = 0;
+    priv->fps_d                 = 0;
+    priv->profile               = (GstVaapiProfile)0;
+    priv->current_picture       = NULL;
+    priv->next_picture          = NULL;
+    priv->prev_picture          = NULL;
+    priv->adapter               = NULL;
+    priv->sub_buffer            = NULL;
+    priv->rbdu_buffer           = NULL;
+    priv->rbdu_buffer_size      = 0;
+    priv->is_constructed        = FALSE;
+    priv->is_opened             = FALSE;
+    priv->is_first_field        = FALSE;
+    priv->has_entrypoint        = FALSE;
+    priv->size_changed          = FALSE;
+    priv->profile_changed       = FALSE;
+    priv->closed_entry          = FALSE;
+    priv->broken_link           = FALSE;
+}
+
+/**
+ * gst_vaapi_decoder_vc1_new:
+ * @display: a #GstVaapiDisplay
+ * @caps: a #GstCaps holding codec information
+ *
+ * Creates a new #GstVaapiDecoder for VC-1 decoding.  The @caps can
+ * hold extra information like codec-data and pictured coded size.
+ *
+ * Return value: the newly allocated #GstVaapiDecoder object
+ */
+GstVaapiDecoder *
+gst_vaapi_decoder_vc1_new(GstVaapiDisplay *display, GstCaps *caps)
+{
+    GstVaapiDecoderVC1 *decoder;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+    g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
+
+    decoder = g_object_new(
+        GST_VAAPI_TYPE_DECODER_VC1,
+        "display",      display,
+        "caps",         caps,
+        NULL
+    );
+    if (!decoder->priv->is_constructed) {
+        g_object_unref(decoder);
+        return NULL;
+    }
+    return GST_VAAPI_DECODER_CAST(decoder);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_vc1.h b/gst-libs/gst/vaapi/gstvaapidecoder_vc1.h
new file mode 100644 (file)
index 0000000..1bed606
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ *  gstvaapidecoder_vc1.h - VC-1 decoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DECODER_VC1_H
+#define GST_VAAPI_DECODER_VC1_H
+
+#include <gst/vaapi/gstvaapidecoder.h>
+#include <gst/base/gstadapter.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_DECODER_VC1 \
+    (gst_vaapi_decoder_vc1_get_type())
+
+#define GST_VAAPI_DECODER_VC1(obj)                              \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_DECODER_VC1,     \
+                                GstVaapiDecoderVC1))
+
+#define GST_VAAPI_DECODER_VC1_CLASS(klass)                      \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_DECODER_VC1,        \
+                             GstVaapiDecoderVC1Class))
+
+#define GST_VAAPI_IS_DECODER_VC1(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_DECODER_VC1))
+
+#define GST_VAAPI_IS_DECODER_VC1_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_DECODER_VC1))
+
+#define GST_VAAPI_DECODER_VC1_GET_CLASS(obj)                    \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_DECODER_VC1,      \
+                               GstVaapiDecoderVC1Class))
+
+typedef struct _GstVaapiDecoderVC1              GstVaapiDecoderVC1;
+typedef struct _GstVaapiDecoderVC1Private       GstVaapiDecoderVC1Private;
+typedef struct _GstVaapiDecoderVC1Class         GstVaapiDecoderVC1Class;
+
+/**
+ * GstVaapiDecoderVC1:
+ *
+ * A decoder based on VC1.
+ */
+struct _GstVaapiDecoderVC1 {
+    /*< private >*/
+    GstVaapiDecoder parent_instance;
+
+    GstVaapiDecoderVC1Private *priv;
+};
+
+/**
+ * GstVaapiDecoderVC1Class:
+ *
+ * A decoder class based on VC1.
+ */
+struct _GstVaapiDecoderVC1Class {
+    /*< private >*/
+    GstVaapiDecoderClass parent_class;
+};
+
+GType
+gst_vaapi_decoder_vc1_get_type(void) G_GNUC_CONST;
+
+GstVaapiDecoder *
+gst_vaapi_decoder_vc1_new(GstVaapiDisplay *display, GstCaps *caps);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DECODER_VC1_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay.c b/gst-libs/gst/vaapi/gstvaapidisplay.c
new file mode 100644 (file)
index 0000000..8876643
--- /dev/null
@@ -0,0 +1,1719 @@
+/*
+ *  gstvaapidisplay.c - VA display abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapidisplay
+ * @short_description: VA display abstraction
+ */
+
+#include "sysdeps.h"
+#include <string.h>
+#include "gstvaapiutils.h"
+#include "gstvaapivalue.h"
+#include "gstvaapidisplay.h"
+#include "gstvaapidisplay_priv.h"
+#include "gstvaapiworkarounds.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+GST_DEBUG_CATEGORY(gst_debug_vaapi);
+
+G_DEFINE_TYPE(GstVaapiDisplay, gst_vaapi_display, G_TYPE_OBJECT);
+
+typedef struct _GstVaapiConfig GstVaapiConfig;
+struct _GstVaapiConfig {
+    GstVaapiProfile     profile;
+    GstVaapiEntrypoint  entrypoint;
+};
+
+typedef struct _GstVaapiProperty GstVaapiProperty;
+struct _GstVaapiProperty {
+    const gchar        *name;
+    VADisplayAttribute  attribute;
+    gint                old_value;
+};
+
+#define DEFAULT_RENDER_MODE     GST_VAAPI_RENDER_MODE_TEXTURE
+#define DEFAULT_ROTATION        GST_VAAPI_ROTATION_0
+
+enum {
+    PROP_0,
+
+    PROP_DISPLAY,
+    PROP_DISPLAY_TYPE,
+    PROP_WIDTH,
+    PROP_HEIGHT,
+    PROP_RENDER_MODE,
+    PROP_ROTATION,
+    PROP_HUE,
+    PROP_SATURATION,
+    PROP_BRIGHTNESS,
+    PROP_CONTRAST,
+
+    N_PROPERTIES
+};
+
+static GstVaapiDisplayCache *g_display_cache = NULL;
+
+static GParamSpec *g_properties[N_PROPERTIES] = { NULL, };
+
+static gboolean
+get_attribute(GstVaapiDisplay *display, VADisplayAttribType type, gint *value);
+
+static gboolean
+set_attribute(GstVaapiDisplay *display, VADisplayAttribType type, gint value);
+
+static gboolean
+get_color_balance(GstVaapiDisplay *display, guint prop_id, gfloat *v);
+
+static gboolean
+set_color_balance(GstVaapiDisplay *display, guint prop_id, gfloat v);
+
+static inline GstVaapiDisplayCache *
+get_display_cache(void)
+{
+    if (!g_display_cache)
+        g_display_cache = gst_vaapi_display_cache_new();
+    return g_display_cache;
+}
+
+GstVaapiDisplayCache *
+gst_vaapi_display_get_cache(void)
+{
+    return get_display_cache();
+}
+
+static void
+free_display_cache(void)
+{
+    if (!g_display_cache)
+        return;
+    if (gst_vaapi_display_cache_get_size(g_display_cache) > 0)
+        return;
+    gst_vaapi_display_cache_free(g_display_cache);
+    g_display_cache = NULL;
+}
+
+/* GstVaapiDisplayType enumerations */
+GType
+gst_vaapi_display_type_get_type(void)
+{
+    static GType g_type = 0;
+
+    static const GEnumValue display_types[] = {
+        { GST_VAAPI_DISPLAY_TYPE_ANY,
+          "Auto detection", "any" },
+#if USE_X11
+        { GST_VAAPI_DISPLAY_TYPE_X11,
+          "VA/X11 display", "x11" },
+#endif
+#if USE_GLX
+        { GST_VAAPI_DISPLAY_TYPE_GLX,
+          "VA/GLX display", "glx" },
+#endif
+#if USE_WAYLAND
+        { GST_VAAPI_DISPLAY_TYPE_WAYLAND,
+          "VA/Wayland display", "wayland" },
+#endif
+#if USE_DRM
+        { GST_VAAPI_DISPLAY_TYPE_DRM,
+          "VA/DRM display", "drm" },
+#endif
+        { 0, NULL, NULL },
+    };
+
+    if (!g_type)
+        g_type = g_enum_register_static("GstVaapiDisplayType", display_types);
+    return g_type;
+}
+
+/* Append GstVaapiImageFormat to formats array */
+static inline void
+append_format(GArray *formats, GstVaapiImageFormat format)
+{
+    g_array_append_val(formats, format);
+}
+
+/* Append VAImageFormats to formats array */
+static void
+append_formats(GArray *formats, const VAImageFormat *va_formats, guint n)
+{
+    GstVaapiImageFormat format;
+    gboolean has_YV12 = FALSE;
+    gboolean has_I420 = FALSE;
+    guint i;
+
+    for (i = 0; i < n; i++) {
+        const VAImageFormat * const va_format = &va_formats[i];
+
+        format = gst_vaapi_image_format(va_format);
+        if (!format) {
+            GST_DEBUG("unsupported format %" GST_FOURCC_FORMAT,
+                      GST_FOURCC_ARGS(va_format->fourcc));
+            continue;
+        }
+
+        switch (format) {
+        case GST_VAAPI_IMAGE_YV12:
+            has_YV12 = TRUE;
+            break;
+        case GST_VAAPI_IMAGE_I420:
+            has_I420 = TRUE;
+            break;
+        default:
+            break;
+        }
+        append_format(formats, format);
+    }
+
+    /* Append I420 (resp. YV12) format if YV12 (resp. I420) is not
+       supported by the underlying driver */
+    if (has_YV12 && !has_I420)
+        append_format(formats, GST_VAAPI_IMAGE_I420);
+    else if (has_I420 && !has_YV12)
+        append_format(formats, GST_VAAPI_IMAGE_YV12);
+}
+
+/* Sort image formats. Prefer YUV formats first */
+static gint
+compare_yuv_formats(gconstpointer a, gconstpointer b)
+{
+    const GstVaapiImageFormat fmt1 = *(GstVaapiImageFormat *)a;
+    const GstVaapiImageFormat fmt2 = *(GstVaapiImageFormat *)b;
+
+    const gboolean is_fmt1_yuv = gst_vaapi_image_format_is_yuv(fmt1);
+    const gboolean is_fmt2_yuv = gst_vaapi_image_format_is_yuv(fmt2);
+
+    if (is_fmt1_yuv != is_fmt2_yuv)
+        return is_fmt1_yuv ? -1 : 1;
+
+    return ((gint)gst_vaapi_image_format_get_score(fmt1) -
+            (gint)gst_vaapi_image_format_get_score(fmt2));
+}
+
+/* Sort subpicture formats. Prefer RGB formats first */
+static gint
+compare_rgb_formats(gconstpointer a, gconstpointer b)
+{
+    const GstVaapiImageFormat fmt1 = *(GstVaapiImageFormat *)a;
+    const GstVaapiImageFormat fmt2 = *(GstVaapiImageFormat *)b;
+
+    const gboolean is_fmt1_rgb = gst_vaapi_image_format_is_rgb(fmt1);
+    const gboolean is_fmt2_rgb = gst_vaapi_image_format_is_rgb(fmt2);
+
+    if (is_fmt1_rgb != is_fmt2_rgb)
+        return is_fmt1_rgb ? -1 : 1;
+
+    return ((gint)gst_vaapi_image_format_get_score(fmt1) -
+            (gint)gst_vaapi_image_format_get_score(fmt2));
+}
+
+/* Check if configs array contains profile at entrypoint */
+static inline gboolean
+find_config(
+    GArray             *configs,
+    GstVaapiProfile     profile,
+    GstVaapiEntrypoint  entrypoint
+)
+{
+    GstVaapiConfig *config;
+    guint i;
+
+    if (!configs)
+        return FALSE;
+
+    for (i = 0; i < configs->len; i++) {
+        config = &g_array_index(configs, GstVaapiConfig, i);
+        if (config->profile == profile && config->entrypoint == entrypoint)
+            return TRUE;
+    }
+    return FALSE;
+}
+
+/* HACK: append H.263 Baseline profile if MPEG-4:2 Simple profile is supported */
+static void
+append_h263_config(GArray *configs)
+{
+    GstVaapiConfig *config, tmp_config;
+    GstVaapiConfig *mpeg4_simple_config = NULL;
+    GstVaapiConfig *h263_baseline_config = NULL;
+    guint i;
+
+    if (!WORKAROUND_H263_BASELINE_DECODE_PROFILE)
+        return;
+
+    if (!configs)
+        return;
+
+    for (i = 0; i < configs->len; i++) {
+        config = &g_array_index(configs, GstVaapiConfig, i);
+        if (config->profile == GST_VAAPI_PROFILE_MPEG4_SIMPLE)
+            mpeg4_simple_config = config;
+        else if (config->profile == GST_VAAPI_PROFILE_H263_BASELINE)
+            h263_baseline_config = config;
+    }
+
+    if (mpeg4_simple_config && !h263_baseline_config) {
+        tmp_config = *mpeg4_simple_config;
+        tmp_config.profile = GST_VAAPI_PROFILE_H263_BASELINE;
+        g_array_append_val(configs, tmp_config);
+    }
+}
+
+/* Convert configs array to profiles as GstCaps */
+static GstCaps *
+get_profile_caps(GArray *configs)
+{
+    GstVaapiConfig *config;
+    GstCaps *out_caps, *caps;
+    guint i;
+
+    if (!configs)
+        return NULL;
+
+    out_caps = gst_caps_new_empty();
+    if (!out_caps)
+        return NULL;
+
+    for (i = 0; i < configs->len; i++) {
+        config = &g_array_index(configs, GstVaapiConfig, i);
+        caps   = gst_vaapi_profile_get_caps(config->profile);
+        if (caps)
+            gst_caps_merge(out_caps, caps);
+    }
+    return out_caps;
+}
+
+/* Check if formats array contains format */
+static inline gboolean
+find_format(GArray *formats, GstVaapiImageFormat format)
+{
+    guint i;
+
+    for (i = 0; i < formats->len; i++)
+        if (g_array_index(formats, GstVaapiImageFormat, i) == format)
+            return TRUE;
+    return FALSE;
+}
+
+/* Convert formats array to GstCaps */
+static GstCaps *
+get_format_caps(GArray *formats)
+{
+    GstVaapiImageFormat format;
+    GstCaps *out_caps, *caps;
+    guint i;
+
+    out_caps = gst_caps_new_empty();
+    if (!out_caps)
+        return NULL;
+
+    for (i = 0; i < formats->len; i++) {
+        format = g_array_index(formats, GstVaapiImageFormat, i);
+        caps   = gst_vaapi_image_format_get_caps(format);
+        if (caps)
+            gst_caps_append(out_caps, caps);
+    }
+    return out_caps;
+}
+
+/* Find display attribute */
+static const GstVaapiProperty *
+find_property(GArray *properties, const gchar *name)
+{
+    GstVaapiProperty *prop;
+    guint i;
+
+    if (!name)
+        return NULL;
+
+    for (i = 0; i < properties->len; i++) {
+        prop = &g_array_index(properties, GstVaapiProperty, i);
+        if (strcmp(prop->name, name) == 0)
+            return prop;
+    }
+    return NULL;
+}
+
+#if 0
+static const GstVaapiProperty *
+find_property_by_type(GArray *properties, VADisplayAttribType type)
+{
+    GstVaapiProperty *prop;
+    guint i;
+
+    for (i = 0; i < properties->len; i++) {
+        prop = &g_array_index(properties, GstVaapiProperty, i);
+        if (prop->attribute.type == type)
+            return prop;
+    }
+    return NULL;
+}
+#endif
+
+static inline const GstVaapiProperty *
+find_property_by_pspec(GstVaapiDisplay *display, GParamSpec *pspec)
+{
+    return find_property(display->priv->properties, pspec->name);
+}
+
+static void
+gst_vaapi_display_calculate_pixel_aspect_ratio(GstVaapiDisplay *display)
+{
+    GstVaapiDisplayPrivate * const priv = display->priv;
+    gdouble ratio, delta;
+    gint i, j, index, windex;
+
+    static const gint par[][2] = {
+        {1, 1},         /* regular screen            */
+        {16, 15},       /* PAL TV                    */
+        {11, 10},       /* 525 line Rec.601 video    */
+        {54, 59},       /* 625 line Rec.601 video    */
+        {64, 45},       /* 1280x1024 on 16:9 display */
+        {5, 3},         /* 1280x1024 on  4:3 display */
+        {4, 3}          /*  800x600  on 16:9 display */
+    };
+
+    /* First, calculate the "real" ratio based on the X values;
+     * which is the "physical" w/h divided by the w/h in pixels of the
+     * display */
+    if (!priv->width || !priv->height || !priv->width_mm || !priv->height_mm)
+        ratio = 1.0;
+    else
+        ratio = (gdouble)(priv->width_mm * priv->height) /
+            (priv->height_mm * priv->width);
+    GST_DEBUG("calculated pixel aspect ratio: %f", ratio);
+
+    /* Now, find the one from par[][2] with the lowest delta to the real one */
+#define DELTA(idx, w) (ABS(ratio - ((gdouble)par[idx][w] / par[idx][!(w)])))
+    delta  = DELTA(0, 0);
+    index  = 0;
+    windex = 0;
+
+    for (i = 1; i < G_N_ELEMENTS(par); i++) {
+        for (j = 0; j < 2; j++) {
+            const gdouble this_delta = DELTA(i, j);
+            if (this_delta < delta) {
+                index  = i;
+                windex = j;
+                delta  = this_delta;
+            }
+        }
+    }
+#undef DELTA
+
+    priv->par_n = par[index][windex];
+    priv->par_d = par[index][windex ^ 1];
+}
+
+static void
+gst_vaapi_display_destroy(GstVaapiDisplay *display)
+{
+    GstVaapiDisplayPrivate * const priv = display->priv;
+
+    if (priv->decoders) {
+        g_array_free(priv->decoders, TRUE);
+        priv->decoders = NULL;
+    }
+
+    if (priv->encoders) {
+        g_array_free(priv->encoders, TRUE);
+        priv->encoders = NULL;
+    }
+
+    if (priv->image_formats) {
+        g_array_free(priv->image_formats, TRUE);
+        priv->image_formats = NULL;
+    }
+
+    if (priv->subpicture_formats) {
+        g_array_free(priv->subpicture_formats, TRUE);
+        priv->subpicture_formats = NULL;
+    }
+
+    if (priv->properties) {
+        g_array_free(priv->properties, TRUE);
+        priv->properties = NULL;
+    }
+
+    if (priv->display) {
+        if (!priv->parent)
+            vaTerminate(priv->display);
+        priv->display = NULL;
+    }
+
+    if (priv->create_display) {
+        GstVaapiDisplayClass *klass = GST_VAAPI_DISPLAY_GET_CLASS(display);
+        if (klass->close_display)
+            klass->close_display(display);
+    }
+
+    g_clear_object(&priv->parent);
+
+    if (g_display_cache) {
+        gst_vaapi_display_cache_remove(get_display_cache(), display);
+        free_display_cache();
+    }
+}
+
+static gboolean
+gst_vaapi_display_create(GstVaapiDisplay *display)
+{
+    GstVaapiDisplayPrivate * const priv = display->priv;
+    GstVaapiDisplayCache *cache;
+    gboolean            has_errors      = TRUE;
+    VADisplayAttribute *display_attrs   = NULL;
+    VAProfile          *profiles        = NULL;
+    VAEntrypoint       *entrypoints     = NULL;
+    VAImageFormat      *formats         = NULL;
+    unsigned int       *flags           = NULL;
+    gint                i, j, n, num_entrypoints, major_version, minor_version;
+    VAStatus            status;
+    GstVaapiDisplayInfo info;
+    const GstVaapiDisplayInfo *cached_info = NULL;
+
+    memset(&info, 0, sizeof(info));
+    info.display = display;
+    info.display_type = priv->display_type;
+
+    if (priv->display)
+        info.va_display = priv->display;
+    else if (priv->create_display) {
+        GstVaapiDisplayClass *klass = GST_VAAPI_DISPLAY_GET_CLASS(display);
+        if (klass->open_display && !klass->open_display(display))
+            return FALSE;
+        if (!klass->get_display || !klass->get_display(display, &info))
+            return FALSE;
+        priv->display = info.va_display;
+        priv->display_type = info.display_type;
+        if (klass->get_size)
+            klass->get_size(display, &priv->width, &priv->height);
+        if (klass->get_size_mm)
+            klass->get_size_mm(display, &priv->width_mm, &priv->height_mm);
+        gst_vaapi_display_calculate_pixel_aspect_ratio(display);
+    }
+    if (!priv->display)
+        return FALSE;
+
+    cache = get_display_cache();
+    if (!cache)
+        return FALSE;
+    cached_info = gst_vaapi_display_cache_lookup_by_va_display(
+        cache,
+        info.va_display
+    );
+    if (cached_info) {
+        g_clear_object(&priv->parent);
+        priv->parent = g_object_ref(cached_info->display);
+        priv->display_type = cached_info->display_type;
+    }
+
+    if (!priv->parent) {
+        status = vaInitialize(priv->display, &major_version, &minor_version);
+        if (!vaapi_check_status(status, "vaInitialize()"))
+            goto end;
+        GST_DEBUG("VA-API version %d.%d", major_version, minor_version);
+    }
+
+    /* VA profiles */
+    profiles = g_new(VAProfile, vaMaxNumProfiles(priv->display));
+    if (!profiles)
+        goto end;
+    entrypoints = g_new(VAEntrypoint, vaMaxNumEntrypoints(priv->display));
+    if (!entrypoints)
+        goto end;
+    status = vaQueryConfigProfiles(priv->display, profiles, &n);
+    if (!vaapi_check_status(status, "vaQueryConfigProfiles()"))
+        goto end;
+
+    GST_DEBUG("%d profiles", n);
+    for (i = 0; i < n; i++) {
+#if VA_CHECK_VERSION(0,34,0)
+        /* Introduced in VA/VPP API */
+        if (profiles[i] == VAProfileNone)
+            continue;
+#endif
+        GST_DEBUG("  %s", string_of_VAProfile(profiles[i]));
+    }
+
+    priv->decoders = g_array_new(FALSE, FALSE, sizeof(GstVaapiConfig));
+    if (!priv->decoders)
+        goto end;
+    priv->encoders = g_array_new(FALSE, FALSE, sizeof(GstVaapiConfig));
+    if (!priv->encoders)
+        goto end;
+
+    for (i = 0; i < n; i++) {
+        GstVaapiConfig config;
+
+        config.profile = gst_vaapi_profile(profiles[i]);
+        if (!config.profile)
+            continue;
+
+        status = vaQueryConfigEntrypoints(
+            priv->display,
+            profiles[i],
+            entrypoints, &num_entrypoints
+        );
+        if (!vaapi_check_status(status, "vaQueryConfigEntrypoints()"))
+            continue;
+
+        for (j = 0; j < num_entrypoints; j++) {
+            config.entrypoint = gst_vaapi_entrypoint(entrypoints[j]);
+            switch (config.entrypoint) {
+            case GST_VAAPI_ENTRYPOINT_VLD:
+            case GST_VAAPI_ENTRYPOINT_IDCT:
+            case GST_VAAPI_ENTRYPOINT_MOCO:
+                g_array_append_val(priv->decoders, config);
+                break;
+            case GST_VAAPI_ENTRYPOINT_SLICE_ENCODE:
+                g_array_append_val(priv->encoders, config);
+                break;
+            }
+        }
+    }
+    append_h263_config(priv->decoders);
+
+    /* VA display attributes */
+    display_attrs =
+        g_new(VADisplayAttribute, vaMaxNumDisplayAttributes(priv->display));
+    if (!display_attrs)
+        goto end;
+
+    n = 0; /* XXX: workaround old GMA500 bug */
+    status = vaQueryDisplayAttributes(priv->display, display_attrs, &n);
+    if (!vaapi_check_status(status, "vaQueryDisplayAttributes()"))
+        goto end;
+
+    priv->properties = g_array_new(FALSE, FALSE, sizeof(GstVaapiProperty));
+    if (!priv->properties)
+        goto end;
+
+    GST_DEBUG("%d display attributes", n);
+    for (i = 0; i < n; i++) {
+        VADisplayAttribute * const attr = &display_attrs[i];
+        GstVaapiProperty prop;
+        gint value;
+
+        GST_DEBUG("  %s", string_of_VADisplayAttributeType(attr->type));
+
+        switch (attr->type) {
+#if !VA_CHECK_VERSION(0,34,0)
+        case VADisplayAttribDirectSurface:
+            prop.name = GST_VAAPI_DISPLAY_PROP_RENDER_MODE;
+            break;
+#endif
+        case VADisplayAttribRenderMode:
+            prop.name = GST_VAAPI_DISPLAY_PROP_RENDER_MODE;
+            break;
+        case VADisplayAttribRotation:
+            prop.name = GST_VAAPI_DISPLAY_PROP_ROTATION;
+            break;
+        case VADisplayAttribHue:
+            prop.name = GST_VAAPI_DISPLAY_PROP_HUE;
+            break;
+        case VADisplayAttribSaturation:
+            prop.name = GST_VAAPI_DISPLAY_PROP_SATURATION;
+            break;
+        case VADisplayAttribBrightness:
+            prop.name = GST_VAAPI_DISPLAY_PROP_BRIGHTNESS;
+            break;
+        case VADisplayAttribContrast:
+            prop.name = GST_VAAPI_DISPLAY_PROP_CONTRAST;
+            break;
+        default:
+            prop.name = NULL;
+            break;
+        }
+        if (!prop.name)
+            continue;
+
+        /* Assume the attribute is really supported if we can get the
+         * actual and current value */
+        if (!get_attribute(display, attr->type, &value))
+            continue;
+
+        /* Some drivers (e.g. EMGD) have completely random initial
+         * values */
+        if (value < attr->min_value || value > attr->max_value)
+            continue;
+
+        prop.attribute = *attr;
+        prop.old_value = value;
+        g_array_append_val(priv->properties, prop);
+    }
+
+    /* VA image formats */
+    formats = g_new(VAImageFormat, vaMaxNumImageFormats(priv->display));
+    if (!formats)
+        goto end;
+    status = vaQueryImageFormats(priv->display, formats, &n);
+    if (!vaapi_check_status(status, "vaQueryImageFormats()"))
+        goto end;
+
+    GST_DEBUG("%d image formats", n);
+    for (i = 0; i < n; i++)
+        GST_DEBUG("  %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS(formats[i].fourcc));
+
+    priv->image_formats =
+        g_array_new(FALSE, FALSE, sizeof(GstVaapiImageFormat));
+    if (!priv->image_formats)
+        goto end;
+    append_formats(priv->image_formats, formats, n);
+    g_array_sort(priv->image_formats, compare_yuv_formats);
+
+    /* VA subpicture formats */
+    n = vaMaxNumSubpictureFormats(priv->display);
+    formats = g_renew(VAImageFormat, formats, n);
+    flags   = g_new(guint, n);
+    if (!formats || !flags)
+        goto end;
+    status = vaQuerySubpictureFormats(priv->display, formats, flags, (guint *)&n);
+    if (!vaapi_check_status(status, "vaQuerySubpictureFormats()"))
+        goto end;
+
+    GST_DEBUG("%d subpicture formats", n);
+    for (i = 0; i < n; i++)
+        GST_DEBUG("  %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS(formats[i].fourcc));
+
+    priv->subpicture_formats =
+        g_array_new(FALSE, FALSE, sizeof(GstVaapiImageFormat));
+    if (!priv->subpicture_formats)
+        goto end;
+    append_formats(priv->subpicture_formats, formats, n);
+    g_array_sort(priv->subpicture_formats, compare_rgb_formats);
+
+    if (!cached_info) {
+        if (!gst_vaapi_display_cache_add(cache, &info))
+            goto end;
+    }
+
+    has_errors = FALSE;
+end:
+    g_free(display_attrs);
+    g_free(profiles);
+    g_free(entrypoints);
+    g_free(formats);
+    g_free(flags);
+    return !has_errors;
+}
+
+static void
+gst_vaapi_display_lock_default(GstVaapiDisplay *display)
+{
+    GstVaapiDisplayPrivate *priv = display->priv;
+
+    if (priv->parent)
+        priv = priv->parent->priv;
+    g_static_rec_mutex_lock(&priv->mutex);
+}
+
+static void
+gst_vaapi_display_unlock_default(GstVaapiDisplay *display)
+{
+    GstVaapiDisplayPrivate *priv = display->priv;
+
+    if (priv->parent)
+        priv = priv->parent->priv;
+    g_static_rec_mutex_unlock(&priv->mutex);
+}
+
+static void
+gst_vaapi_display_finalize(GObject *object)
+{
+    GstVaapiDisplay * const display = GST_VAAPI_DISPLAY(object);
+
+    gst_vaapi_display_destroy(display);
+
+    g_static_rec_mutex_free(&display->priv->mutex);
+
+    G_OBJECT_CLASS(gst_vaapi_display_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_display_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiDisplay * const display = GST_VAAPI_DISPLAY(object);
+
+    switch (prop_id) {
+    case PROP_DISPLAY:
+        display->priv->display = g_value_get_pointer(value);
+        break;
+    case PROP_DISPLAY_TYPE:
+        display->priv->display_type = g_value_get_enum(value);
+        break;
+    case PROP_RENDER_MODE:
+        gst_vaapi_display_set_render_mode(display, g_value_get_enum(value));
+        break;
+    case PROP_ROTATION:
+        gst_vaapi_display_set_rotation(display, g_value_get_enum(value));
+        break;
+    case PROP_HUE:
+    case PROP_SATURATION:
+    case PROP_BRIGHTNESS:
+    case PROP_CONTRAST:
+        set_color_balance(display, prop_id, g_value_get_float(value));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_display_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiDisplay * const display = GST_VAAPI_DISPLAY(object);
+
+    switch (prop_id) {
+    case PROP_DISPLAY:
+        g_value_set_pointer(value, gst_vaapi_display_get_display(display));
+        break;
+    case PROP_DISPLAY_TYPE:
+        g_value_set_enum(value, gst_vaapi_display_get_display_type(display));
+        break;
+    case PROP_WIDTH:
+        g_value_set_uint(value, gst_vaapi_display_get_width(display));
+        break;
+    case PROP_HEIGHT:
+        g_value_set_uint(value, gst_vaapi_display_get_height(display));
+        break;
+    case PROP_RENDER_MODE: {
+        GstVaapiRenderMode mode;
+        if (!gst_vaapi_display_get_render_mode(display, &mode))
+            mode = DEFAULT_RENDER_MODE;
+        g_value_set_enum(value, mode);
+        break;
+    }
+    case PROP_ROTATION:
+        g_value_set_enum(value, gst_vaapi_display_get_rotation(display));
+        break;
+    case PROP_HUE:
+    case PROP_SATURATION:
+    case PROP_BRIGHTNESS:
+    case PROP_CONTRAST: {
+        gfloat v;
+        if (!get_color_balance(display, prop_id, &v))
+            v = G_PARAM_SPEC_FLOAT(pspec)->default_value;
+        g_value_set_float(value, v);
+        break;
+    }
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_display_constructed(GObject *object)
+{
+    GstVaapiDisplay * const display = GST_VAAPI_DISPLAY(object);
+    GObjectClass *parent_class;
+
+    display->priv->create_display = display->priv->display == NULL;
+    if (!gst_vaapi_display_create(display))
+        gst_vaapi_display_destroy(display);
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_display_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+}
+
+static void
+gst_vaapi_display_class_init(GstVaapiDisplayClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstVaapiDisplayClass * const dpy_class = GST_VAAPI_DISPLAY_CLASS(klass);
+
+    GST_DEBUG_CATEGORY_INIT(gst_debug_vaapi, "vaapi", 0, "VA-API helper");
+
+    g_type_class_add_private(klass, sizeof(GstVaapiDisplayPrivate));
+
+    object_class->finalize      = gst_vaapi_display_finalize;
+    object_class->set_property  = gst_vaapi_display_set_property;
+    object_class->get_property  = gst_vaapi_display_get_property;
+    object_class->constructed   = gst_vaapi_display_constructed;
+
+    dpy_class->lock             = gst_vaapi_display_lock_default;
+    dpy_class->unlock           = gst_vaapi_display_unlock_default;
+
+    g_properties[PROP_DISPLAY] =
+        g_param_spec_pointer("display",
+                             "VA display",
+                             "VA display",
+                             G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
+
+    g_properties[PROP_DISPLAY_TYPE] =
+        g_param_spec_enum("display-type",
+                          "VA display type",
+                          "VA display type",
+                          GST_VAAPI_TYPE_DISPLAY_TYPE,
+                          GST_VAAPI_DISPLAY_TYPE_ANY,
+                          G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
+
+    g_properties[PROP_WIDTH] =
+        g_param_spec_uint("width",
+                          "Width",
+                          "The display width",
+                          1, G_MAXUINT32, 1,
+                          G_PARAM_READABLE);
+
+    g_properties[PROP_HEIGHT] =
+        g_param_spec_uint("height",
+                          "height",
+                          "The display height",
+                          1, G_MAXUINT32, 1,
+                          G_PARAM_READABLE);
+
+    /**
+     * GstVaapiDisplay:render-mode:
+     *
+     * The VA display rendering mode, expressed as a #GstVaapiRenderMode.
+     */
+    g_properties[PROP_RENDER_MODE] =
+        g_param_spec_enum(GST_VAAPI_DISPLAY_PROP_RENDER_MODE,
+                          "render mode",
+                          "The display rendering mode",
+                          GST_VAAPI_TYPE_RENDER_MODE,
+                          DEFAULT_RENDER_MODE,
+                          G_PARAM_READWRITE);
+
+    /**
+     * GstVaapiDisplay:rotation:
+     *
+     * The VA display rotation mode, expressed as a #GstVaapiRotation.
+     */
+    g_properties[PROP_ROTATION] =
+        g_param_spec_enum(GST_VAAPI_DISPLAY_PROP_ROTATION,
+                          "rotation",
+                          "The display rotation mode",
+                          GST_VAAPI_TYPE_ROTATION,
+                          DEFAULT_ROTATION,
+                          G_PARAM_READWRITE);
+
+    /**
+     * GstVaapiDisplay:hue:
+     *
+     * The VA display hue, expressed as a float value. Range is -180.0
+     * to 180.0. Default value is 0.0 and represents no modification.
+     */
+    g_properties[PROP_HUE] =
+        g_param_spec_float(GST_VAAPI_DISPLAY_PROP_HUE,
+                           "hue",
+                           "The display hue value",
+                           -180.0, 180.0, 0.0,
+                           G_PARAM_READWRITE);
+
+    /**
+     * GstVaapiDisplay:saturation:
+     *
+     * The VA display saturation, expressed as a float value. Range is
+     * 0.0 to 2.0. Default value is 1.0 and represents no modification.
+     */
+    g_properties[PROP_SATURATION] =
+        g_param_spec_float(GST_VAAPI_DISPLAY_PROP_SATURATION,
+                           "saturation",
+                           "The display saturation value",
+                           0.0, 2.0, 1.0,
+                           G_PARAM_READWRITE);
+
+    /**
+     * GstVaapiDisplay:brightness:
+     *
+     * The VA display brightness, expressed as a float value. Range is
+     * -1.0 to 1.0. Default value is 0.0 and represents no modification.
+     */
+    g_properties[PROP_BRIGHTNESS] =
+        g_param_spec_float(GST_VAAPI_DISPLAY_PROP_BRIGHTNESS,
+                           "brightness",
+                           "The display brightness value",
+                           -1.0, 1.0, 0.0,
+                           G_PARAM_READWRITE);
+
+    /**
+     * GstVaapiDisplay:contrast:
+     *
+     * The VA display contrast, expressed as a float value. Range is
+     * 0.0 to 2.0. Default value is 1.0 and represents no modification.
+     */
+    g_properties[PROP_CONTRAST] =
+        g_param_spec_float(GST_VAAPI_DISPLAY_PROP_CONTRAST,
+                           "contrast",
+                           "The display contrast value",
+                           0.0, 2.0, 1.0,
+                           G_PARAM_READWRITE);
+
+    g_object_class_install_properties(object_class, N_PROPERTIES, g_properties);
+}
+
+static void
+gst_vaapi_display_init(GstVaapiDisplay *display)
+{
+    GstVaapiDisplayPrivate *priv = GST_VAAPI_DISPLAY_GET_PRIVATE(display);
+
+    display->priv               = priv;
+    priv->parent                = NULL;
+    priv->display_type          = GST_VAAPI_DISPLAY_TYPE_ANY;
+    priv->display               = NULL;
+    priv->width                 = 0;
+    priv->height                = 0;
+    priv->width_mm              = 0;
+    priv->height_mm             = 0;
+    priv->par_n                 = 1;
+    priv->par_d                 = 1;
+    priv->decoders              = NULL;
+    priv->encoders              = NULL;
+    priv->image_formats         = NULL;
+    priv->subpicture_formats    = NULL;
+    priv->properties            = NULL;
+    priv->create_display        = TRUE;
+
+    g_static_rec_mutex_init(&priv->mutex);
+}
+
+/**
+ * gst_vaapi_display_new_with_display:
+ * @va_display: a #VADisplay
+ *
+ * Creates a new #GstVaapiDisplay, using @va_display as the VA
+ * display.
+ *
+ * Return value: the newly created #GstVaapiDisplay object
+ */
+GstVaapiDisplay *
+gst_vaapi_display_new_with_display(VADisplay va_display)
+{
+    GstVaapiDisplayCache * const cache = get_display_cache();
+    const GstVaapiDisplayInfo *info;
+
+    g_return_val_if_fail(va_display != NULL, NULL);
+    g_return_val_if_fail(cache != NULL, NULL);
+
+    info = gst_vaapi_display_cache_lookup_by_va_display(cache, va_display);
+    if (info)
+        return g_object_ref(info->display);
+
+    return g_object_new(GST_VAAPI_TYPE_DISPLAY,
+                        "display", va_display,
+                        NULL);
+}
+
+/**
+ * gst_vaapi_display_lock:
+ * @display: a #GstVaapiDisplay
+ *
+ * Locks @display. If @display is already locked by another thread,
+ * the current thread will block until @display is unlocked by the
+ * other thread.
+ */
+void
+gst_vaapi_display_lock(GstVaapiDisplay *display)
+{
+    GstVaapiDisplayClass *klass;
+
+    g_return_if_fail(GST_VAAPI_IS_DISPLAY(display));
+
+    klass = GST_VAAPI_DISPLAY_GET_CLASS(display);
+    if (klass->lock)
+        klass->lock(display);
+}
+
+/**
+ * gst_vaapi_display_unlock:
+ * @display: a #GstVaapiDisplay
+ *
+ * Unlocks @display. If another thread is blocked in a
+ * gst_vaapi_display_lock() call for @display, it will be woken and
+ * can lock @display itself.
+ */
+void
+gst_vaapi_display_unlock(GstVaapiDisplay *display)
+{
+    GstVaapiDisplayClass *klass;
+
+    g_return_if_fail(GST_VAAPI_IS_DISPLAY(display));
+
+    klass = GST_VAAPI_DISPLAY_GET_CLASS(display);
+    if (klass->unlock)
+        klass->unlock(display);
+}
+
+/**
+ * gst_vaapi_display_sync:
+ * @display: a #GstVaapiDisplay
+ *
+ * Flushes any requests queued for the windowing system and waits until
+ * all requests have been handled. This is often used for making sure
+ * that the display is synchronized with the current state of the program.
+ *
+ * This is most useful for X11. On windowing systems where requests are
+ * handled synchronously, this function will do nothing.
+ */
+void
+gst_vaapi_display_sync(GstVaapiDisplay *display)
+{
+    GstVaapiDisplayClass *klass;
+
+    g_return_if_fail(GST_VAAPI_IS_DISPLAY(display));
+
+    klass = GST_VAAPI_DISPLAY_GET_CLASS(display);
+    if (klass->sync)
+        klass->sync(display);
+    else if (klass->flush)
+        klass->flush(display);
+}
+
+/**
+ * gst_vaapi_display_flush:
+ * @display: a #GstVaapiDisplay
+ *
+ * Flushes any requests queued for the windowing system.
+ *
+ * This is most useful for X11. On windowing systems where requests
+ * are handled synchronously, this function will do nothing.
+ */
+void
+gst_vaapi_display_flush(GstVaapiDisplay *display)
+{
+    GstVaapiDisplayClass *klass;
+
+    g_return_if_fail(GST_VAAPI_IS_DISPLAY(display));
+
+    klass = GST_VAAPI_DISPLAY_GET_CLASS(display);
+    if (klass->flush)
+        klass->flush(display);
+}
+
+/**
+ * gst_vaapi_display_get_display:
+ * @display: a #GstVaapiDisplay
+ *
+ * Returns the #GstVaapiDisplayType bound to @display.
+ *
+ * Return value: the #GstVaapiDisplayType
+ */
+GstVaapiDisplayType
+gst_vaapi_display_get_display_type(GstVaapiDisplay *display)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display),
+                         GST_VAAPI_DISPLAY_TYPE_ANY);
+
+    return display->priv->display_type;
+}
+
+/**
+ * gst_vaapi_display_get_display:
+ * @display: a #GstVaapiDisplay
+ *
+ * Returns the #VADisplay bound to @display.
+ *
+ * Return value: the #VADisplay
+ */
+VADisplay
+gst_vaapi_display_get_display(GstVaapiDisplay *display)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+
+    return display->priv->display;
+}
+
+/**
+ * gst_vaapi_display_get_width:
+ * @display: a #GstVaapiDisplay
+ *
+ * Retrieves the width of a #GstVaapiDisplay.
+ *
+ * Return value: the width of the @display, in pixels
+ */
+guint
+gst_vaapi_display_get_width(GstVaapiDisplay *display)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), 0);
+
+    return display->priv->width;
+}
+
+/**
+ * gst_vaapi_display_get_height:
+ * @display: a #GstVaapiDisplay
+ *
+ * Retrieves the height of a #GstVaapiDisplay
+ *
+ * Return value: the height of the @display, in pixels
+ */
+guint
+gst_vaapi_display_get_height(GstVaapiDisplay *display)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), 0);
+
+    return display->priv->height;
+}
+
+/**
+ * gst_vaapi_display_get_size:
+ * @display: a #GstVaapiDisplay
+ * @pwidth: return location for the width, or %NULL
+ * @pheight: return location for the height, or %NULL
+ *
+ * Retrieves the dimensions of a #GstVaapiDisplay.
+ */
+void
+gst_vaapi_display_get_size(GstVaapiDisplay *display, guint *pwidth, guint *pheight)
+{
+    g_return_if_fail(GST_VAAPI_DISPLAY(display));
+
+    if (pwidth)
+        *pwidth = display->priv->width;
+
+    if (pheight)
+        *pheight = display->priv->height;
+}
+
+/**
+ * gst_vaapi_display_get_pixel_aspect_ratio:
+ * @display: a #GstVaapiDisplay
+ * @par_n: return location for the numerator of pixel aspect ratio, or %NULL
+ * @par_d: return location for the denominator of pixel aspect ratio, or %NULL
+ *
+ * Retrieves the pixel aspect ratio of a #GstVaapiDisplay.
+ */
+void
+gst_vaapi_display_get_pixel_aspect_ratio(
+    GstVaapiDisplay *display,
+    guint           *par_n,
+    guint           *par_d
+)
+{
+    g_return_if_fail(GST_VAAPI_IS_DISPLAY(display));
+
+    if (par_n)
+        *par_n = display->priv->par_n;
+
+    if (par_d)
+        *par_d = display->priv->par_d;
+}
+
+/**
+ * gst_vaapi_display_get_decode_caps:
+ * @display: a #GstVaapiDisplay
+ *
+ * Gets the supported profiles for decoding as #GstCaps capabilities.
+ *
+ * Return value: a newly allocated #GstCaps object, possibly empty
+ */
+GstCaps *
+gst_vaapi_display_get_decode_caps(GstVaapiDisplay *display)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+
+    return get_profile_caps(display->priv->decoders);
+}
+
+/**
+ * gst_vaapi_display_has_decoder:
+ * @display: a #GstVaapiDisplay
+ * @profile: a #VAProfile
+ * @entrypoint: a #GstVaaiEntrypoint
+ *
+ * Returns whether VA @display supports @profile for decoding at the
+ * specified @entrypoint.
+ *
+ * Return value: %TRUE if VA @display supports @profile for decoding.
+ */
+gboolean
+gst_vaapi_display_has_decoder(
+    GstVaapiDisplay    *display,
+    GstVaapiProfile     profile,
+    GstVaapiEntrypoint  entrypoint
+)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), FALSE);
+
+    return find_config(display->priv->decoders, profile, entrypoint);
+}
+
+/**
+ * gst_vaapi_display_get_encode_caps:
+ * @display: a #GstVaapiDisplay
+ *
+ * Gets the supported profiles for decoding as #GstCaps capabilities.
+ *
+ * Return value: a newly allocated #GstCaps object, possibly empty
+ */
+GstCaps *
+gst_vaapi_display_get_encode_caps(GstVaapiDisplay *display)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+
+    return get_profile_caps(display->priv->encoders);
+}
+
+/**
+ * gst_vaapi_display_has_encoder:
+ * @display: a #GstVaapiDisplay
+ * @profile: a #VAProfile
+ * @entrypoint: a #GstVaapiEntrypoint
+ *
+ * Returns whether VA @display supports @profile for encoding at the
+ * specified @entrypoint.
+ *
+ * Return value: %TRUE if VA @display supports @profile for encoding.
+ */
+gboolean
+gst_vaapi_display_has_encoder(
+    GstVaapiDisplay    *display,
+    GstVaapiProfile     profile,
+    GstVaapiEntrypoint  entrypoint
+)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), FALSE);
+
+    return find_config(display->priv->encoders, profile, entrypoint);
+}
+
+/**
+ * gst_vaapi_display_get_image_caps:
+ * @display: a #GstVaapiDisplay
+ *
+ * Gets the supported image formats for gst_vaapi_surface_get_image()
+ * or gst_vaapi_surface_put_image() as #GstCaps capabilities.
+ *
+ * Note that this method does not necessarily map image formats
+ * returned by vaQueryImageFormats(). The set of capabilities can be
+ * stripped down, if gstreamer-vaapi does not support the format, or
+ * expanded to cover compatible formats not exposed by the underlying
+ * driver. e.g. I420 can be supported even if the driver only exposes
+ * YV12.
+ *
+ * Return value: a newly allocated #GstCaps object, possibly empty
+ */
+GstCaps *
+gst_vaapi_display_get_image_caps(GstVaapiDisplay *display)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+
+    return get_format_caps(display->priv->image_formats);
+}
+
+/**
+ * gst_vaapi_display_has_image_format:
+ * @display: a #GstVaapiDisplay
+ * @format: a #GstVaapiFormat
+ *
+ * Returns whether VA @display supports @format image format.
+ *
+ * Return value: %TRUE if VA @display supports @format image format
+ */
+gboolean
+gst_vaapi_display_has_image_format(
+    GstVaapiDisplay    *display,
+    GstVaapiImageFormat format
+)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), FALSE);
+    g_return_val_if_fail(format, FALSE);
+
+    if (find_format(display->priv->image_formats, format))
+        return TRUE;
+
+    /* XXX: try subpicture formats since some drivers could report a
+     * set of VA image formats that is not a superset of the set of VA
+     * subpicture formats
+     */
+    return find_format(display->priv->subpicture_formats, format);
+}
+
+/**
+ * gst_vaapi_display_get_subpicture_caps:
+ * @display: a #GstVaapiDisplay
+ *
+ * Gets the supported subpicture formats as #GstCaps capabilities.
+ *
+ * Note that this method does not necessarily map subpicture formats
+ * returned by vaQuerySubpictureFormats(). The set of capabilities can
+ * be stripped down if gstreamer-vaapi does not support the
+ * format. e.g. this is the case for paletted formats like IA44.
+ *
+ * Return value: a newly allocated #GstCaps object, possibly empty
+ */
+GstCaps *
+gst_vaapi_display_get_subpicture_caps(GstVaapiDisplay *display)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+
+    return get_format_caps(display->priv->subpicture_formats);
+}
+
+/**
+ * gst_vaapi_display_has_subpicture_format:
+ * @display: a #GstVaapiDisplay
+ * @format: a #GstVaapiFormat
+ *
+ * Returns whether VA @display supports @format subpicture format.
+ *
+ * Return value: %TRUE if VA @display supports @format subpicture format
+ */
+gboolean
+gst_vaapi_display_has_subpicture_format(
+    GstVaapiDisplay    *display,
+    GstVaapiImageFormat format
+)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), FALSE);
+    g_return_val_if_fail(format, FALSE);
+
+    return find_format(display->priv->subpicture_formats, format);
+}
+
+/**
+ * gst_vaapi_display_has_property:
+ * @display: a #GstVaapiDisplay
+ * @name: the property name to check
+ *
+ * Returns whether VA @display supports the requested property. The
+ * check is performed against the property @name. So, the client
+ * application may perform this check only once and cache this
+ * information.
+ *
+ * Return value: %TRUE if VA @display supports property @name
+ */
+gboolean
+gst_vaapi_display_has_property(GstVaapiDisplay *display, const gchar *name)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), FALSE);
+    g_return_val_if_fail(name, FALSE);
+
+    return find_property(display->priv->properties, name) != NULL;
+}
+
+static gboolean
+get_attribute(GstVaapiDisplay *display, VADisplayAttribType type, gint *value)
+{
+    VADisplayAttribute attr;
+    VAStatus status;
+
+    attr.type  = type;
+    attr.flags = VA_DISPLAY_ATTRIB_GETTABLE;
+    status = vaGetDisplayAttributes(display->priv->display, &attr, 1);
+    if (!vaapi_check_status(status, "vaGetDisplayAttributes()"))
+        return FALSE;
+    *value = attr.value;
+    return TRUE;
+}
+
+static gboolean
+set_attribute(GstVaapiDisplay *display, VADisplayAttribType type, gint value)
+{
+    VADisplayAttribute attr;
+    VAStatus status;
+
+    attr.type  = type;
+    attr.value = value;
+    attr.flags = VA_DISPLAY_ATTRIB_SETTABLE;
+    status = vaSetDisplayAttributes(display->priv->display, &attr, 1);
+    if (!vaapi_check_status(status, "vaSetDisplayAttributes()"))
+        return FALSE;
+    return TRUE;
+}
+
+static gboolean
+get_render_mode_VADisplayAttribRenderMode(
+    GstVaapiDisplay    *display,
+    GstVaapiRenderMode *pmode
+)
+{
+    gint modes, devices;
+
+    if (!get_attribute(display, VADisplayAttribRenderDevice, &devices))
+        return FALSE;
+    if (!devices)
+        return FALSE;
+    if (!get_attribute(display, VADisplayAttribRenderMode, &modes))
+        return FALSE;
+
+    /* Favor "overlay" mode since it is the most restrictive one */
+    if (modes & (VA_RENDER_MODE_LOCAL_OVERLAY|VA_RENDER_MODE_EXTERNAL_OVERLAY))
+        *pmode = GST_VAAPI_RENDER_MODE_OVERLAY;
+    else
+        *pmode = GST_VAAPI_RENDER_MODE_TEXTURE;
+    return TRUE;
+}
+
+static gboolean
+get_render_mode_VADisplayAttribDirectSurface(
+    GstVaapiDisplay    *display,
+    GstVaapiRenderMode *pmode
+)
+{
+#if VA_CHECK_VERSION(0,34,0)
+    /* VADisplayAttribDirectsurface was removed in VA-API >= 0.34.0 */
+    return FALSE;
+#else
+    gint direct_surface;
+
+    if (!get_attribute(display, VADisplayAttribDirectSurface, &direct_surface))
+        return FALSE;
+    if (direct_surface)
+        *pmode = GST_VAAPI_RENDER_MODE_OVERLAY;
+    else
+        *pmode = GST_VAAPI_RENDER_MODE_TEXTURE;
+    return TRUE;
+#endif
+}
+
+static gboolean
+get_render_mode_default(
+    GstVaapiDisplay    *display,
+    GstVaapiRenderMode *pmode
+)
+{
+    switch (display->priv->display_type) {
+#if USE_WAYLAND
+    case GST_VAAPI_DISPLAY_TYPE_WAYLAND:
+        /* wl_buffer mapped from VA surface through vaGetSurfaceBufferWl() */
+        *pmode = GST_VAAPI_RENDER_MODE_OVERLAY;
+        break;
+#endif
+#if USE_DRM
+    case GST_VAAPI_DISPLAY_TYPE_DRM:
+        /* vaGetSurfaceBufferDRM() returns the underlying DRM buffer handle */
+        *pmode = GST_VAAPI_RENDER_MODE_OVERLAY;
+        break;
+#endif
+    default:
+        /* This includes VA/X11 and VA/GLX modes */
+        *pmode = DEFAULT_RENDER_MODE;
+        break;
+    }
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_display_get_render_mode:
+ * @display: a #GstVaapiDisplay
+ * @pmode: return location for the VA @display rendering mode
+ *
+ * Returns the current VA @display rendering mode.
+ *
+ * Return value: %TRUE if VA @display rendering mode could be determined
+ */
+gboolean
+gst_vaapi_display_get_render_mode(
+    GstVaapiDisplay    *display,
+    GstVaapiRenderMode *pmode
+)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), FALSE);
+
+    /* Try with render-mode attribute */
+    if (get_render_mode_VADisplayAttribRenderMode(display, pmode))
+        return TRUE;
+
+    /* Try with direct-surface attribute */
+    if (get_render_mode_VADisplayAttribDirectSurface(display, pmode))
+        return TRUE;
+
+    /* Default: determine from the display type */
+    return get_render_mode_default(display, pmode);
+}
+
+/**
+ * gst_vaapi_display_set_render_mode:
+ * @display: a #GstVaapiDisplay
+ * @mode: the #GstVaapiRenderMode to set
+ *
+ * Sets the VA @display rendering mode to the supplied @mode. This
+ * function returns %FALSE if the rendering mode could not be set,
+ * e.g. run-time switching rendering mode is not supported.
+ *
+ * Return value: %TRUE if VA @display rendering @mode could be changed
+ *   to the requested value
+ */
+gboolean
+gst_vaapi_display_set_render_mode(
+    GstVaapiDisplay   *display,
+    GstVaapiRenderMode mode
+)
+{
+    gint modes, devices;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), FALSE);
+
+    if (!get_attribute(display, VADisplayAttribRenderDevice, &devices))
+        return FALSE;
+
+    modes = 0;
+    switch (mode) {
+    case GST_VAAPI_RENDER_MODE_OVERLAY:
+        if (devices & VA_RENDER_DEVICE_LOCAL)
+            modes |= VA_RENDER_MODE_LOCAL_OVERLAY;
+        if (devices & VA_RENDER_DEVICE_EXTERNAL)
+            modes |= VA_RENDER_MODE_EXTERNAL_OVERLAY;
+        break;
+    case GST_VAAPI_RENDER_MODE_TEXTURE:
+        if (devices & VA_RENDER_DEVICE_LOCAL)
+            modes |= VA_RENDER_MODE_LOCAL_GPU;
+        if (devices & VA_RENDER_DEVICE_EXTERNAL)
+            modes |= VA_RENDER_MODE_EXTERNAL_GPU;
+        break;
+    }
+    if (!modes)
+        return FALSE;
+    if (!set_attribute(display, VADisplayAttribRenderMode, modes))
+        return FALSE;
+
+    g_object_notify_by_pspec(G_OBJECT(display), g_properties[PROP_RENDER_MODE]);
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_display_get_rotation:
+ * @display: a #GstVaapiDisplay
+ *
+ * Returns the current VA @display rotation angle. If the VA driver
+ * does not support "rotation" display attribute, then the display is
+ * assumed to be un-rotated.
+ *
+ * Return value: the current #GstVaapiRotation value
+ */
+GstVaapiRotation
+gst_vaapi_display_get_rotation(GstVaapiDisplay *display)
+{
+    gint value;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), DEFAULT_ROTATION);
+
+    if (!get_attribute(display, VADisplayAttribRotation, &value))
+        value = VA_ROTATION_NONE;
+    return to_GstVaapiRotation(value);
+}
+
+/**
+ * gst_vaapi_display_set_rotation:
+ * @display: a #GstVaapiDisplay
+ * @rotation: the #GstVaapiRotation value to set
+ *
+ * Sets the VA @display rotation angle to the supplied @rotation
+ * value. This function returns %FALSE if the rotation angle could not
+ * be set, e.g. the VA driver does not allow to change the display
+ * rotation angle.
+ *
+ * Return value: %TRUE if VA @display rotation angle could be changed
+ *   to the requested value
+ */
+gboolean
+gst_vaapi_display_set_rotation(
+    GstVaapiDisplay *display,
+    GstVaapiRotation rotation
+)
+{
+    guint value;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), FALSE);
+
+    value = from_GstVaapiRotation(rotation);
+    if (!set_attribute(display, VADisplayAttribRotation, value))
+        return FALSE;
+
+    g_object_notify_by_pspec(G_OBJECT(display), g_properties[PROP_ROTATION]);
+    return TRUE;
+}
+
+/* Get color balance attributes */
+static gboolean
+get_color_balance(GstVaapiDisplay *display, guint prop_id, gfloat *v)
+{
+    GParamSpecFloat * const pspec = G_PARAM_SPEC_FLOAT(g_properties[prop_id]);
+    const GstVaapiProperty *prop;
+    const VADisplayAttribute *attr;
+    gfloat out_value;
+    gint value;
+
+    if (!pspec)
+        return FALSE;
+
+    prop = find_property_by_pspec(display, &pspec->parent_instance);
+    if (!prop)
+        return FALSE;
+    attr = &prop->attribute;
+
+    if (!get_attribute(display, attr->type, &value))
+        return FALSE;
+
+    /* Scale wrt. the medium ("default") value */
+    out_value = pspec->default_value;
+    if (value > attr->value)
+        out_value += ((gfloat)(value - attr->value) /
+                      (attr->max_value - attr->value) *
+                      (pspec->maximum - pspec->default_value));
+    else if (value < attr->value)
+        out_value -= ((gfloat)(attr->value - value) /
+                      (attr->value - attr->min_value) *
+                      (pspec->default_value - pspec->minimum));
+    *v = out_value;
+    return TRUE;
+}
+
+/* Set color balance attribute */
+static gboolean
+set_color_balance(GstVaapiDisplay *display, guint prop_id, gfloat v)
+{
+    GParamSpecFloat * const pspec = G_PARAM_SPEC_FLOAT(g_properties[prop_id]);
+    const GstVaapiProperty *prop;
+    const VADisplayAttribute *attr;
+    gint value;
+
+    if (!pspec)
+        return FALSE;
+
+    prop = find_property_by_pspec(display, &pspec->parent_instance);
+    if (!prop)
+        return FALSE;
+    attr = &prop->attribute;
+
+    /* Scale wrt. the medium ("default") value */
+    value = attr->value;
+    if (v > pspec->default_value)
+        value += ((v - pspec->default_value) /
+                  (pspec->maximum - pspec->default_value) *
+                  (attr->max_value - attr->value));
+    else if (v < pspec->default_value)
+        value -= ((pspec->default_value - v) /
+                  (pspec->default_value - pspec->minimum) *
+                  (attr->value - attr->min_value));
+    if (!set_attribute(display, attr->type, value))
+        return FALSE;
+
+    g_object_notify_by_pspec(G_OBJECT(display), g_properties[prop_id]);
+    return TRUE;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay.h b/gst-libs/gst/vaapi/gstvaapidisplay.h
new file mode 100644 (file)
index 0000000..56ca042
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ *  gstvaapidisplay.h - VA display abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DISPLAY_H
+#define GST_VAAPI_DISPLAY_H
+
+#include <va/va.h>
+#include <gst/gst.h>
+#include <gst/vaapi/gstvaapitypes.h>
+#include <gst/vaapi/gstvaapiimageformat.h>
+#include <gst/vaapi/gstvaapiprofile.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_DISPLAY \
+    (gst_vaapi_display_get_type())
+
+#define GST_VAAPI_DISPLAY(obj)                          \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                  \
+                                GST_VAAPI_TYPE_DISPLAY, \
+                                GstVaapiDisplay))
+
+#define GST_VAAPI_DISPLAY_CLASS(klass)                  \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                   \
+                             GST_VAAPI_TYPE_DISPLAY,    \
+                             GstVaapiDisplayClass))
+
+#define GST_VAAPI_IS_DISPLAY(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_DISPLAY))
+
+#define GST_VAAPI_IS_DISPLAY_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_DISPLAY))
+
+#define GST_VAAPI_DISPLAY_GET_CLASS(obj)                \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                   \
+                               GST_VAAPI_TYPE_DISPLAY,  \
+                               GstVaapiDisplayClass))
+
+typedef enum   _GstVaapiDisplayType             GstVaapiDisplayType;
+typedef struct _GstVaapiDisplayInfo             GstVaapiDisplayInfo;
+typedef struct _GstVaapiDisplay                 GstVaapiDisplay;
+typedef struct _GstVaapiDisplayPrivate          GstVaapiDisplayPrivate;
+typedef struct _GstVaapiDisplayClass            GstVaapiDisplayClass;
+
+/**
+ * GstVaapiDisplayType:
+ * @GST_VAAPI_DISPLAY_TYPE_ANY: Automatic detection of the display type.
+ * @GST_VAAPI_DISPLAY_TYPE_X11: VA/X11 display.
+ * @GST_VAAPI_DISPLAY_TYPE_GLX: VA/GLX display.
+ * @GST_VAAPI_DISPLAY_TYPE_WAYLAND: VA/Wayland display.
+ * @GST_VAAPI_DISPLAY_TYPE_DRM: VA/DRM display.
+ */
+enum _GstVaapiDisplayType {
+    GST_VAAPI_DISPLAY_TYPE_ANY = 0,
+    GST_VAAPI_DISPLAY_TYPE_X11,
+    GST_VAAPI_DISPLAY_TYPE_GLX,
+    GST_VAAPI_DISPLAY_TYPE_WAYLAND,
+    GST_VAAPI_DISPLAY_TYPE_DRM,
+};
+
+#define GST_VAAPI_TYPE_DISPLAY_TYPE \
+    (gst_vaapi_display_type_get_type())
+
+GType
+gst_vaapi_display_type_get_type(void) G_GNUC_CONST;
+
+/**
+ * GstVaapiDisplayInfo:
+ *
+ * Generic class to retrieve VA display info
+ */
+struct _GstVaapiDisplayInfo {
+    GstVaapiDisplay    *display;
+    GstVaapiDisplayType display_type;
+    gchar              *display_name;
+    VADisplay           va_display;
+    gpointer            native_display;
+};
+
+/**
+ * GstVaapiDisplayProperties:
+ * @GST_VAAPI_DISPLAY_PROP_RENDER_MODE: rendering mode (#GstVaapiRenderMode).
+ * @GST_VAAPI_DISPLAY_PROP_ROTATION: rotation angle (#GstVaapiRotation).
+ * @GST_VAAPI_DISPLAY_PROP_HUE: hue (float: [-180 ; 180], default: 0).
+ * @GST_VAAPI_DISPLAY_PROP_SATURATION: saturation (float: [0 ; 2], default: 1).
+ * @GST_VAAPI_DISPLAY_PROP_BRIGHTNESS: brightness (float: [-1 ; 1], default: 0).
+ * @GST_VAAPI_DISPLAY_PROP_CONTRAST: contrast (float: [0 ; 2], default: 1).
+ */
+#define GST_VAAPI_DISPLAY_PROP_RENDER_MODE      "render-mode"
+#define GST_VAAPI_DISPLAY_PROP_ROTATION         "rotation"
+#define GST_VAAPI_DISPLAY_PROP_HUE              "hue"
+#define GST_VAAPI_DISPLAY_PROP_SATURATION       "saturation"
+#define GST_VAAPI_DISPLAY_PROP_BRIGHTNESS       "brightness"
+#define GST_VAAPI_DISPLAY_PROP_CONTRAST         "contrast"
+
+/**
+ * GstVaapiDisplay:
+ *
+ * Base class for VA displays.
+ */
+struct _GstVaapiDisplay {
+    /*< private >*/
+    GObject parent_instance;
+
+    GstVaapiDisplayPrivate *priv;
+};
+
+/**
+ * GstVaapiDisplayClass:
+ * @open_display: virtual function to open a display
+ * @close_display: virtual function to close a display
+ * @lock: (optional) virtual function to lock a display
+ * @unlock: (optional) virtual function to unlock a display
+ * @sync: (optional) virtual function to sync a display
+ * @flush: (optional) virtual function to flush pending requests of a display
+ * @get_display: virtual function to retrieve the #GstVaapiDisplayInfo
+ * @get_size: virtual function to retrieve the display dimensions, in pixels
+ * @get_size_mm: virtual function to retrieve the display dimensions, in millimeters
+ *
+ * Base class for VA displays.
+ */
+struct _GstVaapiDisplayClass {
+    /*< private >*/
+    GObjectClass parent_class;
+
+    /*< public >*/
+    gboolean   (*open_display)  (GstVaapiDisplay *display);
+    void       (*close_display) (GstVaapiDisplay *display);
+    void       (*lock)          (GstVaapiDisplay *display);
+    void       (*unlock)        (GstVaapiDisplay *display);
+    void       (*sync)          (GstVaapiDisplay *display);
+    void       (*flush)         (GstVaapiDisplay *display);
+    gboolean   (*get_display)   (GstVaapiDisplay *display,
+                                 GstVaapiDisplayInfo *info);
+    void       (*get_size)      (GstVaapiDisplay *display,
+                                 guint *pwidth, guint *pheight);
+    void       (*get_size_mm)   (GstVaapiDisplay *display,
+                                 guint *pwidth, guint *pheight);
+};
+
+GType
+gst_vaapi_display_get_type(void) G_GNUC_CONST;
+
+GstVaapiDisplay *
+gst_vaapi_display_new_with_display(VADisplay va_display);
+
+void
+gst_vaapi_display_lock(GstVaapiDisplay *display);
+
+void
+gst_vaapi_display_unlock(GstVaapiDisplay *display);
+
+void
+gst_vaapi_display_sync(GstVaapiDisplay *display);
+
+void
+gst_vaapi_display_flush(GstVaapiDisplay *display);
+
+GstVaapiDisplayType
+gst_vaapi_display_get_display_type(GstVaapiDisplay *display);
+
+VADisplay
+gst_vaapi_display_get_display(GstVaapiDisplay *display);
+
+guint
+gst_vaapi_display_get_width(GstVaapiDisplay *display);
+
+guint
+gst_vaapi_display_get_height(GstVaapiDisplay *display);
+
+void
+gst_vaapi_display_get_size(GstVaapiDisplay *display, guint *pwidth, guint *pheight);
+
+void
+gst_vaapi_display_get_pixel_aspect_ratio(
+    GstVaapiDisplay *display,
+    guint           *par_n,
+    guint           *par_d
+);
+
+GstCaps *
+gst_vaapi_display_get_decode_caps(GstVaapiDisplay *display);
+
+gboolean
+gst_vaapi_display_has_decoder(
+    GstVaapiDisplay    *display,
+    GstVaapiProfile     profile,
+    GstVaapiEntrypoint  entrypoint
+);
+
+GstCaps *
+gst_vaapi_display_get_encode_caps(GstVaapiDisplay *display);
+
+gboolean
+gst_vaapi_display_has_encoder(
+    GstVaapiDisplay    *display,
+    GstVaapiProfile     profile,
+    GstVaapiEntrypoint  entrypoint
+);
+
+GstCaps *
+gst_vaapi_display_get_image_caps(GstVaapiDisplay *display);
+
+gboolean
+gst_vaapi_display_has_image_format(
+    GstVaapiDisplay    *display,
+    GstVaapiImageFormat format
+);
+
+GstCaps *
+gst_vaapi_display_get_subpicture_caps(GstVaapiDisplay *display);
+
+gboolean
+gst_vaapi_display_has_subpicture_format(
+    GstVaapiDisplay    *display,
+    GstVaapiImageFormat format
+);
+
+gboolean
+gst_vaapi_display_has_property(GstVaapiDisplay *display, const gchar *name);
+
+gboolean
+gst_vaapi_display_get_render_mode(
+    GstVaapiDisplay    *display,
+    GstVaapiRenderMode *pmode
+);
+
+gboolean
+gst_vaapi_display_set_render_mode(
+    GstVaapiDisplay   *display,
+    GstVaapiRenderMode mode
+);
+
+GstVaapiRotation
+gst_vaapi_display_get_rotation(GstVaapiDisplay *display);
+
+gboolean
+gst_vaapi_display_set_rotation(
+    GstVaapiDisplay *display,
+    GstVaapiRotation rotation
+);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DISPLAY_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_drm.c b/gst-libs/gst/vaapi/gstvaapidisplay_drm.c
new file mode 100644 (file)
index 0000000..6a1d148
--- /dev/null
@@ -0,0 +1,532 @@
+/*
+ *  gstvaapidisplay_drm.c - VA/DRM display abstraction
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapidisplay_drm
+ * @short_description: VA/DRM display abstraction
+ */
+
+#include "sysdeps.h"
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <libudev.h>
+#include <xf86drm.h>
+#include <va/va_drm.h>
+#include "gstvaapiutils.h"
+#include "gstvaapidisplay_priv.h"
+#include "gstvaapidisplay_drm.h"
+#include "gstvaapidisplay_drm_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiDisplayDRM,
+              gst_vaapi_display_drm,
+              GST_VAAPI_TYPE_DISPLAY);
+
+enum {
+    PROP_0,
+
+    PROP_DEVICE_PATH,
+    PROP_DRM_DEVICE
+};
+
+#define NAME_PREFIX "DRM:"
+#define NAME_PREFIX_LENGTH 4
+
+static inline gboolean
+is_device_path(const gchar *device_path)
+{
+    return strncmp(device_path, NAME_PREFIX, NAME_PREFIX_LENGTH) == 0;
+}
+
+static gboolean
+compare_device_path(gconstpointer a, gconstpointer b, gpointer user_data)
+{
+    const gchar *cached_name = a;
+    const gchar *tested_name = b;
+
+    if (!cached_name || !is_device_path(cached_name))
+        return FALSE;
+    g_return_val_if_fail(tested_name && is_device_path(tested_name), FALSE);
+
+    cached_name += NAME_PREFIX_LENGTH;
+    tested_name += NAME_PREFIX_LENGTH;
+    return strcmp(cached_name, tested_name) == 0;
+}
+
+static void
+gst_vaapi_display_drm_finalize(GObject *object)
+{
+    G_OBJECT_CLASS(gst_vaapi_display_drm_parent_class)->finalize(object);
+}
+
+/* Get default device path. Actually, the first match in the DRM subsystem */
+static const gchar *
+get_default_device_path(gpointer ptr)
+{
+    GstVaapiDisplayDRM * const display = GST_VAAPI_DISPLAY_DRM(ptr);
+    GstVaapiDisplayDRMPrivate * const priv = display->priv;
+    const gchar *syspath, *devpath;
+    struct udev *udev = NULL;
+    struct udev_device *device, *parent;
+    struct udev_enumerate *e = NULL;
+    struct udev_list_entry *l;
+    int fd;
+
+    if (!priv->device_path_default) {
+        udev = udev_new();
+        if (!udev)
+            goto end;
+
+        e = udev_enumerate_new(udev);
+        if (!e)
+            goto end;
+
+        udev_enumerate_add_match_subsystem(e, "drm");
+        udev_enumerate_scan_devices(e);
+        udev_list_entry_foreach(l, udev_enumerate_get_list_entry(e)) {
+            syspath = udev_list_entry_get_name(l);
+            device  = udev_device_new_from_syspath(udev, syspath);
+            parent  = udev_device_get_parent(device);
+            if (strcmp(udev_device_get_subsystem(parent), "pci") != 0) {
+                udev_device_unref(device);
+                continue;
+            }
+
+            devpath = udev_device_get_devnode(device);
+            fd = open(devpath, O_RDWR|O_CLOEXEC);
+            if (fd < 0) {
+                udev_device_unref(device);
+                continue;
+            }
+
+            priv->device_path_default = g_strdup(devpath);
+            close(fd);
+            udev_device_unref(device);
+            break;
+        }
+
+    end:
+        if (e)
+            udev_enumerate_unref(e);
+        if (udev)
+            udev_unref(udev);
+    }
+    return priv->device_path_default;
+}
+
+/* Reconstruct a device path without our prefix */
+static const gchar *
+get_device_path(gpointer ptr)
+{
+    GstVaapiDisplayDRM * const display = GST_VAAPI_DISPLAY_DRM(ptr);
+    const gchar *device_path = display->priv->device_path;
+
+    if (!device_path)
+        return NULL;
+
+    g_return_val_if_fail(is_device_path(device_path), NULL);
+
+    device_path += NAME_PREFIX_LENGTH;
+    if (*device_path == '\0')
+        return NULL;
+    return device_path;
+}
+
+/* Mangle device path with our prefix */
+static void
+set_device_path(GstVaapiDisplayDRM *display, const gchar *device_path)
+{
+    GstVaapiDisplayDRMPrivate * const priv = display->priv;
+
+    g_free(priv->device_path);
+    priv->device_path = NULL;
+
+    if (!device_path) {
+        device_path = get_default_device_path(display);
+        if (!device_path)
+            return;
+    }
+    priv->device_path = g_strdup_printf("%s%s", NAME_PREFIX, device_path);
+}
+
+/* Set device path from file descriptor */
+static void
+set_device_path_from_fd(GstVaapiDisplayDRM *display, gint drm_device)
+{
+    GstVaapiDisplayDRMPrivate * const priv = display->priv;
+    const gchar *busid, *path, *str;
+    gsize busid_length, path_length;
+    struct udev *udev = NULL;
+    struct udev_device *device;
+    struct udev_enumerate *e = NULL;
+    struct udev_list_entry *l;
+
+    g_free(priv->device_path);
+    priv->device_path = NULL;
+
+    if (drm_device < 0)
+        return;
+
+    busid = drmGetBusid(drm_device);
+    if (!busid)
+        return;
+    if (strncmp(busid, "pci:", 4) != 0)
+        return;
+    busid += 4;
+    busid_length = strlen(busid);
+
+    udev = udev_new();
+    if (!udev)
+        goto end;
+
+    e = udev_enumerate_new(udev);
+    if (!e)
+        goto end;
+
+    udev_enumerate_add_match_subsystem(e, "drm");
+    udev_enumerate_scan_devices(e);
+    udev_list_entry_foreach(l, udev_enumerate_get_list_entry(e)) {
+        path = udev_list_entry_get_name(l);
+        str  = strstr(path, busid);
+        if (!str || str <= path || str[-1] != '/')
+            continue;
+
+        path_length = strlen(path);
+        if (str + busid_length >= path + path_length)
+            continue;
+        if (strncmp(&str[busid_length], "/drm/card", 9) != 0)
+            continue;
+
+        device = udev_device_new_from_syspath(udev, path);
+        if (!device)
+            continue;
+
+        path = udev_device_get_devnode(device);
+        priv->device_path = g_strdup_printf("%s%s", NAME_PREFIX, path);
+        udev_device_unref(device);
+        break;
+    }
+
+end:
+    if (e)
+        udev_enumerate_unref(e);
+    if (udev)
+        udev_unref(udev);
+}
+
+static void
+gst_vaapi_display_drm_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiDisplayDRM * const display = GST_VAAPI_DISPLAY_DRM(object);
+
+    switch (prop_id) {
+    case PROP_DEVICE_PATH:
+        set_device_path(display, g_value_get_string(value));
+        break;
+    case PROP_DRM_DEVICE:
+        display->priv->drm_device = g_value_get_int(value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_display_drm_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiDisplayDRM * const display = GST_VAAPI_DISPLAY_DRM(object);
+
+    switch (prop_id) {
+    case PROP_DEVICE_PATH:
+        g_value_set_string(value, get_device_path(display));
+        break;
+    case PROP_DRM_DEVICE:
+        g_value_set_int(value, display->priv->drm_device);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_display_drm_constructed(GObject *object)
+{
+    GstVaapiDisplayDRM * const display = GST_VAAPI_DISPLAY_DRM(object);
+    GstVaapiDisplayDRMPrivate * const priv = display->priv;
+    GstVaapiDisplayCache * const cache = gst_vaapi_display_get_cache();
+    const GstVaapiDisplayInfo *info;
+    GObjectClass *parent_class;
+
+    priv->create_display = priv->drm_device < 0;
+
+    /* Don't create DRM display if there is one in the cache already */
+    if (priv->create_display) {
+        info = gst_vaapi_display_cache_lookup_by_name(
+            cache,
+            priv->device_path,
+            compare_device_path, NULL
+        );
+        if (info) {
+            priv->drm_device     = GPOINTER_TO_INT(info->native_display);
+            priv->create_display = FALSE;
+        }
+    }
+
+    /* Reset device-path if the user provided his own DRM display */
+    if (!priv->create_display)
+        set_device_path_from_fd(display, priv->drm_device);
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_display_drm_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+}
+
+static gboolean
+gst_vaapi_display_drm_open_display(GstVaapiDisplay *display)
+{
+    GstVaapiDisplayDRMPrivate * const priv =
+        GST_VAAPI_DISPLAY_DRM(display)->priv;
+
+    if (priv->create_display) {
+        const gchar *device_path = get_device_path(display);
+        if (!device_path)
+            return FALSE;
+        priv->drm_device = open(device_path, O_RDWR|O_CLOEXEC);
+        if (priv->drm_device < 0)
+            return FALSE;
+    }
+    if (priv->drm_device < 0)
+        return FALSE;
+    return TRUE;
+}
+
+static void
+gst_vaapi_display_drm_close_display(GstVaapiDisplay *display)
+{
+    GstVaapiDisplayDRMPrivate * const priv =
+        GST_VAAPI_DISPLAY_DRM(display)->priv;
+
+    if (priv->drm_device >= 0) {
+        if (priv->create_display)
+            close(priv->drm_device);
+        priv->drm_device = -1;
+    }
+
+    if (priv->device_path) {
+        g_free(priv->device_path);
+        priv->device_path = NULL;
+    }
+
+    if (priv->device_path_default) {
+        g_free(priv->device_path_default);
+        priv->device_path_default = NULL;
+    }
+}
+
+static gboolean
+gst_vaapi_display_drm_get_display_info(
+    GstVaapiDisplay     *display,
+    GstVaapiDisplayInfo *info
+)
+{
+    GstVaapiDisplayDRMPrivate * const priv =
+        GST_VAAPI_DISPLAY_DRM(display)->priv;
+    GstVaapiDisplayCache *cache;
+    const GstVaapiDisplayInfo *cached_info;
+
+    /* Return any cached info even if child has its own VA display */
+    cache = gst_vaapi_display_get_cache();
+    if (!cache)
+        return FALSE;
+    cached_info = gst_vaapi_display_cache_lookup_by_native_display(
+        cache, GINT_TO_POINTER(priv->drm_device));
+    if (cached_info) {
+        *info = *cached_info;
+        return TRUE;
+    }
+
+    /* Otherwise, create VA display if there is none already */
+    info->native_display = GINT_TO_POINTER(priv->drm_device);
+    info->display_name   = priv->device_path;
+    if (!info->va_display) {
+        info->va_display = vaGetDisplayDRM(priv->drm_device);
+        if (!info->va_display)
+            return FALSE;
+        info->display_type = GST_VAAPI_DISPLAY_TYPE_DRM;
+    }
+    return TRUE;
+}
+
+static void
+gst_vaapi_display_drm_class_init(GstVaapiDisplayDRMClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstVaapiDisplayClass * const dpy_class = GST_VAAPI_DISPLAY_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiDisplayDRMPrivate));
+
+    object_class->finalize      = gst_vaapi_display_drm_finalize;
+    object_class->set_property  = gst_vaapi_display_drm_set_property;
+    object_class->get_property  = gst_vaapi_display_drm_get_property;
+    object_class->constructed   = gst_vaapi_display_drm_constructed;
+
+    dpy_class->open_display     = gst_vaapi_display_drm_open_display;
+    dpy_class->close_display    = gst_vaapi_display_drm_close_display;
+    dpy_class->get_display      = gst_vaapi_display_drm_get_display_info;
+
+    /**
+     * GstVaapiDisplayDRM:drm-device:
+     *
+     * The DRM device (file descriptor).
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_DRM_DEVICE,
+         g_param_spec_int("drm-device",
+                          "DRM device",
+                          "DRM device",
+                          -1, G_MAXINT32, -1,
+                          G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    /**
+     * GstVaapiDisplayDRM:device-path:
+     *
+     * The DRM device path.
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_DEVICE_PATH,
+         g_param_spec_string("device-path",
+                             "DRM device path",
+                             "DRM device path",
+                             NULL,
+                             G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gst_vaapi_display_drm_init(GstVaapiDisplayDRM *display)
+{
+    GstVaapiDisplayDRMPrivate * const priv =
+        GST_VAAPI_DISPLAY_DRM_GET_PRIVATE(display);
+
+    display->priv               = priv;
+    priv->device_path_default   = NULL;
+    priv->device_path           = NULL;
+    priv->drm_device            = -1;
+    priv->create_display        = TRUE;
+}
+
+/**
+ * gst_vaapi_display_drm_new:
+ * @device_path: the DRM device path
+ *
+ * Opens an DRM file descriptor using @device_path and returns a newly
+ * allocated #GstVaapiDisplay object. The DRM display will be cloed
+ * when the reference count of the object reaches zero.
+ *
+ * If @device_path is NULL, the DRM device path will be automatically
+ * determined as the first positive match in the list of available DRM
+ * devices.
+ *
+ * Return value: a newly allocated #GstVaapiDisplay object
+ */
+GstVaapiDisplay *
+gst_vaapi_display_drm_new(const gchar *device_path)
+{
+    return g_object_new(GST_VAAPI_TYPE_DISPLAY_DRM,
+                        "device-path", device_path,
+                        NULL);
+}
+
+/**
+ * gst_vaapi_display_drm_new_with_device:
+ * @device: an open DRM device (file descriptor)
+ *
+ * Creates a #GstVaapiDisplay based on the open DRM @device. The
+ * caller still owns the device file descriptor and must call close()
+ * when all #GstVaapiDisplay references are released. Doing so too
+ * early can yield undefined behaviour.
+ *
+ * Return value: a newly allocated #GstVaapiDisplay object
+ */
+GstVaapiDisplay *
+gst_vaapi_display_drm_new_with_device(gint device)
+{
+    g_return_val_if_fail(device >= 0, NULL);
+
+    return g_object_new(GST_VAAPI_TYPE_DISPLAY_DRM,
+                        "drm-device", device,
+                        NULL);
+}
+
+/**
+ * gst_vaapi_display_drm_get_device:
+ * @display: a #GstVaapiDisplayDRM
+ *
+ * Returns the underlying DRM device file descriptor that was created
+ * by gst_vaapi_display_drm_new() or that was bound from
+ * gst_vaapi_display_drm_new_with_device().
+ *
+ * Return value: the DRM file descriptor attached to @display
+ */
+gint
+gst_vaapi_display_drm_get_device(GstVaapiDisplayDRM *display)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY_DRM(display), -1);
+
+    return display->priv->drm_device;
+}
+
+/**
+ * gst_vaapi_display_drm_get_device_path:
+ * @display: a #GstVaapiDisplayDRM
+ *
+ * Returns the underlying DRM device path name was created by
+ * gst_vaapi_display_drm_new() or that was bound from
+ * gst_vaapi_display_drm_new_with_device().
+ *
+ * Note: the #GstVaapiDisplayDRM object owns the resulting string, so
+ * it shall not be deallocated.
+ *
+ * Return value: the DRM device path name attached to @display
+ */
+const gchar *
+gst_vaapi_display_drm_get_device_path(GstVaapiDisplayDRM *display)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY_DRM(display), NULL);
+
+    return display->priv->device_path;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_drm.h b/gst-libs/gst/vaapi/gstvaapidisplay_drm.h
new file mode 100644 (file)
index 0000000..fad0d53
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ *  gstvaapidisplay_drm.h - VA/DRM display abstraction
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DISPLAY_DRM_H
+#define GST_VAAPI_DISPLAY_DRM_H
+
+#include <gst/vaapi/gstvaapidisplay.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_DISPLAY_DRM \
+    (gst_vaapi_display_drm_get_type())
+
+#define GST_VAAPI_DISPLAY_DRM(obj)                              \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_DISPLAY_DRM,     \
+                                GstVaapiDisplayDRM))
+
+#define GST_VAAPI_DISPLAY_DRM_CLASS(klass)                      \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_DISPLAY_DRM,        \
+                             GstVaapiDisplayDRMClass))
+
+#define GST_VAAPI_IS_DISPLAY_DRM(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_DISPLAY_DRM))
+
+#define GST_VAAPI_IS_DISPLAY_DRM_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_DISPLAY_DRM))
+
+#define GST_VAAPI_DISPLAY_DRM_GET_CLASS(obj)                    \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_DISPLAY_DRM,      \
+                               GstVaapiDisplayDRMClass))
+
+typedef struct _GstVaapiDisplayDRM              GstVaapiDisplayDRM;
+typedef struct _GstVaapiDisplayDRMPrivate       GstVaapiDisplayDRMPrivate;
+typedef struct _GstVaapiDisplayDRMClass         GstVaapiDisplayDRMClass;
+
+/**
+ * GstVaapiDisplayDRM:
+ *
+ * VA/DRM display wrapper.
+ */
+struct _GstVaapiDisplayDRM {
+    /*< private >*/
+    GstVaapiDisplay parent_instance;
+
+    GstVaapiDisplayDRMPrivate *priv;
+};
+
+
+/**
+ * GstVaapiDisplayDRMClass:
+ *
+ * VA/DRM display wrapper clas.
+ */
+struct _GstVaapiDisplayDRMClass {
+    /*< private >*/
+    GstVaapiDisplayClass parent_class;
+};
+
+GType
+gst_vaapi_display_drm_get_type(void) G_GNUC_CONST;
+
+GstVaapiDisplay *
+gst_vaapi_display_drm_new(const gchar *device_path);
+
+GstVaapiDisplay *
+gst_vaapi_display_drm_new_with_device(gint device);
+
+gint
+gst_vaapi_display_drm_get_device(GstVaapiDisplayDRM *display);
+
+const gchar *
+gst_vaapi_display_drm_get_device_path(GstVaapiDisplayDRM *display);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DISPLAY_DRM_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_drm_priv.h b/gst-libs/gst/vaapi/gstvaapidisplay_drm_priv.h
new file mode 100644 (file)
index 0000000..f6211a7
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *  gstvaapidisplay_drm_priv.h - Internal VA/DRM interface
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DISPLAY_DRM_PRIV_H
+#define GST_VAAPI_DISPLAY_DRM_PRIV_H
+
+#include <gst/vaapi/gstvaapidisplay_drm.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_DISPLAY_DRM_GET_PRIVATE(obj)                  \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_DISPLAY_DRM,   \
+                                 GstVaapiDisplayDRMPrivate))
+
+#define GST_VAAPI_DISPLAY_DRM_CAST(display) ((GstVaapiDisplayDRM *)(display))
+
+/**
+ * GST_VAAPI_DISPLAY_DRM_DEVICE:
+ * @display: a #GstVaapiDisplay
+ *
+ * Macro that evaluates to the underlying DRM file descriptor of @display
+ */
+#undef  GST_VAAPI_DISPLAY_DRM_DEVICE
+#define GST_VAAPI_DISPLAY_DRM_DEVICE(display) \
+    GST_VAAPI_DISPLAY_DRM_CAST(display)->priv->drm_device
+
+struct _GstVaapiDisplayDRMPrivate {
+    gchar      *device_path_default;
+    gchar      *device_path;
+    gint        drm_device;
+    guint       create_display  : 1;
+};
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DISPLAY_DRM_PRIV_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_glx.c b/gst-libs/gst/vaapi/gstvaapidisplay_glx.c
new file mode 100644 (file)
index 0000000..87ac84a
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ *  gstvaapidisplay_glx.c - VA/GLX display abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapidisplay_glx
+ * @short_description: VA/GLX display abstraction
+ */
+
+#include "sysdeps.h"
+#include "gstvaapicompat.h"
+#include "gstvaapiutils.h"
+#include "gstvaapiutils_glx.h"
+#include "gstvaapidisplay_priv.h"
+#include "gstvaapidisplay_x11_priv.h"
+#include "gstvaapidisplay_glx.h"
+#include "gstvaapidisplay_glx_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiDisplayGLX,
+              gst_vaapi_display_glx,
+              GST_VAAPI_TYPE_DISPLAY_X11);
+
+static void
+gst_vaapi_display_glx_finalize(GObject *object)
+{
+    G_OBJECT_CLASS(gst_vaapi_display_glx_parent_class)->finalize(object);
+}
+
+static gboolean
+gst_vaapi_display_glx_get_display_info(
+    GstVaapiDisplay     *display,
+    GstVaapiDisplayInfo *info
+)
+{
+    GstVaapiDisplayClass * const dpy_class =
+        GST_VAAPI_DISPLAY_CLASS(gst_vaapi_display_glx_parent_class);
+
+    info->va_display = vaGetDisplayGLX(GST_VAAPI_DISPLAY_XDISPLAY(display));
+    if (!info->va_display)
+        return FALSE;
+    info->display_type = GST_VAAPI_DISPLAY_TYPE_GLX;
+    return dpy_class->get_display(display, info);
+}
+
+static void
+gst_vaapi_display_glx_class_init(GstVaapiDisplayGLXClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstVaapiDisplayClass * const dpy_class = GST_VAAPI_DISPLAY_CLASS(klass);
+
+    object_class->finalize      = gst_vaapi_display_glx_finalize;
+    dpy_class->get_display      = gst_vaapi_display_glx_get_display_info;
+}
+
+static void
+gst_vaapi_display_glx_init(GstVaapiDisplayGLX *display)
+{
+}
+
+/**
+ * gst_vaapi_display_glx_new:
+ * @display_name: the X11 display name
+ *
+ * Opens an X11 #Display using @display_name and returns a newly
+ * allocated #GstVaapiDisplay object. The X11 display will be cloed
+ * when the reference count of the object reaches zero.
+ *
+ * Return value: a newly allocated #GstVaapiDisplay object
+ */
+GstVaapiDisplay *
+gst_vaapi_display_glx_new(const gchar *display_name)
+{
+    return g_object_new(GST_VAAPI_TYPE_DISPLAY_GLX,
+                        "display-name", display_name,
+                        NULL);
+}
+
+/**
+ * gst_vaapi_display_glx_new_with_display:
+ * @x11_display: an X11 #Display
+ *
+ * Creates a #GstVaapiDisplay based on the X11 @x11_display
+ * display. The caller still owns the display and must call
+ * XCloseDisplay() when all #GstVaapiDisplay references are
+ * released. Doing so too early can yield undefined behaviour.
+ *
+ * Return value: a newly allocated #GstVaapiDisplay object
+ */
+GstVaapiDisplay *
+gst_vaapi_display_glx_new_with_display(Display *x11_display)
+{
+    return g_object_new(GST_VAAPI_TYPE_DISPLAY_GLX,
+                        "x11-display", x11_display,
+                        NULL);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_glx.h b/gst-libs/gst/vaapi/gstvaapidisplay_glx.h
new file mode 100644 (file)
index 0000000..6f115e5
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *  gstvaapidisplay_glx.h - VA/GLX display abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DISPLAY_GLX_H
+#define GST_VAAPI_DISPLAY_GLX_H
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <gst/vaapi/gstvaapidisplay_x11.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_DISPLAY_GLX \
+    (gst_vaapi_display_glx_get_type())
+
+#define GST_VAAPI_DISPLAY_GLX(obj)                              \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_DISPLAY_GLX,     \
+                                GstVaapiDisplayGLX))
+
+#define GST_VAAPI_DISPLAY_GLX_CLASS(klass)                      \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_DISPLAY_GLX,        \
+                             GstVaapiDisplayGLXClass))
+
+#define GST_VAAPI_IS_DISPLAY_GLX(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_DISPLAY_GLX))
+
+#define GST_VAAPI_IS_DISPLAY_GLX_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_DISPLAY_GLX))
+
+#define GST_VAAPI_DISPLAY_GLX_GET_CLASS(obj)                    \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_DISPLAY_GLX,      \
+                               GstVaapiDisplayGLXClass))
+
+typedef struct _GstVaapiDisplayGLX              GstVaapiDisplayGLX;
+typedef struct _GstVaapiDisplayGLXClass         GstVaapiDisplayGLXClass;
+
+/**
+ * GstVaapiDisplayGLX:
+ *
+ * VA/GLX display wrapper.
+ */
+struct _GstVaapiDisplayGLX {
+    /*< private >*/
+    GstVaapiDisplayX11 parent_instance;
+};
+
+
+/**
+ * GstVaapiDisplayGLXClass:
+ *
+ * VA/GLX display wrapper clas.
+ */
+struct _GstVaapiDisplayGLXClass {
+    /*< private >*/
+    GstVaapiDisplayX11Class parent_class;
+};
+
+GType
+gst_vaapi_display_glx_get_type(void) G_GNUC_CONST;
+
+GstVaapiDisplay *
+gst_vaapi_display_glx_new(const gchar *display_name);
+
+GstVaapiDisplay *
+gst_vaapi_display_glx_new_with_display(Display *x11_display);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DISPLAY_GLX_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_glx_priv.h b/gst-libs/gst/vaapi/gstvaapidisplay_glx_priv.h
new file mode 100644 (file)
index 0000000..a843b38
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *  gstvaapidisplay_glx_priv.h - Internal VA/GLX interface
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DISPLAY_GLX_PRIV_H
+#define GST_VAAPI_DISPLAY_GLX_PRIV_H
+
+#include <gst/vaapi/gstvaapiutils_glx.h>
+#include <gst/vaapi/gstvaapidisplay_glx.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_DISPLAY_GLX_CAST(display) ((GstVaapiDisplayGLX *)(display))
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DISPLAY_GLX_PRIV_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_priv.h b/gst-libs/gst/vaapi/gstvaapidisplay_priv.h
new file mode 100644 (file)
index 0000000..ac0555e
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ *  gstvaapidisplay_priv.h - Base VA display (private definitions)
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DISPLAY_PRIV_H
+#define GST_VAAPI_DISPLAY_PRIV_H
+
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapidisplaycache.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_DISPLAY_GET_PRIVATE(obj)                      \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_DISPLAY,       \
+                                 GstVaapiDisplayPrivate))
+
+#define GST_VAAPI_DISPLAY_CAST(display) ((GstVaapiDisplay *)(display))
+
+/**
+ * GST_VAAPI_DISPLAY_VADISPLAY:
+ * @display_: a #GstVaapiDisplay
+ *
+ * Macro that evaluates to the #VADisplay of @display.
+ * This is an internal macro that does not do any run-time type check.
+ */
+#undef  GST_VAAPI_DISPLAY_VADISPLAY
+#define GST_VAAPI_DISPLAY_VADISPLAY(display_) \
+    GST_VAAPI_DISPLAY_CAST(display_)->priv->display
+
+/**
+ * GST_VAAPI_DISPLAY_LOCK:
+ * @display: a #GstVaapiDisplay
+ *
+ * Locks @display
+ */
+#undef  GST_VAAPI_DISPLAY_LOCK
+#define GST_VAAPI_DISPLAY_LOCK(display) \
+    gst_vaapi_display_lock(GST_VAAPI_DISPLAY_CAST(display))
+
+/**
+ * GST_VAAPI_DISPLAY_UNLOCK:
+ * @display: a #GstVaapiDisplay
+ *
+ * Unlocks @display
+ */
+#undef  GST_VAAPI_DISPLAY_UNLOCK
+#define GST_VAAPI_DISPLAY_UNLOCK(display) \
+    gst_vaapi_display_unlock(GST_VAAPI_DISPLAY_CAST(display))
+
+/**
+ * GstVaapiDisplayPrivate:
+ *
+ * Base class for VA displays.
+ */
+struct _GstVaapiDisplayPrivate {
+    GstVaapiDisplay    *parent;
+    GStaticRecMutex     mutex;
+    GstVaapiDisplayType display_type;
+    VADisplay           display;
+    guint               width;
+    guint               height;
+    guint               width_mm;
+    guint               height_mm;
+    guint               par_n;
+    guint               par_d;
+    GArray             *decoders;
+    GArray             *encoders;
+    GArray             *image_formats;
+    GArray             *subpicture_formats;
+    GArray             *properties;
+    guint               create_display  : 1;
+};
+
+GstVaapiDisplayCache *
+gst_vaapi_display_get_cache(void);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DISPLAY_PRIV_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_wayland.c b/gst-libs/gst/vaapi/gstvaapidisplay_wayland.c
new file mode 100644 (file)
index 0000000..6ebf9da
--- /dev/null
@@ -0,0 +1,538 @@
+/*
+ *  gstvaapidisplay_wayland.c - VA/Wayland display abstraction
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapidisplay_wayland
+ * @short_description: VA/Wayland display abstraction
+ */
+
+#include "sysdeps.h"
+#include <string.h>
+#include "gstvaapidisplay_priv.h"
+#include "gstvaapidisplay_wayland.h"
+#include "gstvaapidisplay_wayland_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiDisplayWayland,
+              gst_vaapi_display_wayland,
+              GST_VAAPI_TYPE_DISPLAY);
+
+enum {
+    PROP_0,
+
+    PROP_DISPLAY_NAME,
+    PROP_WL_DISPLAY
+};
+
+#define NAME_PREFIX "WLD:"
+#define NAME_PREFIX_LENGTH 4
+
+static inline gboolean
+is_display_name(const gchar *display_name)
+{
+    return strncmp(display_name, NAME_PREFIX, NAME_PREFIX_LENGTH) == 0;
+}
+
+static inline const gchar *
+get_default_display_name(void)
+{
+    static const gchar *g_display_name;
+
+    if (!g_display_name)
+        g_display_name = getenv("WAYLAND_DISPLAY");
+    return g_display_name;
+}
+
+static inline guint
+get_display_name_length(const gchar *display_name)
+{
+    const gchar *str;
+
+    str = strchr(display_name, '-');
+    if (str)
+        return str - display_name;
+    return strlen(display_name);
+}
+
+static gboolean
+compare_display_name(gconstpointer a, gconstpointer b, gpointer user_data)
+{
+    const gchar *cached_name = a;
+    const gchar *tested_name = b;
+    guint cached_name_length, tested_name_length;
+
+    if (!cached_name || !is_display_name(cached_name))
+        return FALSE;
+    cached_name += NAME_PREFIX_LENGTH;
+    cached_name_length = get_display_name_length(cached_name);
+
+    g_return_val_if_fail(tested_name && is_display_name(tested_name), FALSE);
+    tested_name += NAME_PREFIX_LENGTH;
+    tested_name_length = get_display_name_length(tested_name);
+
+    /* XXX: handle screen number and default WAYLAND_DISPLAY name */
+    if (cached_name_length != tested_name_length)
+        return FALSE;
+    if (strncmp(cached_name, tested_name, cached_name_length) != 0)
+        return FALSE;
+    return TRUE;
+}
+
+static void
+gst_vaapi_display_wayland_finalize(GObject *object)
+{
+    G_OBJECT_CLASS(gst_vaapi_display_wayland_parent_class)->finalize(object);
+}
+
+/* Reconstruct a display name without our prefix */
+static const gchar *
+get_display_name(gpointer ptr)
+{
+    GstVaapiDisplayWayland * const display = GST_VAAPI_DISPLAY_WAYLAND(ptr);
+    const gchar *display_name = display->priv->display_name;
+
+    if (!display_name)
+        return NULL;
+
+    if (is_display_name(display_name)) {
+        display_name += NAME_PREFIX_LENGTH;
+        if (*display_name == '\0')
+            return NULL;
+        return display_name;
+    }
+
+    /* XXX: this should not happen */
+    g_assert(0 && "display name without prefix");
+    return display_name;
+}
+
+/* Mangle display name with our prefix */
+static void
+set_display_name(GstVaapiDisplayWayland *display, const gchar *display_name)
+{
+    GstVaapiDisplayWaylandPrivate * const priv = display->priv;
+
+    g_free(priv->display_name);
+
+    if (!display_name) {
+        display_name = get_default_display_name();
+        if (!display_name)
+            display_name = "";
+    }
+    priv->display_name = g_strdup_printf("%s%s", NAME_PREFIX, display_name);
+}
+
+static void
+gst_vaapi_display_wayland_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiDisplayWayland * const display = GST_VAAPI_DISPLAY_WAYLAND(object);
+
+    switch (prop_id) {
+    case PROP_DISPLAY_NAME:
+        set_display_name(display, g_value_get_string(value));
+        break;
+    case PROP_WL_DISPLAY:
+        display->priv->wl_display = g_value_get_pointer(value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+static void
+gst_vaapi_display_wayland_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiDisplayWayland * const display = GST_VAAPI_DISPLAY_WAYLAND(object);
+
+    switch (prop_id) {
+    case PROP_DISPLAY_NAME:
+        g_value_set_string(value, get_display_name(display));
+        break;
+    case PROP_WL_DISPLAY:
+        g_value_set_pointer(value, gst_vaapi_display_wayland_get_display(display));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_display_wayland_constructed(GObject *object)
+{
+    GstVaapiDisplayWayland * const display = GST_VAAPI_DISPLAY_WAYLAND(object);
+    GstVaapiDisplayWaylandPrivate * const priv = display->priv;
+    GstVaapiDisplayCache * const cache = gst_vaapi_display_get_cache();
+    const GstVaapiDisplayInfo *info;
+    GObjectClass *parent_class;
+
+    priv->create_display = priv->wl_display == NULL;
+
+    /* Don't create Wayland display if there is one in the cache already */
+    if (priv->create_display) {
+        info = gst_vaapi_display_cache_lookup_by_name(
+            cache,
+            priv->display_name,
+            compare_display_name, NULL
+        );
+        if (info) {
+            priv->wl_display     = info->native_display;
+            priv->create_display = FALSE;
+        }
+    }
+
+    /* Reset display-name if the user provided his own Wayland display */
+    if (!priv->create_display) {
+        /* XXX: how to get socket/display name? */
+        GST_WARNING("wayland: get display name");
+        set_display_name(display, NULL);
+    }
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_display_wayland_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+}
+
+static void
+output_handle_geometry(void *data, struct wl_output *output,
+                       int x, int y, int physical_width, int physical_height,
+                       int subpixel, const char *make, const char *model,
+                       int transform)
+{
+    GstVaapiDisplayWaylandPrivate * const priv = data;
+
+    priv->phys_width  = physical_width;
+    priv->phys_height = physical_height;
+}
+
+static void
+output_handle_mode(void *data, struct wl_output *wl_output,
+                   uint32_t flags, int width, int height, int refresh)
+{
+    GstVaapiDisplayWaylandPrivate * const priv = data;
+
+    if (flags & WL_OUTPUT_MODE_CURRENT) {
+        priv->width  = width;
+        priv->height = height;
+    }
+}
+
+static const struct wl_output_listener output_listener = {
+    output_handle_geometry,
+    output_handle_mode,
+};
+
+static void
+display_handle_global(
+    struct wl_display *display,
+    uint32_t           id,
+    const char        *interface,
+    uint32_t           version,
+    void              *data
+)
+{
+    GstVaapiDisplayWaylandPrivate * const priv = data;
+
+    if (strcmp(interface, "wl_compositor") == 0)
+        priv->compositor = wl_display_bind(display, id, &wl_compositor_interface);
+    else if (strcmp(interface, "wl_shell") == 0)
+        priv->shell = wl_display_bind(display, id, &wl_shell_interface);
+    else if (strcmp(interface, "wl_output") == 0) {
+        priv->output = wl_display_bind(display, id, &wl_output_interface);
+        wl_output_add_listener(priv->output, &output_listener, priv);
+    }
+}
+
+static int
+event_mask_update(uint32_t mask, void *data)
+{
+    GstVaapiDisplayWaylandPrivate * const priv = data;
+
+    priv->event_mask = mask;
+    return 0;
+}
+
+static gboolean
+gst_vaapi_display_wayland_open_display(GstVaapiDisplay * display)
+{
+    GstVaapiDisplayWaylandPrivate * const priv =
+        GST_VAAPI_DISPLAY_WAYLAND(display)->priv;
+
+    if (!priv->create_display)
+        return priv->wl_display != NULL;
+
+    priv->wl_display = wl_display_connect(get_display_name(display));
+    if (!priv->wl_display)
+        return FALSE;
+
+    wl_display_set_user_data(priv->wl_display, priv);
+    wl_display_add_global_listener(priv->wl_display, display_handle_global, priv);
+    priv->event_fd = wl_display_get_fd(priv->wl_display, event_mask_update, priv);
+    wl_display_iterate(priv->wl_display, priv->event_mask);
+    wl_display_roundtrip(priv->wl_display);
+
+    if (!priv->compositor) {
+        GST_ERROR("failed to bind compositor interface");
+        return FALSE;
+    }
+
+    if (!priv->shell) {
+        GST_ERROR("failed to bind shell interface");
+        return FALSE;
+    }
+    return TRUE;
+}
+
+static void
+gst_vaapi_display_wayland_close_display(GstVaapiDisplay * display)
+{
+    GstVaapiDisplayWaylandPrivate * const priv =
+        GST_VAAPI_DISPLAY_WAYLAND(display)->priv;
+
+    if (priv->compositor) {
+        wl_compositor_destroy(priv->compositor);
+        priv->compositor = NULL;
+    }
+
+    if (priv->wl_display) {
+        if (priv->create_display)
+            wl_display_disconnect(priv->wl_display);
+        priv->wl_display = NULL;
+    }
+
+    if (priv->display_name) {
+        g_free(priv->display_name);
+        priv->display_name = NULL;
+    }
+}
+
+static gboolean
+gst_vaapi_display_wayland_get_display_info(
+    GstVaapiDisplay     *display,
+    GstVaapiDisplayInfo *info
+)
+{
+    GstVaapiDisplayWaylandPrivate * const priv =
+        GST_VAAPI_DISPLAY_WAYLAND(display)->priv;
+    GstVaapiDisplayCache *cache;
+    const GstVaapiDisplayInfo *cached_info;
+
+    /* Return any cached info even if child has its own VA display */
+    cache = gst_vaapi_display_get_cache();
+    if (!cache)
+        return FALSE;
+    cached_info =
+        gst_vaapi_display_cache_lookup_by_native_display(cache, priv->wl_display);
+    if (cached_info) {
+        *info = *cached_info;
+        return TRUE;
+    }
+
+    /* Otherwise, create VA display if there is none already */
+    info->native_display = priv->wl_display;
+    info->display_name   = priv->display_name;
+    if (!info->va_display) {
+        info->va_display = vaGetDisplayWl(priv->wl_display);
+        if (!info->va_display)
+            return FALSE;
+        info->display_type = GST_VAAPI_DISPLAY_TYPE_WAYLAND;
+    }
+    return TRUE;
+}
+
+static void
+gst_vaapi_display_wayland_get_size(
+    GstVaapiDisplay *display,
+    guint           *pwidth,
+    guint           *pheight
+)
+{
+    GstVaapiDisplayWaylandPrivate * const priv =
+        GST_VAAPI_DISPLAY_WAYLAND(display)->priv;
+
+    if (!priv->output)
+        return;
+
+    if (pwidth)
+        *pwidth = priv->width;
+
+    if (pheight)
+        *pheight = priv->height;
+}
+
+static void
+gst_vaapi_display_wayland_get_size_mm(
+    GstVaapiDisplay *display,
+    guint           *pwidth,
+    guint           *pheight
+)
+{
+    GstVaapiDisplayWaylandPrivate * const priv =
+        GST_VAAPI_DISPLAY_WAYLAND(display)->priv;
+
+    if (!priv->output)
+        return;
+
+    if (pwidth)
+        *pwidth = priv->phys_width;
+
+    if (pheight)
+        *pheight = priv->phys_height;
+}
+
+static void
+gst_vaapi_display_wayland_class_init(GstVaapiDisplayWaylandClass * klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstVaapiDisplayClass * const dpy_class = GST_VAAPI_DISPLAY_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiDisplayWaylandPrivate));
+
+    object_class->finalize      = gst_vaapi_display_wayland_finalize;
+    object_class->set_property  = gst_vaapi_display_wayland_set_property;
+    object_class->get_property  = gst_vaapi_display_wayland_get_property;
+    object_class->constructed   = gst_vaapi_display_wayland_constructed;
+
+    dpy_class->open_display     = gst_vaapi_display_wayland_open_display;
+    dpy_class->close_display    = gst_vaapi_display_wayland_close_display;
+    dpy_class->get_display      = gst_vaapi_display_wayland_get_display_info;
+    dpy_class->get_size         = gst_vaapi_display_wayland_get_size;
+    dpy_class->get_size_mm      = gst_vaapi_display_wayland_get_size_mm;
+
+    /**
+     * GstVaapiDisplayWayland:wayland-display:
+     *
+     * The Wayland #wl_display that was created by
+     * gst_vaapi_display_wayland_new() or that was bound from
+     * gst_vaapi_display_wayland_new_with_display().
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_WL_DISPLAY,
+         g_param_spec_pointer("wl-display",
+                              "Wayland display",
+                              "Wayland display",
+                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    /**
+     * GstVaapiDisplayWayland:display-name:
+     *
+     * The Wayland display name.
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_DISPLAY_NAME,
+         g_param_spec_string("display-name",
+                             "Wayland display name",
+                             "Wayland display name",
+                             NULL,
+                             G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gst_vaapi_display_wayland_init(GstVaapiDisplayWayland *display)
+{
+    GstVaapiDisplayWaylandPrivate * const priv =
+        GST_VAAPI_DISPLAY_WAYLAND_GET_PRIVATE(display);
+
+    display->priv        = priv;
+    priv->create_display = TRUE;
+    priv->display_name   = NULL;
+    priv->wl_display     = NULL;
+    priv->compositor     = NULL;
+    priv->shell          = NULL;
+    priv->output         = NULL;
+    priv->width          = 0;
+    priv->height         = 0;
+    priv->phys_width     = 0;
+    priv->phys_height    = 0;
+    priv->event_fd       = -1;
+    priv->event_mask     = 0;
+}
+
+/**
+ * gst_vaapi_display_wayland_new:
+ * @display_name: the Wayland display name
+ *
+ * Opens an Wayland #wl_display using @display_name and returns a
+ * newly allocated #GstVaapiDisplay object. The Wayland display will
+ * be cloed when the reference count of the object reaches zero.
+ *
+ * Return value: a newly allocated #GstVaapiDisplay object
+ */
+GstVaapiDisplay *
+gst_vaapi_display_wayland_new(const gchar *display_name)
+{
+    return g_object_new(GST_VAAPI_TYPE_DISPLAY_WAYLAND,
+                        "display-name", display_name,
+                        NULL);
+}
+
+/**
+ * gst_vaapi_display_wayland_new_with_display:
+ * @wl_display: an Wayland #wl_display
+ *
+ * Creates a #GstVaapiDisplay based on the Wayland @wl_display
+ * display. The caller still owns the display and must call
+ * wl_display_disconnect() when all #GstVaapiDisplay references are
+ * released. Doing so too early can yield undefined behaviour.
+ *
+ * Return value: a newly allocated #GstVaapiDisplay object
+ */
+GstVaapiDisplay *
+gst_vaapi_display_wayland_new_with_display(struct wl_display *wl_display)
+{
+    g_return_val_if_fail(wl_display, NULL);
+
+    return g_object_new(GST_VAAPI_TYPE_DISPLAY_WAYLAND,
+                        "wl-display", wl_display,
+                        NULL);
+}
+
+/**
+ * gst_vaapi_display_wayland_get_display:
+ * @display: a #GstVaapiDisplayWayland
+ *
+ * Returns the underlying Wayland #wl_display that was created by
+ * gst_vaapi_display_wayland_new() or that was bound from
+ * gst_vaapi_display_wayland_new_with_display().
+ *
+ * Return value: the Wayland #wl_display attached to @display
+ */
+struct wl_display *
+gst_vaapi_display_wayland_get_display(GstVaapiDisplayWayland *display)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY_WAYLAND(display), NULL);
+
+    return display->priv->wl_display;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_wayland.h b/gst-libs/gst/vaapi/gstvaapidisplay_wayland.h
new file mode 100644 (file)
index 0000000..c5fc0f6
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *  gstvaapidisplay_wayland.h - VA/Wayland display abstraction
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DISPLAY_WAYLAND_H
+#define GST_VAAPI_DISPLAY_WAYLAND_H
+
+#include <va/va_wayland.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_DISPLAY_WAYLAND \
+    (gst_vaapi_display_wayland_get_type())
+
+#define GST_VAAPI_DISPLAY_WAYLAND(obj)                          \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_DISPLAY_WAYLAND, \
+                                GstVaapiDisplayWayland))
+
+#define GST_VAAPI_DISPLAY_WAYLAND_CLASS(klass)                  \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_DISPLAY_WAYLAND,    \
+                             GstVaapiDisplayWaylandClass))
+
+#define GST_VAAPI_IS_DISPLAY_WAYLAND(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_DISPLAY_WAYLAND))
+
+#define GST_VAAPI_IS_DISPLAY_WAYLAND_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_DISPLAY_WAYLAND))
+
+#define GST_VAAPI_DISPLAY_WAYLAND_GET_CLASS(obj)                \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_DISPLAY_WAYLAND,  \
+                               GstVaapiDisplayWaylandClass))
+
+typedef struct _GstVaapiDisplayWayland          GstVaapiDisplayWayland;
+typedef struct _GstVaapiDisplayWaylandPrivate   GstVaapiDisplayWaylandPrivate;
+typedef struct _GstVaapiDisplayWaylandClass     GstVaapiDisplayWaylandClass;
+
+/**
+ * GstVaapiDisplayWayland:
+ *
+ * VA/Wayland display wrapper.
+ */
+struct _GstVaapiDisplayWayland {
+    /*< private >*/
+    GstVaapiDisplay parent_instance;
+
+    GstVaapiDisplayWaylandPrivate *priv;
+};
+
+/**
+ * GstVaapiDisplayWaylandClass:
+ *
+ * VA/Wayland display wrapper clas.
+ */
+struct _GstVaapiDisplayWaylandClass {
+    /*< private >*/
+    GstVaapiDisplayClass parent_class;
+};
+
+GType
+gst_vaapi_display_wayland_get_type(void) G_GNUC_CONST;
+
+GstVaapiDisplay *
+gst_vaapi_display_wayland_new(const gchar *display_name);
+
+GstVaapiDisplay *
+gst_vaapi_display_wayland_new_with_display(struct wl_display *wl_display);
+
+struct wl_display *
+gst_vaapi_display_wayland_get_display(GstVaapiDisplayWayland *display);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DISPLAY_WAYLAND_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_wayland_priv.h b/gst-libs/gst/vaapi/gstvaapidisplay_wayland_priv.h
new file mode 100644 (file)
index 0000000..b98303e
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *  gstvaapidisplay_wayland_priv.h - Internal VA/Wayland interface
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DISPLAY_WAYLAND_PRIV_H
+#define GST_VAAPI_DISPLAY_WAYLAND_PRIV_H
+
+#include <gst/vaapi/gstvaapidisplay_wayland.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_DISPLAY_WAYLAND_GET_PRIVATE(obj)                      \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                                 \
+                                 GST_VAAPI_TYPE_DISPLAY_WAYLAND,       \
+                                 GstVaapiDisplayWaylandPrivate))
+
+#define GST_VAAPI_DISPLAY_WAYLAND_CAST(display) \
+    ((GstVaapiDisplayWayland *)(display))
+
+/**
+ * GST_VAAPI_DISPLAY_WL_DISPLAY:
+ * @display: a #GstVaapiDisplay
+ *
+ * Macro that evaluates to the underlying Wayland #wl_display object
+ * of @display
+ */
+#undef  GST_VAAPI_DISPLAY_WL_DISPLAY
+#define GST_VAAPI_DISPLAY_WL_DISPLAY(display) \
+    GST_VAAPI_DISPLAY_WAYLAND_CAST(display)->priv->wl_display
+
+struct _GstVaapiDisplayWaylandPrivate {
+    gchar                      *display_name;
+    struct wl_display          *wl_display;
+    struct wl_compositor       *compositor;
+    struct wl_shell            *shell;
+    struct wl_output           *output;
+    guint                       width;
+    guint                       height;
+    guint                       phys_width;
+    guint                       phys_height;
+    gint                        event_fd;
+    guint32                     event_mask;
+    guint                       create_display  : 1;
+};
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DISPLAY_WAYLAND_PRIV_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_x11.c b/gst-libs/gst/vaapi/gstvaapidisplay_x11.c
new file mode 100644 (file)
index 0000000..f00b5af
--- /dev/null
@@ -0,0 +1,605 @@
+/*
+ *  gstvaapidisplay_x11.c - VA/X11 display abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapidisplay_x11
+ * @short_description: VA/X11 display abstraction
+ */
+
+#include "sysdeps.h"
+#include <string.h>
+#include "gstvaapiutils.h"
+#include "gstvaapidisplay_priv.h"
+#include "gstvaapidisplay_x11.h"
+#include "gstvaapidisplay_x11_priv.h"
+
+#ifdef HAVE_XRANDR
+# include <X11/extensions/Xrandr.h>
+#endif
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiDisplayX11,
+              gst_vaapi_display_x11,
+              GST_VAAPI_TYPE_DISPLAY);
+
+enum {
+    PROP_0,
+
+    PROP_SYNCHRONOUS,
+    PROP_DISPLAY_NAME,
+    PROP_X11_DISPLAY,
+    PROP_X11_SCREEN
+};
+
+#define NAME_PREFIX "X11:"
+#define NAME_PREFIX_LENGTH 4
+
+static inline gboolean
+is_display_name(const gchar *display_name)
+{
+    return strncmp(display_name, NAME_PREFIX, NAME_PREFIX_LENGTH) == 0;
+}
+
+static inline const gchar *
+get_default_display_name(void)
+{
+    static const gchar *g_display_name;
+
+    if (!g_display_name)
+        g_display_name = getenv("DISPLAY");
+    return g_display_name;
+}
+
+static gboolean
+compare_display_name(gconstpointer a, gconstpointer b, gpointer user_data)
+{
+    const gchar *cached_name = a, *cached_name_end;
+    const gchar *tested_name = b, *tested_name_end;
+    guint cached_name_length, tested_name_length;
+
+    if (!cached_name || !is_display_name(cached_name))
+        return FALSE;
+    g_return_val_if_fail(tested_name && is_display_name(tested_name), FALSE);
+
+    cached_name += NAME_PREFIX_LENGTH;
+    cached_name_end = strchr(cached_name, ':');
+    if (cached_name_end)
+        cached_name_length = cached_name_end - cached_name;
+    else
+        cached_name_length = strlen(cached_name);
+
+    tested_name += NAME_PREFIX_LENGTH;
+    tested_name_end = strchr(tested_name, ':');
+    if (tested_name_end)
+        tested_name_length = tested_name_end - tested_name;
+    else
+        tested_name_length = strlen(tested_name);
+
+    if (cached_name_length != tested_name_length)
+        return FALSE;
+    if (strncmp(cached_name, tested_name, cached_name_length) != 0)
+        return FALSE;
+
+    /* XXX: handle screen number? */
+    return TRUE;
+}
+
+static void
+gst_vaapi_display_x11_finalize(GObject *object)
+{
+    G_OBJECT_CLASS(gst_vaapi_display_x11_parent_class)->finalize(object);
+}
+
+/* Reconstruct a display name without our prefix */
+static const gchar *
+get_display_name(gpointer ptr)
+{
+    GstVaapiDisplayX11 * const display = GST_VAAPI_DISPLAY_X11(ptr);
+    const gchar *display_name = display->priv->display_name;
+
+    if (!display_name)
+        return NULL;
+
+    if (is_display_name(display_name)) {
+        display_name += NAME_PREFIX_LENGTH;
+        if (*display_name == '\0')
+            return NULL;
+        return display_name;
+    }
+
+    /* XXX: this should not happen */
+    g_assert(0 && "display name without prefix");
+    return display_name;
+}
+
+/* Mangle display name with our prefix */
+static void
+set_display_name(GstVaapiDisplayX11 *display, const gchar *display_name)
+{
+    GstVaapiDisplayX11Private * const priv = display->priv;
+
+    g_free(priv->display_name);
+
+    if (!display_name) {
+        display_name = get_default_display_name();
+        if (!display_name)
+            display_name = "";
+    }
+    priv->display_name = g_strdup_printf("%s%s", NAME_PREFIX, display_name);
+}
+
+static void
+set_synchronous(GstVaapiDisplayX11 *display, gboolean synchronous)
+{
+    GstVaapiDisplayX11Private * const priv = display->priv;
+
+    if (priv->synchronous != synchronous) {
+        priv->synchronous = synchronous;
+        if (priv->x11_display)
+            XSynchronize(priv->x11_display, synchronous);
+    }
+}
+
+static void
+gst_vaapi_display_x11_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiDisplayX11 * const display = GST_VAAPI_DISPLAY_X11(object);
+
+    switch (prop_id) {
+    case PROP_SYNCHRONOUS:
+        set_synchronous(display, g_value_get_boolean(value));
+        break;
+    case PROP_DISPLAY_NAME:
+        set_display_name(display, g_value_get_string(value));
+        break;
+    case PROP_X11_DISPLAY:
+        display->priv->x11_display = g_value_get_pointer(value);
+        break;
+    case PROP_X11_SCREEN:
+        display->priv->x11_screen = g_value_get_int(value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_display_x11_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiDisplayX11 * const display = GST_VAAPI_DISPLAY_X11(object);
+
+    switch (prop_id) {
+    case PROP_SYNCHRONOUS:
+        g_value_set_boolean(value, display->priv->synchronous);
+        break;
+    case PROP_DISPLAY_NAME:
+        g_value_set_string(value, get_display_name(display));
+        break;
+    case PROP_X11_DISPLAY:
+        g_value_set_pointer(value, gst_vaapi_display_x11_get_display(display));
+        break;
+    case PROP_X11_SCREEN:
+        g_value_set_int(value, gst_vaapi_display_x11_get_screen(display));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_display_x11_constructed(GObject *object)
+{
+    GstVaapiDisplayX11 * const display = GST_VAAPI_DISPLAY_X11(object);
+    GstVaapiDisplayX11Private * const priv = display->priv;
+    GstVaapiDisplayCache * const cache = gst_vaapi_display_get_cache();
+    const GstVaapiDisplayInfo *info;
+    GObjectClass *parent_class;
+
+    priv->create_display = priv->x11_display == NULL;
+
+    /* Don't create X11 display if there is one in the cache already */
+    if (priv->create_display) {
+        info = gst_vaapi_display_cache_lookup_by_name(
+            cache,
+            priv->display_name,
+            compare_display_name, NULL
+        );
+        if (info) {
+            priv->x11_display    = info->native_display;
+            priv->create_display = FALSE;
+        }
+    }
+
+    /* Reset display-name if the user provided his own X11 display */
+    if (!priv->create_display)
+        set_display_name(display, XDisplayString(priv->x11_display));
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_display_x11_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+}
+
+static gboolean
+gst_vaapi_display_x11_open_display(GstVaapiDisplay *display)
+{
+    GstVaapiDisplayX11Private * const priv =
+        GST_VAAPI_DISPLAY_X11(display)->priv;
+
+    if (priv->create_display) {
+        priv->x11_display = XOpenDisplay(get_display_name(display));
+        if (!priv->x11_display)
+            return FALSE;
+        priv->x11_screen = DefaultScreen(priv->x11_display);
+    }
+    if (!priv->x11_display)
+        return FALSE;
+
+    if (priv->synchronous)
+        XSynchronize(priv->x11_display, True);
+
+#ifdef HAVE_XRANDR
+    {
+        int evt_base, err_base;
+        priv->use_xrandr = XRRQueryExtension(
+            priv->x11_display, &evt_base, &err_base);
+    }
+#endif
+    return TRUE;
+}
+
+static void
+gst_vaapi_display_x11_close_display(GstVaapiDisplay *display)
+{
+    GstVaapiDisplayX11Private * const priv =
+        GST_VAAPI_DISPLAY_X11(display)->priv;
+
+    if (priv->x11_display) {
+        if (priv->create_display)
+            XCloseDisplay(priv->x11_display);
+        priv->x11_display = NULL;
+    }
+
+    if (priv->display_name) {
+        g_free(priv->display_name);
+        priv->display_name = NULL;
+    }
+}
+
+static void
+gst_vaapi_display_x11_sync(GstVaapiDisplay *display)
+{
+    GstVaapiDisplayX11Private * const priv =
+        GST_VAAPI_DISPLAY_X11(display)->priv;
+
+    if (priv->x11_display) {
+        GST_VAAPI_DISPLAY_LOCK(display);
+        XSync(priv->x11_display, False);
+        GST_VAAPI_DISPLAY_UNLOCK(display);
+    }
+}
+
+static void
+gst_vaapi_display_x11_flush(GstVaapiDisplay *display)
+{
+    GstVaapiDisplayX11Private * const priv =
+        GST_VAAPI_DISPLAY_X11(display)->priv;
+
+    if (priv->x11_display) {
+        GST_VAAPI_DISPLAY_LOCK(display);
+        XFlush(priv->x11_display);
+        GST_VAAPI_DISPLAY_UNLOCK(display);
+    }
+}
+
+static gboolean
+gst_vaapi_display_x11_get_display_info(
+    GstVaapiDisplay     *display,
+    GstVaapiDisplayInfo *info
+)
+{
+    GstVaapiDisplayX11Private * const priv =
+        GST_VAAPI_DISPLAY_X11(display)->priv;
+    GstVaapiDisplayCache *cache;
+    const GstVaapiDisplayInfo *cached_info;
+
+    /* Return any cached info even if child has its own VA display */
+    cache = gst_vaapi_display_get_cache();
+    if (!cache)
+        return FALSE;
+    cached_info = gst_vaapi_display_cache_lookup_by_native_display(
+        cache, priv->x11_display);
+    if (cached_info) {
+        *info = *cached_info;
+        return TRUE;
+    }
+
+    /* Otherwise, create VA display if there is none already */
+    info->native_display = priv->x11_display;
+    info->display_name   = priv->display_name;
+    if (!info->va_display) {
+        info->va_display = vaGetDisplay(priv->x11_display);
+        if (!info->va_display)
+            return FALSE;
+        info->display_type = GST_VAAPI_DISPLAY_TYPE_X11;
+    }
+    return TRUE;
+}
+
+static void
+gst_vaapi_display_x11_get_size(
+    GstVaapiDisplay *display,
+    guint           *pwidth,
+    guint           *pheight
+)
+{
+    GstVaapiDisplayX11Private * const priv =
+        GST_VAAPI_DISPLAY_X11(display)->priv;
+
+    if (!priv->x11_display)
+        return;
+
+    if (pwidth)
+        *pwidth = DisplayWidth(priv->x11_display, priv->x11_screen);
+
+    if (pheight)
+        *pheight = DisplayHeight(priv->x11_display, priv->x11_screen);
+}
+
+static void
+gst_vaapi_display_x11_get_size_mm(
+    GstVaapiDisplay *display,
+    guint           *pwidth,
+    guint           *pheight
+)
+{
+    GstVaapiDisplayX11Private * const priv =
+        GST_VAAPI_DISPLAY_X11(display)->priv;
+    guint width_mm, height_mm;
+
+    if (!priv->x11_display)
+        return;
+
+    width_mm  = DisplayWidthMM(priv->x11_display, priv->x11_screen);
+    height_mm = DisplayHeightMM(priv->x11_display, priv->x11_screen);
+
+#ifdef HAVE_XRANDR
+    /* XXX: fix up physical size if the display is rotated */
+    if (priv->use_xrandr) {
+        XRRScreenConfiguration *xrr_config = NULL;
+        XRRScreenSize *xrr_sizes;
+        Window win;
+        int num_xrr_sizes, size_id, screen;
+        Rotation rotation;
+
+        do {
+            win    = DefaultRootWindow(priv->x11_display);
+            screen = XRRRootToScreen(priv->x11_display, win);
+
+            xrr_config = XRRGetScreenInfo(priv->x11_display, win);
+            if (!xrr_config)
+                break;
+
+            size_id = XRRConfigCurrentConfiguration(xrr_config, &rotation);
+            if (rotation == RR_Rotate_0 || rotation == RR_Rotate_180)
+                break;
+
+            xrr_sizes = XRRSizes(priv->x11_display, screen, &num_xrr_sizes);
+            if (!xrr_sizes || size_id >= num_xrr_sizes)
+                break;
+
+            width_mm  = xrr_sizes[size_id].mheight;
+            height_mm = xrr_sizes[size_id].mwidth;
+        } while (0);
+        if (xrr_config)
+            XRRFreeScreenConfigInfo(xrr_config);
+    }
+#endif
+
+    if (pwidth)
+        *pwidth = width_mm;
+
+    if (pheight)
+        *pheight = height_mm;
+}
+
+static void
+gst_vaapi_display_x11_class_init(GstVaapiDisplayX11Class *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstVaapiDisplayClass * const dpy_class = GST_VAAPI_DISPLAY_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiDisplayX11Private));
+
+    object_class->finalize      = gst_vaapi_display_x11_finalize;
+    object_class->set_property  = gst_vaapi_display_x11_set_property;
+    object_class->get_property  = gst_vaapi_display_x11_get_property;
+    object_class->constructed   = gst_vaapi_display_x11_constructed;
+
+    dpy_class->open_display     = gst_vaapi_display_x11_open_display;
+    dpy_class->close_display    = gst_vaapi_display_x11_close_display;
+    dpy_class->sync             = gst_vaapi_display_x11_sync;
+    dpy_class->flush            = gst_vaapi_display_x11_flush;
+    dpy_class->get_display      = gst_vaapi_display_x11_get_display_info;
+    dpy_class->get_size         = gst_vaapi_display_x11_get_size;
+    dpy_class->get_size_mm      = gst_vaapi_display_x11_get_size_mm;
+
+    /**
+     * GstVaapiDisplayX11:synchronous:
+     *
+     * When enabled, runs the X display in synchronous mode. Note that
+     * this is used only for debugging.
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_SYNCHRONOUS,
+         g_param_spec_boolean("synchronous",
+                              "Synchronous mode",
+                              "Toggles X display synchronous mode",
+                              FALSE,
+                              G_PARAM_READWRITE));
+
+    /**
+     * GstVaapiDisplayX11:x11-display:
+     *
+     * The X11 #Display that was created by gst_vaapi_display_x11_new()
+     * or that was bound from gst_vaapi_display_x11_new_with_display().
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_X11_DISPLAY,
+         g_param_spec_pointer("x11-display",
+                              "X11 display",
+                              "X11 display",
+                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    /**
+     * GstVaapiDisplayX11:x11-screen:
+     *
+     * The X11 screen that was created by gst_vaapi_display_x11_new()
+     * or that was bound from gst_vaapi_display_x11_new_with_display().
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_X11_SCREEN,
+         g_param_spec_int("x11-screen",
+                          "X11 screen",
+                          "X11 screen",
+                          0, G_MAXINT32, 0,
+                          G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    /**
+     * GstVaapiDisplayX11:display-name:
+     *
+     * The X11 display name.
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_DISPLAY_NAME,
+         g_param_spec_string("display-name",
+                             "X11 display name",
+                             "X11 display name",
+                             NULL,
+                             G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gst_vaapi_display_x11_init(GstVaapiDisplayX11 *display)
+{
+    GstVaapiDisplayX11Private *priv = GST_VAAPI_DISPLAY_X11_GET_PRIVATE(display);
+
+    display->priv        = priv;
+    priv->create_display = TRUE;
+    priv->x11_display    = NULL;
+    priv->x11_screen     = 0;
+    priv->display_name   = NULL;
+    priv->use_xrandr     = FALSE;
+}
+
+/**
+ * gst_vaapi_display_x11_new:
+ * @display_name: the X11 display name
+ *
+ * Opens an X11 #Display using @display_name and returns a newly
+ * allocated #GstVaapiDisplay object. The X11 display will be cloed
+ * when the reference count of the object reaches zero.
+ *
+ * Return value: a newly allocated #GstVaapiDisplay object
+ */
+GstVaapiDisplay *
+gst_vaapi_display_x11_new(const gchar *display_name)
+{
+    return g_object_new(GST_VAAPI_TYPE_DISPLAY_X11,
+                        "display-name", display_name,
+                        NULL);
+}
+
+/**
+ * gst_vaapi_display_x11_new_with_display:
+ * @x11_display: an X11 #Display
+ *
+ * Creates a #GstVaapiDisplay based on the X11 @x11_display
+ * display. The caller still owns the display and must call
+ * XCloseDisplay() when all #GstVaapiDisplay references are
+ * released. Doing so too early can yield undefined behaviour.
+ *
+ * Return value: a newly allocated #GstVaapiDisplay object
+ */
+GstVaapiDisplay *
+gst_vaapi_display_x11_new_with_display(Display *x11_display)
+{
+    g_return_val_if_fail(x11_display, NULL);
+
+    return g_object_new(GST_VAAPI_TYPE_DISPLAY_X11,
+                        "x11-display", x11_display,
+                        "x11-screen",  DefaultScreen(x11_display),
+                        NULL);
+}
+
+/**
+ * gst_vaapi_display_x11_get_display:
+ * @display: a #GstVaapiDisplayX11
+ *
+ * Returns the underlying X11 #Display that was created by
+ * gst_vaapi_display_x11_new() or that was bound from
+ * gst_vaapi_display_x11_new_with_display().
+ *
+ * Return value: the X11 #Display attached to @display
+ */
+Display *
+gst_vaapi_display_x11_get_display(GstVaapiDisplayX11 *display)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY_X11(display), NULL);
+
+    return display->priv->x11_display;
+}
+
+/**
+ * gst_vaapi_display_x11_get_screen:
+ * @display: a #GstVaapiDisplayX11
+ *
+ * Returns the default X11 screen that was created by
+ * gst_vaapi_display_x11_new() or that was bound from
+ * gst_vaapi_display_x11_new_with_display().
+ *
+ * Return value: the X11 #Display attached to @display
+ */
+int
+gst_vaapi_display_x11_get_screen(GstVaapiDisplayX11 *display)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY_X11(display), -1);
+
+    return display->priv->x11_screen;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_x11.h b/gst-libs/gst/vaapi/gstvaapidisplay_x11.h
new file mode 100644 (file)
index 0000000..358f59f
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ *  gstvaapidisplay_x11.h - VA/X11 display abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DISPLAY_X11_H
+#define GST_VAAPI_DISPLAY_X11_H
+
+#include <va/va_x11.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_DISPLAY_X11 \
+    (gst_vaapi_display_x11_get_type())
+
+#define GST_VAAPI_DISPLAY_X11(obj)                              \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_DISPLAY_X11,     \
+                                GstVaapiDisplayX11))
+
+#define GST_VAAPI_DISPLAY_X11_CLASS(klass)                      \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_DISPLAY_X11,        \
+                             GstVaapiDisplayX11Class))
+
+#define GST_VAAPI_IS_DISPLAY_X11(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_DISPLAY_X11))
+
+#define GST_VAAPI_IS_DISPLAY_X11_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_DISPLAY_X11))
+
+#define GST_VAAPI_DISPLAY_X11_GET_CLASS(obj)                    \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_DISPLAY_X11,      \
+                               GstVaapiDisplayX11Class))
+
+typedef struct _GstVaapiDisplayX11              GstVaapiDisplayX11;
+typedef struct _GstVaapiDisplayX11Private       GstVaapiDisplayX11Private;
+typedef struct _GstVaapiDisplayX11Class         GstVaapiDisplayX11Class;
+
+/**
+ * GstVaapiDisplayX11:
+ *
+ * VA/X11 display wrapper.
+ */
+struct _GstVaapiDisplayX11 {
+    /*< private >*/
+    GstVaapiDisplay parent_instance;
+
+    GstVaapiDisplayX11Private *priv;
+};
+
+
+/**
+ * GstVaapiDisplayX11Class:
+ *
+ * VA/X11 display wrapper clas.
+ */
+struct _GstVaapiDisplayX11Class {
+    /*< private >*/
+    GstVaapiDisplayClass parent_class;
+};
+
+GType
+gst_vaapi_display_x11_get_type(void) G_GNUC_CONST;
+
+GstVaapiDisplay *
+gst_vaapi_display_x11_new(const gchar *display_name);
+
+GstVaapiDisplay *
+gst_vaapi_display_x11_new_with_display(Display *x11_display);
+
+Display *
+gst_vaapi_display_x11_get_display(GstVaapiDisplayX11 *display);
+
+int
+gst_vaapi_display_x11_get_screen(GstVaapiDisplayX11 *display);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DISPLAY_X11_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_x11_priv.h b/gst-libs/gst/vaapi/gstvaapidisplay_x11_priv.h
new file mode 100644 (file)
index 0000000..bc04ecb
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *  gstvaapidisplay_x11_priv.h - Internal VA/X11 interface
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DISPLAY_X11_PRIV_H
+#define GST_VAAPI_DISPLAY_X11_PRIV_H
+
+#include <gst/vaapi/gstvaapiutils_x11.h>
+#include <gst/vaapi/gstvaapidisplay_x11.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_DISPLAY_X11_GET_PRIVATE(obj)                  \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_DISPLAY_X11,   \
+                                 GstVaapiDisplayX11Private))
+
+#define GST_VAAPI_DISPLAY_X11_CAST(display) ((GstVaapiDisplayX11 *)(display))
+
+/**
+ * GST_VAAPI_DISPLAY_XDISPLAY:
+ * @display: a #GstVaapiDisplay
+ *
+ * Macro that evaluates to the underlying X11 #Display of @display
+ */
+#undef  GST_VAAPI_DISPLAY_XDISPLAY
+#define GST_VAAPI_DISPLAY_XDISPLAY(display) \
+    GST_VAAPI_DISPLAY_X11_CAST(display)->priv->x11_display
+
+/**
+ * GST_VAAPI_DISPLAY_XSCREEN:
+ * @display: a #GstVaapiDisplay
+ *
+ * Macro that evaluates to the underlying X11 screen of @display
+ */
+#undef  GST_VAAPI_DISPLAY_XSCREEN
+#define GST_VAAPI_DISPLAY_XSCREEN(display) \
+    GST_VAAPI_DISPLAY_X11_CAST(display)->priv->x11_screen
+
+struct _GstVaapiDisplayX11Private {
+    gchar      *display_name;
+    Display    *x11_display;
+    int         x11_screen;
+    guint       create_display  : 1;
+    guint       synchronous     : 1;
+    guint       use_xrandr      : 1;
+};
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DISPLAY_X11_PRIV_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidisplaycache.c b/gst-libs/gst/vaapi/gstvaapidisplaycache.c
new file mode 100644 (file)
index 0000000..0e6ef36
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ *  gstvaapidisplaycache.c - VA display cache
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "sysdeps.h"
+#include <glib.h>
+#include <string.h>
+#include "gstvaapidisplaycache.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+typedef struct _CacheEntry CacheEntry;
+struct _CacheEntry {
+    GstVaapiDisplayInfo info;
+};
+
+struct _GstVaapiDisplayCache {
+    GStaticMutex        mutex;
+    GList              *list;
+};
+
+static void
+cache_entry_free(CacheEntry *entry)
+{
+    GstVaapiDisplayInfo *info;
+
+    if (!entry)
+        return;
+
+    info = &entry->info;
+
+    if (info->display_name) {
+        g_free(info->display_name);
+        info->display_name = NULL;
+    }
+    g_slice_free(CacheEntry, entry);
+}
+
+static CacheEntry *
+cache_entry_new(const GstVaapiDisplayInfo *di)
+{
+    GstVaapiDisplayInfo *info;
+    CacheEntry *entry;
+
+    entry = g_slice_new(CacheEntry);
+    if (!entry)
+        return NULL;
+
+    info                 = &entry->info;
+    info->display        = di->display;
+    info->va_display     = di->va_display;
+    info->native_display = di->native_display;
+    info->display_type   = di->display_type;
+    info->display_name   = NULL;
+
+    if (di->display_name) {
+        info->display_name = g_strdup(di->display_name);
+        if (!info->display_name)
+            goto error;
+    }
+    return entry;
+
+error:
+    cache_entry_free(entry);
+    return NULL;
+}
+
+#define CACHE_LOOKUP(cache, res, prop, comp_func, comp_data, user_data) do { \
+        GList *l;                                                       \
+                                                                        \
+        g_static_mutex_lock(&(cache)->mutex);                           \
+        for (l = (cache)->list; l != NULL; l = l->next) {               \
+            GstVaapiDisplayInfo * const info =                          \
+                &((CacheEntry *)l->data)->info;                         \
+            if (comp_func(info->prop, comp_data, user_data))            \
+                break;                                                  \
+        }                                                               \
+        g_static_mutex_unlock(&(cache)->mutex);                         \
+        res = l;                                                        \
+    } while (0)
+
+#define compare_equal(a, b, user_data) \
+    ((a) == (b))
+
+#define compare_string(a, b, user_data) \
+    ((a) == (b) || ((a) && (b) && strcmp(a, b) == 0))
+
+static GList *
+cache_lookup_display(GstVaapiDisplayCache *cache, GstVaapiDisplay *display)
+{
+    GList *m;
+
+    CACHE_LOOKUP(cache, m, display, compare_equal, display, NULL);
+    return m;
+}
+
+static GList *
+cache_lookup_va_display(GstVaapiDisplayCache *cache, VADisplay va_display)
+{
+    GList *m;
+
+    CACHE_LOOKUP(cache, m, va_display, compare_equal, va_display, NULL);
+    return m;
+}
+
+static GList *
+cache_lookup_native_display(GstVaapiDisplayCache *cache, gpointer native_display)
+{
+    GList *m;
+
+    CACHE_LOOKUP(cache, m, native_display, compare_equal, native_display, NULL);
+    return m;
+}
+
+/**
+ * gst_vaapi_display_cache_new:
+ *
+ * Creates a new VA display cache.
+ *
+ * Return value: the newly created #GstVaapiDisplayCache object
+ */
+GstVaapiDisplayCache *
+gst_vaapi_display_cache_new(void)
+{
+    GstVaapiDisplayCache *cache;
+
+    cache = g_slice_new0(GstVaapiDisplayCache);
+    if (!cache)
+        return NULL;
+
+    g_static_mutex_init(&cache->mutex);
+    return cache;
+}
+
+/**
+ * gst_vaapi_display_cache_new:
+ * @cache: the #GstVaapiDisplayCache to destroy
+ *
+ * Destroys a VA display cache.
+ */
+void
+gst_vaapi_display_cache_free(GstVaapiDisplayCache *cache)
+{
+    GList *l;
+
+    if (!cache)
+        return;
+
+    if (cache->list) {
+        for (l = cache->list; l != NULL; l = l->next)
+            cache_entry_free(l->data);
+        g_list_free(cache->list);
+        cache->list = NULL;
+    }
+    g_static_mutex_free(&cache->mutex);
+    g_slice_free(GstVaapiDisplayCache, cache);
+}
+
+/**
+ * gst_vaapi_display_cache_get_size:
+ * @cache: the #GstVaapiDisplayCache
+ *
+ * Gets the size of the display cache @cache.
+ *
+ * Return value: the size of the display cache
+ */
+guint
+gst_vaapi_display_cache_get_size(GstVaapiDisplayCache *cache)
+{
+    guint size;
+
+    g_return_val_if_fail(cache != NULL, 0);
+
+    g_static_mutex_lock(&cache->mutex);
+    size = g_list_length(cache->list);
+    g_static_mutex_unlock(&cache->mutex);
+    return size;
+}
+
+/**
+ * gst_vaapi_display_cache_add:
+ * @cache: the #GstVaapiDisplayCache
+ * @info: the display cache info to add
+ *
+ * Adds a new entry with data from @info. The display @info data is
+ * copied into the newly created cache entry.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_display_cache_add(
+    GstVaapiDisplayCache       *cache,
+    GstVaapiDisplayInfo        *info
+)
+{
+    CacheEntry *entry;
+
+    g_return_val_if_fail(cache != NULL, FALSE);
+    g_return_val_if_fail(info != NULL, FALSE);
+
+    entry = cache_entry_new(info);
+    if (!entry)
+        return FALSE;
+
+    g_static_mutex_lock(&cache->mutex);
+    cache->list = g_list_prepend(cache->list, entry);
+    g_static_mutex_unlock(&cache->mutex);
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_display_cache_remove:
+ * @cache: the #GstVaapiDisplayCache
+ * @display: the display to remove from cache
+ *
+ * Removes any cache entry that matches the specified #GstVaapiDisplay.
+ */
+void
+gst_vaapi_display_cache_remove(
+    GstVaapiDisplayCache       *cache,
+    GstVaapiDisplay            *display
+)
+{
+    GList *m;
+
+    m = cache_lookup_display(cache, display);
+    if (!m)
+        return;
+
+    cache_entry_free(m->data);
+    g_static_mutex_lock(&cache->mutex);
+    cache->list = g_list_delete_link(cache->list, m);
+    g_static_mutex_unlock(&cache->mutex);
+}
+
+/**
+ * gst_vaapi_display_cache_lookup:
+ * @cache: the #GstVaapiDisplayCache
+ * @display: the display to find
+ *
+ * Looks up the display cache for the specified #GstVaapiDisplay.
+ *
+ * Return value: a #GstVaapiDisplayInfo matching @display, or %NULL if
+ *   none was found
+ */
+const GstVaapiDisplayInfo *
+gst_vaapi_display_cache_lookup(
+    GstVaapiDisplayCache       *cache,
+    GstVaapiDisplay            *display
+)
+{
+    CacheEntry *entry;
+    GList *m;
+
+    g_return_val_if_fail(cache != NULL, NULL);
+    g_return_val_if_fail(display != NULL, NULL);
+
+    m = cache_lookup_display(cache, display);
+    if (!m)
+        return NULL;
+
+    entry = m->data;
+    return &entry->info;
+}
+
+/**
+ * gst_vaapi_display_cache_lookup_by_va_display:
+ * @cache: the #GstVaapiDisplayCache
+ * @va_display: the VA display to find
+ *
+ * Looks up the display cache for the specified VA display.
+ *
+ * Return value: a #GstVaapiDisplayInfo matching @va_display, or %NULL
+ *   if none was found
+ */
+const GstVaapiDisplayInfo *
+gst_vaapi_display_cache_lookup_by_va_display(
+    GstVaapiDisplayCache       *cache,
+    VADisplay                   va_display
+)
+{
+    CacheEntry *entry;
+    GList *m;
+
+    g_return_val_if_fail(cache != NULL, NULL);
+    g_return_val_if_fail(va_display != NULL, NULL);
+
+    m = cache_lookup_va_display(cache, va_display);
+    if (!m)
+        return NULL;
+
+    entry = m->data;
+    return &entry->info;
+}
+
+/**
+ * gst_vaapi_display_cache_lookup_by_native_display:
+ * @cache: the #GstVaapiDisplayCache
+ * @native_display: the native display to find
+ *
+ * Looks up the display cache for the specified native display.
+ *
+ * Return value: a #GstVaapiDisplayInfo matching @native_display, or
+ *   %NULL if none was found
+ */
+const GstVaapiDisplayInfo *
+gst_vaapi_display_cache_lookup_by_native_display(
+    GstVaapiDisplayCache       *cache,
+    gpointer                    native_display
+)
+{
+    CacheEntry *entry;
+    GList *m;
+
+    g_return_val_if_fail(cache != NULL, NULL);
+    g_return_val_if_fail(native_display != NULL, NULL);
+
+    m = cache_lookup_native_display(cache, native_display);
+    if (!m)
+        return NULL;
+
+    entry = m->data;
+    return &entry->info;
+}
+
+/**
+ * gst_vaapi_display_cache_lookup_by_name:
+ * @cache: the #GstVaapiDisplayCache
+ * @display_name: the display name to match
+ * @compare_func: an optional string comparison function
+ * @user_data: any relevant data pointer to the comparison function
+ *
+ * Looks up the display cache for the specified display name. A
+ * specific comparison function can be provided to avoid a plain
+ * strcmp().
+ *
+ * Return value: a #GstVaapiDisplayInfo matching @display_name, or
+ *   %NULL if none was found
+ */
+const GstVaapiDisplayInfo *
+gst_vaapi_display_cache_lookup_by_name(
+    GstVaapiDisplayCache       *cache,
+    const gchar                *display_name,
+    GCompareDataFunc            compare_func,
+    gpointer                    user_data
+)
+{
+    CacheEntry *entry;
+    GList *m;
+
+    g_return_val_if_fail(cache != NULL, NULL);
+
+    if (compare_func)
+        CACHE_LOOKUP(cache, m, display_name, compare_func, display_name, user_data);
+    else
+        CACHE_LOOKUP(cache, m, display_name, compare_string, display_name, NULL);
+    if (!m)
+        return NULL;
+
+    entry = m->data;
+    return &entry->info;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidisplaycache.h b/gst-libs/gst/vaapi/gstvaapidisplaycache.h
new file mode 100644 (file)
index 0000000..12c2953
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ *  gstvaapidisplaycache.h - VA display cache
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GSTVAAPIDISPLAYCACHE_H
+#define GSTVAAPIDISPLAYCACHE_H
+
+#include <gst/vaapi/gstvaapidisplay.h>
+
+typedef struct _GstVaapiDisplayCache    GstVaapiDisplayCache;
+
+GstVaapiDisplayCache *
+gst_vaapi_display_cache_new(void);
+
+void
+gst_vaapi_display_cache_free(GstVaapiDisplayCache *cache);
+
+guint
+gst_vaapi_display_cache_get_size(GstVaapiDisplayCache *cache);
+
+gboolean
+gst_vaapi_display_cache_add(
+    GstVaapiDisplayCache       *cache,
+    GstVaapiDisplayInfo        *info
+);
+
+void
+gst_vaapi_display_cache_remove(
+    GstVaapiDisplayCache       *cache,
+    GstVaapiDisplay            *display
+);
+
+const GstVaapiDisplayInfo *
+gst_vaapi_display_cache_lookup(
+    GstVaapiDisplayCache       *cache,
+    GstVaapiDisplay            *display
+);
+
+const GstVaapiDisplayInfo *
+gst_vaapi_display_cache_lookup_by_va_display(
+    GstVaapiDisplayCache       *cache,
+    VADisplay                   va_display
+);
+
+const GstVaapiDisplayInfo *
+gst_vaapi_display_cache_lookup_by_native_display(
+    GstVaapiDisplayCache       *cache,
+    gpointer                    native_display
+);
+
+const GstVaapiDisplayInfo *
+gst_vaapi_display_cache_lookup_by_name(
+    GstVaapiDisplayCache       *cache,
+    const gchar                *display_name,
+    GCompareDataFunc            compare_func,
+    gpointer                    user_data
+);
+
+#endif /* GSTVAAPIDISPLAYCACHE_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder.c b/gst-libs/gst/vaapi/gstvaapiencoder.c
new file mode 100644 (file)
index 0000000..a49c719
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ *  gstvaapiencoder.c - VA-API encoder interface
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "gstvaapiencoder.h"
+
+#include <string.h>
+
+#include "gstvaapidisplay_x11.h"
+#include "gstvaapiobject_priv.h"
+#include "gstvaapidisplay_priv.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_vaapi_encoder_debug);
+#define GST_CAT_DEFAULT gst_vaapi_encoder_debug
+
+
+G_DEFINE_TYPE(GstVaapiEncoder, gst_vaapi_encoder, G_TYPE_OBJECT)
+
+gboolean
+gst_vaapi_encoder_set_display(
+    GstVaapiEncoder* encoder,
+    GstVaapiDisplay *display
+)
+{
+  GstVaapiEncoderPrivate *priv = encoder->priv;
+  if (display == priv->display) {
+    return TRUE;
+  }
+
+  if (VAAPI_ENC_INIT < priv->state) {
+    return FALSE;
+  }
+  if (priv->display) {
+    g_object_unref(priv->display);
+    priv->display = NULL;
+    priv->va_display = NULL;
+  }
+  if (display) {
+    priv->display = g_object_ref(display);
+    priv->va_display = gst_vaapi_display_get_display(display);
+  }
+  return TRUE;
+}
+
+GstVaapiDisplay *
+gst_vaapi_encoder_get_display(GstVaapiEncoder* encoder)
+{
+  GstVaapiEncoderPrivate *priv = encoder->priv;
+  return (priv->display ? g_object_ref(priv->display) : NULL);
+}
+
+GstVaapiContext *
+gst_vaapi_encoder_get_context(GstVaapiEncoder* encoder)
+{
+  GstVaapiEncoderPrivate *priv = encoder->priv;
+  return (priv->context ? g_object_ref(priv->context) : NULL);
+}
+
+
+VAAPI_Encode_State
+gst_vaapi_encoder_get_state(GstVaapiEncoder* encoder)
+{
+  GstVaapiEncoderPrivate *priv = encoder->priv;
+  return priv->state;
+}
+
+
+EncoderStatus
+gst_vaapi_encoder_initialize(GstVaapiEncoder* encoder)
+{
+  EncoderStatus ret = ENCODER_NO_ERROR;
+  GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
+  GstVaapiEncoderPrivate *priv = encoder->priv;
+
+  /* check state */
+  if (VAAPI_ENC_INIT == priv->state) {
+    return ENCODER_NO_ERROR;
+  }
+  ENCODER_ASSERT(VAAPI_ENC_NULL == priv->state);
+  if (VAAPI_ENC_NULL != priv->state) {
+    return ENCODER_STATE_ERR;
+  }
+
+  /* create va_dpy*/
+  if (!priv->display) {
+    priv->display = gst_vaapi_display_x11_new(NULL);
+    ENCODER_CHECK_STATUS(priv->display,
+                         ENCODER_DISPLAY_ERR,
+                         "gst_vaapi_display_x11_new failed.");
+  }
+  priv->va_display = gst_vaapi_display_get_display(priv->display);
+
+  if (encoder_class->initialize) {
+    ret = encoder_class->initialize(encoder);
+    ENCODER_CHECK_STATUS (ENCODER_NO_ERROR == ret,
+                          ret,
+                          "encoder <initialize> failed.");
+  }
+  priv->state = VAAPI_ENC_INIT;
+
+end:
+  return ret;
+}
+
+EncoderStatus
+gst_vaapi_encoder_open(GstVaapiEncoder* encoder)
+{
+  EncoderStatus ret = ENCODER_NO_ERROR;
+  GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
+  GstVaapiEncoderPrivate *priv = encoder->priv;
+
+  /* check state */
+  if (VAAPI_ENC_OPENED == priv->state) {
+    return ENCODER_NO_ERROR;
+  }
+  ENCODER_ASSERT(VAAPI_ENC_INIT == priv->state);
+  if (VAAPI_ENC_INIT != priv->state) {
+    return ENCODER_STATE_ERR;
+  }
+  ENCODER_ASSERT(!priv->context);
+
+  ENCODER_CHECK_STATUS(encoder_class->open,
+                       ENCODER_FUNC_PTR_ERR,
+                       "encoder <open> function pointer empty.");
+  ret = encoder_class->open(encoder, &priv->context);
+  ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret,
+                       ret,
+                       "encoder <open> failed.");
+  ENCODER_CHECK_STATUS(priv->context,
+                       ENCODER_CONTEXT_ERR,
+                       "encoder <open> context failed.");
+  priv->va_context = gst_vaapi_context_get_id(priv->context);
+  priv->state = VAAPI_ENC_OPENED;
+
+end:
+  return ret;
+}
+
+EncoderStatus
+gst_vaapi_encoder_encode(
+    GstVaapiEncoder* encoder,
+    GstBuffer *pic
+)
+{
+  EncoderStatus ret = ENCODER_NO_ERROR;
+  GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
+  GstVaapiEncoderPrivate *priv = encoder->priv;
+
+  ENCODER_CHECK_STATUS(priv->state >= VAAPI_ENC_OPENED,
+                       ENCODER_STATE_ERR,
+                       "encoder was not opened before <encode>.");
+  ENCODER_CHECK_STATUS(encoder_class->encode,
+                       ENCODER_FUNC_PTR_ERR,
+                       "encoder <encode> function pointer empty.");
+  ret = encoder_class->encode(encoder, pic);
+  ENCODER_CHECK_STATUS(ENCODER_NO_ERROR <= ret,
+                       ret,
+                       "encoder <encode> failed.");
+  if (priv->state < VAAPI_ENC_ENCODING) {
+    priv->state = VAAPI_ENC_ENCODING;
+  }
+end:
+  return ret;
+}
+
+EncoderStatus
+gst_vaapi_encoder_get_encoded_buffer(
+    GstVaapiEncoder* encoder,
+    GstBuffer **buf
+)
+{
+  EncoderStatus ret = ENCODER_NO_ERROR;
+  GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
+  GstVaapiEncoderPrivate *priv = encoder->priv;
+
+  ENCODER_CHECK_STATUS(priv->state >= VAAPI_ENC_OPENED,
+                       ENCODER_STATE_ERR,
+                       "encoder was not encoding <encode>.");
+  ENCODER_CHECK_STATUS(encoder_class->get_buf,
+                       ENCODER_FUNC_PTR_ERR,
+                       "encoder <get_buf> function pointer empty.");
+  ret = encoder_class->get_buf(encoder, buf);
+  ENCODER_CHECK_STATUS(ENCODER_NO_ERROR <= ret,
+                       ret,
+                       "encoder <get_buf> failed.");
+end:
+  return ret;
+}
+
+
+EncoderStatus
+gst_vaapi_encoder_get_codec_data(
+    GstVaapiEncoder* encoder,
+    GstBuffer **codec_data
+)
+{
+  EncoderStatus ret = ENCODER_NO_ERROR;
+  GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
+  GstVaapiEncoderPrivate *priv = encoder->priv;
+
+  ENCODER_CHECK_STATUS(priv->state >= VAAPI_ENC_OPENED,
+                       ENCODER_STATE_ERR,
+                       "encoder was not opened before <get_codec_data>.");
+  if (!encoder_class->get_codec_data) {
+    *codec_data = NULL;
+    ENCODER_LOG_INFO("There's no codec_data");
+    return ret;
+  }
+  ret = encoder_class->get_codec_data(encoder, codec_data);
+
+end:
+  return ret;
+}
+
+EncoderStatus
+gst_vaapi_encoder_flush(
+    GstVaapiEncoder* encoder
+)
+{
+  EncoderStatus ret = ENCODER_NO_ERROR;
+  GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
+  GstVaapiEncoderPrivate *priv = encoder->priv;
+
+  if (priv->state < VAAPI_ENC_OPENED) {
+    return ENCODER_STATE_ERR;
+  }
+  ENCODER_CHECK_STATUS(encoder_class->flush,
+                       ENCODER_FUNC_PTR_ERR,
+                       "encoder <flush> function pointer empty.");
+  ret = encoder_class->flush(encoder);
+  ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret,
+                       ret,
+                       "encoder <flush> failed.");
+end:
+  return ret;
+}
+
+EncoderStatus
+gst_vaapi_encoder_close(GstVaapiEncoder* encoder)
+{
+  EncoderStatus ret = ENCODER_NO_ERROR;
+  GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
+  GstVaapiEncoderPrivate *priv = encoder->priv;
+
+  if (VAAPI_ENC_INIT >= priv->state) {
+    return ENCODER_NO_ERROR;
+  }
+  ENCODER_CHECK_STATUS(encoder_class->close,
+                       ENCODER_FUNC_PTR_ERR,
+                       "encoder <close> function pointers empty.");
+  ret = encoder_class->close(encoder);
+  ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret,
+                       ret,
+                       "encoder <close> failed.");
+end:
+  if (priv->context) {
+    g_object_unref(priv->context);
+    priv->context = NULL;
+    priv->va_context = VA_INVALID_ID;
+  }
+
+  priv->state = VAAPI_ENC_INIT;
+  return ret;
+}
+
+EncoderStatus
+gst_vaapi_encoder_render_picture(
+    GstVaapiEncoder *encoder,
+    GstVaapiSurface *surface,
+    VABufferID *bufs,
+    guint num
+)
+{
+  GstVaapiDisplay *display;
+  VASurfaceID  surface_id;
+  VAContextID context_id;
+  VADisplay   va_display;
+  VAStatus    va_status;
+  gboolean is_locked = FALSE;
+  EncoderStatus ret = ENCODER_NO_ERROR;
+
+  display = ENCODER_DISPLAY(encoder);
+
+  g_return_val_if_fail(surface, ENCODER_PARAMETER_ERR);
+  g_return_val_if_fail(ENCODER_CONTEXT(encoder), ENCODER_PARAMETER_ERR);
+
+  surface_id = (VASurfaceID)GST_VAAPI_OBJECT_ID(surface);
+  context_id = ENCODER_VA_CONTEXT(encoder);
+  va_display = ENCODER_VA_DISPLAY(encoder);
+  g_return_val_if_fail(surface_id != VA_INVALID_SURFACE, ENCODER_PARAMETER_ERR);
+
+  /* begin surface*/
+  ENCODER_ACQUIRE_DISPLAY_LOCK(display);
+  va_status = vaBeginPicture(va_display, context_id, surface_id);
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+                       ENCODER_PARAMETER_ERR,
+                                          "vaBeginPicture failed");
+
+  va_status = vaRenderPicture(va_display,
+                              context_id,
+                              bufs,
+                              num);
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+                       ENCODER_PARAMETER_ERR,
+                                          "vaRenderPicture failed");
+
+  va_status = vaEndPicture(va_display, context_id);
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+                       ENCODER_PARAMETER_ERR,
+                                          "vaRenderPicture failed");
+
+end:
+  ENCODER_RELEASE_DISPLAY_LOCK(display);
+  return ret;
+}
+
+EncoderStatus
+gst_vaapi_encoder_uninitialize(GstVaapiEncoder* encoder)
+{
+  EncoderStatus ret = ENCODER_NO_ERROR;
+  GstVaapiEncoderClass *encoder_class = GST_VAAPI_ENCODER_GET_CLASS(encoder);
+  GstVaapiEncoderPrivate *priv = encoder->priv;
+
+  if (VAAPI_ENC_NULL == priv->state) {
+    return ENCODER_NO_ERROR;
+  }
+
+  if (VAAPI_ENC_INIT < priv->state) {
+    ret = gst_vaapi_encoder_close(encoder);
+  }
+  ENCODER_ASSERT(VAAPI_ENC_INIT == priv->state);
+  if (encoder_class->uninitialize) {
+    ret = encoder_class->uninitialize(encoder);
+    ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret,
+                         ret,
+                         "encoder <uninitialize> failed.");
+  }
+
+end:
+  if (priv->display) {
+    g_object_unref(priv->display);
+    priv->display = NULL;
+    priv->va_display = NULL;
+  }
+  priv->state = VAAPI_ENC_NULL;
+  return ret;
+
+}
+
+char *
+vaapi_encoder_dump_bytes(const guint8 *buf, guint32 num)
+{
+  static char tmp[1024];
+  guint32 i = 0;
+  memset(tmp, 0, sizeof(tmp));
+
+  char *p = tmp;
+  for (i = 0; i < num; i++) {
+    snprintf(p, 1024-(p-tmp), "%02x", (guint8)buf[i]);
+    p += strlen(p);
+  }
+  return tmp;
+}
+
+static void
+gst_vaapi_encoder_init(GstVaapiEncoder *encoder)
+{
+  GstVaapiEncoderPrivate *priv;
+
+  encoder->priv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
+  priv = encoder->priv;
+  ENCODER_ASSERT(priv);
+
+  priv->display = NULL;
+  priv->va_display = NULL;
+  priv->context = NULL;
+  priv->va_context = VA_INVALID_ID;
+  priv->state = VAAPI_ENC_NULL;
+
+  encoder->width = 0;
+  encoder->height = 0;
+  encoder->frame_rate = 0;
+  encoder->rate_control = GST_VAAPI_RATECONTROL_NONE;
+}
+
+static void
+gst_vaapi_encoder_finalize(GObject *object)
+{
+  GstVaapiEncoder* encoder = GST_VAAPI_ENCODER(object);
+  GstVaapiEncoderPrivate *priv = encoder->priv;
+  if (VAAPI_ENC_NULL != priv->state) {
+    gst_vaapi_encoder_uninitialize(encoder);
+  }
+
+  if (priv->context) {
+    g_object_unref(priv->context);
+    priv->context = NULL;
+    priv->va_context = VA_INVALID_ID;
+  }
+
+  if (priv->display) {
+    g_object_unref(priv->display);
+    priv->display = NULL;
+    priv->va_display = NULL;
+  }
+
+  G_OBJECT_CLASS (gst_vaapi_encoder_parent_class)->finalize (object);
+}
+
+static void
+gst_vaapi_encoder_class_init(GstVaapiEncoderClass *kclass)
+{
+  GObjectClass * const object_class = G_OBJECT_CLASS(kclass);
+  g_type_class_add_private(kclass, sizeof(GstVaapiEncoderPrivate));
+
+
+  GST_DEBUG_CATEGORY_INIT (gst_vaapi_encoder_debug,
+                           "gst_va_encoder",
+                           0,
+                           "gst_va_encoder element");
+
+  object_class->finalize = gst_vaapi_encoder_finalize;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder.h b/gst-libs/gst/vaapi/gstvaapiencoder.h
new file mode 100644 (file)
index 0000000..b8fc6d3
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ *  gstvaapiencoder.h - VA-API encoder interface
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_ENCODER_H
+#define GST_VAAPI_ENCODER_H
+
+#include <stdio.h>
+#include <stdint.h>
+
+#include "gst/gstinfo.h"
+#include "gst/gstbuffer.h"
+
+#include "gst/vaapi/gstvaapidisplay.h"
+#include "gst/vaapi/gstvaapicontext.h"
+
+G_BEGIN_DECLS
+
+#define ENCODER_NO_ERROR       0
+#define ENCODER_NO_DATA        1
+#define ENCODER_NO_BUSY_BUF    2
+#define ENCODER_NO_IDLE_BUF    3
+#define ENCODER_FRAME_IN_ORDER 4
+
+#define ENCODER_MEM_ERR       -1
+#define ENCODER_DISPLAY_ERR   -2
+#define ENCODER_CONFIG_ERR    -3
+#define ENCODER_CONTEXT_ERR    -3
+#define ENCODER_STATE_ERR     -4
+#define ENCODER_ENC_RES_ERR   -5
+#define ENCODER_PICTURE_ERR   -6
+#define ENCODER_SURFACE_ERR   -7
+#define ENCODER_QUERY_STATUS_ERR -8
+#define ENCODER_DATA_NOT_READY   -9
+#define ENCODER_DATA_ERR      -10
+#define ENCODER_PROFILE_ERR   -11
+#define ENCODER_PARAMETER_ERR -12
+#define ENCODER_FUNC_PTR_ERR  -13
+
+#ifdef DEBUG
+  #define ENCODER_LOG_ERROR(str_fmt,...)   \
+      fprintf(stdout, str_fmt "\n", ## __VA_ARGS__)
+  #define ENCODER_LOG_WARNING(str_fmt,...) \
+      fprintf(stdout, str_fmt "\n", ## __VA_ARGS__)
+  #define ENCODER_LOG_DEBUG(str_fmt,...)   \
+      fprintf(stdout, str_fmt "\n", ## __VA_ARGS__)
+  #define ENCODER_LOG_INFO(str_fmt,...)    \
+      fprintf(stdout, str_fmt "\n", ## __VA_ARGS__)
+#else
+  #define ENCODER_LOG_ERROR(...)   GST_ERROR( __VA_ARGS__)
+  #define ENCODER_LOG_WARNING(...) GST_WARNING( __VA_ARGS__)
+  #define ENCODER_LOG_DEBUG(...)   GST_DEBUG( __VA_ARGS__)
+  #define ENCODER_LOG_INFO(...)    GST_INFO( __VA_ARGS__)
+#endif
+
+#define VAAPI_UNUSED_ARG(arg) (void)(arg)
+
+#ifdef DEBUG
+#include <assert.h>
+#define ENCODER_ASSERT(exp) assert(exp)
+#else
+#define ENCODER_ASSERT(exp) g_assert(exp)
+#endif
+
+#define ENCODER_CHECK_STATUS(exp, err_num, err_reason, ...)  \
+  if (!(exp)) {                                   \
+    ENCODER_ASSERT(FALSE);                         \
+    ret = err_num;                                 \
+    ENCODER_LOG_ERROR(err_reason, ## __VA_ARGS__); \
+    goto end;                                      \
+  }
+
+/* must have <gboolean is_locked = FALSE;> declared first*/
+#define ENCODER_ACQUIRE_DISPLAY_LOCK(display)    \
+     if (!is_locked) {                     \
+      GST_VAAPI_DISPLAY_LOCK(display);     \
+      is_locked = TRUE;                    \
+     }
+
+#define ENCODER_RELEASE_DISPLAY_LOCK(display)    \
+    if (is_locked) {                       \
+     GST_VAAPI_DISPLAY_UNLOCK(display);    \
+     is_locked = FALSE;                    \
+    }
+
+
+typedef enum {
+  VAAPI_ENC_NULL,
+  VAAPI_ENC_INIT,
+  VAAPI_ENC_OPENED,
+  VAAPI_ENC_ENCODING,
+} VAAPI_Encode_State;
+
+typedef int                                  EncoderStatus;
+typedef struct _GstVaapiEncoder              GstVaapiEncoder;
+typedef struct _GstVaapiEncoderPrivate       GstVaapiEncoderPrivate;
+typedef struct _GstVaapiEncoderClass         GstVaapiEncoderClass;
+
+#define GST_TYPE_VAAPI_ENCODER \
+    (gst_vaapi_encoder_get_type())
+
+#define GST_IS_VAAPI_ENCODER(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_ENCODER))
+
+#define GST_IS_VAAPI_ENCODER_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VAAPI_ENCODER))
+
+#define GST_VAAPI_ENCODER_GET_CLASS(obj)                 \
+    (G_TYPE_INSTANCE_GET_CLASS ((obj),                   \
+                                GST_TYPE_VAAPI_ENCODER,  \
+                                GstVaapiEncoderClass))
+
+#define GST_VAAPI_ENCODER(obj)                           \
+    (G_TYPE_CHECK_INSTANCE_CAST ((obj),                  \
+                                 GST_TYPE_VAAPI_ENCODER, \
+                                 GstVaapiEncoder))
+
+#define GST_VAAPI_ENCODER_CLASS(klass)                   \
+    (G_TYPE_CHECK_CLASS_CAST ((klass),                   \
+                              GST_TYPE_VAAPI_ENCODER,    \
+                              GstVaapiEncoderClass))
+
+#define GST_VAAPI_ENCODER_GET_PRIVATE(obj)               \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                  \
+                                 GST_TYPE_VAAPI_ENCODER, \
+                                 GstVaapiEncoderPrivate))
+
+#define GST_VAAPI_ENCODER_CAST(encoder) \
+    ((GstVaapiEncoder *)(encoder))
+
+/* Get GstVaapiDisplay* */
+#define ENCODER_DISPLAY(encoder) \
+    (((GstVaapiEncoder*)(encoder))->priv->display)
+
+/* Get VADisplay */
+#define ENCODER_VA_DISPLAY(encoder) \
+    (((GstVaapiEncoder*)(encoder))->priv->va_display)
+
+/* Get GstVaapiContext* */
+#define ENCODER_CONTEXT(encoder) \
+    (((GstVaapiEncoder*)(encoder))->priv->context)
+
+/* Get VAContext */
+#define ENCODER_VA_CONTEXT(encoder) \
+    (((GstVaapiEncoder*)(encoder))->priv->va_context)
+
+#define ENCODER_WIDTH(encoder)   (((GstVaapiEncoder*)(encoder))->width)
+#define ENCODER_HEIGHT(encoder)  (((GstVaapiEncoder*)(encoder))->height)
+#define ENCODER_FPS(encoder)     (((GstVaapiEncoder*)(encoder))->frame_rate)
+#define ENCODER_RATE_CONTROL(encoder)   \
+    (((GstVaapiEncoder*)(encoder))->rate_control)
+
+struct _GstVaapiEncoder {
+  GObject parent;
+  GstVaapiEncoderPrivate *priv;
+
+  guint32 width;
+  guint32 height;
+  guint32 frame_rate;
+  GstVaapiRateControl rate_control;
+};
+
+struct _GstVaapiEncoderClass {
+  GObjectClass parent_class;
+
+  EncoderStatus (*initialize)    (GstVaapiEncoder* encoder);  /* can be NULL */
+  EncoderStatus (*uninitialize)  (GstVaapiEncoder* encoder);  /* can be NULL */
+
+  /* context [out] */
+  EncoderStatus (*open)          (GstVaapiEncoder* encoder,
+                                  GstVaapiContext **context);
+
+  EncoderStatus (*close)         (GstVaapiEncoder* encoder);
+  EncoderStatus (*encode)        (GstVaapiEncoder* encoder,
+                                  GstBuffer *pic);
+  /* buf [out] */
+  EncoderStatus (*get_buf)       (GstVaapiEncoder* encoder,
+                                  GstBuffer **buf);
+  EncoderStatus (*flush)         (GstVaapiEncoder* encoder);
+
+  /* get_codec_data can be NULL */
+  EncoderStatus (*get_codec_data)(GstVaapiEncoder* encoder, GstBuffer **codec_data);
+};
+
+struct _GstVaapiEncoderPrivate {
+  GstVaapiDisplay     *display;
+  VADisplay            va_display;
+  GstVaapiContext     *context;
+  VAContextID          va_context;
+  VAAPI_Encode_State   state;
+};
+
+GType
+gst_vaapi_encoder_get_type(void);
+
+/* set/get display */
+gboolean
+gst_vaapi_encoder_set_display(
+    GstVaapiEncoder* encoder,
+    GstVaapiDisplay *display
+);
+GstVaapiDisplay *
+gst_vaapi_encoder_get_display(GstVaapiEncoder* encoder);
+
+/* get context */
+GstVaapiContext *
+gst_vaapi_encoder_get_context(GstVaapiEncoder* encoder);
+
+/* get encoding state */
+VAAPI_Encode_State
+gst_vaapi_encoder_get_state(GstVaapiEncoder* encoder);
+
+/* check/open display */
+EncoderStatus
+gst_vaapi_encoder_initialize(GstVaapiEncoder* encoder);
+
+/* check/open context */
+EncoderStatus
+gst_vaapi_encoder_open(GstVaapiEncoder* encoder);
+
+/* encode one frame */
+EncoderStatus
+gst_vaapi_encoder_encode(
+    GstVaapiEncoder* encoder,
+    GstBuffer *pic
+);
+
+EncoderStatus
+gst_vaapi_encoder_get_encoded_buffer(
+    GstVaapiEncoder* encoder,
+    GstBuffer **buf
+);
+
+EncoderStatus
+gst_vaapi_encoder_get_codec_data(
+    GstVaapiEncoder* encoder,
+    GstBuffer **codec_data
+);
+
+/* flush all frames */
+EncoderStatus
+gst_vaapi_encoder_flush(GstVaapiEncoder* encoder);
+
+/* close context */
+EncoderStatus
+gst_vaapi_encoder_close(GstVaapiEncoder* encoder);
+
+EncoderStatus
+gst_vaapi_encoder_render_picture(
+    GstVaapiEncoder *encoder,
+    GstVaapiSurface *buffer_surface,
+    VABufferID *bufs,
+    guint num
+);
+
+/* close display */
+EncoderStatus
+gst_vaapi_encoder_uninitialize(GstVaapiEncoder* encoder);
+
+static inline void
+gst_vaapi_encoder_unref (GstVaapiEncoder *encoder)
+{
+  g_object_unref (encoder);
+}
+
+/* other functions */
+char *vaapi_encoder_dump_bytes(const guint8 *buf, guint32 num);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_ENCODER_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_h263.c b/gst-libs/gst/vaapi/gstvaapiencoder_h263.c
new file mode 100644 (file)
index 0000000..507a2fa
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ *  gstvaapiencoder_h263.c - H.263 encoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "gstvaapiencoder_h263.h"
+
+#include <string.h>
+#include <gst/gstclock.h>
+
+#include "gstvaapiobject.h"
+#include "gstvaapiobject_priv.h"
+#include "gstvaapicontext.h"
+#include "gstvaapisurface.h"
+#include "gstvaapivideobuffer.h"
+#include "gstvaapidisplay_priv.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_vaapi_h263_encoder_debug);
+#define GST_CAT_DEFAULT gst_vaapi_h263_encoder_debug
+
+#define GST_VAAPI_ENCODER_H263_CAST(encoder)    ((GstVaapiEncoderH263 *)(encoder))
+
+struct _GstVaapiEncoderH263Private {
+  GstVaapiSurface  *ref_surface;  /* reference buffer*/
+  GstVaapiSurface  *recon_surface; /* reconstruct buffer*/
+
+  VABufferID        seq_param_id;
+  VABufferID        pic_param_id;
+  VABufferID        slic_param_id;
+};
+
+G_DEFINE_TYPE(GstVaapiEncoderH263, gst_vaapi_encoder_h263, GST_TYPE_VAAPI_BASE_ENCODER)
+
+GstVaapiEncoderH263 *
+gst_vaapi_encoder_h263_new(void)
+{
+  return GST_VAAPI_ENCODER_H263_CAST(g_object_new(GST_TYPE_VAAPI_ENCODER_H263, NULL));
+}
+
+static gboolean
+gst_vaapi_encoder_h263_validate_attributes(
+    GstVaapiBaseEncoder* base
+)
+{
+  GstVaapiEncoderH263 *encoder = GST_VAAPI_ENCODER_H263_CAST(base);
+  if (!ENCODER_WIDTH(encoder) ||
+      !ENCODER_HEIGHT(encoder) ||
+      !ENCODER_FPS(encoder))
+  {
+    return FALSE;
+  }
+  if (!encoder->intra_period) {
+    encoder->intra_period = H263_DEFAULT_INTRA_PERIOD;
+  }
+  if (-1 == encoder->init_qp) {
+    encoder->init_qp = H263_DEFAULT_INIT_QP;
+  }
+  if (-1 == encoder->min_qp) {
+    encoder->min_qp = H263_DEFAULT_MIN_QP;
+  }
+
+  /* default compress ratio 1: (4*8*1.5) */
+  if (!encoder->bitrate) {
+    encoder->bitrate =
+        ENCODER_WIDTH(encoder)*ENCODER_HEIGHT(encoder)*ENCODER_FPS(encoder)/4/1024;
+  }
+  gst_vaapi_base_encoder_set_va_profile(GST_VAAPI_BASE_ENCODER(encoder),
+                                        VAProfileH263Baseline);
+  return TRUE;
+
+}
+
+
+static void
+h263_release_parameters(
+    GstVaapiEncoderH263 *encoder
+)
+{
+  GstVaapiEncoderH263Private *priv = encoder->priv;
+  VADisplay va_dpy = ENCODER_VA_DISPLAY(encoder);
+  VAStatus va_status = VA_STATUS_SUCCESS;
+
+  VAAPI_UNUSED_ARG(va_status);
+
+  if (VA_INVALID_ID != priv->seq_param_id) {
+    va_status = vaDestroyBuffer(va_dpy, priv->seq_param_id);
+    priv->seq_param_id = VA_INVALID_ID;
+  }
+  if (VA_INVALID_ID != priv->pic_param_id) {
+    va_status = vaDestroyBuffer(va_dpy, priv->pic_param_id);
+    priv->pic_param_id = VA_INVALID_ID;
+  }
+  if (VA_INVALID_ID != priv->slic_param_id) {
+    va_status = vaDestroyBuffer(va_dpy, priv->slic_param_id);
+    priv->slic_param_id = VA_INVALID_ID;
+  }
+
+}
+
+static gboolean
+gst_vaapi_encoder_h263_release_resource(
+    GstVaapiBaseEncoder* base
+)
+{
+  GstVaapiEncoderH263 *encoder = GST_VAAPI_ENCODER_H263_CAST(base);
+  GstVaapiEncoderH263Private *priv = encoder->priv;
+  GstVaapiContext *context = ENCODER_CONTEXT(base);
+
+  h263_release_parameters(encoder);
+
+  /*remove ref_surface*/
+  if (priv->ref_surface) {
+    if (context) {
+      gst_vaapi_context_put_surface(context, priv->ref_surface);
+    } else {
+      g_object_unref(priv->ref_surface);
+    }
+    priv->ref_surface = NULL;
+  }
+
+  /*remove recon_surface*/
+  if (priv->recon_surface) {
+    if (context) {
+      gst_vaapi_context_put_surface(context, priv->recon_surface);
+    } else {
+      g_object_unref(priv->recon_surface);
+    }
+    priv->recon_surface = NULL;
+  }
+
+  return TRUE;
+}
+
+static EncoderStatus
+gst_vaapi_encoder_h263_rendering(
+    GstVaapiBaseEncoder *base,
+    GstVaapiSurface *surface,
+    guint frame_index,
+    VABufferID coded_buf,
+    gboolean *is_key
+)
+
+{
+  GstVaapiEncoderH263 *encoder = GST_VAAPI_ENCODER_H263_CAST(base);
+  GstVaapiEncoderH263Private *priv = encoder->priv;
+  GstVaapiContext *context = ENCODER_CONTEXT(base);
+  VADisplay va_dpy = ENCODER_VA_DISPLAY(base);
+  VAContextID context_id = ENCODER_VA_CONTEXT(base);
+  VABufferID va_buffers[64];
+  guint32    va_buffers_count = 0;
+
+  VAStatus va_status = VA_STATUS_SUCCESS;
+  EncoderStatus ret = ENCODER_NO_ERROR;
+
+  *is_key = (frame_index % encoder->intra_period == 0);
+
+  /* initialize sequence parameter set, only first time */
+  if (VA_INVALID_ID == priv->seq_param_id) { /*only the first time*/
+    VAEncSequenceParameterBufferH263 seq_param = {0};
+
+    seq_param.intra_period = encoder->intra_period;
+    seq_param.bits_per_second = encoder->bitrate * 1024;
+    seq_param.frame_rate = ENCODER_FPS(encoder);
+    seq_param.initial_qp = encoder->init_qp;
+    seq_param.min_qp = encoder->min_qp;
+
+    va_status = vaCreateBuffer(va_dpy, context_id,
+                               VAEncSequenceParameterBufferType,
+                               sizeof(seq_param), 1,
+                               &seq_param,
+                               &priv->seq_param_id);
+    ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+                         ENCODER_ENC_RES_ERR,
+                         "h263 alloc seq-buffer failed.");
+    va_buffers[va_buffers_count++] = priv->seq_param_id;
+  }
+
+  /* set reference and reconstructed surfaces */
+  if (!priv->ref_surface) {
+    priv->ref_surface = gst_vaapi_context_get_surface(context);
+    ENCODER_CHECK_STATUS(priv->ref_surface,
+                         ENCODER_SURFACE_ERR,
+                         "h263 reference surface, h263_pop_free_surface failed.");
+  }
+  if (!priv->recon_surface) {
+    priv->recon_surface = gst_vaapi_context_get_surface(context);
+    ENCODER_CHECK_STATUS(priv->recon_surface,
+                         ENCODER_SURFACE_ERR,
+                         "h263 reconstructed surface, h263_pop_free_surface failed.");
+  }
+
+  /* initialize picture, every time, every frame */
+  VAEncPictureParameterBufferH263 pic_param = {0};
+  pic_param.reference_picture = GST_VAAPI_OBJECT_ID(priv->ref_surface);
+  pic_param.reconstructed_picture = GST_VAAPI_OBJECT_ID(priv->recon_surface);
+  pic_param.coded_buf = coded_buf;
+  pic_param.picture_width = ENCODER_WIDTH(encoder);
+  pic_param.picture_height = ENCODER_HEIGHT(encoder);
+  pic_param.picture_type = (*is_key) ? VAEncPictureTypeIntra : VAEncPictureTypePredictive;
+  if (VA_INVALID_ID != priv->pic_param_id) { /* destroy first*/
+    va_status = vaDestroyBuffer(va_dpy, priv->pic_param_id);
+    priv->pic_param_id = VA_INVALID_ID;
+  }
+
+  va_status = vaCreateBuffer(va_dpy, context_id, VAEncPictureParameterBufferType,
+                               sizeof(pic_param), 1, &pic_param, &priv->pic_param_id);
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status,
+                       ENCODER_ENC_RES_ERR, "h263 creating pic-param buffer failed.");
+  va_buffers[va_buffers_count++] = priv->pic_param_id;
+
+  /*initialize slice parameters, only ONE slice for h263*/
+  VAEncSliceParameterBuffer slice_param = { 0 };
+  slice_param.start_row_number = 0;
+  slice_param.slice_height = (ENCODER_HEIGHT(encoder)+15)/16; /*MB?*/
+  slice_param.slice_flags.bits.is_intra = *is_key;
+  slice_param.slice_flags.bits.disable_deblocking_filter_idc = 0;
+  if (VA_INVALID_ID != priv->slic_param_id) {
+    vaDestroyBuffer(va_dpy, priv->slic_param_id);
+    priv->slic_param_id = VA_INVALID_ID;
+  }
+
+  va_status = vaCreateBuffer(va_dpy,
+                             context_id,
+                             VAEncSliceParameterBufferType,
+                             sizeof(slice_param),
+                             1,
+                             &slice_param,
+                             &priv->slic_param_id);
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status,
+                       ENCODER_ENC_RES_ERR,
+                       "h263 creating slice-parameters buffer failed.");
+  va_buffers[va_buffers_count++] = priv->slic_param_id;
+
+  ret = gst_vaapi_encoder_render_picture(GST_VAAPI_ENCODER_CAST(encoder),
+                                         surface,
+                                         va_buffers,
+                                         va_buffers_count);
+  ENCODER_CHECK_STATUS(ret == ENCODER_NO_ERROR,
+                       ENCODER_PICTURE_ERR,
+                       "h263 rendering slice-parameters buffer failed.");
+
+  /*swap ref_surface and recon_surface */
+  GstVaapiSurface *swap = priv->ref_surface;
+  priv->ref_surface = priv->recon_surface;
+  priv->recon_surface = swap;
+
+end:
+  return ret;
+}
+
+static void
+gst_vaapi_encoder_h263_init(GstVaapiEncoderH263 *encoder)
+{
+  GstVaapiEncoderH263Private *priv = GST_VAAPI_ENCODER_H263_GET_PRIVATE(encoder);
+  encoder->priv = priv;
+  ENCODER_ASSERT(priv);
+
+  /* init public */
+  encoder->bitrate = 0;
+  encoder->intra_period = H263_DEFAULT_INTRA_PERIOD;
+  encoder->init_qp = H263_DEFAULT_INIT_QP;
+  encoder->min_qp = H263_DEFAULT_MIN_QP;
+
+  /* init private */
+  priv->ref_surface = NULL;
+  priv->recon_surface = NULL;
+
+  priv->seq_param_id = VA_INVALID_ID;
+  priv->pic_param_id = VA_INVALID_ID;
+  priv->slic_param_id = VA_INVALID_ID;
+}
+
+static void
+gst_vaapi_encoder_h263_finalize(GObject *object)
+{
+  /*free private buffers*/
+  GstVaapiEncoder *encoder = GST_VAAPI_ENCODER(object);
+
+  if (gst_vaapi_encoder_get_state(encoder) != VAAPI_ENC_NULL) {
+    gst_vaapi_encoder_uninitialize(encoder);
+  }
+  G_OBJECT_CLASS(gst_vaapi_encoder_h263_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_encoder_h263_class_init(GstVaapiEncoderH263Class *klass)
+{
+  GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+  GstVaapiBaseEncoderClass * const base_class = GST_VAAPI_BASE_ENCODER_CLASS(klass);
+  GstVaapiEncoderClass * const encoder_class = GST_VAAPI_ENCODER_CLASS(klass);
+  g_type_class_add_private(klass, sizeof(GstVaapiEncoderH263Private));
+
+  GST_DEBUG_CATEGORY_INIT (gst_vaapi_h263_encoder_debug, "gst_va_h263_encoder", 0,
+      "gst_va_h263_encoder element");
+
+  object_class->finalize = gst_vaapi_encoder_h263_finalize;
+
+  base_class->validate_attributes = gst_vaapi_encoder_h263_validate_attributes;
+  base_class->pre_alloc_resource  = NULL;
+  base_class->release_resource    = gst_vaapi_encoder_h263_release_resource;
+  base_class->render_frame = gst_vaapi_encoder_h263_rendering;
+  base_class->notify_buffer = NULL;
+  base_class->wrap_buffer = NULL;
+
+  /*
+  encoder_class->flush = gst_vaapi_encoder_h263_flush;
+  */
+  encoder_class->get_codec_data = NULL;
+
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_h263.h b/gst-libs/gst/vaapi/gstvaapiencoder_h263.h
new file mode 100644 (file)
index 0000000..610a135
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ *  gstvaapiencoder_h263.h - H.263 encoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_ENCODER_H263_H
+#define GST_VAAPI_ENCODER_H263_H
+
+#include "gst/vaapi/gstvaapisurfacepool.h"
+#include "gst/vaapi/gstvaapibaseencoder.h"
+
+G_BEGIN_DECLS
+
+#define H263_DEFAULT_INTRA_PERIOD 30
+#define H263_DEFAULT_INIT_QP      15
+#define H263_DEFAULT_MIN_QP       1
+
+
+typedef struct _GstVaapiEncoderH263              GstVaapiEncoderH263;
+typedef struct _GstVaapiEncoderH263Private       GstVaapiEncoderH263Private;
+typedef struct _GstVaapiEncoderH263Class         GstVaapiEncoderH263Class;
+
+
+#define GST_TYPE_VAAPI_ENCODER_H263 \
+    (gst_vaapi_encoder_h263_get_type())
+
+#define GST_IS_VAAPI_ENCODER_H263(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_ENCODER_H263))
+
+#define GST_IS_VAAPI_ENCODER_H263_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VAAPI_ENCODER_H263))
+
+#define GST_VAAPI_ENCODER_H263_GET_CLASS(obj)                  \
+    (G_TYPE_INSTANCE_GET_CLASS ((obj),                         \
+                                GST_TYPE_VAAPI_ENCODER_H263,   \
+                                GstVaapiEncoderH263Class))
+
+#define GST_VAAPI_ENCODER_H263(obj)                            \
+    (G_TYPE_CHECK_INSTANCE_CAST ((obj),                        \
+                                 GST_TYPE_VAAPI_ENCODER_H263,  \
+                                 GstVaapiEncoderH263))
+
+#define GST_VAAPI_ENCODER_H263_CLASS(klass)                    \
+    (G_TYPE_CHECK_CLASS_CAST ((klass),                         \
+                              GST_TYPE_VAAPI_ENCODER_H263,     \
+                              GstVaapiEncoderH263Class))
+
+#define GST_VAAPI_ENCODER_H263_GET_PRIVATE(obj)                \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                        \
+                                 GST_TYPE_VAAPI_ENCODER_H263,  \
+                                 GstVaapiEncoderH263Private))
+
+struct _GstVaapiEncoderH263 {
+  GstVaapiBaseEncoder parent;   /*based on gobject*/
+
+  guint32  bitrate;  /*kbps*/
+  guint32  intra_period;
+  guint32  init_qp;  /*default 15, 1~31*/
+  guint32  min_qp;   /*default 1, 1~31*/
+
+  GstVaapiEncoderH263Private *priv;
+};
+
+struct _GstVaapiEncoderH263Class {
+    GstVaapiBaseEncoderClass parent_class;
+};
+
+
+GType
+gst_vaapi_encoder_h263_get_type(void);
+
+GstVaapiEncoderH263 *
+gst_vaapi_encoder_h263_new(void);
+
+static inline void
+gst_vaapi_encoder_h263_unref (GstVaapiEncoderH263 * encoder)
+{
+  g_object_unref (encoder);
+}
+
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_ENCODER_H263_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_h264.c b/gst-libs/gst/vaapi/gstvaapiencoder_h264.c
new file mode 100644 (file)
index 0000000..b98ff47
--- /dev/null
@@ -0,0 +1,2209 @@
+/*
+ *  gstvaapiencoder_h264.c -  H.264 encoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "gstvaapiencoder_h264.h"
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <va/va.h>
+#include <va/va_x11.h>
+#if !HAVE_OLD_H264_ENCODER
+#include <va/va_enc_h264.h>
+#endif
+#include <X11/Xlib.h>
+#include <glib.h>
+
+#include "gst/gstclock.h"
+#include "gst/gstvalue.h"
+
+#include "gstvaapiobject.h"
+#include "gstvaapiobject_priv.h"
+#include "gstvaapicontext.h"
+#include "gstvaapisurface.h"
+#include "gstvaapivideobuffer.h"
+#include "gstvaapidisplay_priv.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_vaapi_h264_encoder_debug);
+
+#define GST_CAT_DEFAULT gst_vaapi_h264_encoder_debug
+
+#define GST_VAAPI_ENCODER_H264_CAST(encoder)    ((GstVaapiEncoderH264 *)(encoder))
+
+#define SHARE_CODED_BUF         0
+
+#define DEFAULT_SURFACE_NUMBER  3
+#define DEFAULT_CODEDBUF_NUM    5
+#define DEFAULT_SID_INPUT       0 // suface_ids[0]
+
+#define REF_RECON_SURFACE_NUM   2
+
+#define ENTROPY_MODE_CAVLC      0
+#define ENTROPY_MODE_CABAC      1
+
+#define BR_CBR          0
+#define BR_VBR          1
+#define BR_CQP          2
+
+#define NAL_REF_IDC_NONE        0
+#define NAL_REF_IDC_LOW         1
+#define NAL_REF_IDC_MEDIUM      2
+#define NAL_REF_IDC_HIGH        3
+
+
+typedef enum {
+  NAL_UNKNOWN     = 0,
+  NAL_NON_IDR     = 1,
+  NAL_IDR         = 5,    /* ref_idc != 0 */
+  NAL_SEI         = 6,    /* ref_idc == 0 */
+  NAL_SPS         = 7,
+  NAL_PPS         = 8,
+  NAL_AUD         = 9,
+  NAL_FILLER      = 12,
+}H264_NAL_TYPE;
+
+
+typedef enum {
+  SLICE_TYPE_P  = 0,
+  SLICE_TYPE_B  = 1,
+  SLICE_TYPE_I  = 2
+} H264_SLICE_TYPE;
+
+struct _GstVaapiEncoderH264Private {
+  GstVaapiEncoderH264   *public;
+  guint32           format;   /*NV12, I420,*/
+  gboolean          avc_flag;  /*elementary flag*/
+
+  /* private data*/
+  GQueue           *video_buffer_caches; /*not used for baseline*/
+
+  GstVaapiSurface  *ref_surface1;  /* reference buffer*/
+  GstVaapiSurface  *ref_surface2;  /* for B frames */
+  GstVaapiSurface  *recon_surface; /* reconstruct buffer*/
+
+  VABufferID        seq_param_id;
+  VABufferID        pic_param_id;
+  VABufferID        slice_param_id;
+  VABufferID        misc_param_hdr_id;
+  VABufferID        packed_seq_param_id;
+  VABufferID        packed_seq_data_id;
+  VABufferID        packed_pic_param_id;
+  VABufferID        packed_pic_data_id;
+  gboolean          is_seq_param_set;
+#if HAVE_OLD_H264_ENCODER
+  VAEncSliceParameterBuffer     *slice_param_buffers;
+#else
+  VAEncSliceParameterBufferH264 *slice_param_buffers;
+#endif
+  guint32           default_slice_height;
+  guint32           slice_mod_mb_num;
+  guint32           default_cts_offset;
+
+  GstBuffer        *sps_data;
+  GstBuffer        *pps_data;
+
+  GQueue           *queued_buffers;  /* GstVaapiVideoBuffers with surface*/
+
+  guint32           gop_count;
+  guint32           cur_display_num;
+  guint32           cur_decode_num;
+  H264_SLICE_TYPE   cur_slice_type;
+  guint64           last_decode_time;
+  guint32           max_frame_num;
+  guint32           max_pic_order_cnt;
+  guint16           idr_num;
+};
+
+G_DEFINE_TYPE(GstVaapiEncoderH264, gst_vaapi_encoder_h264, GST_TYPE_VAAPI_BASE_ENCODER)
+
+// 4096-1
+#define H264_BITSTREAM_ALLOC_ALIGN_MASK 0x0FFF
+
+#define BIT_STREAM_BUFFER(stream)    ((stream)->buffer)
+#define BIT_STREAM_BIT_SIZE(stream)  ((stream)->bit_size)
+
+struct _H264Bitstream {
+  guint8   *buffer;
+  guint32   bit_size;
+  guint32   max_bit_capability;
+};
+
+typedef struct _H264Bitstream H264Bitstream;
+
+static const guint8 h264_bit_mask[9] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
+
+/* h264 bitstream functions */
+static void
+h264_bitstream_init(H264Bitstream *bitstream, guint32 bit_capability);
+
+static gboolean
+h264_bitstream_write_uint(
+    H264Bitstream *bitstream,
+    guint32 value,
+    guint32 bit_size
+);
+
+static gboolean
+h264_bitstream_align(H264Bitstream *bitstream, guint32 value);
+
+static gboolean
+h264_bitstream_write_ue(H264Bitstream *bitstream, guint32 value);
+
+static gboolean
+h264_bitstream_write_se(H264Bitstream *bitstream, gint32 value);
+
+static gboolean
+h264_bitstream_write_trailing_bits(H264Bitstream *bitstream);
+
+static gboolean
+h264_bitstream_write_byte_array(
+    H264Bitstream *bitstream,
+    const guint8 *buf,
+    guint32 byte_size
+);
+
+static void
+h264_bitstream_destroy(H264Bitstream *bitstream, gboolean free_flag);
+
+static gboolean
+h264_bitstream_auto_grow(H264Bitstream *bitstream, guint32 extra_bit_size);
+
+static gboolean
+h264_bitstream_write_sps(
+    H264Bitstream *bitstream,
+    VAEncSequenceParameterBufferH264 *seq,
+    H264_Profile profile
+);
+static gboolean
+h264_bitstream_write_pps(
+    H264Bitstream *bitstream,
+    VAEncPictureParameterBufferH264 *pic
+);
+
+static gboolean
+h264_bitstream_write_nal_header(
+    H264Bitstream *bitstream,
+    guint nal_ref_idc,
+    guint nal_unit_type
+);
+
+static VAProfile
+h264_get_va_profile(guint32 profile)
+{
+  switch (profile) {
+    case H264_PROFILE_BASELINE:
+      return VAProfileH264Baseline;
+
+    case H264_PROFILE_MAIN:
+      return VAProfileH264Main;
+
+    case H264_PROFILE_HIGH:
+      return VAProfileH264High;
+
+    default:
+      break;
+  }
+  return (-1);
+}
+
+GstVaapiEncoderH264 *
+gst_vaapi_encoder_h264_new(void)
+{
+  return GST_VAAPI_ENCODER_H264_CAST(
+             g_object_new(GST_TYPE_VAAPI_ENCODER_H264, NULL));
+}
+
+static void
+gst_vaapi_encoder_h264_init_public_values(GstVaapiEncoderH264* encoder)
+{
+  encoder->profile = 0;
+  encoder->level = 0;
+  encoder->bitrate = 0;
+  encoder->intra_period = 0;
+  encoder->init_qp = -1;
+  encoder->min_qp = -1;
+  encoder->slice_num = 0;
+  encoder->b_frame_num = 0;
+}
+
+void
+gst_vaapi_encoder_h264_set_avc_flag(GstVaapiEncoderH264* encoder, gboolean avc)
+{
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  priv->avc_flag = avc;
+}
+
+gboolean
+gst_vaapi_encoder_h264_get_avc_flag(GstVaapiEncoderH264* encoder)
+{
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  return priv->avc_flag;
+}
+
+gboolean
+gst_vaapi_encoder_h264_validate_attributes(GstVaapiBaseEncoder *base)
+{
+  GstVaapiEncoderH264 *encoder = GST_VAAPI_ENCODER_H264_CAST(base);
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  if (!ENCODER_WIDTH(encoder) ||
+      !ENCODER_HEIGHT(encoder) ||
+      !ENCODER_FPS(encoder)) {
+    return FALSE;
+  }
+  if (!encoder->profile) {
+    encoder->profile = H264_DEFAULT_PROFILE;
+  }
+  gst_vaapi_base_encoder_set_va_profile(base, h264_get_va_profile(encoder->profile));
+  if (!encoder->level) {
+    if (encoder->profile <= H264_PROFILE_BASELINE)
+      encoder->level = H264_LEVEL_31;
+    else
+      encoder->level = H264_LEVEL_41;
+  }
+  if (!encoder->intra_period) {
+    encoder->intra_period = H264_DEFAULT_INTRA_PERIOD;
+  }
+  if (-1 == encoder->init_qp) {
+    encoder->init_qp = H264_DEFAULT_INIT_QP;
+  }
+  if (-1 == encoder->min_qp) {
+    if (GST_VAAPI_RATECONTROL_CQP == ENCODER_RATE_CONTROL(encoder))
+      encoder->min_qp = encoder->init_qp;
+    else
+      encoder->min_qp = H264_DEFAULT_MIN_QP;
+  }
+
+  if (encoder->min_qp > encoder->init_qp) {
+    encoder->min_qp = encoder->init_qp;
+  }
+
+  /* default compress ratio 1: (4*8*1.5) */
+  if (GST_VAAPI_RATECONTROL_CBR == ENCODER_RATE_CONTROL(encoder) ||
+      GST_VAAPI_RATECONTROL_VBR == ENCODER_RATE_CONTROL(encoder) ||
+      GST_VAAPI_RATECONTROL_VBR_CONSTRAINED == ENCODER_RATE_CONTROL(encoder))
+  {
+    if (!encoder->bitrate)
+      encoder->bitrate = ENCODER_WIDTH(encoder) *
+                         ENCODER_HEIGHT(encoder) *
+                         ENCODER_FPS(encoder) / 4 / 1024;
+  } else
+    encoder->bitrate = 0;
+
+  if (!encoder->slice_num) {
+    encoder->slice_num = H264_DEFAULT_SLICE_NUM;
+  }
+
+  /* need  calculate slice-num and each slice-height
+        suppose:  ((encoder->height+15)/16) = 13, slice_num = 8
+        then: slice_1_height = 2
+                 slice_2_height = 2
+                 slice_3_height = 2
+                 slice_4_height = 2
+                 slice_5_height = 2
+                 slice_6_height = 1
+                 slice_7_height = 1
+                 slice_8_height = 1
+   */
+  priv->default_slice_height = (ENCODER_HEIGHT(encoder)+15)/16/encoder->slice_num;
+  if (0 == priv->default_slice_height) { /* special value */
+    priv->default_slice_height = 1;
+    priv->slice_mod_mb_num = 0;
+    encoder->slice_num = (ENCODER_HEIGHT(encoder)+15)/16;
+  } else {
+    priv->slice_mod_mb_num = ((ENCODER_HEIGHT(encoder)+15)/16)%encoder->slice_num;
+  }
+
+  if (encoder->b_frame_num) {
+    priv->default_cts_offset = GST_SECOND/ENCODER_FPS(encoder);
+  } else {
+    priv->default_cts_offset = 0;
+  }
+  return TRUE;
+}
+
+
+static gboolean
+h264_encoder_release_parameters(GstVaapiEncoderH264 *encoder)
+{
+  VAStatus va_status = VA_STATUS_SUCCESS;
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  GstVaapiDisplay *display = ENCODER_DISPLAY(encoder);
+  GstVaapiContext *context = ENCODER_CONTEXT(encoder);
+
+  ENCODER_ASSERT(display);
+  ENCODER_ASSERT(context);
+  VAAPI_UNUSED_ARG(va_status);
+  VADisplay va_dpy = gst_vaapi_display_get_display(display);
+
+  if (VA_INVALID_ID != priv->seq_param_id) {
+    va_status = vaDestroyBuffer(va_dpy, priv->seq_param_id);
+    priv->seq_param_id = VA_INVALID_ID;
+  }
+  if (VA_INVALID_ID != priv->pic_param_id) {
+    va_status = vaDestroyBuffer(va_dpy, priv->pic_param_id);
+    priv->pic_param_id = VA_INVALID_ID;
+  }
+  if (VA_INVALID_ID != priv->slice_param_id) {
+    va_status = vaDestroyBuffer(va_dpy, priv->slice_param_id);
+    priv->slice_param_id = VA_INVALID_ID;
+  }
+  if (VA_INVALID_ID != priv->misc_param_hdr_id) {
+    va_status = vaDestroyBuffer(va_dpy, priv->misc_param_hdr_id);
+    priv->misc_param_hdr_id = VA_INVALID_ID;
+  }
+
+  if (VA_INVALID_ID != priv->packed_seq_param_id) {
+    va_status = vaDestroyBuffer(va_dpy, priv->packed_seq_param_id);
+    priv->packed_seq_param_id = VA_INVALID_ID;
+  }
+  if (VA_INVALID_ID != priv->packed_seq_data_id) {
+    va_status = vaDestroyBuffer(va_dpy, priv->packed_seq_data_id);
+    priv->packed_seq_data_id = VA_INVALID_ID;
+  }
+  if (VA_INVALID_ID != priv->packed_pic_param_id) {
+    va_status = vaDestroyBuffer(va_dpy, priv->packed_pic_param_id);
+    priv->packed_pic_param_id = VA_INVALID_ID;
+  }
+  if (VA_INVALID_ID != priv->packed_pic_data_id) {
+    va_status = vaDestroyBuffer(va_dpy, priv->packed_pic_data_id);
+    priv->packed_pic_data_id = VA_INVALID_ID;
+  }
+
+  if (priv->slice_param_buffers) {
+    g_free(priv->slice_param_buffers);
+    priv->slice_param_buffers = NULL;
+  }
+
+  if (priv->sps_data) {
+    gst_buffer_unref(priv->sps_data);
+    priv->sps_data = NULL;
+  }
+  if (priv->pps_data) {
+    gst_buffer_unref(priv->pps_data);
+    priv->pps_data = NULL;
+  }
+
+  return TRUE;
+}
+
+static void
+h264_release_queued_buffers(GstVaapiEncoderH264Private *priv)
+{
+    while (!g_queue_is_empty(priv->queued_buffers)) {
+    GstBuffer* tmp = g_queue_pop_head(priv->queued_buffers);
+    if (tmp)
+      gst_buffer_unref(tmp);
+  }
+}
+
+
+static gboolean
+gst_vaapi_encoder_h264_release_resource(
+    GstVaapiBaseEncoder* base
+)
+{
+  GstVaapiEncoderH264* encoder = GST_VAAPI_ENCODER_H264_CAST(base);
+  gboolean ret = TRUE;
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  GstVaapiContext *context = ENCODER_CONTEXT(base);
+
+  /* release buffers first */
+  h264_encoder_release_parameters(encoder);
+  h264_release_queued_buffers(priv);
+  priv->cur_display_num = 0;
+  priv->cur_decode_num = 0;
+  priv->cur_slice_type = SLICE_TYPE_I;
+  priv->gop_count = 0;
+  priv->last_decode_time = 0LL;
+  priv->default_cts_offset = 0;
+  priv->is_seq_param_set = FALSE;
+
+  /*remove ref_surface1*/
+  if (priv->ref_surface1) {
+    if (context) {
+      gst_vaapi_context_put_surface(context, priv->ref_surface1);
+    } else {
+      g_object_unref(priv->ref_surface1);
+    }
+    priv->ref_surface1 = NULL;
+  }
+
+  if (priv->ref_surface2) {
+    if (context) {
+      gst_vaapi_context_put_surface(context, priv->ref_surface2);
+    } else {
+      g_object_unref(priv->ref_surface2);
+    }
+    priv->ref_surface2 = NULL;
+  }
+
+  /*remove recon_surface*/
+  if (priv->recon_surface) {
+    if (context) {
+      gst_vaapi_context_put_surface(context, priv->recon_surface);
+    } else {
+      g_object_unref(priv->recon_surface);
+    }
+    priv->recon_surface = NULL;
+  }
+
+  return ret;
+}
+
+static gboolean
+gst_vaapi_encoder_h264_alloc_slices(
+    GstVaapiBaseEncoder *base,
+    GstVaapiContext *context
+)
+{
+  gboolean ret = TRUE;
+  GstVaapiEncoderH264 *encoder = GST_VAAPI_ENCODER_H264_CAST(base);
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+
+  priv->slice_param_buffers =
+#if HAVE_OLD_H264_ENCODER
+  (VAEncSliceParameterBuffer*)
+#else
+  (VAEncSliceParameterBufferH264*)
+#endif
+          g_malloc0_n(encoder->slice_num,
+              sizeof(priv->slice_param_buffers[0]));
+
+  return ret;
+}
+
+static void
+gst_vaapi_encoder_h264_frame_failed(
+    GstVaapiBaseEncoder *base,
+    GstVaapiVideoBuffer* buffer
+)
+{
+  GstVaapiEncoderH264 *encoder = GST_VAAPI_ENCODER_H264_CAST(base);
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+
+  h264_release_queued_buffers(priv);
+  priv->cur_display_num = 0;
+  priv->cur_decode_num = 0;
+  priv->cur_slice_type = SLICE_TYPE_I;
+  priv->gop_count = 0;
+  priv->last_decode_time = 0LL;
+}
+
+static EncoderStatus
+gst_vaapi_encoder_h264_prepare_next_buffer(
+    GstVaapiBaseEncoder* base,
+    GstBuffer *display_buf,
+    gboolean need_flush,
+    GstBuffer **out_buf
+)
+{
+  EncoderStatus ret = ENCODER_NO_ERROR;
+  GstVaapiEncoderH264 *encoder = GST_VAAPI_ENCODER_H264_CAST(base);
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  GstBuffer  *return_buf = NULL;
+  //guint64 pts = 0;
+
+  if (NULL == display_buf && g_queue_is_empty(priv->queued_buffers)) {
+    ret = ENCODER_FRAME_IN_ORDER;
+    if (priv->gop_count >= encoder->intra_period || need_flush)
+      priv->gop_count = 0;
+    goto end;
+  }
+
+  if (display_buf) {
+    ++priv->gop_count;
+    gst_buffer_ref(GST_BUFFER_CAST(display_buf));
+    priv->last_decode_time = GST_BUFFER_TIMESTAMP(display_buf);
+  }
+
+  /* first frame */
+  if (priv->gop_count == 1) {
+    ENCODER_ASSERT(display_buf);
+    priv->cur_display_num = 0;
+    priv->cur_decode_num = 0;
+    priv->cur_slice_type = SLICE_TYPE_I;
+    ++priv->idr_num;
+    return_buf = display_buf;
+    goto end;
+  }
+
+  if (display_buf) {
+    if (encoder->b_frame_num &&
+        priv->gop_count < encoder->intra_period &&
+        g_queue_get_length(priv->queued_buffers) < encoder->b_frame_num
+        )
+    {
+      g_queue_push_tail(priv->queued_buffers, display_buf);
+      ret = ENCODER_FRAME_IN_ORDER;
+      goto end;
+    }
+    priv->cur_slice_type = SLICE_TYPE_P;
+    priv->cur_display_num = priv->gop_count-1;
+    ++priv->cur_decode_num;
+    return_buf = display_buf;
+  } else {
+    if (need_flush) {
+      return_buf = (GstBuffer*)g_queue_pop_tail(priv->queued_buffers);
+      priv->cur_slice_type = SLICE_TYPE_P;
+      priv->cur_display_num = priv->gop_count - 1;
+      ++priv->cur_decode_num;
+    } else {
+      return_buf = (GstBuffer*)g_queue_pop_head(priv->queued_buffers);
+      priv->cur_slice_type = SLICE_TYPE_B;
+      priv->cur_display_num =
+        priv->gop_count - 2 - g_queue_get_length(priv->queued_buffers);
+    }
+  }
+
+end:
+  *out_buf = return_buf;
+
+  return ret;
+}
+
+static inline void
+h264_swap_surface(GstVaapiSurface **s1, GstVaapiSurface **s2)
+{
+  GstVaapiSurface *tmp;
+
+  g_return_if_fail(s1 && s2);
+  tmp = *s1;
+  *s1 = *s2;
+  *s2 = tmp;
+}
+
+static inline const char *
+get_slice_type(H264_SLICE_TYPE type)
+{
+    switch (type) {
+    case SLICE_TYPE_I:
+        return "I";
+    case SLICE_TYPE_P:
+        return "P";
+    case SLICE_TYPE_B:
+        return "B";
+    default:
+        return "Unknown";
+    }
+}
+
+#if HAVE_OLD_H264_ENCODER
+
+static gboolean
+set_sequence_parameters(
+    GstVaapiEncoderH264 *encoder,
+    VAEncSequenceParameterBufferH264 *seq_param
+)
+{
+  seq_param->seq_parameter_set_id = 0;
+  seq_param->level_idc = encoder->level; /* 3.0 */
+  seq_param->intra_period = encoder->intra_period;
+  seq_param->intra_idr_period = encoder->intra_period;
+  seq_param->max_num_ref_frames = 1; /*Only I, P frames*/
+  seq_param->picture_width_in_mbs = (ENCODER_WIDTH(encoder)+15)/16;
+  seq_param->picture_height_in_mbs = (ENCODER_HEIGHT(encoder)+15)/16;
+
+  seq_param->bits_per_second = encoder->bitrate * 1024;
+  seq_param->frame_rate = ENCODER_FPS(encoder);
+  seq_param->initial_qp = encoder->init_qp; /*qp_value; 15, 24, 26?*/
+  seq_param->min_qp = encoder->min_qp;     /*1, 6, 10*/
+  seq_param->basic_unit_size = 0;
+  seq_param->vui_flag = FALSE;
+
+  return TRUE;
+}
+
+static gboolean
+set_picture_parameters(
+    GstVaapiEncoderH264 *encoder,
+    VAEncPictureParameterBufferH264 *pic_param,
+    VABufferID coded_buf
+)
+{
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+
+  pic_param->reference_picture = GST_VAAPI_OBJECT_ID(priv->ref_surface1);
+  pic_param->reconstructed_picture = GST_VAAPI_OBJECT_ID(priv->recon_surface);
+  pic_param->coded_buf = coded_buf;
+  pic_param->picture_width = ENCODER_WIDTH(encoder);
+  pic_param->picture_height = ENCODER_HEIGHT(encoder);
+  pic_param->last_picture = 0; // last pic or not
+
+  return TRUE;
+}
+
+static gboolean
+set_slices_parameters(
+    GstVaapiEncoderH264 *encoder,
+    VAEncSliceParameterBuffer *slices,
+    guint slice_num
+)
+{
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  VAEncSliceParameterBuffer *slice_param;
+
+  int i = 0;
+  guint32 last_row_num = 0;
+  guint32 slice_mod_num = priv->slice_mod_mb_num;
+
+  for (i = 0; i < slice_num; ++i) {
+    slice_param = &slices[i];
+    slice_param->start_row_number = last_row_num;               /* unit MB*/
+    slice_param->slice_height = priv->default_slice_height; /* unit MB */
+    if (slice_mod_num) {
+      ++slice_param->slice_height;
+      --slice_mod_num;
+    }
+    last_row_num += slice_param->slice_height;
+    slice_param->slice_flags.bits.is_intra =
+        (priv->cur_slice_type == SLICE_TYPE_I);
+    slice_param->slice_flags.bits.disable_deblocking_filter_idc = FALSE;
+    slice_param->slice_flags.bits.uses_long_term_ref = FALSE;
+    slice_param->slice_flags.bits.is_long_term_ref = FALSE;
+  }
+
+  ENCODER_ASSERT(last_row_num == (ENCODER_HEIGHT(encoder)+15)/16);
+  return TRUE;
+}
+
+#else  /* extended libva, new parameter structures*/
+
+static gboolean
+set_sequence_parameters(
+    GstVaapiEncoderH264 *encoder,
+    VAEncSequenceParameterBufferH264 *seq_param
+)
+{
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  guint width_in_mbs, height_in_mbs;
+
+  width_in_mbs = (ENCODER_WIDTH(encoder)+15)/16;
+  height_in_mbs = (ENCODER_HEIGHT(encoder)+15)/16;
+
+  seq_param->seq_parameter_set_id = 0;
+  seq_param->level_idc = encoder->level; /* 3.0 */
+  seq_param->intra_period = encoder->intra_period;
+  seq_param->ip_period = 0;           // ?
+  if (encoder->bitrate> 0)
+      seq_param->bits_per_second = encoder->bitrate * 1024;
+  else
+      seq_param->bits_per_second = 0;
+
+  seq_param->max_num_ref_frames =
+      (encoder->b_frame_num < 2 ? 3 : encoder->b_frame_num+1);  // ?, why 4
+  seq_param->picture_width_in_mbs = width_in_mbs;
+  seq_param->picture_height_in_mbs = height_in_mbs;
+
+  /*sequence field values*/
+  seq_param->seq_fields.value = 0;
+  seq_param->seq_fields.bits.chroma_format_idc = 1;
+  seq_param->seq_fields.bits.frame_mbs_only_flag = 1;
+  seq_param->seq_fields.bits.mb_adaptive_frame_field_flag = FALSE;
+  seq_param->seq_fields.bits.seq_scaling_matrix_present_flag = FALSE;
+  /* direct_8x8_inference_flag default false */
+  seq_param->seq_fields.bits.direct_8x8_inference_flag = FALSE;
+  seq_param->seq_fields.bits.log2_max_frame_num_minus4 = 4; // log2(seq.intra_period)-3 : 0
+  /* picture order count */
+  seq_param->seq_fields.bits.pic_order_cnt_type = 0;
+  seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 =
+        seq_param->seq_fields.bits.log2_max_frame_num_minus4 + 2;
+  seq_param->seq_fields.bits.delta_pic_order_always_zero_flag = TRUE;
+
+  priv->max_frame_num =
+      1<<(seq_param->seq_fields.bits.log2_max_frame_num_minus4 + 4);
+  priv->max_pic_order_cnt =
+      1 <<(seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 + 4);
+
+  seq_param->bit_depth_luma_minus8 = 0;
+  seq_param->bit_depth_chroma_minus8 = 0;
+
+  /* not used if pic_order_cnt_type == 0 */
+  seq_param->num_ref_frames_in_pic_order_cnt_cycle = 0;
+  seq_param->offset_for_non_ref_pic = 0;
+  seq_param->offset_for_top_to_bottom_field = 0;
+  memset(seq_param->offset_for_ref_frame,
+         0,
+         sizeof(seq_param->offset_for_ref_frame));
+
+  if (height_in_mbs*16 - ENCODER_HEIGHT(encoder)) {
+    seq_param->frame_cropping_flag = 1;
+    seq_param->frame_crop_left_offset = 0;
+    seq_param->frame_crop_right_offset = 0;
+    seq_param->frame_crop_top_offset = 0;
+    seq_param->frame_crop_bottom_offset =
+        ((height_in_mbs * 16 - ENCODER_HEIGHT(encoder))/
+         (2 * (!seq_param->seq_fields.bits.frame_mbs_only_flag + 1)));
+  }
+#if 0
+  if (h264_encoder->init_qp == -1)
+      seq.rate_control_method = BR_CBR;
+  else if (h264_encoder->init_qp == -2)
+      seq.rate_control_method = BR_VBR;
+  else {
+      ENCODER_ASSERT(h264_encoder->init_qp >= 0 && h264_encoder->init_qp <= 51);
+      seq.rate_control_method = BR_CQP;
+  }
+#endif
+
+  /*vui not set*/
+  seq_param->vui_parameters_present_flag = (encoder->bitrate> 0 ? TRUE : FALSE);
+  if (seq_param->vui_parameters_present_flag) {
+    seq_param->vui_fields.bits.aspect_ratio_info_present_flag = FALSE;
+    seq_param->vui_fields.bits.bitstream_restriction_flag = FALSE;
+    seq_param->vui_fields.bits.timing_info_present_flag = (encoder->bitrate> 0 ? TRUE : FALSE);
+    if (seq_param->vui_fields.bits.timing_info_present_flag) {
+      seq_param->num_units_in_tick = 100;
+      seq_param->time_scale = ENCODER_FPS(encoder)*2*100;
+    }
+  }
+  return TRUE;
+}
+
+static gboolean
+ensure_packed_sps_data(
+    GstVaapiEncoderH264 *encoder,
+    VAEncSequenceParameterBufferH264 *seq_param
+)
+{
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  VAEncPackedHeaderParameterBuffer packed_header_param_buffer = { 0 };
+  VADisplay va_dpy = ENCODER_VA_DISPLAY(encoder);
+  VAContextID context_id = ENCODER_VA_CONTEXT(encoder);
+  guint32 length_in_bits;
+  guint8 *packed_seq_buffer = NULL;
+  H264Bitstream bitstream;
+  gboolean ret = TRUE;
+  VAStatus va_status = VA_STATUS_SUCCESS;
+
+  if (priv->sps_data) 
+    return TRUE;
+
+  h264_bitstream_init(&bitstream, 128*8);
+  h264_bitstream_write_uint(&bitstream, 0x00000001, 32); /* start code*/
+  h264_bitstream_write_nal_header(&bitstream, NAL_REF_IDC_HIGH, NAL_SPS);
+  h264_bitstream_write_sps(&bitstream, seq_param, encoder->profile);
+  ENCODER_ASSERT(BIT_STREAM_BIT_SIZE(&bitstream)%8 == 0);
+  length_in_bits = BIT_STREAM_BIT_SIZE(&bitstream);
+  packed_seq_buffer = BIT_STREAM_BUFFER(&bitstream);
+
+  /* set codec data sps */
+  priv->sps_data = gst_buffer_new_and_alloc((length_in_bits+7)/8);
+  GST_BUFFER_SIZE(priv->sps_data) = (length_in_bits+7)/8-4; /* start code size == 4*/
+  memcpy(GST_BUFFER_DATA(priv->sps_data),
+         packed_seq_buffer+4,
+         GST_BUFFER_SIZE(priv->sps_data));
+
+  packed_header_param_buffer.type = VAEncPackedHeaderSequence;
+  packed_header_param_buffer.bit_length = length_in_bits;
+  packed_header_param_buffer.has_emulation_bytes = 0;
+  va_status = vaCreateBuffer(va_dpy,
+                             context_id,
+                             VAEncPackedHeaderParameterBufferType,
+                             sizeof(packed_header_param_buffer), 1,
+                             &packed_header_param_buffer,
+                             &priv->packed_seq_param_id);
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+                       FALSE,
+                       "EncPackedSeqHeaderParameterBuffer failed");
+  va_status = vaCreateBuffer(va_dpy,
+                             context_id,
+                             VAEncPackedHeaderDataBufferType,
+                             (length_in_bits + 7) / 8, 1,
+                             packed_seq_buffer,
+                             &priv->packed_seq_data_id);
+  h264_bitstream_destroy(&bitstream, TRUE);
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+                       FALSE,
+                       "EncPackedSeqHeaderDataBuffer failed");
+end:
+    return ret;
+
+}
+
+static gboolean
+set_picture_parameters(
+    GstVaapiEncoderH264 *encoder,
+    VAEncPictureParameterBufferH264 *pic_param,
+    VABufferID coded_buf
+)
+{
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+
+  pic_param->pic_parameter_set_id = 0;
+  pic_param->seq_parameter_set_id = 0;
+  pic_param->last_picture = 0; /* means last encoding picture */
+  pic_param->frame_num = (priv->cur_slice_type == SLICE_TYPE_B ?
+                       (priv->cur_decode_num + 1) : priv->cur_decode_num);
+  //pic_param.coding_type = 0;
+  pic_param->pic_init_qp = encoder->init_qp;
+  pic_param->num_ref_idx_l0_active_minus1 = 0; /* only 1 reference */
+  pic_param->num_ref_idx_l1_active_minus1 = 0; /* B frames only have 1 backward and 1 forward reference*/
+  pic_param->chroma_qp_index_offset = 0;
+  pic_param->second_chroma_qp_index_offset = 0;
+
+  /* set picture fields */
+  pic_param->pic_fields.value = 0;
+  pic_param->pic_fields.bits.idr_pic_flag = (priv->cur_slice_type == SLICE_TYPE_I);
+  pic_param->pic_fields.bits.reference_pic_flag = (priv->cur_slice_type != SLICE_TYPE_B);
+  pic_param->pic_fields.bits.entropy_coding_mode_flag = ENTROPY_MODE_CABAC;
+  pic_param->pic_fields.bits.weighted_pred_flag = FALSE;
+  pic_param->pic_fields.bits.weighted_bipred_idc = 0;
+  pic_param->pic_fields.bits.constrained_intra_pred_flag = 0;
+  pic_param->pic_fields.bits.transform_8x8_mode_flag = TRUE; /* enable 8x8 */
+  pic_param->pic_fields.bits.deblocking_filter_control_present_flag = TRUE; /* enable debloking */
+  pic_param->pic_fields.bits.redundant_pic_cnt_present_flag = FALSE;
+  /* bottom_field_pic_order_in_frame_present_flag */
+  pic_param->pic_fields.bits.pic_order_present_flag = FALSE;
+  pic_param->pic_fields.bits.pic_scaling_matrix_present_flag = FALSE;
+
+  /* reference list,  */
+  pic_param->CurrPic.picture_id = GST_VAAPI_OBJECT_ID(priv->recon_surface);
+  pic_param->CurrPic.TopFieldOrderCnt = priv->cur_display_num * 2;   // ??? /**/
+  pic_param->ReferenceFrames[0].picture_id = GST_VAAPI_OBJECT_ID(priv->ref_surface1);
+  pic_param->ReferenceFrames[1].picture_id = GST_VAAPI_OBJECT_ID(priv->ref_surface2);
+  pic_param->ReferenceFrames[2].picture_id = VA_INVALID_ID;
+  pic_param->coded_buf = coded_buf;
+
+  ENCODER_LOG_INFO("type:%s, frame_num:%d, display_num:%d",
+    get_slice_type(priv->cur_slice_type),
+    pic_param->frame_num,
+    pic_param->CurrPic.TopFieldOrderCnt);
+  return TRUE;
+}
+
+static gboolean
+ensure_packed_pps_data(
+    GstVaapiEncoderH264 *encoder,
+    VAEncPictureParameterBufferH264 *pic_param
+)
+{
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  VAEncPackedHeaderParameterBuffer packed_header_param_buffer = { 0 };
+  H264Bitstream bitstream;
+  VADisplay va_dpy = ENCODER_VA_DISPLAY(encoder);
+  VAContextID context_id = ENCODER_VA_CONTEXT(encoder);
+  guint32 length_in_bits;
+  guint8 *packed_pic_buffer = NULL;
+  gboolean ret = TRUE;
+  VAStatus va_status = VA_STATUS_SUCCESS;
+
+  if (VA_INVALID_ID != priv->packed_pic_data_id)
+      return TRUE;
+
+  h264_bitstream_init(&bitstream, 128*8);
+  h264_bitstream_write_uint(&bitstream, 0x00000001, 32); /* start code*/
+  h264_bitstream_write_nal_header(&bitstream, NAL_REF_IDC_HIGH, NAL_PPS);
+  h264_bitstream_write_pps(&bitstream, pic_param);
+  ENCODER_ASSERT(BIT_STREAM_BIT_SIZE(&bitstream)%8 == 0);
+  length_in_bits = BIT_STREAM_BIT_SIZE(&bitstream);
+  packed_pic_buffer = BIT_STREAM_BUFFER(&bitstream);
+
+  /*set codec data pps*/
+  priv->pps_data = gst_buffer_new_and_alloc((length_in_bits+7)/8);
+  GST_BUFFER_SIZE(priv->pps_data) = (length_in_bits+7)/8-4;
+  memcpy(GST_BUFFER_DATA(priv->pps_data),
+         packed_pic_buffer+4,
+         GST_BUFFER_SIZE(priv->pps_data));
+
+  packed_header_param_buffer.type = VAEncPackedHeaderPicture;
+  packed_header_param_buffer.bit_length = length_in_bits;
+  packed_header_param_buffer.has_emulation_bytes = 0;
+
+  va_status = vaCreateBuffer(va_dpy,
+                             context_id,
+                             VAEncPackedHeaderParameterBufferType,
+                             sizeof(packed_header_param_buffer), 1,
+                             &packed_header_param_buffer,
+                             &priv->packed_pic_param_id);
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+                       FALSE,
+                       "EncPackedPicHeaderParameterBuffer failed");
+
+  va_status = vaCreateBuffer(va_dpy,
+                             context_id,
+                             VAEncPackedHeaderDataBufferType,
+                             (length_in_bits + 7) / 8, 1,
+                             packed_pic_buffer,
+                             &priv->packed_pic_data_id);
+  h264_bitstream_destroy(&bitstream, TRUE);
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+                       FALSE,
+                       "EncPackedPicHeaderDataBuffer failed");
+end:
+  return ret;
+}
+
+static gboolean
+set_slices_parameters(
+    GstVaapiEncoderH264 *encoder,
+    VAEncSliceParameterBufferH264 *slices,
+    guint slice_num
+)
+{
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  VAEncSliceParameterBufferH264 *slice_param;
+
+  guint width_in_mbs = (ENCODER_WIDTH(encoder)+15)/16;
+  int i = 0;
+  guint32 last_row_num = 0;
+  guint32 slice_mod_num = priv->slice_mod_mb_num;
+
+  for (i = 0; i < slice_num; ++i) {
+    int i_pic = 0;
+    slice_param = slices + i;
+
+    slice_param->macroblock_address = last_row_num*width_in_mbs;
+    slice_param->num_macroblocks = width_in_mbs*priv->default_slice_height;
+    last_row_num += priv->default_slice_height;
+    if (slice_mod_num) {
+      slice_param->num_macroblocks += width_in_mbs;
+      ++last_row_num;
+      --slice_mod_num;
+    }
+    slice_param->macroblock_info = VA_INVALID_ID;
+    slice_param->slice_type = priv->cur_slice_type;
+    slice_param->pic_parameter_set_id = 0;
+    slice_param->idr_pic_id = priv->idr_num;
+    slice_param->pic_order_cnt_lsb =
+        (priv->cur_display_num*2) % priv->max_pic_order_cnt;
+
+    /* not used if pic_order_cnt_type = 0 */
+    slice_param->delta_pic_order_cnt_bottom = 0;
+    memset(slice_param->delta_pic_order_cnt,
+           0,
+           sizeof(slice_param->delta_pic_order_cnt));
+
+    /*only works for B frames*/
+    slice_param->direct_spatial_mv_pred_flag = FALSE;
+    /* default equal to picture parameters */
+    slice_param->num_ref_idx_active_override_flag = FALSE;
+    slice_param->num_ref_idx_l0_active_minus1 = 0;
+    slice_param->num_ref_idx_l1_active_minus1 = 0;
+
+    slice_param->RefPicList0[0].picture_id =
+        GST_VAAPI_OBJECT_ID(priv->ref_surface1);
+    for (i_pic = 1;
+         i_pic < sizeof(slice_param->RefPicList0)/sizeof(slice_param->RefPicList0[0]);
+         i_pic++) {
+      slice_param->RefPicList0[i_pic].picture_id = VA_INVALID_ID;
+    }
+
+    if (SLICE_TYPE_B == priv->cur_slice_type) {
+      slice_param->RefPicList1[0].picture_id =
+          GST_VAAPI_OBJECT_ID(priv->ref_surface2);
+      i_pic = 1;
+    } else
+      i_pic = 0;
+    for (;
+         i_pic < sizeof(slice_param->RefPicList1)/sizeof(slice_param->RefPicList1[0]);
+         i_pic++)
+      slice_param->RefPicList1[i_pic].picture_id = VA_INVALID_ID;
+
+    /* not used if  pic_param.pic_fields.bits.weighted_pred_flag == FALSE */
+    slice_param->luma_log2_weight_denom = 0;
+    slice_param->chroma_log2_weight_denom = 0;
+    slice_param->luma_weight_l0_flag = FALSE;
+    memset(slice_param->luma_weight_l0, 0, sizeof(slice_param->luma_weight_l0));
+    memset(slice_param->luma_offset_l0, 0, sizeof(slice_param->luma_offset_l0));
+    slice_param->chroma_weight_l0_flag = FALSE;
+    memset(slice_param->chroma_weight_l0, 0, sizeof(slice_param->chroma_weight_l0));
+    memset(slice_param->chroma_offset_l0, 0, sizeof(slice_param->chroma_offset_l0));
+    slice_param->luma_weight_l1_flag = FALSE;
+    memset(slice_param->luma_weight_l1, 0, sizeof(slice_param->luma_weight_l1));
+    memset(slice_param->luma_offset_l1, 0, sizeof(slice_param->luma_offset_l1));
+    slice_param->chroma_weight_l1_flag = FALSE;
+    memset(slice_param->chroma_weight_l1, 0, sizeof(slice_param->chroma_weight_l1));
+    memset(slice_param->chroma_offset_l1, 0, sizeof(slice_param->chroma_offset_l1));
+
+    slice_param->cabac_init_idc = 0;
+    slice_param->slice_qp_delta = encoder->init_qp - encoder->min_qp;
+    if (slice_param->slice_qp_delta > 4)
+      slice_param->slice_qp_delta = 4;
+    slice_param->disable_deblocking_filter_idc = 0;
+    slice_param->slice_alpha_c0_offset_div2 = 2;
+    slice_param->slice_beta_offset_div2 = 2;
+
+  }
+  ENCODER_ASSERT(last_row_num == (ENCODER_HEIGHT(encoder)+15)/16);
+  return TRUE;
+}
+
+static gboolean
+h264_fill_hdr_buffer(GstVaapiEncoderH264 *encoder)
+{
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  VAEncMiscParameterBuffer *misc_param;
+  VAEncMiscParameterHRD *misc_hrd_param;
+  VADisplay va_dpy       = ENCODER_VA_DISPLAY(encoder);
+  VAContextID context_id = ENCODER_VA_CONTEXT(encoder);
+  gboolean ret = TRUE;
+  VAStatus va_status = VA_STATUS_SUCCESS;
+
+  if (VA_INVALID_ID != priv->misc_param_hdr_id) {
+    vaDestroyBuffer(va_dpy, priv->misc_param_hdr_id);
+    priv->misc_param_hdr_id = VA_INVALID_ID;
+  }
+
+  /*  hrd parameter */
+  va_status = vaCreateBuffer(
+      va_dpy,
+      context_id,
+      VAEncMiscParameterBufferType,
+      sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterRateControl),
+      1,
+      NULL,
+      &priv->misc_param_hdr_id);
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+                       FALSE,
+                       "vaCreateEncMiscParameterBuffer failed");
+
+  va_status = vaMapBuffer(va_dpy,
+                          priv->misc_param_hdr_id,
+                          (void **)&misc_param);
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+                       FALSE,
+                       "H264 HDR buffer map failed");
+  misc_param->type = VAEncMiscParameterTypeHRD;
+  misc_hrd_param = (VAEncMiscParameterHRD *)misc_param->data;
+
+  if (encoder->bitrate > 0) {
+      misc_hrd_param->initial_buffer_fullness = encoder->bitrate * 1024 * 4;
+      misc_hrd_param->buffer_size = encoder->bitrate * 1024 * 8;
+  } else {
+      misc_hrd_param->initial_buffer_fullness = 0;
+      misc_hrd_param->buffer_size = 0;
+  }
+
+  vaUnmapBuffer(va_dpy, priv->misc_param_hdr_id);
+
+end:
+  return ret;
+}
+#endif
+
+static gboolean
+h264_fill_sequence_buffer(GstVaapiEncoderH264 *encoder)
+{
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  VAEncSequenceParameterBufferH264 seq_param = { 0 };
+  VADisplay va_dpy       = ENCODER_VA_DISPLAY(encoder);
+  VAContextID context_id = ENCODER_VA_CONTEXT(encoder);
+  gboolean ret = TRUE;
+  VAStatus va_status = VA_STATUS_SUCCESS;
+
+  /* only once */
+  if (VA_INVALID_ID != priv->seq_param_id)
+    return TRUE;
+
+  set_sequence_parameters(encoder, &seq_param);
+  va_status = vaCreateBuffer(va_dpy, context_id,
+                             VAEncSequenceParameterBufferType,
+                             sizeof(seq_param), 1,
+                             &seq_param, &priv->seq_param_id);
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+                       FALSE,
+                       "alloc seq-buffer failed.");
+
+#if !HAVE_OLD_H264_ENCODER
+  ensure_packed_sps_data(encoder, &seq_param);
+#endif
+
+end:
+  return ret;
+}
+
+static gboolean
+h264_fill_picture_buffer(
+    GstVaapiEncoderH264 *encoder,
+    VABufferID coded_buf
+)
+{
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  VAEncPictureParameterBufferH264 pic_param;
+  VADisplay va_dpy = ENCODER_VA_DISPLAY(encoder);
+  VAContextID context_id = ENCODER_VA_CONTEXT(encoder);
+  gboolean ret = TRUE;
+  VAStatus va_status = VA_STATUS_SUCCESS;
+
+  VAAPI_UNUSED_ARG(va_status);
+  memset(&pic_param, 0, sizeof(pic_param));
+  set_picture_parameters(encoder, &pic_param, coded_buf);
+
+  if (VA_INVALID_ID != priv->pic_param_id) { /* share the same pic_param_id*/
+    vaDestroyBuffer(va_dpy, priv->pic_param_id);
+    priv->pic_param_id = VA_INVALID_ID;
+  }
+  va_status = vaCreateBuffer(va_dpy,
+                             context_id,
+                             VAEncPictureParameterBufferType,
+                             sizeof(pic_param), 1,
+                             &pic_param,
+                             &priv->pic_param_id);
+
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+                       FALSE,
+                       "creating pic-param buffer failed.");
+#if !HAVE_OLD_H264_ENCODER
+  ensure_packed_pps_data(encoder, &pic_param);
+#endif
+
+end:
+  return ret;
+}
+
+static gboolean
+h264_fill_slice_buffers(
+    GstVaapiEncoderH264 *encoder
+)
+{
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  VADisplay va_dpy       = ENCODER_VA_DISPLAY(encoder);
+  VAContextID context_id = ENCODER_VA_CONTEXT(encoder);
+  gboolean ret = TRUE;
+  VAStatus va_status = VA_STATUS_SUCCESS;
+
+  memset(priv->slice_param_buffers,
+         0,
+         encoder->slice_num * sizeof(priv->slice_param_buffers[0]));
+  set_slices_parameters(encoder,
+                        priv->slice_param_buffers,
+                        encoder->slice_num);
+
+  if (VA_INVALID_ID != priv->slice_param_id) {
+    vaDestroyBuffer(va_dpy, priv->slice_param_id);
+    priv->slice_param_id = VA_INVALID_ID;
+  }
+  va_status = vaCreateBuffer(va_dpy,
+                             context_id,
+                             VAEncSliceParameterBufferType,
+                             sizeof(priv->slice_param_buffers[0]),
+                             encoder->slice_num,
+                             priv->slice_param_buffers,
+                             &priv->slice_param_id);
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+                       FALSE,
+                       "creating slice-parameters buffer failed.");
+
+end:
+  return ret;
+}
+
+static EncoderStatus
+gst_vaapi_encoder_h264_rendering(
+    GstVaapiBaseEncoder *base,
+    GstVaapiSurface *surface,
+    guint frame_index,
+    VABufferID coded_buf,
+    gboolean *is_key
+)
+{
+  EncoderStatus ret = ENCODER_NO_ERROR;
+  GstVaapiEncoderH264 *encoder = GST_VAAPI_ENCODER_H264_CAST(base);
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  GstVaapiContext *context = ENCODER_CONTEXT(base);
+  VABufferID va_buffers[64];
+  guint32    va_buffers_count = 0;
+  gboolean is_params_ok = TRUE;
+
+  ENCODER_ASSERT(context);
+
+  *is_key = (priv->cur_slice_type == SLICE_TYPE_I);
+
+  if (!priv->ref_surface1) {
+    priv->ref_surface1 = gst_vaapi_context_get_surface(context);
+    ENCODER_CHECK_STATUS(priv->ref_surface1,
+                         ENCODER_SURFACE_ERR,
+                         "reference surface, h264_pop_free_surface failed.");
+  }
+  if (!priv->ref_surface2) {
+    priv->ref_surface2 = gst_vaapi_context_get_surface(context);
+    ENCODER_CHECK_STATUS(priv->ref_surface2,
+                         ENCODER_SURFACE_ERR,
+                         "reference surface, h264_pop_free_surface failed.");
+  }
+  if (!priv->recon_surface) {
+    priv->recon_surface = gst_vaapi_context_get_surface(context);
+    ENCODER_CHECK_STATUS(priv->recon_surface,
+                         ENCODER_SURFACE_ERR,
+                         "reconstructed surface, h264_pop_free_surface failed.");
+  }
+
+  if (SLICE_TYPE_P == priv->cur_slice_type) {
+    h264_swap_surface(&priv->ref_surface1, &priv->ref_surface2);
+  }
+
+  /* fill sequence parameters, need set every time */
+  is_params_ok = h264_fill_sequence_buffer(encoder);
+  ENCODER_CHECK_STATUS(is_params_ok,
+                       ENCODER_PARAMETER_ERR,
+                       "h264_recreate_seq_param failed");
+  /* set pic_parameters*/
+  is_params_ok = h264_fill_picture_buffer(encoder, coded_buf);
+  ENCODER_CHECK_STATUS(is_params_ok,
+                       ENCODER_PARAMETER_ERR,
+                       "h264_recreate_pic_param failed");
+
+#if !HAVE_OLD_H264_ENCODER
+  /* set misc_hdr_parameters*/
+  is_params_ok = h264_fill_hdr_buffer(encoder);
+  ENCODER_CHECK_STATUS(is_params_ok,
+                       ENCODER_PARAMETER_ERR,
+                       "h264_fill_hdr__param failed");
+#endif
+
+  /* set slice parameters, support multiple slices */
+  is_params_ok = h264_fill_slice_buffers(encoder);
+  ENCODER_CHECK_STATUS(is_params_ok,
+                       ENCODER_PARAMETER_ERR,
+                       "h264_recreate_slice_param failed");
+
+  /*render all buffers*/
+  if (VA_INVALID_ID != priv->seq_param_id) {
+  #if HAVE_OLD_H264_ENCODER
+    if (!priv->is_seq_param_set) {
+      priv->is_seq_param_set = TRUE;
+      va_buffers[va_buffers_count++] = priv->seq_param_id;
+    }
+  #else
+    va_buffers[va_buffers_count++] = priv->seq_param_id;
+  #endif
+  }
+  if (VA_INVALID_ID != priv->pic_param_id) {
+    va_buffers[va_buffers_count++] = priv->pic_param_id;
+  }
+  if (VA_INVALID_ID != priv->misc_param_hdr_id) {
+    va_buffers[va_buffers_count++] = priv->misc_param_hdr_id;
+  }
+  if (VA_INVALID_ID != priv->slice_param_id) {
+    va_buffers[va_buffers_count++] = priv->slice_param_id;
+  }
+  if (SLICE_TYPE_I == priv->cur_slice_type) {
+    if (VA_INVALID_ID != priv->packed_seq_param_id) {
+      va_buffers[va_buffers_count++] = priv->packed_seq_param_id;
+    }
+    if (VA_INVALID_ID != priv->packed_seq_data_id) {
+      va_buffers[va_buffers_count++] = priv->packed_seq_data_id;
+    }
+    if (VA_INVALID_ID != priv->packed_pic_param_id) {
+      va_buffers[va_buffers_count++] = priv->packed_pic_param_id;
+    }
+    if (VA_INVALID_ID != priv->packed_pic_data_id) {
+      va_buffers[va_buffers_count++] = priv->packed_pic_data_id;
+    }
+  }
+  ret = gst_vaapi_encoder_render_picture(GST_VAAPI_ENCODER_CAST(encoder),
+                                         surface,
+                                         va_buffers,
+                                         va_buffers_count);
+  ENCODER_CHECK_STATUS(ret == ENCODER_NO_ERROR,
+                       ENCODER_PICTURE_ERR,
+                       "vaRenderH264Picture failed.");
+
+  /*after finished,  swap  recon and surface2*/
+  if (SLICE_TYPE_P == priv->cur_slice_type ||
+      SLICE_TYPE_I == priv->cur_slice_type) {
+    h264_swap_surface(&priv->recon_surface, &priv->ref_surface2);
+  }
+
+  end:
+  return ret;
+}
+
+static const guint8 *
+h264_next_nal(const guint8 *buffer, guint32 len, guint32 *nal_size)
+{
+    const guint8 *cur = buffer;
+    const guint8 *end = buffer + len;
+    const guint8 *nal_start = NULL;
+    guint32 flag = 0xFFFFFFFF;
+    guint32 nal_start_len = 0;
+
+    ENCODER_ASSERT(len >= 0 && buffer && nal_size);
+    if (len < 3) {
+        *nal_size = len;
+        nal_start = (len ? buffer : NULL);
+        return nal_start;
+    }
+
+    /*locate head postion*/
+    if (!buffer[0] && !buffer[1]) {
+        if (buffer[2] == 1) { // 0x000001
+            nal_start_len = 3;
+        } else if (!buffer[2] && len >=4 && buffer[3] == 1) { //0x00000001
+            nal_start_len = 4;
+        }
+    }
+    nal_start = buffer + nal_start_len;
+    cur = nal_start;
+
+    /*find next nal start position*/
+    while (cur < end) {
+        flag = ((flag<<8) | ((*cur++)&0xFF));
+        if ((flag&0x00FFFFFF) == 0x00000001) {
+            if (flag == 0x00000001)
+                *nal_size = cur - 4 - nal_start;
+            else
+                *nal_size = cur - 3 - nal_start;
+            break;
+        }
+    }
+    if (cur >= end) {
+      *nal_size = end - nal_start;
+      if (nal_start >= end) {
+        nal_start = NULL;
+      }
+    }
+    return nal_start;
+}
+
+static GstBuffer *
+gst_vaapi_encoder_h264_wrap_buffer(
+    GstVaapiBaseEncoder *base,
+    GstBuffer *buf
+)
+{
+  GstVaapiEncoderH264 *encoder = GST_VAAPI_ENCODER_H264_CAST(base);
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  GstBuffer *ret_buffer;
+  guint32   nal_size;
+  const guint8   *nal_start;
+  guint8  *frame_end;
+  H264Bitstream bitstream;
+
+  if (!priv->avc_flag) {
+    gst_buffer_ref(buf);
+    return buf;
+  }
+
+  ret_buffer = gst_buffer_new();
+  ENCODER_ASSERT(ret_buffer);
+  h264_bitstream_init(&bitstream, (GST_BUFFER_SIZE(buf)+32)*8);
+  h264_bitstream_align(&bitstream, 0);
+  ENCODER_ASSERT(bitstream.bit_size == 0);
+
+
+  frame_end = GST_BUFFER_DATA(buf) + GST_BUFFER_SIZE(buf);
+  nal_start = GST_BUFFER_DATA(buf);
+  nal_size = 0;
+  while(NULL !=
+        (nal_start = h264_next_nal(nal_start, frame_end-nal_start, &nal_size))
+       ) {
+    ENCODER_ASSERT(nal_size);
+    if (!nal_size) {
+      nal_start += nal_size;
+      continue;
+    }
+    h264_bitstream_write_uint(&bitstream, nal_size, 32);
+    h264_bitstream_write_byte_array(&bitstream, nal_start, nal_size);
+    nal_start += nal_size;
+  }
+  h264_bitstream_align(&bitstream, 0);
+
+  GST_BUFFER_MALLOCDATA(ret_buffer) =
+        GST_BUFFER_DATA(ret_buffer) = BIT_STREAM_BUFFER(&bitstream);
+  GST_BUFFER_SIZE(ret_buffer) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
+  h264_bitstream_destroy(&bitstream, FALSE);
+
+  return ret_buffer;
+}
+
+static EncoderStatus
+read_sps_pps(GstVaapiEncoderH264Private *priv, const guint8 *buf, guint32 size)
+{
+  const guint8 *end = buf + size;
+  const guint8 *nal_start = buf;
+  guint32 nal_size = 0;
+  guint8 nal_type;
+  GstBuffer *sps = NULL, *pps = NULL;
+
+  while((!sps || !pps) &&
+        (nal_start = h264_next_nal(nal_start, end-nal_start, &nal_size)) != NULL
+       ) {
+    if (!nal_size) {
+      nal_start += nal_size;
+      continue;
+    }
+
+    nal_type = (*nal_start)&0x1F;
+    switch (nal_type) {
+      case NAL_SPS: {
+        sps = gst_buffer_new_and_alloc(nal_size);
+        memcpy(GST_BUFFER_DATA(sps), nal_start, nal_size);
+        gst_buffer_replace(&priv->sps_data, sps);
+        gst_buffer_unref(sps); /*don't set to NULL*/
+        break;
+      }
+
+      case NAL_PPS: {
+        pps = gst_buffer_new_and_alloc(nal_size);
+        memcpy(GST_BUFFER_DATA(pps), nal_start, nal_size);
+        gst_buffer_replace(&priv->pps_data, pps);
+        gst_buffer_unref(pps);
+        break;
+      }
+
+      default:
+        break;
+    }
+    nal_start += nal_size;
+  }
+
+  if (!sps || !pps) {
+    return ENCODER_DATA_NOT_READY;
+  }
+
+  return ENCODER_NO_ERROR;
+}
+
+static void
+gst_vaapi_encoder_h264_notify_frame(
+    GstVaapiBaseEncoder *base,
+    guint8 *buf,
+    guint32 size
+)
+{
+  GstVaapiEncoderH264 *encoder = GST_VAAPI_ENCODER_H264_CAST(base);
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  if (!priv->sps_data || !priv->pps_data) {
+    read_sps_pps(priv, buf, size);
+  }
+  if (priv->sps_data && priv->pps_data) {
+    gst_vaapi_base_encoder_set_frame_notify(base, FALSE);
+  }
+}
+
+static gboolean
+read_sps_attributes(
+    const guint8 *sps_data,
+    guint32 sps_size,
+    guint32 *profile_idc,
+    guint32 *profile_comp,
+    guint32 *level_idc
+)
+{
+  ENCODER_ASSERT(profile_idc && profile_comp && level_idc);
+  ENCODER_ASSERT(sps_size >= 4);
+  if (sps_size < 4) {
+    return FALSE;
+  }
+  /*skip sps_data[0], nal_type*/
+  *profile_idc = sps_data[1];
+  *profile_comp = sps_data[2];
+  *level_idc = sps_data[3];
+  return TRUE;
+}
+
+static EncoderStatus
+gst_vaapi_encoder_h264_flush(
+    GstVaapiEncoder* base
+)
+{
+  GstVaapiEncoderH264* encoder = GST_VAAPI_ENCODER_H264_CAST(base);
+  EncoderStatus ret = ENCODER_NO_ERROR;
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+
+  //priv->frame_count = 0;
+  priv->cur_display_num = 0;
+  priv->cur_decode_num = 0;
+  priv->cur_slice_type = SLICE_TYPE_I;
+  priv->gop_count = g_queue_get_length(priv->queued_buffers);
+  //gst_vaapi_base_encoder_set_frame_notify((GST_VAAPI_BASE_ENCODER)encoder, TRUE);
+
+  //end:
+  return ret;
+}
+
+static EncoderStatus
+gst_vaapi_encoder_h264_get_avcC_codec_data(
+    GstVaapiEncoderH264 *encoder,
+    GstBuffer **buffer
+)
+{
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+  GstBuffer *avc_codec;
+  const guint32 configuration_version = 0x01;
+  const guint32 length_size_minus_one = 0x03;
+  guint32 profile, profile_comp, level_idc;
+
+  ENCODER_ASSERT(buffer);
+  if (!priv->sps_data || !priv->pps_data) {
+    return ENCODER_DATA_NOT_READY;
+  }
+
+  if (FALSE == read_sps_attributes(GST_BUFFER_DATA(priv->sps_data),
+                                   GST_BUFFER_SIZE(priv->sps_data),
+                                   &profile, &profile_comp, &level_idc))
+  {
+    ENCODER_ASSERT(0);
+    return ENCODER_DATA_ERR;
+  }
+
+  H264Bitstream bitstream;
+  h264_bitstream_init(&bitstream,
+                      (GST_BUFFER_SIZE(priv->sps_data) +
+                       GST_BUFFER_SIZE(priv->pps_data) + 32)*8);
+
+  /*codec_data*/
+  h264_bitstream_write_uint(&bitstream, configuration_version, 8);
+  h264_bitstream_write_uint(&bitstream, profile, 8);
+  h264_bitstream_write_uint(&bitstream, profile_comp, 8);
+  h264_bitstream_write_uint(&bitstream, level_idc, 8);
+  h264_bitstream_write_uint(&bitstream, h264_bit_mask[6], 6); /*111111*/
+  h264_bitstream_write_uint(&bitstream, length_size_minus_one, 2);
+  h264_bitstream_write_uint(&bitstream, h264_bit_mask[3], 3); /*111*/
+
+  /*write sps*/
+  h264_bitstream_write_uint(&bitstream, 1, 5);   /* sps count = 1*/
+  ENCODER_ASSERT( BIT_STREAM_BIT_SIZE(&bitstream)%8 == 0);
+  h264_bitstream_write_uint(&bitstream, GST_BUFFER_SIZE(priv->sps_data), 16);
+  h264_bitstream_write_byte_array(&bitstream,
+                                  GST_BUFFER_DATA(priv->sps_data),
+                                  GST_BUFFER_SIZE(priv->sps_data));
+
+  /*write pps*/
+  h264_bitstream_write_uint(&bitstream, 1, 8); /*pps count = 1*/
+  h264_bitstream_write_uint(&bitstream, GST_BUFFER_SIZE(priv->pps_data), 16);
+  h264_bitstream_write_byte_array(&bitstream,
+                                  GST_BUFFER_DATA(priv->pps_data),
+                                  GST_BUFFER_SIZE(priv->pps_data));
+
+  avc_codec = gst_buffer_new();
+  GST_BUFFER_MALLOCDATA(avc_codec) =
+         GST_BUFFER_DATA(avc_codec) =
+         BIT_STREAM_BUFFER(&bitstream);
+  GST_BUFFER_SIZE(avc_codec) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
+  h264_bitstream_destroy(&bitstream, FALSE);
+  *buffer = avc_codec;
+
+  return ENCODER_NO_ERROR;
+}
+
+static EncoderStatus
+gst_vaapi_encoder_h264_get_codec_data(
+    GstVaapiEncoder* base,
+    GstBuffer **buffer)
+{
+  GstVaapiEncoderH264 *encoder = GST_VAAPI_ENCODER_H264_CAST(base);
+  GstVaapiEncoderH264Private *priv = encoder->priv;
+
+  if (priv->avc_flag)
+    return gst_vaapi_encoder_h264_get_avcC_codec_data(encoder, buffer);
+  return ENCODER_NO_DATA;
+}
+
+static void
+gst_vaapi_encoder_h264_init(GstVaapiEncoderH264 *encoder)
+{
+  GstVaapiEncoderH264Private *priv = GST_VAAPI_ENCODER_H264_GET_PRIVATE(encoder);
+  ENCODER_ASSERT(priv);
+  priv->public = encoder;
+  encoder->priv = priv;
+
+  /* init public attributes */
+  gst_vaapi_encoder_h264_init_public_values(encoder);
+  gst_vaapi_base_encoder_set_frame_notify(GST_VAAPI_BASE_ENCODER(encoder), TRUE);
+
+  /* init private values*/
+  priv->format = GST_MAKE_FOURCC('N','V','1','2');
+  priv->avc_flag = FALSE;
+
+  priv->ref_surface1 = NULL;
+  priv->ref_surface2 = NULL;
+  priv->recon_surface = NULL;
+
+  priv->seq_param_id = VA_INVALID_ID;
+  priv->pic_param_id = VA_INVALID_ID;
+  priv->slice_param_id = VA_INVALID_ID;
+  priv->misc_param_hdr_id = VA_INVALID_ID;
+  priv->packed_seq_param_id = VA_INVALID_ID;
+  priv->packed_seq_data_id = VA_INVALID_ID;
+  priv->packed_pic_param_id = VA_INVALID_ID;
+  priv->packed_pic_data_id = VA_INVALID_ID;
+  priv->is_seq_param_set = FALSE;
+  priv->slice_param_buffers = NULL;
+  priv->default_slice_height = 0;
+  priv->slice_mod_mb_num = 0;
+
+  priv->sps_data = NULL;
+  priv->pps_data = NULL;
+
+  priv->queued_buffers = g_queue_new();
+  priv->gop_count = 0;
+  priv->cur_display_num = 0;
+  priv->cur_decode_num = 0;
+  priv->cur_slice_type = SLICE_TYPE_I;
+  priv->last_decode_time = 0LL;
+  priv->default_cts_offset = 0;
+
+  priv->max_frame_num = 0;
+  priv->max_pic_order_cnt = 0;
+  priv->idr_num = 0;
+}
+
+static void
+gst_vaapi_encoder_h264_finalize(GObject *object)
+{
+  /*free private buffers*/
+  GstVaapiEncoder *encoder = GST_VAAPI_ENCODER(object);
+  GstVaapiEncoderH264Private *priv = GST_VAAPI_ENCODER_H264_GET_PRIVATE(object);
+
+  if (gst_vaapi_encoder_get_state(encoder) != VAAPI_ENC_NULL) {
+    gst_vaapi_encoder_uninitialize(encoder);
+  }
+
+  if (priv->sps_data) {
+    gst_buffer_unref(priv->sps_data);
+    priv->sps_data = NULL;
+  }
+  if (priv->pps_data) {
+    gst_buffer_unref(priv->pps_data);
+    priv->pps_data = NULL;
+  }
+  if (priv->slice_param_buffers) {
+    g_free(priv->slice_param_buffers);
+    priv->slice_param_buffers = NULL;
+  }
+
+  if (priv->queued_buffers) {
+    ENCODER_ASSERT(g_queue_is_empty(priv->queued_buffers));
+    g_queue_free(priv->queued_buffers);
+    priv->queued_buffers = NULL;
+  }
+
+  G_OBJECT_CLASS(gst_vaapi_encoder_h264_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_encoder_h264_class_init(GstVaapiEncoderH264Class *klass)
+{
+  GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+  GstVaapiEncoderClass * const encoder_class = GST_VAAPI_ENCODER_CLASS(klass);
+  GstVaapiBaseEncoderClass * const base_class = GST_VAAPI_BASE_ENCODER_CLASS(klass);
+
+  g_type_class_add_private(klass, sizeof(GstVaapiEncoderH264Private));
+
+  GST_DEBUG_CATEGORY_INIT (gst_vaapi_h264_encoder_debug,
+                           "gst_va_h264_encoder",
+                           0,
+                           "gst_va_h264_encoder element");
+
+  object_class->finalize = gst_vaapi_encoder_h264_finalize;
+
+  base_class->validate_attributes = gst_vaapi_encoder_h264_validate_attributes;
+  base_class->pre_alloc_resource  = gst_vaapi_encoder_h264_alloc_slices;
+  base_class->release_resource    = gst_vaapi_encoder_h264_release_resource;
+  base_class->prepare_next_input_buffer =
+      gst_vaapi_encoder_h264_prepare_next_buffer;
+  base_class->render_frame = gst_vaapi_encoder_h264_rendering;
+  base_class->notify_buffer = gst_vaapi_encoder_h264_notify_frame;
+  base_class->wrap_buffer = gst_vaapi_encoder_h264_wrap_buffer;
+  base_class->encode_frame_failed = gst_vaapi_encoder_h264_frame_failed;
+
+  encoder_class->flush = gst_vaapi_encoder_h264_flush;
+  encoder_class->get_codec_data = gst_vaapi_encoder_h264_get_codec_data;
+}
+
+static void
+h264_bitstream_init(H264Bitstream *bitstream, guint32 bit_capability)
+{
+  bitstream->bit_size = 0;
+  bitstream->buffer = NULL;
+  bitstream->max_bit_capability = 0;
+  if (bit_capability) {
+    h264_bitstream_auto_grow(bitstream, bit_capability);
+  }
+}
+
+static gboolean
+h264_bitstream_write_uint(
+    H264Bitstream *bitstream,
+    guint32 value,
+    guint32 bit_size
+)
+{
+  gboolean ret = TRUE;
+  guint32 byte_pos, bit_offset;
+  guint8  *cur_byte;
+  guint32 fill_bits;
+
+  if(!bit_size) {
+    return TRUE;
+  }
+
+  VAAPI_UNUSED_ARG(ret);
+  ENCODER_CHECK_STATUS(h264_bitstream_auto_grow(bitstream, bit_size),
+                       FALSE,
+                       "h264_bitstream_auto_grow failed.");
+  byte_pos = (bitstream->bit_size>>3);
+  bit_offset = (bitstream->bit_size&0x07);
+  cur_byte = bitstream->buffer + byte_pos;
+  ENCODER_ASSERT(bit_offset < 8 &&
+                 bitstream->bit_size <= bitstream->max_bit_capability);
+
+  while (bit_size) {
+    fill_bits = ((8-bit_offset) < bit_size ? (8-bit_offset) : bit_size);
+    bit_size -= fill_bits;
+    bitstream->bit_size += fill_bits;
+
+    *cur_byte |=
+        ((value>>bit_size) & h264_bit_mask[fill_bits])<<(8-bit_offset-fill_bits);
+    ++cur_byte;
+    bit_offset = 0;
+  }
+  ENCODER_ASSERT(cur_byte <=
+                 (bitstream->buffer + bitstream->max_bit_capability/8));
+
+  end:
+  return ret;
+}
+
+static gboolean
+h264_bitstream_align(H264Bitstream *bitstream, guint32 value)
+{
+  guint32 bit_offset, bit_left;
+
+  bit_offset = (bitstream->bit_size&0x07);
+  if (!bit_offset) {
+    return TRUE;
+  }
+  bit_left = 8 - bit_offset;
+  if (value) value = h264_bit_mask[bit_left];
+  return h264_bitstream_write_uint(bitstream, value, bit_left);
+}
+
+
+static gboolean
+h264_bitstream_write_byte_array(
+    H264Bitstream *bitstream,
+    const guint8 *buf,
+    guint32 byte_size
+)
+{
+  gboolean ret = TRUE;
+  if (!byte_size) {
+    return 0;
+  }
+
+  VAAPI_UNUSED_ARG(ret);
+  ENCODER_CHECK_STATUS(h264_bitstream_auto_grow(bitstream, byte_size<<3),
+                       FALSE,
+                       "h264_bitstream_auto_grow failed.");
+  if (0 == (bitstream->bit_size&0x07)) {
+    memcpy(&bitstream->buffer[bitstream->bit_size>>3], buf, byte_size);
+    bitstream->bit_size += (byte_size<<3);
+  } else {
+    ENCODER_ASSERT(0);
+    while(byte_size) {
+      h264_bitstream_write_uint(bitstream, *buf, 8);
+      --byte_size;
+      ++buf;
+    }
+  }
+
+end:
+  return ret;
+}
+
+static gboolean
+h264_bitstream_write_ue(H264Bitstream *bitstream, guint32 value)
+{
+  gboolean ret = TRUE;
+  guint32  size_in_bits = 0;
+  guint32  tmp_value = ++value;
+  while (tmp_value) {
+    ++size_in_bits;
+    tmp_value >>= 1;
+  }
+  ENCODER_CHECK_STATUS(h264_bitstream_write_uint(bitstream, 0, size_in_bits-1),
+                       FALSE,
+                       "h264_bitstream_write_ue failed.");
+  ENCODER_CHECK_STATUS(h264_bitstream_write_uint(bitstream, value, size_in_bits),
+                       FALSE,
+                       "h264_bitstream_write_ue failed.");
+
+end:
+  return ret;
+}
+
+static gboolean
+h264_bitstream_write_se(H264Bitstream *bitstream, gint32 value)
+{
+  gboolean ret = TRUE;
+  guint32 new_val;
+
+  if (value <= 0) {
+    new_val = -(value<<1);
+  } else {
+    new_val = (value<<1) - 1;
+  }
+
+  ENCODER_CHECK_STATUS(h264_bitstream_write_ue(bitstream, new_val),
+                       FALSE,
+                       "h264_bitstream_write_se failed.");
+
+end:
+  return ret;
+}
+
+static gboolean
+h264_bitstream_write_trailing_bits(H264Bitstream *bitstream)
+{
+    h264_bitstream_write_uint(bitstream, 1, 1);
+    h264_bitstream_align(bitstream, 0);
+    return TRUE;
+}
+
+static void
+h264_bitstream_destroy(H264Bitstream *bitstream, gboolean free_flag)
+{
+  if (bitstream->buffer && free_flag) {
+    free (bitstream->buffer);
+  }
+  bitstream->buffer = NULL;
+  bitstream->bit_size = 0;
+  bitstream->max_bit_capability = 0;
+}
+
+static gboolean
+h264_bitstream_auto_grow(H264Bitstream *bitstream, guint32 extra_bit_size)
+{
+  guint32 new_bit_size = extra_bit_size + bitstream->bit_size;
+  guint32 clear_pos;
+
+  ENCODER_ASSERT(bitstream->bit_size <= bitstream->max_bit_capability);
+  if (new_bit_size <= bitstream->max_bit_capability) {
+    return TRUE;
+  }
+
+  new_bit_size = ((new_bit_size + H264_BITSTREAM_ALLOC_ALIGN_MASK)
+                &(~H264_BITSTREAM_ALLOC_ALIGN_MASK));
+  ENCODER_ASSERT(new_bit_size%(H264_BITSTREAM_ALLOC_ALIGN_MASK+1) == 0);
+  clear_pos = ((bitstream->bit_size+7)>>3);
+  bitstream->buffer = realloc(bitstream->buffer, new_bit_size>>3);
+  memset(bitstream->buffer+clear_pos, 0, (new_bit_size>>3)-clear_pos);
+  bitstream->max_bit_capability = new_bit_size;
+  return TRUE;
+}
+
+static gboolean
+h264_bitstream_write_nal_header(
+    H264Bitstream *bitstream,
+    guint nal_ref_idc,
+    guint nal_unit_type
+)
+{
+  h264_bitstream_write_uint(bitstream, 0, 1);
+  h264_bitstream_write_uint(bitstream, nal_ref_idc, 2);
+  h264_bitstream_write_uint(bitstream, nal_unit_type, 5);
+  return TRUE;
+}
+
+#if !HAVE_OLD_H264_ENCODER
+
+static gboolean
+h264_bitstream_write_sps(
+    H264Bitstream *bitstream,
+    VAEncSequenceParameterBufferH264 *seq,
+    H264_Profile profile
+)
+{
+  guint32 constraint_set0_flag, constraint_set1_flag;
+  guint32 constraint_set2_flag, constraint_set3_flag;
+  guint32 gaps_in_frame_num_value_allowed_flag = 0; // ??
+  gboolean nal_hrd_parameters_present_flag;
+
+  guint32 b_qpprime_y_zero_transform_bypass = 0;
+  guint32 residual_color_transform_flag = 0;
+  guint32 pic_height_in_map_units =
+    (seq->seq_fields.bits.frame_mbs_only_flag ?
+     seq->picture_height_in_mbs :
+     seq->picture_height_in_mbs/2);
+  guint32 mb_adaptive_frame_field = !seq->seq_fields.bits.frame_mbs_only_flag;
+  guint32 i = 0;
+
+  constraint_set0_flag = profile == H264_PROFILE_BASELINE;
+  constraint_set1_flag = profile <= H264_PROFILE_MAIN;
+  constraint_set2_flag = 0;
+  constraint_set3_flag = 0;
+
+  /* profile_idc */
+  h264_bitstream_write_uint(bitstream, profile, 8);
+  /* constraint_set0_flag */
+  h264_bitstream_write_uint(bitstream, constraint_set0_flag, 1);
+  /* constraint_set1_flag */
+  h264_bitstream_write_uint(bitstream, constraint_set1_flag, 1);
+  /* constraint_set2_flag */
+  h264_bitstream_write_uint(bitstream, constraint_set2_flag, 1);
+  /* constraint_set3_flag */
+  h264_bitstream_write_uint(bitstream, constraint_set3_flag, 1);
+  /* reserved_zero_4bits */
+  h264_bitstream_write_uint(bitstream, 0, 4);
+  /* level_idc */
+  h264_bitstream_write_uint(bitstream, seq->level_idc, 8);
+  /* seq_parameter_set_id */
+  h264_bitstream_write_ue(bitstream, seq->seq_parameter_set_id);
+
+  if (profile >= H264_PROFILE_HIGH) {
+    /* for high profile */
+    ENCODER_ASSERT(0);
+    /* chroma_format_idc  = 1, 4:2:0*/
+    h264_bitstream_write_ue(bitstream, seq->seq_fields.bits.chroma_format_idc);
+    if (3 == seq->seq_fields.bits.chroma_format_idc) {
+      h264_bitstream_write_uint(bitstream, residual_color_transform_flag, 1);
+    }
+    /* bit_depth_luma_minus8 */
+    h264_bitstream_write_ue(bitstream, seq->bit_depth_luma_minus8);
+    /* bit_depth_chroma_minus8 */
+    h264_bitstream_write_ue(bitstream, seq->bit_depth_chroma_minus8);
+    /* b_qpprime_y_zero_transform_bypass */
+    h264_bitstream_write_uint(bitstream, b_qpprime_y_zero_transform_bypass, 1);
+    ENCODER_ASSERT(seq->seq_fields.bits.seq_scaling_matrix_present_flag == 0);
+    /*seq_scaling_matrix_present_flag  */
+    h264_bitstream_write_uint(bitstream,
+                              seq->seq_fields.bits.seq_scaling_matrix_present_flag,
+                              1);
+
+    #if 0
+    if (seq->seq_fields.bits.seq_scaling_matrix_present_flag) {
+      for (i = 0; i < (seq->seq_fields.bits.chroma_format_idc != 3 ? 8 : 12); i++) {
+        h264_bitstream_write_uint(bitstream, seq->seq_fields.bits.seq_scaling_list_present_flag, 1);
+        if (seq->seq_fields.bits.seq_scaling_list_present_flag) {
+          ENCODER_ASSERT(0);
+          /* FIXME, need write scaling list if seq_scaling_matrix_present_flag ==1*/
+        }
+      }
+    }
+    #endif
+  }
+
+  /* log2_max_frame_num_minus4 */
+  h264_bitstream_write_ue(bitstream,
+                          seq->seq_fields.bits.log2_max_frame_num_minus4);
+  /* pic_order_cnt_type */
+  h264_bitstream_write_ue(bitstream, seq->seq_fields.bits.pic_order_cnt_type);
+
+  if (seq->seq_fields.bits.pic_order_cnt_type == 0) {
+    /* log2_max_pic_order_cnt_lsb_minus4 */
+    h264_bitstream_write_ue(bitstream,
+                            seq->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4);
+  } else if (seq->seq_fields.bits.pic_order_cnt_type == 1) {
+    ENCODER_ASSERT(0);
+    h264_bitstream_write_uint(bitstream,
+                              seq->seq_fields.bits.delta_pic_order_always_zero_flag,
+                              1);
+    h264_bitstream_write_se(bitstream, seq->offset_for_non_ref_pic);
+    h264_bitstream_write_se(bitstream,
+                            seq->offset_for_top_to_bottom_field);
+    h264_bitstream_write_ue(bitstream,
+                            seq->num_ref_frames_in_pic_order_cnt_cycle);
+    for ( i = 0; i < seq->num_ref_frames_in_pic_order_cnt_cycle; i++) {
+      h264_bitstream_write_se(bitstream, seq->offset_for_ref_frame[i]);
+    }
+  }
+
+  /* num_ref_frames */
+  h264_bitstream_write_ue(bitstream, seq->max_num_ref_frames);
+  /* gaps_in_frame_num_value_allowed_flag */
+  h264_bitstream_write_uint(bitstream,
+                            gaps_in_frame_num_value_allowed_flag,
+                            1);
+
+  /* pic_width_in_mbs_minus1 */
+  h264_bitstream_write_ue(bitstream, seq->picture_width_in_mbs - 1);
+  /* pic_height_in_map_units_minus1 */
+  h264_bitstream_write_ue(bitstream, pic_height_in_map_units - 1);
+  /* frame_mbs_only_flag */
+  h264_bitstream_write_uint(bitstream,
+                            seq->seq_fields.bits.frame_mbs_only_flag,
+                            1);
+
+  if (!seq->seq_fields.bits.frame_mbs_only_flag) { //ONLY mbs
+      ENCODER_ASSERT(0);
+      h264_bitstream_write_uint(bitstream, mb_adaptive_frame_field, 1);
+  }
+
+  /* direct_8x8_inference_flag */
+  h264_bitstream_write_uint(bitstream, 0, 1);
+  /* frame_cropping_flag */
+  h264_bitstream_write_uint(bitstream, seq->frame_cropping_flag, 1);
+
+  if (seq->frame_cropping_flag) {
+      /* frame_crop_left_offset */
+      h264_bitstream_write_ue(bitstream, seq->frame_crop_left_offset);
+      /* frame_crop_right_offset */
+      h264_bitstream_write_ue(bitstream, seq->frame_crop_right_offset);
+      /* frame_crop_top_offset */
+      h264_bitstream_write_ue(bitstream, seq->frame_crop_top_offset);
+      /* frame_crop_bottom_offset */
+      h264_bitstream_write_ue(bitstream, seq->frame_crop_bottom_offset);
+  }
+
+  /* vui_parameters_present_flag */
+  h264_bitstream_write_uint(bitstream, seq->vui_parameters_present_flag, 1);
+  if (seq->vui_parameters_present_flag) {
+    /* aspect_ratio_info_present_flag */
+    h264_bitstream_write_uint(bitstream,
+                              seq->vui_fields.bits.aspect_ratio_info_present_flag,
+                              1);
+    if (seq->vui_fields.bits.aspect_ratio_info_present_flag) {
+      h264_bitstream_write_uint(bitstream, seq->aspect_ratio_idc, 8);
+      if (seq->aspect_ratio_idc == 0xFF) {
+        h264_bitstream_write_uint(bitstream, seq->sar_width, 16);
+        h264_bitstream_write_uint(bitstream, seq->sar_height, 16);
+      }
+    }
+
+    /* overscan_info_present_flag */
+    h264_bitstream_write_uint(bitstream, 0, 1);
+    /* video_signal_type_present_flag */
+    h264_bitstream_write_uint(bitstream, 0, 1);
+    /* chroma_loc_info_present_flag */
+    h264_bitstream_write_uint(bitstream, 0, 1);
+
+    /* timing_info_present_flag */
+    h264_bitstream_write_uint(bitstream,
+                              seq->vui_fields.bits.timing_info_present_flag,
+                              1);
+    if (seq->vui_fields.bits.timing_info_present_flag) {
+      h264_bitstream_write_uint(bitstream, seq->num_units_in_tick, 32);
+      h264_bitstream_write_uint(bitstream, seq->time_scale, 32);
+      h264_bitstream_write_uint(bitstream, 1, 1); /* fixed_frame_rate_flag */
+    }
+
+    nal_hrd_parameters_present_flag = (seq->bits_per_second > 0 ? TRUE : FALSE);
+    /* nal_hrd_parameters_present_flag */
+    h264_bitstream_write_uint(bitstream, nal_hrd_parameters_present_flag, 1);
+    if (nal_hrd_parameters_present_flag) {
+      /* hrd_parameters */
+      /* cpb_cnt_minus1 */
+      h264_bitstream_write_ue(bitstream, 0);
+      h264_bitstream_write_uint(bitstream, 4, 4); /* bit_rate_scale */
+      h264_bitstream_write_uint(bitstream, 6, 4); /* cpb_size_scale */
+
+      for (i = 0; i < 1; ++i) {
+        /* bit_rate_value_minus1[0] */
+        h264_bitstream_write_ue(bitstream, seq->bits_per_second/1024- 1);
+        /* cpb_size_value_minus1[0] */
+        h264_bitstream_write_ue(bitstream, seq->bits_per_second/1024*8 - 1);
+        /* cbr_flag[0] */
+        h264_bitstream_write_uint(bitstream, 1, 1);
+      }
+      /* initial_cpb_removal_delay_length_minus1 */
+      h264_bitstream_write_uint(bitstream, 23, 5);
+      /* cpb_removal_delay_length_minus1 */
+      h264_bitstream_write_uint(bitstream, 23, 5);
+      /* dpb_output_delay_length_minus1 */
+      h264_bitstream_write_uint(bitstream, 23, 5);
+      /* time_offset_length  */
+      h264_bitstream_write_uint(bitstream, 23, 5);
+    }
+    /* vcl_hrd_parameters_present_flag */
+    h264_bitstream_write_uint(bitstream, 0, 1);
+    if (nal_hrd_parameters_present_flag || 0/*vcl_hrd_parameters_present_flag*/) {
+      /* low_delay_hrd_flag */
+      h264_bitstream_write_uint(bitstream, 0, 1);
+    }
+    /* pic_struct_present_flag */
+    h264_bitstream_write_uint(bitstream, 0, 1);
+    /* bitstream_restriction_flag */
+    h264_bitstream_write_uint(bitstream, 0, 1);
+  }
+  /* rbsp_trailing_bits */
+  h264_bitstream_write_trailing_bits(bitstream);
+  return TRUE;
+}
+
+static gboolean
+h264_bitstream_write_pps(
+    H264Bitstream *bitstream,
+    VAEncPictureParameterBufferH264 *pic
+)
+{
+  guint32 num_slice_groups_minus1 = 0;
+  guint32 pic_init_qs_minus26 = 0;
+  guint32 redundant_pic_cnt_present_flag = 0;
+
+  /* pic_parameter_set_id */
+  h264_bitstream_write_ue(bitstream, pic->pic_parameter_set_id);
+  /* seq_parameter_set_id */
+  h264_bitstream_write_ue(bitstream, pic->seq_parameter_set_id);
+  /* entropy_coding_mode_flag */
+  h264_bitstream_write_uint(bitstream,
+                            pic->pic_fields.bits.entropy_coding_mode_flag,
+                            1);
+  /* pic_order_present_flag */
+  h264_bitstream_write_uint(bitstream,
+                            pic->pic_fields.bits.pic_order_present_flag,
+                            1);
+  /*slice_groups-1*/
+  h264_bitstream_write_ue(bitstream, num_slice_groups_minus1);
+
+  if (num_slice_groups_minus1 > 0) {
+    /*FIXME*/
+    ENCODER_ASSERT(0);
+  }
+  h264_bitstream_write_ue(bitstream, pic->num_ref_idx_l0_active_minus1);
+  h264_bitstream_write_ue(bitstream, pic->num_ref_idx_l1_active_minus1);
+  h264_bitstream_write_uint(bitstream,
+                            pic->pic_fields.bits.weighted_pred_flag,
+                            1);
+  h264_bitstream_write_uint(bitstream,
+                            pic->pic_fields.bits.weighted_bipred_idc,
+                            2);
+  /* pic_init_qp_minus26 */
+  h264_bitstream_write_se(bitstream, pic->pic_init_qp-26);
+  /* pic_init_qs_minus26 */
+  h264_bitstream_write_se(bitstream, pic_init_qs_minus26);
+  /*chroma_qp_index_offset*/
+  h264_bitstream_write_se(bitstream, pic->chroma_qp_index_offset);
+
+  h264_bitstream_write_uint(bitstream,
+                            pic->pic_fields.bits.deblocking_filter_control_present_flag,
+                            1);
+  h264_bitstream_write_uint(bitstream,
+                            pic->pic_fields.bits.constrained_intra_pred_flag,
+                            1);
+  h264_bitstream_write_uint(bitstream, redundant_pic_cnt_present_flag, 1);
+
+  /*more_rbsp_data*/
+  h264_bitstream_write_uint(bitstream,
+                            pic->pic_fields.bits.transform_8x8_mode_flag,
+                            1);
+  h264_bitstream_write_uint(bitstream,
+                            pic->pic_fields.bits.pic_scaling_matrix_present_flag,
+                            1);
+  if (pic->pic_fields.bits.pic_scaling_matrix_present_flag) {
+    ENCODER_ASSERT(0);
+    /* FIXME */
+    /*
+    for (i = 0; i <
+      (6+(-( (chroma_format_idc ! = 3) ? 2 : 6) * -pic->pic_fields.bits.transform_8x8_mode_flag));
+      i++) {
+      h264_bitstream_write_uint(bitstream, pic->pic_fields.bits.pic_scaling_list_present_flag, 1);
+    }
+    */
+  }
+
+  h264_bitstream_write_se(bitstream, pic->second_chroma_qp_index_offset);
+  h264_bitstream_write_trailing_bits(bitstream);
+  return TRUE;
+}
+#endif
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_h264.h b/gst-libs/gst/vaapi/gstvaapiencoder_h264.h
new file mode 100644 (file)
index 0000000..2de9769
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ *  gstvaapiencoder_h264.h -  H.264 encoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_ENCODER_H264_H
+#define GST_VAAPI_ENCODER_H264_H
+
+#include "gst/vaapi/gstvaapisurfacepool.h"
+#include "gst/vaapi/gstvaapibaseencoder.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GstVaapiEncoderH264              GstVaapiEncoderH264;
+typedef struct _GstVaapiEncoderH264Private       GstVaapiEncoderH264Private;
+typedef struct _GstVaapiEncoderH264Class         GstVaapiEncoderH264Class;
+
+#define GST_TYPE_VAAPI_ENCODER_H264 \
+    (gst_vaapi_encoder_h264_get_type())
+
+#define GST_IS_VAAPI_ENCODER_H264(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_ENCODER_H264))
+
+#define GST_IS_VAAPI_ENCODER_H264_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VAAPI_ENCODER_H264))
+
+#define GST_VAAPI_ENCODER_H264_GET_CLASS(obj)                  \
+    (G_TYPE_INSTANCE_GET_CLASS ((obj),                         \
+                                GST_TYPE_VAAPI_ENCODER_H264,   \
+                                GstVaapiEncoderH264Class))
+
+#define GST_VAAPI_ENCODER_H264(obj)                            \
+    (G_TYPE_CHECK_INSTANCE_CAST ((obj),                        \
+                                 GST_TYPE_VAAPI_ENCODER_H264,  \
+                                 GstVaapiEncoderH264))
+
+#define GST_VAAPI_ENCODER_H264_CLASS(klass)                    \
+    (G_TYPE_CHECK_CLASS_CAST ((klass),                         \
+                              GST_TYPE_VAAPI_ENCODER_H264,     \
+                              GstVaapiEncoderH264Class))
+
+#define GST_VAAPI_ENCODER_H264_GET_PRIVATE(obj)                \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                        \
+                                 GST_TYPE_VAAPI_ENCODER_H264,  \
+                                 GstVaapiEncoderH264Private))
+
+typedef enum {
+  H264_PROFILE_BASELINE = 66,
+  H264_PROFILE_MAIN     = 77,
+  H264_PROFILE_EXTENDED = 88,
+  H264_PROFILE_HIGH    = 100,
+  H264_PROFILE_HIGH10  = 110,
+  H264_PROFILE_HIGH422 = 122,
+  H264_PROFILE_HIGH444 = 144,
+  H264_PROFILE_HIGH444_PREDICTIVE = 244,
+} H264_Profile;
+
+typedef enum {
+  H264_LEVEL_10 = 10,  /* QCIF format, < 380160 samples/sec */
+  H264_LEVEL_11 = 11,  /* CIF format,   < 768000 samples/sec */
+  H264_LEVEL_12 = 12,  /* CIF format,   < 1536000  samples/sec */
+  H264_LEVEL_13 = 13,  /* CIF format,   < 3041280  samples/sec */
+  H264_LEVEL_20 = 20,  /* CIF format,   < 3041280  samples/sec */
+  H264_LEVEL_21 = 21,  /* HHR format,  < 5068800  samples/sec */
+  H264_LEVEL_22 = 22,  /* SD/4CIF format,     < 5184000      samples/sec */
+  H264_LEVEL_30 = 30,  /* SD/4CIF format,     < 10368000    samples/sec */
+  H264_LEVEL_31 = 31,  /* 720pHD format,      < 27648000    samples/sec */
+  H264_LEVEL_32 = 32,  /* SXGA  format,         < 55296000    samples/sec */
+  H264_LEVEL_40 = 40,  /* 2Kx1K format,         < 62914560    samples/sec */
+  H264_LEVEL_41 = 41,  /* 2Kx1K format,         < 62914560    samples/sec */
+  H264_LEVEL_42 = 42,  /* 2Kx1K format,         < 125829120  samples/sec */
+  H264_LEVEL_50 = 50,  /* 3672x1536 format,  < 150994944  samples/sec */
+  H264_LEVEL_51 = 51,  /* 4096x2304 format,  < 251658240  samples/sec */
+} H264_Level;
+
+#define H264_DEFAULT_PROFILE      H264_PROFILE_BASELINE
+#define H264_DEFAULT_LEVEL        H264_LEVEL_30
+#define H264_DEFAULT_INIT_QP      26
+#define H264_DEFAULT_MIN_QP       1
+#define H264_DEFAULT_INTRA_PERIOD 30
+#define H264_DEFAULT_FPS          30
+#define H264_DEFAULT_SLICE_NUM    1
+
+struct _GstVaapiEncoderH264 {
+  GstVaapiBaseEncoder parent;   /*based on gobject*/
+
+  GstVaapiEncoderH264Private *priv;
+
+  guint32         profile;
+  guint32         level;
+  guint32         bitrate;  /*kbps*/
+  guint32         intra_period;
+  guint32         init_qp;  /*default 24*/
+  guint32         min_qp;   /*default 1*/
+  guint32         slice_num;
+  guint32         b_frame_num;
+};
+
+struct _GstVaapiEncoderH264Class {
+    GstVaapiBaseEncoderClass parent_class;
+};
+
+
+GType
+gst_vaapi_encoder_h264_get_type(void);
+
+GstVaapiEncoderH264 *
+gst_vaapi_encoder_h264_new(void);
+
+static inline void
+gst_vaapi_encoder_h264_unref (GstVaapiEncoderH264 * encoder)
+{
+  g_object_unref (encoder);
+}
+
+void
+gst_vaapi_encoder_h264_set_avc_flag(
+    GstVaapiEncoderH264* encoder,
+    gboolean avc
+);
+
+gboolean
+gst_vaapi_encoder_h264_get_avc_flag(GstVaapiEncoderH264* encoder);
+
+G_END_DECLS
+
+#endif /*GST_VAAPI_ENCODER_H264_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_mpeg4.c b/gst-libs/gst/vaapi/gstvaapiencoder_mpeg4.c
new file mode 100644 (file)
index 0000000..70e08d7
--- /dev/null
@@ -0,0 +1,523 @@
+/*
+ *  gstvaapiencoder_mpeg4.c - MPEG-4 encoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "gstvaapiencoder_mpeg4.h"
+
+#include <string.h>
+#include "gst/gstclock.h"
+
+#include "gstvaapiobject.h"
+#include "gstvaapiobject_priv.h"
+#include "gstvaapicontext.h"
+#include "gstvaapisurface.h"
+#include "gstvaapivideobuffer.h"
+#include "gstvaapidisplay_priv.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_vaapi_mpeg4_encoder_debug);
+#define GST_CAT_DEFAULT gst_vaapi_mpeg4_encoder_debug
+
+#define GST_VAAPI_ENCODER_MPEG4_CAST(encoder)    ((GstVaapiEncoderMpeg4 *)(encoder))
+
+#define VISUAL_OBJECT_SEQUENCE_START_CODE  0x000001B0
+#define VISUAL_OBJECT_SEQUENCE_END_CODE    0x000001B1
+#define VISUAL_OBJECT_START_CODE           0x000001B5
+#define VIDEO_OBJECT_PLANE_START_CODE      0x000001B6
+/* Video Object Start Code range */
+#define VIDEO_OBJECT_START_CODE_MIN        0x00000100
+#define VIDEO_OBJECT_START_CODE_MAX        0x0000011F
+/* Video Object Layer Start Code range 0x00000120 ~ 0x0000012F*/
+#define VIDEO_OBJECT_LAYER_START_CODE      0x00000120
+#define VIDEO_OBJECT_LAYER_START_CODE_MASK 0xFFFFFFF0
+
+
+struct _GstVaapiEncoderMpeg4Private {
+  GstVaapiSurface  *ref_surface;  /* reference buffer*/
+  GstVaapiSurface  *recon_surface; /* reconstruct buffer*/
+
+  VABufferID        seq_param_id;
+  VABufferID        pic_param_id;
+  VABufferID        slice_param_id;
+
+  GstBuffer        *codec_data;
+};
+
+G_DEFINE_TYPE(GstVaapiEncoderMpeg4, gst_vaapi_encoder_mpeg4, GST_TYPE_VAAPI_BASE_ENCODER)
+
+GstVaapiEncoderMpeg4 *
+gst_vaapi_encoder_mpeg4_new(void)
+{
+  return GST_VAAPI_ENCODER_MPEG4_CAST(
+             g_object_new(GST_TYPE_VAAPI_ENCODER_MPEG4, NULL));
+}
+
+gboolean
+gst_vaapi_encoder_mpeg4_validate_attributes(
+    GstVaapiBaseEncoder *base
+)
+{
+  GstVaapiEncoderMpeg4 *encoder = GST_VAAPI_ENCODER_MPEG4_CAST(base);
+
+  if (!ENCODER_WIDTH(encoder) ||
+      !ENCODER_HEIGHT(encoder) ||
+      !ENCODER_FPS(encoder)) {
+    return FALSE;
+  }
+  if (VAProfileMPEG4Simple != encoder->profile &&
+      VAProfileMPEG4AdvancedSimple != encoder->profile) {
+    return FALSE;
+  }
+  gst_vaapi_base_encoder_set_va_profile(base, encoder->profile);
+
+  if (!encoder->intra_period) {
+    encoder->intra_period = MPEG4_DEFAULT_INTRA_PERIOD;
+  }
+  if (-1 == encoder->init_qp) {
+    encoder->init_qp = MPEG4_DEFAULT_INIT_QP;
+  }
+  if (-1 == encoder->min_qp) {
+    encoder->min_qp = MPEG4_DEFAULT_MIN_QP;
+  }
+
+  /* default compress ratio 1: (4*8*1.5) */
+  if (!encoder->bitrate) {
+    encoder->bitrate =
+        ENCODER_WIDTH(encoder)*ENCODER_HEIGHT(encoder)*ENCODER_FPS(encoder)/4/1024;
+  }
+  return TRUE;
+
+}
+
+static void
+mpeg4_release_parameters(
+    GstVaapiEncoderMpeg4 *encoder
+)
+{
+  GstVaapiEncoderMpeg4Private *priv = encoder->priv;
+  VADisplay va_dpy = ENCODER_DISPLAY(encoder);
+  VAStatus va_status = VA_STATUS_SUCCESS;
+
+  VAAPI_UNUSED_ARG(va_status);
+
+  if (VA_INVALID_ID != priv->seq_param_id) {
+    va_status = vaDestroyBuffer(va_dpy, priv->seq_param_id);
+    priv->seq_param_id = VA_INVALID_ID;
+  }
+  if (VA_INVALID_ID != priv->pic_param_id) {
+    va_status = vaDestroyBuffer(va_dpy, priv->pic_param_id);
+    priv->pic_param_id = VA_INVALID_ID;
+  }
+  if (VA_INVALID_ID != priv->slice_param_id) {
+    va_status = vaDestroyBuffer(va_dpy, priv->slice_param_id);
+    priv->slice_param_id = VA_INVALID_ID;
+  }
+}
+
+static gboolean
+gst_vaapi_encoder_mpeg4_release_resource(
+    GstVaapiBaseEncoder* base
+)
+{
+  GstVaapiEncoderMpeg4 *encoder = GST_VAAPI_ENCODER_MPEG4_CAST(base);
+  GstVaapiEncoderMpeg4Private *priv = encoder->priv;
+  GstVaapiContext *context = ENCODER_CONTEXT(base);
+
+  mpeg4_release_parameters(encoder);
+
+  /*remove ref_surface*/
+  if (priv->ref_surface) {
+    if (context) {
+      gst_vaapi_context_put_surface(context, priv->ref_surface);
+    } else {
+      g_object_unref(priv->ref_surface);
+    }
+    priv->ref_surface = NULL;
+  }
+
+  /*remove recon_surface*/
+  if (priv->recon_surface) {
+    if (context) {
+      gst_vaapi_context_put_surface(context, priv->recon_surface);
+    } else {
+      g_object_unref(priv->recon_surface);
+    }
+    priv->recon_surface = NULL;
+  }
+
+  if (priv->codec_data) {
+    gst_buffer_unref(priv->codec_data);
+    priv->codec_data = NULL;
+  }
+
+  return TRUE;
+}
+
+static guint32
+mpeg4_get_profile_level_indication(guint32 profile)
+{
+  switch(profile) {
+  case VAProfileMPEG4Simple:
+    return MPEG4_DEFAULT_SIMPLE_PROFILE_AND_LEVEL;
+  case VAProfileMPEG4AdvancedSimple:
+    return MPEG4_DEFAULT_ADVANCED_SIMPLE_PROFILE_AND_LEVEL;
+  default:
+    return 0;
+  }
+  return 0;
+}
+
+static EncoderStatus
+gst_vaapi_encoder_mpeg4_rendering(
+    GstVaapiBaseEncoder *base,
+    GstVaapiSurface *surface,
+    guint frame_index,
+    VABufferID coded_buf,
+    gboolean *is_key
+)
+{
+  GstVaapiEncoderMpeg4 *encoder = GST_VAAPI_ENCODER_MPEG4_CAST(base);
+  GstVaapiEncoderMpeg4Private *priv = encoder->priv;
+  GstVaapiContext *context = ENCODER_CONTEXT(base);
+  VADisplay va_dpy = ENCODER_VA_DISPLAY(encoder);
+  VAContextID context_id = ENCODER_VA_CONTEXT(encoder);
+  VABufferID va_buffers[64];
+  guint32    va_buffers_count = 0;
+
+  VAStatus va_status = VA_STATUS_SUCCESS;
+  EncoderStatus ret = ENCODER_NO_ERROR;
+
+  *is_key = (frame_index % encoder->intra_period == 0);
+
+  /* initialize sequence parameter set, only first time */
+  if (VA_INVALID_ID == priv->seq_param_id) { /*only the first time*/
+    VAEncSequenceParameterBufferMPEG4 seq_param = {0};
+
+    seq_param.profile_and_level_indication =
+        mpeg4_get_profile_level_indication(encoder->profile);
+    seq_param.intra_period = encoder->intra_period;
+    seq_param.video_object_layer_width = ENCODER_WIDTH(encoder);
+    seq_param.video_object_layer_height = ENCODER_HEIGHT(encoder);
+    seq_param.vop_time_increment_resolution = ENCODER_FPS(encoder);
+    seq_param.fixed_vop_rate = MPEG4_DEFAULT_FIXED_VOP_RATE;
+    if (seq_param.fixed_vop_rate) {
+      seq_param.fixed_vop_time_increment = 1;
+    }
+    seq_param.bits_per_second = encoder->bitrate * 1024;
+    seq_param.frame_rate = ENCODER_FPS(encoder);
+    seq_param.initial_qp = encoder->init_qp;
+    seq_param.min_qp = encoder->min_qp; //mpeg4_encoder->min_qp;
+
+    va_status = vaCreateBuffer(va_dpy, context_id,
+                               VAEncSequenceParameterBufferType,
+                               sizeof(seq_param), 1,
+                               &seq_param,
+                               &priv->seq_param_id);
+    ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+                         ENCODER_ENC_RES_ERR,
+                         "mpeg4 alloc seq-buffer failed.");
+    va_buffers[va_buffers_count++] = priv->seq_param_id;
+  }
+
+  /* set reference and reconstructed surfaces */
+  if (!priv->ref_surface) {
+    priv->ref_surface = gst_vaapi_context_get_surface(context);
+    ENCODER_CHECK_STATUS(priv->ref_surface,
+                         ENCODER_SURFACE_ERR,
+                         "mpeg4 reference surface, mpeg4_pop_free_surface failed.");
+  }
+  if (!priv->recon_surface) {
+    priv->recon_surface = gst_vaapi_context_get_surface(context);
+    ENCODER_CHECK_STATUS(priv->recon_surface,
+                         ENCODER_SURFACE_ERR,
+                         "mpeg4 reconstructed surface, mpeg4_pop_free_surface failed.");
+  }
+
+  /* initialize picture, every time, every frame */
+  VAEncPictureParameterBufferMPEG4 pic_param = {0};
+  pic_param.reference_picture = GST_VAAPI_OBJECT_ID(priv->ref_surface);
+  pic_param.reconstructed_picture = GST_VAAPI_OBJECT_ID(priv->recon_surface);
+  pic_param.coded_buf = coded_buf;
+  pic_param.picture_width = ENCODER_WIDTH(encoder);
+  pic_param.picture_height = ENCODER_HEIGHT(encoder);
+  if (0 == frame_index) {
+    pic_param.modulo_time_base = 0;
+  } else {
+    pic_param.modulo_time_base =
+        ((frame_index%ENCODER_FPS(encoder)) == 0 ? 1 : 0);
+  }
+  pic_param.vop_time_increment = 301%ENCODER_FPS(encoder);
+  pic_param.picture_type =
+    (*is_key ? VAEncPictureTypeIntra : VAEncPictureTypePredictive);
+
+  if (VA_INVALID_ID != priv->pic_param_id) { /* destroy first*/
+    va_status = vaDestroyBuffer(va_dpy, priv->pic_param_id);
+    priv->pic_param_id = VA_INVALID_ID;
+  }
+
+  va_status = vaCreateBuffer(va_dpy,
+                             context_id,
+                             VAEncPictureParameterBufferType,
+                             sizeof(pic_param), 1,
+                             &pic_param,
+                             &priv->pic_param_id);
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status,
+                       ENCODER_ENC_RES_ERR,
+                       "mpeg4 creating pic-param buffer failed.");
+
+  va_buffers[va_buffers_count++] = priv->pic_param_id;
+
+  /*initialize slice parameters, only ONE slice for mpeg4*/
+  VAEncSliceParameterBuffer slice_param = { 0 };
+  slice_param.start_row_number = 0;
+  slice_param.slice_height = (ENCODER_HEIGHT(encoder)+15)/16; /*MB?*/
+  slice_param.slice_flags.bits.is_intra = *is_key;
+  slice_param.slice_flags.bits.disable_deblocking_filter_idc = 0;
+  if (VA_INVALID_ID != priv->slice_param_id) {
+    vaDestroyBuffer(va_dpy, priv->slice_param_id);
+    priv->slice_param_id = VA_INVALID_ID;
+  }
+
+  va_status = vaCreateBuffer(va_dpy,
+                             context_id,
+                             VAEncSliceParameterBufferType,
+                             sizeof(slice_param),
+                             1,
+                             &slice_param,
+                             &priv->slice_param_id);
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+                       ENCODER_ENC_RES_ERR,
+                       "mpeg4 creating slice-parameters buffer failed.");
+
+  va_buffers[va_buffers_count++] = priv->slice_param_id;
+
+  ret = gst_vaapi_encoder_render_picture(GST_VAAPI_ENCODER_CAST(encoder),
+                                         surface,
+                                         va_buffers,
+                                         va_buffers_count);
+  ENCODER_CHECK_STATUS(ret == ENCODER_NO_ERROR,
+                       ENCODER_PICTURE_ERR,
+                       "mpeg4 rendering slice-parameters buffer failed.");
+
+  /*swap ref_surface and recon_surface */
+  GstVaapiSurface *swap = priv->ref_surface;
+  priv->ref_surface = priv->recon_surface;
+  priv->recon_surface = swap;
+
+end:
+  return ret;
+}
+
+#if 0
+static GstBuffer *
+gst_vaapi_encoder_mpeg4_copy_coded_buffer(GstVaapiBaseEncoder *encoder,
+            guint8 *frame, guint32 frame_size, VABufferID *coded_buf)
+
+{
+   /*process data*/
+  GstBuffer* buffer = gst_buffer_new_and_alloc(frame_size);
+  memcpy(GST_BUFFER_DATA(buffer), frame, frame_size);
+
+  #if 0
+  GstVaapiEncoderMpeg4 *mpeg4_encoder = GST_VAAPI_ENCODER_MPEG4_CAST(encoder);
+  if (mpeg4_encoder->profile == VAProfileMPEG4AdvancedSimple) {
+    guint8 *start_code = GST_BUFFER_DATA(buffer)+16; /*fix old issue of ASP in mrst platform*/
+    if (start_code[0] == 0x01 && start_code[1] == 0x20
+        && start_code[-1] == 0x00 && start_code[-2] == 0x00)
+    {
+      start_code[2] = 0x08;
+    }
+  }
+  #endif
+
+  return buffer;
+}
+#endif
+
+static gboolean
+find_video_object_configuration_info(
+    const guint8 *in_buffer,
+    guint32 in_size,
+    const guint8 **out_buffer,
+    guint32 *out_size
+)
+{
+  guint32 value = 0x00;
+  const guint8 *end = in_buffer + in_size;
+
+  while(in_buffer < end) {
+    value = ((value<<8)|(*in_buffer));
+    if (VISUAL_OBJECT_SEQUENCE_START_CODE == value) {
+      *out_buffer = in_buffer - 3;
+      ++in_buffer;
+      break;
+    }
+    ++in_buffer;
+  }
+  if (in_buffer >= end)
+    return FALSE;
+
+  while(in_buffer < end) {
+    value = ((value<<8)|(*in_buffer));
+    if (VIDEO_OBJECT_PLANE_START_CODE == value) {
+      *out_size = (in_buffer - 3 - *out_buffer);
+      return TRUE;
+    }
+    ++in_buffer;
+  }
+  return FALSE;
+}
+
+static gboolean
+mpeg4_encoder_generate_codec_data(
+    const guint8 *in_buffer,
+    guint32 in_size,
+    GstBuffer **out_buffer
+)
+{
+  const guint8 *codec_buffer = NULL;
+  guint32 codec_size = 0;
+  guint8 *visual_obj_seq_end = NULL;
+
+  if (!find_video_object_configuration_info(in_buffer,
+                                            in_size,
+                                            &codec_buffer,
+                                            &codec_size)
+     ) {
+    return FALSE;
+  }
+  ENCODER_ASSERT(codec_size);
+  *out_buffer = gst_buffer_new_and_alloc(codec_size+4);
+  memcpy(GST_BUFFER_DATA(*out_buffer), codec_buffer, codec_size);
+  visual_obj_seq_end = GST_BUFFER_DATA(*out_buffer) + codec_size;
+  visual_obj_seq_end[0] = (VISUAL_OBJECT_SEQUENCE_END_CODE>>24);
+  visual_obj_seq_end[1] = (VISUAL_OBJECT_SEQUENCE_END_CODE>>16);
+  visual_obj_seq_end[2] = (VISUAL_OBJECT_SEQUENCE_END_CODE>>8);
+  visual_obj_seq_end[3] = (guint8)VISUAL_OBJECT_SEQUENCE_END_CODE;
+  return TRUE;
+}
+
+static void
+gst_vaapi_encoder_mpeg4_notify_frame(
+    GstVaapiBaseEncoder *base,
+    guint8 *buf,
+    guint32 size
+)
+{
+  GstVaapiEncoderMpeg4 *encoder = GST_VAAPI_ENCODER_MPEG4_CAST(base);
+  GstVaapiEncoderMpeg4Private *priv = encoder->priv;
+  if (!priv->codec_data) {
+    if (!mpeg4_encoder_generate_codec_data(buf, size, &priv->codec_data)) {
+      ENCODER_LOG_ERROR("mpeg4 encoder coded data error,"
+                        "please check <mpeg4_encoder_generate_codec_data>.");
+    }
+  }
+  if (priv->codec_data) {
+    gst_vaapi_base_encoder_set_frame_notify(base, FALSE);
+  }
+}
+
+static EncoderStatus
+gst_vaapi_encoder_mpeg4_flush(
+    GstVaapiEncoder* base
+)
+{
+  GstVaapiEncoderMpeg4 *encoder = GST_VAAPI_ENCODER_MPEG4_CAST(base);
+
+  mpeg4_release_parameters(encoder);
+  return ENCODER_NO_ERROR;
+}
+
+static EncoderStatus
+gst_vaapi_encoder_mpeg4_get_codec_data(
+    GstVaapiEncoder *base,
+    GstBuffer **buffer
+)
+{
+  GstVaapiEncoderMpeg4 *encoder = GST_VAAPI_ENCODER_MPEG4_CAST(base);
+  GstVaapiEncoderMpeg4Private *priv = encoder->priv;
+
+  if (!priv->codec_data)
+    return ENCODER_DATA_NOT_READY;
+  *buffer = gst_buffer_ref(priv->codec_data);
+  return ENCODER_NO_ERROR;
+}
+
+static void
+gst_vaapi_encoder_mpeg4_init(GstVaapiEncoderMpeg4 *encoder)
+{
+  GstVaapiEncoderMpeg4Private *priv = GST_VAAPI_ENCODER_MPEG4_GET_PRIVATE(encoder);
+  ENCODER_ASSERT(priv);
+  encoder->priv = priv;
+
+  /* init public */
+  encoder->profile = VAProfileMPEG4Simple;
+  encoder->bitrate = 0;
+  encoder->intra_period = MPEG4_DEFAULT_INTRA_PERIOD;
+  encoder->init_qp = MPEG4_DEFAULT_INIT_QP;
+  encoder->min_qp = MPEG4_DEFAULT_MIN_QP;
+
+  gst_vaapi_base_encoder_set_frame_notify(GST_VAAPI_BASE_ENCODER(encoder), TRUE);
+  /* init private */
+  priv->ref_surface = NULL;
+  priv->recon_surface = NULL;
+
+  priv->seq_param_id = VA_INVALID_ID;
+  priv->pic_param_id = VA_INVALID_ID;
+  priv->slice_param_id = VA_INVALID_ID;
+
+  priv->codec_data = NULL;
+}
+
+static void
+gst_vaapi_encoder_mpeg4_finalize(GObject *object)
+{
+  /*free private buffers*/
+  GstVaapiEncoder *encoder = GST_VAAPI_ENCODER(object);
+
+  if (gst_vaapi_encoder_get_state(encoder) != VAAPI_ENC_NULL) {
+    gst_vaapi_encoder_uninitialize(encoder);
+  }
+  G_OBJECT_CLASS(gst_vaapi_encoder_mpeg4_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_encoder_mpeg4_class_init(GstVaapiEncoderMpeg4Class *klass)
+{
+  GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+  GstVaapiEncoderClass * const encoder_class = GST_VAAPI_ENCODER_CLASS(klass);
+  GstVaapiBaseEncoderClass * const base_class = GST_VAAPI_BASE_ENCODER_CLASS(klass);
+
+  g_type_class_add_private(klass, sizeof(GstVaapiEncoderMpeg4Private));
+
+  GST_DEBUG_CATEGORY_INIT (gst_vaapi_mpeg4_encoder_debug, "gst_va_mpeg4_encoder", 0,
+      "gst_va_mpeg4_encoder element");
+
+  object_class->finalize = gst_vaapi_encoder_mpeg4_finalize;
+
+  base_class->validate_attributes = gst_vaapi_encoder_mpeg4_validate_attributes;
+  base_class->pre_alloc_resource  = NULL;
+  base_class->release_resource    = gst_vaapi_encoder_mpeg4_release_resource;
+  base_class->render_frame = gst_vaapi_encoder_mpeg4_rendering;
+  base_class->notify_buffer = gst_vaapi_encoder_mpeg4_notify_frame;
+  base_class->wrap_buffer = NULL;
+
+  encoder_class->flush = gst_vaapi_encoder_mpeg4_flush;
+  encoder_class->get_codec_data = gst_vaapi_encoder_mpeg4_get_codec_data;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_mpeg4.h b/gst-libs/gst/vaapi/gstvaapiencoder_mpeg4.h
new file mode 100644 (file)
index 0000000..62e7c89
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ *  gstvaapiencoder_mpeg4.h - MPEG-4 encoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_ENCODER_MPEG4_H
+#define GST_VAAPI_ENCODER_MPEG4_H
+
+#include "gst/vaapi/gstvaapisurfacepool.h"
+#include "gst/vaapi/gstvaapibaseencoder.h"
+
+G_BEGIN_DECLS
+
+#define MPEG4_DEFAULT_INTRA_PERIOD 30
+#define MPEG4_DEFAULT_INIT_QP      15
+#define MPEG4_DEFAULT_MIN_QP       1
+#define MPEG4_DEFAULT_SIMPLE_PROFILE_AND_LEVEL          0x03
+#define MPEG4_DEFAULT_ADVANCED_SIMPLE_PROFILE_AND_LEVEL 0xF3
+
+#define MPEG4_DEFAULT_FIXED_VOP_RATE FALSE
+
+
+typedef struct _GstVaapiEncoderMpeg4              GstVaapiEncoderMpeg4;
+typedef struct _GstVaapiEncoderMpeg4Private       GstVaapiEncoderMpeg4Private;
+typedef struct _GstVaapiEncoderMpeg4Class         GstVaapiEncoderMpeg4Class;
+
+
+#define GST_TYPE_VAAPI_ENCODER_MPEG4 \
+    (gst_vaapi_encoder_mpeg4_get_type())
+
+#define GST_IS_VAAPI_ENCODER_MPEG4(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_ENCODER_MPEG4))
+
+#define GST_IS_VAAPI_ENCODER_MPEG4_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VAAPI_ENCODER_MPEG4))
+
+#define GST_VAAPI_ENCODER_MPEG4_GET_CLASS(obj)                 \
+    (G_TYPE_INSTANCE_GET_CLASS ((obj),                         \
+                                GST_TYPE_VAAPI_ENCODER_MPEG4,  \
+                                GstVaapiEncoderMpeg4Class))
+
+#define GST_VAAPI_ENCODER_MPEG4(obj)                           \
+    (G_TYPE_CHECK_INSTANCE_CAST ((obj),                        \
+                                 GST_TYPE_VAAPI_ENCODER_MPEG4, \
+                                 GstVaapiEncoderMpeg4))
+
+#define GST_VAAPI_ENCODER_MPEG4_CLASS(klass)                   \
+    (G_TYPE_CHECK_CLASS_CAST ((klass),                         \
+                              GST_TYPE_VAAPI_ENCODER_MPEG4,    \
+                              GstVaapiEncoderMpeg4Class))
+
+#define GST_VAAPI_ENCODER_MPEG4_GET_PRIVATE(obj)               \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                        \
+                                 GST_TYPE_VAAPI_ENCODER_MPEG4, \
+                                 GstVaapiEncoderMpeg4Private))
+
+struct _GstVaapiEncoderMpeg4 {
+  GstVaapiBaseEncoder parent;   /*based on gobject*/
+  VAProfile profile;  /* VAProfileMPEG4Simple, VAProfileMPEG4AdvancedSimple */
+  guint32   bitrate;
+  guint32   intra_period;
+  guint32   init_qp;  /*default 15, 1~31*/
+  guint32   min_qp;   /*default 1, 1~31*/
+
+  GstVaapiEncoderMpeg4Private *priv;
+};
+
+struct _GstVaapiEncoderMpeg4Class {
+    GstVaapiBaseEncoderClass parent_class;
+};
+
+GType
+gst_vaapi_encoder_mpeg4_get_type(void);
+
+GstVaapiEncoderMpeg4 *
+gst_vaapi_encoder_mpeg4_new(void);
+
+static inline void
+gst_vaapi_encoder_mpeg4_unref (GstVaapiEncoderMpeg4 * encoder)
+{
+  g_object_unref (encoder);
+}
+
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_ENCODER_MPEG4_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiimage.c b/gst-libs/gst/vaapi/gstvaapiimage.c
new file mode 100644 (file)
index 0000000..d4e9306
--- /dev/null
@@ -0,0 +1,1698 @@
+/*
+ *  gstvaapiimage.c - VA image abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapiimage
+ * @short_description: VA image abstraction
+ */
+
+#include "sysdeps.h"
+#include <string.h>
+#include "gst/gstutils.h"
+#include "gstvaapicompat.h"
+#include "gstvaapiutils.h"
+#include "gstvaapiimage.h"
+#include "gstvaapi_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiImage, gst_vaapi_image, GST_VAAPI_TYPE_OBJECT);
+
+#define GST_VAAPI_IMAGE_GET_PRIVATE(obj)                \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                 \
+                                 GST_VAAPI_TYPE_IMAGE, \
+                                 GstVaapiImagePrivate))
+
+struct _GstVaapiImagePrivate {
+    VAImage             internal_image;
+    VAImage             image;
+    guchar             *image_data;
+    GstVaapiImageFormat internal_format;
+    GstVaapiImageFormat format;
+    guint               width;
+    guint               height;
+    guint               create_image    : 1;
+    guint               is_constructed  : 1;
+    guint               is_linear       : 1;
+};
+
+enum {
+    PROP_0,
+
+    PROP_IMAGE,
+    PROP_FORMAT,
+    PROP_WIDTH,
+    PROP_HEIGHT
+};
+
+#define SWAP_UINT(a, b) do { \
+        guint v = a;         \
+        a = b;               \
+        b = v;               \
+    } while (0)
+
+static gboolean
+_gst_vaapi_image_map(GstVaapiImage *image, GstVaapiImageRaw *raw_image);
+
+static gboolean
+_gst_vaapi_image_unmap(GstVaapiImage *image);
+
+static gboolean
+_gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image);
+
+/*
+ * VAImage wrapper
+ */
+
+#define VAAPI_TYPE_IMAGE vaapi_image_get_type()
+
+static gpointer
+vaapi_image_copy(gpointer va_image)
+{
+    return g_slice_dup(VAImage, va_image);
+}
+
+static void
+vaapi_image_free(gpointer va_image)
+{
+    if (G_LIKELY(va_image))
+        g_slice_free(VAImage, va_image);
+}
+
+static GType
+vaapi_image_get_type(void)
+{
+    static GType type = 0;
+
+    if (G_UNLIKELY(type == 0))
+        type = g_boxed_type_register_static(
+            "VAImage",
+            vaapi_image_copy,
+            vaapi_image_free
+        );
+    return type;
+}
+
+static gboolean
+vaapi_image_is_linear(const VAImage *va_image)
+{
+    guint i, width, height, width2, height2, data_size;
+
+    for (i = 1; i < va_image->num_planes; i++)
+        if (va_image->offsets[i] < va_image->offsets[i - 1])
+            return FALSE;
+
+    width   = va_image->width;
+    height  = va_image->height;
+    width2  = (width  + 1) / 2;
+    height2 = (height + 1) / 2;
+
+    switch (va_image->format.fourcc) {
+    case VA_FOURCC('N','V','1','2'):
+    case VA_FOURCC('Y','V','1','2'):
+    case VA_FOURCC('I','4','2','0'):
+        data_size = width * height + 2 * width2 * height2;
+        break;
+    case VA_FOURCC('A','Y','U','V'):
+    case VA_FOURCC('A','R','G','B'):
+    case VA_FOURCC('R','G','B','A'):
+    case VA_FOURCC('A','B','G','R'):
+    case VA_FOURCC('B','G','R','A'):
+        data_size = 4 * width * height;
+        break;
+    default:
+        g_error("FIXME: incomplete formats");
+        break;
+    }
+    return va_image->data_size == data_size;
+}
+
+static void
+gst_vaapi_image_destroy(GstVaapiImage *image)
+{
+    GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(image);
+    VAImageID image_id;
+    VAStatus status;
+
+    _gst_vaapi_image_unmap(image);
+
+    image_id = GST_VAAPI_OBJECT_ID(image);
+    GST_DEBUG("image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(image_id));
+
+    if (image_id != VA_INVALID_ID) {
+        GST_VAAPI_DISPLAY_LOCK(display);
+        status = vaDestroyImage(GST_VAAPI_DISPLAY_VADISPLAY(display), image_id);
+        GST_VAAPI_DISPLAY_UNLOCK(display);
+        if (!vaapi_check_status(status, "vaDestroyImage()"))
+            g_warning("failed to destroy image %" GST_VAAPI_ID_FORMAT,
+                      GST_VAAPI_ID_ARGS(image_id));
+        GST_VAAPI_OBJECT_ID(image) = VA_INVALID_ID;
+    }
+}
+
+static gboolean
+_gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
+{
+    GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(image);
+    GstVaapiImagePrivate * const priv = image->priv;
+    const VAImageFormat *va_format;
+    VAStatus status;
+
+    if (!gst_vaapi_display_has_image_format(display, format))
+        return FALSE;
+
+    va_format = gst_vaapi_image_format_get_va_format(format);
+    if (!va_format)
+        return FALSE;
+
+    GST_VAAPI_DISPLAY_LOCK(display);
+    status = vaCreateImage(
+        GST_VAAPI_DISPLAY_VADISPLAY(display),
+        (VAImageFormat *)va_format,
+        priv->width,
+        priv->height,
+        &priv->internal_image
+    );
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+    if (status != VA_STATUS_SUCCESS ||
+        priv->internal_image.format.fourcc != va_format->fourcc)
+        return FALSE;
+
+    priv->internal_format = format;
+    return TRUE;
+}
+
+static gboolean
+gst_vaapi_image_create(GstVaapiImage *image)
+{
+    GstVaapiImagePrivate * const priv = image->priv;
+    GstVaapiImageFormat format = priv->format;
+    const VAImageFormat *va_format;
+    VAImageID image_id;
+
+    if (!priv->create_image)
+        return (priv->image.image_id != VA_INVALID_ID &&
+                priv->image.buf      != VA_INVALID_ID);
+
+    if (!_gst_vaapi_image_create(image, format)) {
+        switch (format) {
+        case GST_VAAPI_IMAGE_I420:
+            format = GST_VAAPI_IMAGE_YV12;
+            break;
+        case GST_VAAPI_IMAGE_YV12:
+            format = GST_VAAPI_IMAGE_I420;
+            break;
+        default:
+            format = 0;
+            break;
+        }
+        if (!format || !_gst_vaapi_image_create(image, format))
+            return FALSE;
+    }
+    priv->image = priv->internal_image;
+    image_id    = priv->image.image_id;
+
+    if (priv->format != priv->internal_format) {
+        switch (priv->format) {
+        case GST_VAAPI_IMAGE_YV12:
+        case GST_VAAPI_IMAGE_I420:
+            va_format = gst_vaapi_image_format_get_va_format(priv->format);
+            if (!va_format)
+                return FALSE;
+            priv->image.format = *va_format;
+            SWAP_UINT(priv->image.offsets[1], priv->image.offsets[2]);
+            SWAP_UINT(priv->image.pitches[1], priv->image.pitches[2]);
+            break;
+        default:
+            break;
+        }
+    }
+    priv->is_linear = vaapi_image_is_linear(&priv->image);
+
+    GST_DEBUG("image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(image_id));
+    GST_VAAPI_OBJECT_ID(image) = image_id;
+    return TRUE;
+}
+
+static void
+gst_vaapi_image_finalize(GObject *object)
+{
+    gst_vaapi_image_destroy(GST_VAAPI_IMAGE(object));
+
+    G_OBJECT_CLASS(gst_vaapi_image_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_image_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiImage        * const image = GST_VAAPI_IMAGE(object);
+    GstVaapiImagePrivate * const priv  = image->priv;
+
+    switch (prop_id) {
+    case PROP_IMAGE: {
+        const VAImage * const va_image = g_value_get_boxed(value);
+        if (va_image)
+            _gst_vaapi_image_set_image(image, va_image);
+        break;
+    }
+    case PROP_FORMAT:
+        if (priv->create_image)
+            priv->format = g_value_get_uint(value);
+        break;
+    case PROP_WIDTH:
+        if (priv->create_image)
+            priv->width = g_value_get_uint(value);
+        break;
+    case PROP_HEIGHT:
+        if (priv->create_image)
+            priv->height = g_value_get_uint(value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_image_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
+
+    switch (prop_id) {
+    case PROP_IMAGE:
+        g_value_set_boxed(value, &image->priv->image);
+        break;
+    case PROP_FORMAT:
+        g_value_set_uint(value, gst_vaapi_image_get_format(image));
+        break;
+    case PROP_WIDTH:
+        g_value_set_uint(value, gst_vaapi_image_get_width(image));
+        break;
+    case PROP_HEIGHT:
+        g_value_set_uint(value, gst_vaapi_image_get_height(image));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_image_constructed(GObject *object)
+{
+    GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
+    GObjectClass *parent_class;
+
+    image->priv->is_constructed = gst_vaapi_image_create(image);
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_image_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+}
+
+static void
+gst_vaapi_image_class_init(GstVaapiImageClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiImagePrivate));
+
+    object_class->finalize     = gst_vaapi_image_finalize;
+    object_class->set_property = gst_vaapi_image_set_property;
+    object_class->get_property = gst_vaapi_image_get_property;
+    object_class->constructed  = gst_vaapi_image_constructed;
+
+    g_object_class_install_property
+        (object_class,
+         PROP_IMAGE,
+         g_param_spec_boxed("image",
+                            "Image",
+                            "The underlying VA image",
+                            VAAPI_TYPE_IMAGE,
+                            G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_WIDTH,
+         g_param_spec_uint("width",
+                           "width",
+                           "The image width",
+                           0, G_MAXUINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_HEIGHT,
+         g_param_spec_uint("height",
+                           "heighr",
+                           "The image height",
+                           0, G_MAXUINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    /**
+     * GstVaapiImage:format:
+     *
+     * The #GstVaapiImageFormat of the image
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_FORMAT,
+         g_param_spec_uint("format",
+                           "Format",
+                           "The underlying image format",
+                           0, G_MAXUINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gst_vaapi_image_init(GstVaapiImage *image)
+{
+    GstVaapiImagePrivate *priv = GST_VAAPI_IMAGE_GET_PRIVATE(image);
+
+    image->priv                   = priv;
+    priv->image_data              = NULL;
+    priv->width                   = 0;
+    priv->height                  = 0;
+    priv->internal_format         = 0;
+    priv->format                  = 0;
+    priv->create_image            = TRUE;
+    priv->is_constructed          = FALSE;
+    priv->is_linear               = FALSE;
+
+    memset(&priv->internal_image, 0, sizeof(priv->internal_image));
+    priv->internal_image.image_id = VA_INVALID_ID;
+    priv->internal_image.buf      = VA_INVALID_ID;
+
+    memset(&priv->image, 0, sizeof(priv->image));
+    priv->image.image_id          = VA_INVALID_ID;
+    priv->image.buf               = VA_INVALID_ID;
+}
+
+/**
+ * gst_vaapi_image_new:
+ * @display: a #GstVaapiDisplay
+ * @format: a #GstVaapiImageFormat
+ * @width: the requested image width
+ * @height: the requested image height
+ *
+ * Creates a new #GstVaapiImage with the specified format and
+ * dimensions.
+ *
+ * Return value: the newly allocated #GstVaapiImage object
+ */
+GstVaapiImage *
+gst_vaapi_image_new(
+    GstVaapiDisplay    *display,
+    GstVaapiImageFormat format,
+    guint               width,
+    guint               height
+)
+{
+    GstVaapiImage *image;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+    g_return_val_if_fail(width > 0, NULL);
+    g_return_val_if_fail(height > 0, NULL);
+
+    GST_DEBUG("format %" GST_FOURCC_FORMAT ", size %ux%u",
+              GST_FOURCC_ARGS(format), width, height);
+
+    image = g_object_new(
+        GST_VAAPI_TYPE_IMAGE,
+        "display", display,
+        "id",      GST_VAAPI_ID(VA_INVALID_ID),
+        "format",  format,
+        "width",   width,
+        "height",  height,
+        NULL
+    );
+    if (!image)
+        return NULL;
+
+    if (!image->priv->is_constructed) {
+        g_object_unref(image);
+        return NULL;
+    }
+    return image;
+}
+
+/**
+ * gst_vaapi_image_new_with_image:
+ * @display: a #GstVaapiDisplay
+ * @va_image: a VA image
+ *
+ * Creates a new #GstVaapiImage from a foreign VA image. The image
+ * format and dimensions will be extracted from @va_image. This
+ * function is mainly used by gst_vaapi_surface_derive_image() to bind
+ * a VA image to a #GstVaapiImage object.
+ *
+ * Return value: the newly allocated #GstVaapiImage object
+ */
+GstVaapiImage *
+gst_vaapi_image_new_with_image(GstVaapiDisplay *display, VAImage *va_image)
+{
+    GstVaapiImage *image;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+    g_return_val_if_fail(va_image, NULL);
+    g_return_val_if_fail(va_image->image_id != VA_INVALID_ID, NULL);
+    g_return_val_if_fail(va_image->buf != VA_INVALID_ID, NULL);
+
+    GST_DEBUG("VA image 0x%08x, format %" GST_FOURCC_FORMAT ", size %ux%u",
+              va_image->image_id,
+              GST_FOURCC_ARGS(va_image->format.fourcc),
+              va_image->width, va_image->height);
+
+    image = g_object_new(
+        GST_VAAPI_TYPE_IMAGE,
+        "display", display,
+        "id",      GST_VAAPI_ID(va_image->image_id),
+        "image",   va_image,
+        NULL
+    );
+    if (!image)
+        return NULL;
+
+    if (!image->priv->is_constructed) {
+        g_object_unref(image);
+        return NULL;
+    }
+    return image;
+}
+
+/**
+ * gst_vaapi_image_get_id:
+ * @image: a #GstVaapiImage
+ *
+ * Returns the underlying VAImageID of the @image.
+ *
+ * Return value: the underlying VA image id
+ */
+GstVaapiID
+gst_vaapi_image_get_id(GstVaapiImage *image)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), VA_INVALID_ID);
+    g_return_val_if_fail(image->priv->is_constructed, VA_INVALID_ID);
+
+    return GST_VAAPI_OBJECT_ID(image);
+}
+
+/**
+ * gst_vaapi_image_get_image:
+ * @image: a #GstVaapiImage
+ * @va_image: a VA image
+ *
+ * Fills @va_image with the VA image used internally.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_image_get_image(GstVaapiImage *image, VAImage *va_image)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
+    g_return_val_if_fail(image->priv->is_constructed, FALSE);
+
+    if (va_image)
+        *va_image = image->priv->image;
+
+    return TRUE;
+}
+
+/*
+ * _gst_vaapi_image_set_image:
+ * @image: a #GstVaapiImage
+ * @va_image: a VA image
+ *
+ * Initializes #GstVaapiImage with a foreign VA image. This function
+ * will try to "linearize" the VA image. i.e. making sure that the VA
+ * image offsets into the data buffer are in increasing order with the
+ * number of planes available in the image.
+ *
+ * This is an internal function used by gst_vaapi_image_new_with_image().
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+_gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image)
+{
+    GstVaapiImagePrivate * const priv = image->priv;
+    GstVaapiImageFormat format;
+    VAImage alt_va_image;
+    const VAImageFormat *alt_va_format;
+
+    if (!va_image)
+        return FALSE;
+
+    format = gst_vaapi_image_format(&va_image->format);
+    if (!format)
+        return FALSE;
+
+    priv->create_image    = FALSE;
+    priv->internal_image  = *va_image;
+    priv->internal_format = format;
+    priv->is_linear       = vaapi_image_is_linear(va_image);
+    priv->image           = *va_image;
+    priv->format          = format;
+    priv->width           = va_image->width;
+    priv->height          = va_image->height;
+
+    /* Try to linearize image */
+    if (!priv->is_linear) {
+        switch (format) {
+        case GST_VAAPI_IMAGE_I420:
+            format = GST_VAAPI_IMAGE_YV12;
+            break;
+        case GST_VAAPI_IMAGE_YV12:
+            format = GST_VAAPI_IMAGE_I420;
+            break;
+        default:
+            format = 0;
+            break;
+        }
+        if (format &&
+            (alt_va_format = gst_vaapi_image_format_get_va_format(format))) {
+            alt_va_image = *va_image;
+            alt_va_image.format = *alt_va_format;
+            SWAP_UINT(alt_va_image.offsets[1], alt_va_image.offsets[2]);
+            SWAP_UINT(alt_va_image.pitches[1], alt_va_image.pitches[2]);
+            if (vaapi_image_is_linear(&alt_va_image)) {
+                priv->image     = alt_va_image;
+                priv->format    = format;
+                priv->is_linear = TRUE;
+                GST_DEBUG("linearized image to %" GST_FOURCC_FORMAT " format",
+                          GST_FOURCC_ARGS(format));
+            }
+        }
+    }
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_image_get_format:
+ * @image: a #GstVaapiImage
+ *
+ * Returns the #GstVaapiImageFormat the @image was created with.
+ *
+ * Return value: the #GstVaapiImageFormat
+ */
+GstVaapiImageFormat
+gst_vaapi_image_get_format(GstVaapiImage *image)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
+    g_return_val_if_fail(image->priv->is_constructed, 0);
+
+    return image->priv->format;
+}
+
+/**
+ * gst_vaapi_image_get_width:
+ * @image: a #GstVaapiImage
+ *
+ * Returns the @image width.
+ *
+ * Return value: the image width, in pixels
+ */
+guint
+gst_vaapi_image_get_width(GstVaapiImage *image)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
+    g_return_val_if_fail(image->priv->is_constructed, 0);
+
+    return image->priv->width;
+}
+
+/**
+ * gst_vaapi_image_get_height:
+ * @image: a #GstVaapiImage
+ *
+ * Returns the @image height.
+ *
+ * Return value: the image height, in pixels.
+ */
+guint
+gst_vaapi_image_get_height(GstVaapiImage *image)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
+    g_return_val_if_fail(image->priv->is_constructed, 0);
+
+    return image->priv->height;
+}
+
+/**
+ * gst_vaapi_image_get_size:
+ * @image: a #GstVaapiImage
+ * @pwidth: return location for the width, or %NULL
+ * @pheight: return location for the height, or %NULL
+ *
+ * Retrieves the dimensions of a #GstVaapiImage.
+ */
+void
+gst_vaapi_image_get_size(GstVaapiImage *image, guint *pwidth, guint *pheight)
+{
+    g_return_if_fail(GST_VAAPI_IS_IMAGE(image));
+    g_return_if_fail(image->priv->is_constructed);
+
+    if (pwidth)
+        *pwidth = image->priv->width;
+
+    if (pheight)
+        *pheight = image->priv->height;
+}
+
+/**
+ * gst_vaapi_image_is_linear:
+ * @image: a #GstVaapiImage
+ *
+ * Checks whether the @image has data planes allocated from a single
+ * buffer and offsets into that buffer are in increasing order with
+ * the number of planes.
+ *
+ * Return value: %TRUE if image data planes are allocated from a single buffer
+ */
+gboolean
+gst_vaapi_image_is_linear(GstVaapiImage *image)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
+    g_return_val_if_fail(image->priv->is_constructed, FALSE);
+
+    return image->priv->is_linear;
+}
+
+/**
+ * gst_vaapi_image_is_mapped:
+ * @image: a #GstVaapiImage
+ *
+ * Checks whether the @image is currently mapped or not.
+ *
+ * Return value: %TRUE if the @image is mapped
+ */
+static inline gboolean
+_gst_vaapi_image_is_mapped(GstVaapiImage *image)
+{
+    return image->priv->image_data != NULL;
+}
+
+gboolean
+gst_vaapi_image_is_mapped(GstVaapiImage *image)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
+    g_return_val_if_fail(image->priv->is_constructed, FALSE);
+
+    return _gst_vaapi_image_is_mapped(image);
+}
+
+/**
+ * gst_vaapi_image_map:
+ * @image: a #GstVaapiImage
+ *
+ * Maps the image data buffer. The actual pixels are returned by the
+ * gst_vaapi_image_get_plane() function.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_image_map(GstVaapiImage *image)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
+    g_return_val_if_fail(image->priv->is_constructed, FALSE);
+
+    return _gst_vaapi_image_map(image, NULL);
+}
+
+gboolean
+_gst_vaapi_image_map(GstVaapiImage *image, GstVaapiImageRaw *raw_image)
+{
+    GstVaapiImagePrivate * const priv = image->priv;
+    GstVaapiDisplay *display;
+    void *image_data;
+    VAStatus status;
+    guint i;
+
+    if (_gst_vaapi_image_is_mapped(image))
+        return TRUE;
+
+    display = GST_VAAPI_OBJECT_DISPLAY(image);
+    if (!display)
+        return FALSE;
+
+    GST_VAAPI_DISPLAY_LOCK(display);
+    status = vaMapBuffer(
+        GST_VAAPI_DISPLAY_VADISPLAY(display),
+        image->priv->image.buf,
+        &image_data
+    );
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+    if (!vaapi_check_status(status, "vaMapBuffer()"))
+        return FALSE;
+
+    image->priv->image_data = image_data;
+
+    if (raw_image) {
+        const VAImage * const va_image = &priv->image;
+        raw_image->format     = priv->format;
+        raw_image->width      = va_image->width;
+        raw_image->height     = va_image->height;
+        raw_image->num_planes = va_image->num_planes;
+        for (i = 0; i < raw_image->num_planes; i++) {
+            raw_image->pixels[i] = image_data + va_image->offsets[i];
+            raw_image->stride[i] = va_image->pitches[i];
+        }
+    }
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_image_unmap:
+ * @image: a #GstVaapiImage
+ *
+ * Unmaps the image data buffer. Pointers to pixels returned by
+ * gst_vaapi_image_get_plane() are then no longer valid.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_image_unmap(GstVaapiImage *image)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
+    g_return_val_if_fail(image->priv->is_constructed, FALSE);
+
+    return _gst_vaapi_image_unmap(image);
+}
+
+gboolean
+_gst_vaapi_image_unmap(GstVaapiImage *image)
+{
+    GstVaapiDisplay *display;
+    VAStatus status;
+
+    if (!_gst_vaapi_image_is_mapped(image))
+        return FALSE;
+
+    display = GST_VAAPI_OBJECT_DISPLAY(image);
+    if (!display)
+        return FALSE;
+
+    GST_VAAPI_DISPLAY_LOCK(display);
+    status = vaUnmapBuffer(
+        GST_VAAPI_DISPLAY_VADISPLAY(display),
+        image->priv->image.buf
+    );
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+    if (!vaapi_check_status(status, "vaUnmapBuffer()"))
+        return FALSE;
+
+    image->priv->image_data = NULL;
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_image_ensure_mapped_buffer:
+ * @image: a #GstVaapiImage
+ *
+ * initialize mapped image buffer in case of optimizition on
+ * nothing did between map and unmap operations.
+ *
+ * Return value: %TRUE on success
+ */
+
+gboolean
+gst_vaapi_image_ensure_mapped_buffer(GstVaapiImage *image)
+{
+    GstVaapiImagePrivate * const priv = image->priv;
+    guchar *user_ptr;
+    guchar tmp;
+    guint index;
+
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
+    g_return_val_if_fail(priv->is_constructed, FALSE);
+
+    if (!_gst_vaapi_image_is_mapped(image) || !priv->image_data)
+        return FALSE;
+
+#undef GST_VAAPI_IMAGE_PAGE_SIZE
+#define GST_VAAPI_IMAGE_PAGE_SIZE 4096
+
+    /* read each page make sure virtual buffer mapped*/
+    user_ptr = priv->image_data;
+    for (index = 0;
+         index < priv->image.data_size;
+         index += GST_VAAPI_IMAGE_PAGE_SIZE) {
+        tmp = *(user_ptr + index);
+        /*prevent from compiling optimization*/
+        if (tmp == 0)
+            *(user_ptr + index) = 0;
+    }
+
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_image_get_plane_count:
+ * @image: a #GstVaapiImage
+ *
+ * Retrieves the number of planes available in the @image. The @image
+ * must be mapped for this function to work properly.
+ *
+ * Return value: the number of planes available in the @image
+ */
+guint
+gst_vaapi_image_get_plane_count(GstVaapiImage *image)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
+    g_return_val_if_fail(image->priv->is_constructed, FALSE);
+    g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
+
+    return image->priv->image.num_planes;
+}
+
+/**
+ * gst_vaapi_image_get_plane:
+ * @image: a #GstVaapiImage
+ * @plane: the requested plane number
+ *
+ * Retrieves the pixels data to the specified @plane. The @image must
+ * be mapped for this function to work properly.
+ *
+ * Return value: the pixels data of the specified @plane
+ */
+guchar *
+gst_vaapi_image_get_plane(GstVaapiImage *image, guint plane)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL);
+    g_return_val_if_fail(image->priv->is_constructed, FALSE);
+    g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), NULL);
+    g_return_val_if_fail(plane < image->priv->image.num_planes, NULL);
+
+    return image->priv->image_data + image->priv->image.offsets[plane];
+}
+
+/**
+ * gst_vaapi_image_get_pitch:
+ * @image: a #GstVaapiImage
+ * @plane: the requested plane number
+ *
+ * Retrieves the line size (stride) of the specified @plane. The
+ * @image must be mapped for this function to work properly.
+ *
+ * Return value: the line size (stride) of the specified plane
+ */
+guint
+gst_vaapi_image_get_pitch(GstVaapiImage *image, guint plane)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
+    g_return_val_if_fail(image->priv->is_constructed, FALSE);
+    g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
+    g_return_val_if_fail(plane < image->priv->image.num_planes, 0);
+
+    return image->priv->image.pitches[plane];
+}
+
+/**
+ * gst_vaapi_image_get_data_size:
+ * @image: a #GstVaapiImage
+ *
+ * Retrieves the underlying image data size. This function could be
+ * used to determine whether the image has a compatible layout with
+ * another image structure.
+ *
+ * Return value: the whole image data size of the @image
+ */
+guint
+gst_vaapi_image_get_data_size(GstVaapiImage *image)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
+    g_return_val_if_fail(image->priv->is_constructed, FALSE);
+
+    return image->priv->image.data_size;
+}
+
+static gboolean
+init_image_from_buffer(GstVaapiImageRaw *raw_image, GstBuffer *buffer)
+{
+    GstStructure *structure;
+    GstCaps *caps;
+    GstVaapiImageFormat format;
+    guint width2, height2, size2;
+    gint width, height;
+    guchar *data;
+    guint32 data_size;
+
+    data      = GST_BUFFER_DATA(buffer);
+    data_size = GST_BUFFER_SIZE(buffer);
+    caps      = GST_BUFFER_CAPS(buffer);
+
+    if (!caps)
+        return FALSE;
+
+    format = gst_vaapi_image_format_from_caps(caps);
+
+    structure = gst_caps_get_structure(caps, 0);
+    gst_structure_get_int(structure, "width",  &width);
+    gst_structure_get_int(structure, "height", &height);
+
+    /* XXX: copied from gst_video_format_get_row_stride() -- no NV12? */
+    raw_image->format = format;
+    raw_image->width  = width;
+    raw_image->height = height;
+    width2  = (width + 1) / 2;
+    height2 = (height + 1) / 2;
+    size2   = 0;
+    switch (format) {
+    case GST_VAAPI_IMAGE_NV12:
+        raw_image->num_planes = 2;
+        raw_image->pixels[0]  = data;
+        raw_image->stride[0]  = GST_ROUND_UP_4(width);
+        size2                += height * raw_image->stride[0];
+        raw_image->pixels[1]  = data + size2;
+        raw_image->stride[1]  = raw_image->stride[0];
+        size2                += height2 * raw_image->stride[1];
+        break;
+    case GST_VAAPI_IMAGE_YV12:
+    case GST_VAAPI_IMAGE_I420:
+        raw_image->num_planes = 3;
+        raw_image->pixels[0]  = data;
+        raw_image->stride[0]  = GST_ROUND_UP_4(width);
+        size2                += height * raw_image->stride[0];
+        raw_image->pixels[1]  = data + size2;
+        raw_image->stride[1]  = GST_ROUND_UP_4(width2);
+        size2                += height2 * raw_image->stride[1];
+        raw_image->pixels[2]  = data + size2;
+        raw_image->stride[2]  = raw_image->stride[1];
+        size2                += height2 * raw_image->stride[2];
+        break;
+    case GST_VAAPI_IMAGE_ARGB:
+    case GST_VAAPI_IMAGE_RGBA:
+    case GST_VAAPI_IMAGE_ABGR:
+    case GST_VAAPI_IMAGE_BGRA:
+        raw_image->num_planes = 1;
+        raw_image->pixels[0]  = data;
+        raw_image->stride[0]  = width * 4;
+        size2                += height * raw_image->stride[0];
+        break;
+    default:
+        g_error("could not compute row-stride for %" GST_FOURCC_FORMAT,
+                GST_FOURCC_ARGS(format));
+        return FALSE;
+    }
+
+    if (size2 != data_size) {
+        g_error("data_size mismatch %d / %u", size2, data_size);
+        if (size2 > data_size)
+            return FALSE;
+    }
+    return TRUE;
+}
+
+/* Copy N lines of an image */
+static inline void
+memcpy_pic(
+    guchar       *dst,
+    guint         dst_stride,
+    const guchar *src,
+    guint         src_stride,
+    guint         len,
+    guint         height
+)
+{
+    guint i;
+
+    for (i = 0; i < height; i++)  {
+        memcpy(dst, src, len);
+        dst += dst_stride;
+        src += src_stride;
+    }
+}
+
+/* Copy NV12 images */
+static void
+copy_image_NV12(
+    GstVaapiImageRaw        *dst_image,
+    GstVaapiImageRaw        *src_image,
+    const GstVaapiRectangle *rect
+)
+{
+    guchar *dst, *src;
+    guint dst_stride, src_stride;
+
+    /* Y plane */
+    dst_stride = dst_image->stride[0];
+    dst = dst_image->pixels[0] + rect->y * dst_stride + rect->x;
+    src_stride = src_image->stride[0];
+    src = src_image->pixels[0] + rect->y * src_stride + rect->x;
+    memcpy_pic(dst, dst_stride, src, src_stride, rect->width, rect->height);
+
+    /* UV plane */
+    dst_stride = dst_image->stride[1];
+    dst = dst_image->pixels[1] + (rect->y / 2) * dst_stride + (rect->x & -2);
+    src_stride = src_image->stride[1];
+    src = src_image->pixels[1] + (rect->y / 2) * src_stride + (rect->x & -2);
+    memcpy_pic(dst, dst_stride, src, src_stride, rect->width, rect->height / 2);
+}
+
+/* Copy YV12 images */
+static void
+copy_image_YV12(
+    GstVaapiImageRaw        *dst_image,
+    GstVaapiImageRaw        *src_image,
+    const GstVaapiRectangle *rect
+)
+{
+    guchar *dst, *src;
+    guint dst_stride, src_stride;
+    guint i, x, y, w, h;
+
+    /* Y plane */
+    dst_stride = dst_image->stride[0];
+    dst = dst_image->pixels[0] + rect->y * dst_stride + rect->x;
+    src_stride = src_image->stride[0];
+    src = src_image->pixels[0] + rect->y * src_stride + rect->x;
+    memcpy_pic(dst, dst_stride, src, src_stride, rect->width, rect->height);
+
+    /* U/V planes */
+    x = rect->x / 2;
+    y = rect->y / 2;
+    w = rect->width / 2;
+    h = rect->height / 2;
+    for (i = 1; i < dst_image->num_planes; i++) {
+        dst_stride = dst_image->stride[i];
+        dst = dst_image->pixels[i] + y * dst_stride + x;
+        src_stride = src_image->stride[i];
+        src = src_image->pixels[i] + y * src_stride + x;
+        memcpy_pic(dst, dst_stride, src, src_stride, w, h);
+    }
+}
+
+/* Copy RGBA images */
+static void
+copy_image_RGBA(
+    GstVaapiImageRaw        *dst_image,
+    GstVaapiImageRaw        *src_image,
+    const GstVaapiRectangle *rect
+)
+{
+    guchar *dst, *src;
+    guint dst_stride, src_stride;
+
+    dst_stride = dst_image->stride[0];
+    dst = dst_image->pixels[0] + rect->y * dst_stride + rect->x;
+    src_stride = src_image->stride[0];
+    src = src_image->pixels[0] + rect->y * src_stride + rect->x;
+    memcpy_pic(dst, dst_stride, src, src_stride, 4 * rect->width, rect->height);
+}
+
+static gboolean
+copy_image(
+    GstVaapiImageRaw        *dst_image,
+    GstVaapiImageRaw        *src_image,
+    const GstVaapiRectangle *rect
+)
+{
+    GstVaapiRectangle default_rect;
+
+    if (dst_image->format != src_image->format ||
+        dst_image->width  != src_image->width  ||
+        dst_image->height < src_image->height)
+        return FALSE;
+
+    if (rect) {
+        if (rect->x >= src_image->width ||
+            rect->x + src_image->width > src_image->width ||
+            rect->y >= src_image->height ||
+            rect->y + src_image->height > src_image->height)
+            return FALSE;
+    }
+    else {
+        default_rect.x      = 0;
+        default_rect.y      = 0;
+        default_rect.width  = src_image->width;
+        default_rect.height = src_image->height;
+        rect                = &default_rect;
+    }
+
+    switch (dst_image->format) {
+    case GST_VAAPI_IMAGE_NV12:
+        copy_image_NV12(dst_image, src_image, rect);
+        break;
+    case GST_VAAPI_IMAGE_YV12:
+    case GST_VAAPI_IMAGE_I420:
+        copy_image_YV12(dst_image, src_image, rect);
+        break;
+    case GST_VAAPI_IMAGE_ARGB:
+    case GST_VAAPI_IMAGE_RGBA:
+    case GST_VAAPI_IMAGE_ABGR:
+    case GST_VAAPI_IMAGE_BGRA:
+        copy_image_RGBA(dst_image, src_image, rect);
+        break;
+    default:
+        GST_ERROR("unsupported image format for copy");
+        return FALSE;
+    }
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_image_get_buffer:
+ * @image: a #GstVaapiImage
+ * @buffer: a #GstBuffer
+ * @rect: a #GstVaapiRectangle expressing a region, or %NULL for the
+ *   whole image
+ *
+ * Transfers pixels data contained in the @image into the #GstBuffer.
+ * Both image structures shall have the same format.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_image_get_buffer(
+    GstVaapiImage     *image,
+    GstBuffer         *buffer,
+    GstVaapiRectangle *rect
+)
+{
+    GstVaapiImagePrivate *priv;
+    GstVaapiImageRaw dst_image, src_image;
+    gboolean success;
+
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
+    g_return_val_if_fail(image->priv->is_constructed, FALSE);
+    g_return_val_if_fail(GST_IS_BUFFER(buffer), FALSE);
+
+    priv = image->priv;
+
+    if (!init_image_from_buffer(&dst_image, buffer))
+        return FALSE;
+    if (dst_image.format != priv->format)
+        return FALSE;
+    if (dst_image.width != priv->width || dst_image.height != priv->height)
+        return FALSE;
+
+    if (!_gst_vaapi_image_map(image, &src_image))
+        return FALSE;
+
+    success = copy_image(&dst_image, &src_image, rect);
+
+    if (!_gst_vaapi_image_unmap(image))
+        return FALSE;
+
+    return success;
+}
+
+/**
+ * gst_vaapi_image_get_raw:
+ * @image: a #GstVaapiImage
+ * @dst_image: a #GstVaapiImageRaw
+ * @rect: a #GstVaapiRectangle expressing a region, or %NULL for the
+ *   whole image
+ *
+ * Transfers pixels data contained in the @image into the #GstVaapiImageRaw.
+ * Both image structures shall have the same format.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_image_get_raw(
+    GstVaapiImage     *image,
+    GstVaapiImageRaw  *dst_image,
+    GstVaapiRectangle *rect
+)
+{
+    GstVaapiImageRaw src_image;
+    gboolean success;
+
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
+    g_return_val_if_fail(image->priv->is_constructed, FALSE);
+
+    if (!_gst_vaapi_image_map(image, &src_image))
+        return FALSE;
+
+    success = copy_image(dst_image, &src_image, rect);
+
+    if (!_gst_vaapi_image_unmap(image))
+        return FALSE;
+
+    return success;
+}
+
+/**
+ * gst_vaapi_image_update_from_buffer:
+ * @image: a #GstVaapiImage
+ * @buffer: a #GstBuffer
+ * @rect: a #GstVaapiRectangle expressing a region, or %NULL for the
+ *   whole image
+ *
+ * Transfers pixels data contained in the #GstBuffer into the
+ * @image. Both image structures shall have the same format.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_image_update_from_buffer(
+    GstVaapiImage     *image,
+    GstBuffer         *buffer,
+    GstVaapiRectangle *rect
+)
+{
+    GstVaapiImagePrivate *priv;
+    GstVaapiImageRaw dst_image, src_image;
+    gboolean success;
+
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
+    g_return_val_if_fail(image->priv->is_constructed, FALSE);
+    g_return_val_if_fail(GST_IS_BUFFER(buffer), FALSE);
+
+    priv = image->priv;
+
+    if (!init_image_from_buffer(&src_image, buffer))
+        return FALSE;
+    if (src_image.format != priv->format)
+        return FALSE;
+    if (src_image.width != priv->width || src_image.height > priv->height)
+        return FALSE;
+
+    if (!_gst_vaapi_image_map(image, &dst_image))
+        return FALSE;
+
+    success = copy_image(&dst_image, &src_image, rect);
+
+    if (!_gst_vaapi_image_unmap(image))
+        return FALSE;
+
+    return success;
+}
+
+/**
+ * gst_vaapi_image_update_from_raw:
+ * @image: a #GstVaapiImage
+ * @src_image: a #GstVaapiImageRaw
+ * @buffer: a #GstBuffer
+ * @rect: a #GstVaapiRectangle expressing a region, or %NULL for the
+ *   whole image
+ *
+ * Transfers pixels data contained in the #GstVaapiImageRaw into the
+ * @image. Both image structures shall have the same format.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_image_update_from_raw(
+    GstVaapiImage     *image,
+    GstVaapiImageRaw  *src_image,
+    GstVaapiRectangle *rect
+)
+{
+    GstVaapiImageRaw dst_image;
+    gboolean success;
+
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
+    g_return_val_if_fail(image->priv->is_constructed, FALSE);
+
+    if (!_gst_vaapi_image_map(image, &dst_image))
+        return FALSE;
+
+    success = copy_image(&dst_image, src_image, rect);
+
+    if (!_gst_vaapi_image_unmap(image))
+        return FALSE;
+
+    return success;
+}
+
+static void
+_yuv411_to_nv12(
+    const guint8 *y_src,
+    guint32 y_src_stride,
+    const guint8 *u_src,
+    guint32 u_src_stride,
+    const guint8 *v_src,
+    guint32 v_src_stride,
+    guint8 *y_dest,
+    guint32 y_dest_stride,
+    guint8 *uv_dest,
+    guint32 uv_dest_stride,
+    guint32 width,
+    guint32 height
+)
+{
+    guint32 row, column;
+    guint32 uv_height;
+
+    memcpy_pic(y_dest, y_dest_stride, y_src, y_src_stride, width, height);
+    uv_height = GST_ROUND_UP_2(height)/2;
+    for (row = 0; row < uv_height; row++) {
+        for (column = 0; column < width/2; column++) {
+            uv_dest[column*2] = u_src[column];
+            uv_dest[column*2+1] = v_src[column];
+        }
+        u_src += u_src_stride;
+        v_src += v_src_stride;
+        uv_dest += uv_dest_stride;
+    }
+}
+
+static void
+_nv12_to_yuv411(
+    const guint8 *y_src,
+    guint32 y_src_stride,
+    const guint8 *uv_src,
+    guint32 uv_src_stride,
+    guint8 *y_dest,
+    guint32 y_dest_stride,
+    guint8 *u_dest,
+    guint32 u_dest_stride,
+    guint8 *v_dest,
+    guint32 v_dest_stride,
+    guint32 width,
+    guint32 height
+)
+{
+    guint32 row, column;
+    guint32 uv_height;
+
+    memcpy_pic(y_dest, y_dest_stride, y_src, y_src_stride, width, height);
+    uv_height = GST_ROUND_UP_2(height)/2;
+    for (row = 0; row < uv_height; row++) {
+        for (column = 0; column < width/2; column++) {
+            u_dest[column] = uv_src[column*2];
+            v_dest[column] = uv_src[column*2+1];
+        }
+        uv_src += uv_src_stride;
+        u_dest += u_dest_stride;
+        v_dest += v_dest_stride;
+    }
+}
+
+static void
+_yuy2_to_yuv411(
+    const guint8 *yuv_src,
+    guint32 yuv_src_stride,
+    guint8 *y_dest,
+    guint32 y_dest_stride,
+    guint8 *u_dest,
+    guint32 u_dest_stride,
+    guint8 *v_dest,
+    guint32 v_dest_stride,
+    gboolean uv_interlaced,
+    guint32 width,
+    guint32 height
+)
+{
+    guint32 row, column;
+    const guint8 *yuv_next_src;
+    guint8 *y_next_dest;
+    guint32 interval;
+
+    interval = uv_interlaced ? 2 : 1;
+    for (row = 0; row < height/2; row++) {
+        yuv_next_src = yuv_src + yuv_src_stride;
+        y_next_dest = y_dest + y_dest_stride;
+        for (column = 0; column < width/2; column++) {
+            y_dest[column*2] = yuv_src[column*4];
+            y_dest[column*2+1] = yuv_src[column*4+2];
+            y_next_dest[column*2] = yuv_next_src[column*4];
+            y_next_dest[column*2+1] = yuv_next_src[column*4+2];
+            u_dest[column*interval] = ((yuv_src[column*4+1] + yuv_next_src[column*4+1])>>1);
+            v_dest[column*interval] = ((yuv_src[column*4+3] + yuv_next_src[column*4+3])>>1);
+        }
+        yuv_src = yuv_next_src + yuv_src_stride;
+        y_dest = y_next_dest + y_dest_stride;
+        u_dest += u_dest_stride;
+        v_dest += v_dest_stride;
+    }
+
+    /*  odd line */
+    if (height%2) {
+        for (column = 0; column < width/2; column++) {
+          y_dest[column*2] = yuv_src[column*4];
+          y_dest[column*2+1] = yuv_src[column*4+2];
+          u_dest[column*interval] = yuv_src[column*4+1];
+          v_dest[column*interval] = yuv_src[column*4+3];
+        }
+    }
+
+}
+
+static gboolean
+_image_convert_to_nv12(
+    const guint8 *src,
+    guint32 width,
+    guint32 height,
+    guint32 src_format,
+    guint8 *y_dest,
+    guint32 y_dest_stride,
+    guint8 *uv_dest,
+    guint32 uv_dest_stride
+)
+{
+    const guint8 *y_src, *u_src, *v_src, *uv_src;
+    guint32 ystride, ustride, vstride, uv_stride;
+
+    switch (src_format) {
+        case GST_MAKE_FOURCC('N','V','1','2'): {
+            y_src = src;
+            ystride = GST_ROUND_UP_4(width);
+            uv_src = src + ystride*GST_ROUND_UP_2(height);
+            uv_stride = ystride;
+            memcpy_pic(y_dest, y_dest_stride, y_src, ystride, width, height);
+            memcpy_pic(uv_dest, uv_dest_stride, uv_src, uv_stride,
+                       width, GST_ROUND_UP_2(height)/2);
+            break;
+        }
+
+        case GST_MAKE_FOURCC('I','4','2','0'): {
+            y_src = src;
+            ystride = GST_ROUND_UP_4(width);
+            u_src = src + ystride*GST_ROUND_UP_2(height);
+            ustride = GST_ROUND_UP_8(ystride)/2;
+            v_src = u_src + ustride*GST_ROUND_UP_2(height)/2;
+            vstride = GST_ROUND_UP_8(ystride)/2;
+
+            _yuv411_to_nv12(y_src, ystride, u_src, ustride, v_src, vstride,
+                            y_dest, y_dest_stride,
+                            uv_dest, uv_dest_stride,
+                            width, height);
+            break;
+        }
+
+        case GST_MAKE_FOURCC('Y','V','1','2'):{
+            y_src = src;
+            ystride = GST_ROUND_UP_4(width);
+            v_src = src + ystride*GST_ROUND_UP_2(height);
+            vstride = GST_ROUND_UP_8(ystride)/2;
+            u_src = v_src + vstride*GST_ROUND_UP_2(height)/2;
+            ustride = GST_ROUND_UP_8(ystride)/2;
+
+            _yuv411_to_nv12(y_src, ystride, u_src, ustride, v_src, vstride,
+                            y_dest, y_dest_stride, uv_dest, uv_dest_stride,
+                            width, height);
+            break;
+        }
+
+        case GST_MAKE_FOURCC('Y', 'U', 'Y', '2'): {
+            y_src = src;
+            ystride = GST_ROUND_UP_2(width)*2;
+            _yuy2_to_yuv411(y_src, ystride,
+                            y_dest, y_dest_stride,
+                            uv_dest, uv_dest_stride,
+                            uv_dest+1, uv_dest_stride,
+                            TRUE,
+                            width, height);
+            break;
+        }
+
+        default:
+          return FALSE;
+    }
+    return TRUE;
+}
+
+static gboolean
+_image_convert_to_yuv411(
+    const guint8 *src,
+    guint32 width,
+    guint32 height,
+    guint32 src_format,
+    guint8 *y_dest,
+    guint32 y_dest_stride,
+    guint8 *u_dest,
+    guint32 u_dest_stride,
+    guint8 *v_dest,
+    guint32 v_dest_stride
+)
+{
+    const guint8 *y_src, *u_src, *v_src, *uv_src;
+    guint32 ystride, ustride, vstride, uv_stride;
+
+    switch (src_format) {
+        case GST_MAKE_FOURCC('N','V','1','2'): {
+            y_src = src;
+            ystride = GST_ROUND_UP_4(width);
+            uv_src = src + ystride*GST_ROUND_UP_2(height);
+            uv_stride = ystride;
+            _nv12_to_yuv411(y_src, ystride, uv_src, uv_stride,
+                            y_dest, y_dest_stride,
+                            u_dest, u_dest_stride,
+                            v_dest, v_dest_stride,
+                            width, height);
+            break;
+        }
+
+        case GST_MAKE_FOURCC('I','4','2','0'):
+        case GST_MAKE_FOURCC('Y','V','1','2'):{
+            y_src = src;
+            ystride = GST_ROUND_UP_4(width);
+            if (GST_MAKE_FOURCC('I','4','2','0') == src_format) {
+                u_src = src + ystride*GST_ROUND_UP_2(height);
+                ustride = GST_ROUND_UP_8(ystride)/2;
+                v_src = u_src + ustride*GST_ROUND_UP_2(height)/2;
+                vstride = GST_ROUND_UP_8(ystride)/2;
+            } else {
+                v_src = src + ystride*GST_ROUND_UP_2(height);
+                vstride = GST_ROUND_UP_8(ystride)/2;
+                u_src = v_src + vstride*GST_ROUND_UP_2(height)/2;
+                ustride = GST_ROUND_UP_8(ystride)/2;
+            }
+
+            memcpy_pic(y_dest, y_dest_stride, y_src, ystride, width, height);
+            memcpy_pic(u_dest, u_dest_stride, u_src, ustride, width/2, GST_ROUND_UP_2(height)/2);
+            memcpy_pic(v_dest, v_dest_stride, v_src, vstride, width/2, GST_ROUND_UP_2(height)/2);
+            break;
+        }
+
+        case GST_MAKE_FOURCC('Y', 'U', 'Y', '2'): {
+            y_src = src;
+            ystride = GST_ROUND_UP_2(width)*2;
+            _yuy2_to_yuv411(y_src, ystride,
+                            y_dest, y_dest_stride,
+                            u_dest, u_dest_stride,
+                            v_dest, v_dest_stride,
+                            FALSE,
+                            width, height);
+            break;
+        }
+
+        default:
+          return FALSE;
+    }
+    return TRUE;
+}
+
+
+gboolean
+gst_vaapi_convert_buffer_to_image(
+    GstVaapiImage *image,
+    GstBuffer *inbuf
+    )
+{
+    GstVaapiImagePrivate *priv;
+    guint width, height;
+    GstVaapiImageFormat image_format;
+    gboolean success = TRUE;
+    GstCaps *buffer_caps;
+    GstStructure *structure;
+    guint32 in_format = 0;
+
+    priv = image->priv;
+    gst_vaapi_image_get_size(image, &width, &height);
+    image_format = gst_vaapi_image_get_format(image);
+
+    /* get buffer format */
+    buffer_caps = GST_BUFFER_CAPS(inbuf);
+    if (!buffer_caps)
+        return FALSE;
+    structure = gst_caps_get_structure(buffer_caps, 0);
+    if (!structure)
+        return FALSE;
+    if (!gst_structure_get_fourcc(structure, "format", &in_format))
+        return FALSE;
+
+    /* currently only support YUV convert */
+    if ( (in_format != GST_MAKE_FOURCC('N','V','1','2')
+          && in_format != GST_MAKE_FOURCC('Y','V','1','2')
+          && in_format != GST_MAKE_FOURCC('I','4','2','0')
+          && in_format != GST_MAKE_FOURCC('Y', 'U', 'Y', '2'))
+        || (image_format != GST_VAAPI_IMAGE_NV12
+          && image_format != GST_VAAPI_IMAGE_YV12
+          && image_format != GST_VAAPI_IMAGE_I420)
+        )
+    {
+        return FALSE;
+    }
+
+
+    gst_vaapi_image_map(image);
+    switch (image_format) {
+      case GST_VAAPI_IMAGE_NV12: {
+          g_assert(priv->image.num_planes == 2);
+          success = _image_convert_to_nv12(GST_BUFFER_DATA(inbuf),
+                                           width, height, in_format,
+                                           priv->image_data+priv->image.offsets[0],
+                                           priv->image.pitches[0],
+                                           priv->image_data+priv->image.offsets[1],
+                                           priv->image.pitches[1]);
+          break;
+      }
+
+      case GST_VAAPI_IMAGE_I420: {
+          g_assert(priv->image.num_planes == 3);
+          success = _image_convert_to_yuv411(GST_BUFFER_DATA(inbuf),
+                                           width, height, in_format,
+                                           priv->image_data+priv->image.offsets[0],
+                                           priv->image.pitches[0],
+                                           priv->image_data+priv->image.offsets[1],
+                                           priv->image.pitches[1],
+                                           priv->image_data+priv->image.offsets[2],
+                                           priv->image.pitches[2]);
+          break;
+      }
+      case GST_VAAPI_IMAGE_YV12:{
+          g_assert(priv->image.num_planes == 3);
+          success = _image_convert_to_yuv411(GST_BUFFER_DATA(inbuf),
+                                           width, height, in_format,
+                                           priv->image_data+priv->image.offsets[0],
+                                           priv->image.pitches[0],
+                                           priv->image_data+priv->image.offsets[2],
+                                           priv->image.pitches[2],
+                                           priv->image_data+priv->image.offsets[1],
+                                           priv->image.pitches[1]);
+          break;
+      }
+
+      default:
+        success = FALSE;
+        break;
+    }
+    gst_vaapi_image_unmap(image);
+
+    return success;
+}
+
diff --git a/gst-libs/gst/vaapi/gstvaapiimage.h b/gst-libs/gst/vaapi/gstvaapiimage.h
new file mode 100644 (file)
index 0000000..95ea781
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ *  gstvaapiimage.h - VA image abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_IMAGE_H
+#define GST_VAAPI_IMAGE_H
+
+#include <gst/gstbuffer.h>
+#include <gst/vaapi/gstvaapiobject.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapiimageformat.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_IMAGE \
+    (gst_vaapi_image_get_type())
+
+#define GST_VAAPI_IMAGE(obj)                            \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                  \
+                                GST_VAAPI_TYPE_IMAGE,   \
+                                GstVaapiImage))
+
+#define GST_VAAPI_IMAGE_CLASS(klass)                    \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                   \
+                             GST_VAAPI_TYPE_IMAGE,      \
+                             GstVaapiImageClass))
+
+#define GST_VAAPI_IS_IMAGE(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_IMAGE))
+
+#define GST_VAAPI_IS_IMAGE_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_IMAGE))
+
+#define GST_VAAPI_IMAGE_GET_CLASS(obj)                  \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                   \
+                               GST_VAAPI_TYPE_IMAGE,    \
+                               GstVaapiImageClass))
+
+/**
+ * GST_VAAPI_IMAGE_FORMAT:
+ * @image: a #GstVaapiImage
+ *
+ * Macro that evaluates to the #GstVaapiImageFormat of @image.
+ */
+#define GST_VAAPI_IMAGE_FORMAT(image)   gst_vaapi_image_get_format(image)
+
+/**
+ * GST_VAAPI_IMAGE_WIDTH:
+ * @image: a #GstVaapiImage
+ *
+ * Macro that evaluates to the width of @image.
+ */
+#define GST_VAAPI_IMAGE_WIDTH(image)    gst_vaapi_image_get_width(image)
+
+/**
+ * GST_VAAPI_IMAGE_HEIGHT:
+ * @image: a #GstVaapiImage
+ *
+ * Macro that evaluates to the height of @image.
+ */
+#define GST_VAAPI_IMAGE_HEIGHT(image)   gst_vaapi_image_get_height(image)
+
+typedef struct _GstVaapiImage                   GstVaapiImage;
+typedef struct _GstVaapiImagePrivate            GstVaapiImagePrivate;
+typedef struct _GstVaapiImageClass              GstVaapiImageClass;
+typedef struct _GstVaapiImageRaw                GstVaapiImageRaw;
+
+/**
+ * GstVaapiImage:
+ *
+ * A VA image wrapper
+ */
+struct _GstVaapiImage {
+    /*< private >*/
+    GstVaapiObject parent_instance;
+
+    GstVaapiImagePrivate *priv;
+};
+
+/**
+ * GstVaapiImageClass:
+ *
+ * A VA image wrapper class
+ */
+struct _GstVaapiImageClass {
+    /*< private >*/
+    GstVaapiObjectClass parent_class;
+};
+
+/**
+ * GstVaapiImageRaw:
+ *
+ * A raw image wrapper. The caller is responsible for initializing all
+ * the fields with sensible values.
+ */
+struct _GstVaapiImageRaw {
+    GstVaapiImageFormat format;
+    guint               width;
+    guint               height;
+    guint               num_planes;
+    guchar             *pixels[3];
+    guint               stride[3];
+};
+
+GType
+gst_vaapi_image_get_type(void) G_GNUC_CONST;
+
+GstVaapiImage *
+gst_vaapi_image_new(
+    GstVaapiDisplay    *display,
+    GstVaapiImageFormat format,
+    guint               width,
+    guint               height
+);
+
+GstVaapiImage *
+gst_vaapi_image_new_with_image(GstVaapiDisplay *display, VAImage *va_image);
+
+GstVaapiID
+gst_vaapi_image_get_id(GstVaapiImage *image);
+
+gboolean
+gst_vaapi_image_get_image(GstVaapiImage *image, VAImage *va_image);
+
+GstVaapiImageFormat
+gst_vaapi_image_get_format(GstVaapiImage *image);
+
+guint
+gst_vaapi_image_get_width(GstVaapiImage *image);
+
+guint
+gst_vaapi_image_get_height(GstVaapiImage *image);
+
+void
+gst_vaapi_image_get_size(GstVaapiImage *image, guint *pwidth, guint *pheight);
+
+gboolean
+gst_vaapi_image_is_linear(GstVaapiImage *image);
+
+gboolean
+gst_vaapi_image_is_mapped(GstVaapiImage *image);
+
+gboolean
+gst_vaapi_image_map(GstVaapiImage *image);
+
+gboolean
+gst_vaapi_image_unmap(GstVaapiImage *image);
+
+gboolean
+gst_vaapi_image_ensure_mapped_buffer(GstVaapiImage *image);
+
+guint
+gst_vaapi_image_get_plane_count(GstVaapiImage *image);
+
+guchar *
+gst_vaapi_image_get_plane(GstVaapiImage *image, guint plane);
+
+guint
+gst_vaapi_image_get_pitch(GstVaapiImage *image, guint plane);
+
+guint
+gst_vaapi_image_get_data_size(GstVaapiImage *image);
+
+gboolean
+gst_vaapi_image_get_buffer(
+    GstVaapiImage     *image,
+    GstBuffer         *buffer,
+    GstVaapiRectangle *rect
+);
+
+gboolean
+gst_vaapi_image_get_raw(
+    GstVaapiImage     *image,
+    GstVaapiImageRaw  *dst_image,
+    GstVaapiRectangle *rect
+);
+
+gboolean
+gst_vaapi_image_update_from_buffer(
+    GstVaapiImage     *image,
+    GstBuffer         *buffer,
+    GstVaapiRectangle *rect
+);
+
+gboolean
+gst_vaapi_image_update_from_raw(
+    GstVaapiImage     *image,
+    GstVaapiImageRaw  *src_image,
+    GstVaapiRectangle *rect
+);
+
+gboolean
+gst_vaapi_convert_buffer_to_image(
+    GstVaapiImage *image,
+    GstBuffer *buffer);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_IMAGE_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiimageformat.c b/gst-libs/gst/vaapi/gstvaapiimageformat.c
new file mode 100644 (file)
index 0000000..dd03157
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ *  gstvaapiimageformat.c - VA image format abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapiimageformat
+ * @short_description: VA image format abstraction
+ */
+
+#include "sysdeps.h"
+#include <gst/video/video.h>
+#include "gstvaapicompat.h"
+#include "gstvaapiimageformat.h"
+
+typedef enum _GstVaapiImageFormatType           GstVaapiImageFormatType;
+typedef struct _GstVaapiImageFormatMap          GstVaapiImageFormatMap;
+
+enum _GstVaapiImageFormatType {
+    GST_VAAPI_IMAGE_FORMAT_TYPE_YCBCR = 1,      /* YUV */
+    GST_VAAPI_IMAGE_FORMAT_TYPE_RGB,            /* RGB */
+    GST_VAAPI_IMAGE_FORMAT_TYPE_INDEXED         /* paletted */
+};
+
+struct _GstVaapiImageFormatMap {
+    GstVaapiImageFormatType     type;
+    GstVaapiImageFormat         format;
+    const char                 *caps_str;
+    VAImageFormat               va_format;
+};
+
+#define DEF(TYPE, FORMAT, CAPS_STR)                                     \
+    GST_VAAPI_IMAGE_FORMAT_TYPE_##TYPE,                                 \
+    GST_VAAPI_IMAGE_##FORMAT,                                           \
+    CAPS_STR
+#define DEF_YUV(FORMAT, FOURCC, ENDIAN, BPP)                            \
+    { DEF(YCBCR, FORMAT, GST_VIDEO_CAPS_YUV(#FORMAT)),                  \
+        { VA_FOURCC FOURCC, VA_##ENDIAN##_FIRST, BPP, }, }
+#define DEF_RGB(FORMAT, FOURCC, ENDIAN, BPP, DEPTH, R,G,B,A)            \
+    { DEF(RGB, FORMAT, GST_VIDEO_CAPS_##FORMAT),                        \
+        { VA_FOURCC FOURCC, VA_##ENDIAN##_FIRST, BPP, DEPTH, R,G,B,A }, }
+
+/* Image formats, listed in HW order preference */
+static const GstVaapiImageFormatMap gst_vaapi_image_formats[] = {
+    DEF_YUV(NV12, ('N','V','1','2'), LSB, 12),
+    DEF_YUV(YV12, ('Y','V','1','2'), LSB, 12),
+    DEF_YUV(I420, ('I','4','2','0'), LSB, 12),
+    DEF_YUV(AYUV, ('A','Y','U','V'), LSB, 32),
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+    DEF_RGB(ARGB, ('A','R','G','B'), MSB, 32,
+            32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000),
+    DEF_RGB(ABGR, ('A','B','G','R'), MSB, 32,
+            32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000),
+#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
+    DEF_RGB(BGRA, ('B','G','R','A'), LSB, 32,
+            32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000),
+    DEF_RGB(RGBA, ('R','G','B','A'), LSB, 32,
+            32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000),
+#endif
+    { 0, }
+};
+
+#undef DEF_RGB
+#undef DEF_YUV
+#undef DEF
+
+static inline gboolean
+match_va_format_rgb(const VAImageFormat *fmt1, const VAImageFormat *fmt2)
+{
+    return (fmt1->byte_order == fmt2->byte_order &&
+            fmt1->red_mask   == fmt2->red_mask   &&
+            fmt1->green_mask == fmt2->green_mask &&
+            fmt1->blue_mask  == fmt2->blue_mask  &&
+            fmt1->alpha_mask == fmt2->alpha_mask);
+}
+
+static const GstVaapiImageFormatMap *
+get_map(GstVaapiImageFormat format)
+{
+    const GstVaapiImageFormatMap *m;
+
+    for (m = gst_vaapi_image_formats; m->format; m++)
+        if (m->format == format)
+            return m;
+    return NULL;
+}
+
+/**
+ * gst_vaapi_image_format_is_rgb:
+ * @format: a #GstVaapiImageFormat
+ *
+ * Checks whether the format is an RGB format.
+ *
+ * Return value: %TRUE if @format is RGB format
+ */
+gboolean
+gst_vaapi_image_format_is_rgb(GstVaapiImageFormat format)
+{
+    const GstVaapiImageFormatMap * const m = get_map(format);
+
+    return m ? (m->type == GST_VAAPI_IMAGE_FORMAT_TYPE_RGB) : FALSE;
+}
+
+/**
+ * gst_vaapi_image_format_is_yuv:
+ * @format: a #GstVaapiImageFormat
+ *
+ * Checks whether the format is an YUV format.
+ *
+ * Return value: %TRUE if @format is YUV format
+ */
+gboolean
+gst_vaapi_image_format_is_yuv(GstVaapiImageFormat format)
+{
+    const GstVaapiImageFormatMap * const m = get_map(format);
+
+    return m ? (m->type == GST_VAAPI_IMAGE_FORMAT_TYPE_YCBCR) : FALSE;
+}
+
+/**
+ * gst_vaapi_image_format:
+ * @va_format: a #VAImageFormat
+ *
+ * Converts a VA image format into the corresponding #GstVaapiImageFormat.
+ * If the image format cannot be represented by #GstVaapiImageFormat,
+ * then zero is returned.
+ *
+ * Return value: the #GstVaapiImageFormat describing the @va_format
+ */
+GstVaapiImageFormat
+gst_vaapi_image_format(const VAImageFormat *va_format)
+{
+    const GstVaapiImageFormatMap *m;
+
+    for (m = gst_vaapi_image_formats; m->format; m++)
+        if (m->va_format.fourcc == va_format->fourcc &&
+            (m->type == GST_VAAPI_IMAGE_FORMAT_TYPE_RGB ?
+             match_va_format_rgb(&m->va_format, va_format) :
+             TRUE))
+            return m->format;
+
+    return 0;
+}
+
+/**
+ * gst_vaapi_image_format_from_caps:
+ * @caps: a #GstCaps
+ *
+ * Converts @caps into the corresponding #GstVaapiImageFormat. If the
+ * image format cannot be represented by #GstVaapiImageFormat, then
+ * zero is returned.
+ *
+ * Return value: the #GstVaapiImageFormat describing the @caps
+ */
+GstVaapiImageFormat
+gst_vaapi_image_format_from_caps(GstCaps *caps)
+{
+    const GstVaapiImageFormatMap *m;
+    GstStructure *structure;
+    VAImageFormat *va_format, va_formats[2];
+    gint endian, rmask, gmask, bmask, amask = 0;
+    guint32 fourcc;
+
+    if (!caps)
+        return 0;
+
+    structure = gst_caps_get_structure(caps, 0);
+    if (!structure)
+        return 0;
+
+    /* Check for YUV format */
+    if (gst_structure_get_fourcc(structure, "format", &fourcc))
+        return gst_vaapi_image_format_from_fourcc(fourcc);
+
+    /* Check for RGB format */
+    gst_structure_get_int(structure, "endianness", &endian);
+    gst_structure_get_int(structure, "red_mask",   &rmask);
+    gst_structure_get_int(structure, "green_mask", &gmask);
+    gst_structure_get_int(structure, "blue_mask",  &bmask);
+    gst_structure_get_int(structure, "alpha_mask", &amask);
+
+    va_format = &va_formats[0];
+    va_format->byte_order = endian == G_BIG_ENDIAN ? VA_MSB_FIRST : VA_LSB_FIRST;
+    va_format->red_mask   = rmask;
+    va_format->green_mask = gmask;
+    va_format->blue_mask  = bmask;
+    va_format->alpha_mask = amask;
+
+    va_format = &va_formats[1];
+    va_format->byte_order = endian == G_BIG_ENDIAN ? VA_LSB_FIRST : VA_MSB_FIRST;
+    va_format->red_mask   = GUINT32_SWAP_LE_BE(rmask);
+    va_format->green_mask = GUINT32_SWAP_LE_BE(gmask);
+    va_format->blue_mask  = GUINT32_SWAP_LE_BE(bmask);
+    va_format->alpha_mask = GUINT32_SWAP_LE_BE(amask);
+
+    for (m = gst_vaapi_image_formats; m->format; m++)
+        if (match_va_format_rgb(&m->va_format, &va_formats[0]) ||
+            match_va_format_rgb(&m->va_format, &va_formats[1]))
+            return m->format;
+
+    return 0;
+}
+
+/**
+ * gst_vaapi_image_format_from_fourcc:
+ * @fourcc: a FOURCC value
+ *
+ * Converts a FOURCC value into the corresponding #GstVaapiImageFormat.
+ * If the image format cannot be represented by #GstVaapiImageFormat,
+ * then zero is returned.
+ *
+ * Return value: the #GstVaapiImageFormat describing the FOURCC value
+ */
+GstVaapiImageFormat
+gst_vaapi_image_format_from_fourcc(guint32 fourcc)
+{
+    return (GstVaapiImageFormat)fourcc;
+}
+
+/**
+ * gst_vaapi_image_format_from_video:
+ * @format: a #GstVideoFormat
+ *
+ * Converts a #GstVideoFormat into the corresponding
+ * #GstVaapiImageFormat.  If the image format cannot be represented by
+ * #GstVaapiImageFormat, then zero is returned.
+ *
+ * Return value: the #GstVaapiImageFormat describing the video format
+ */
+GstVaapiImageFormat
+gst_vaapi_image_format_from_video(GstVideoFormat format)
+{
+    GstVaapiImageFormat va_format;
+
+    switch (format) {
+    case GST_VIDEO_FORMAT_NV12: va_format = GST_VAAPI_IMAGE_NV12;   break;
+    case GST_VIDEO_FORMAT_YV12: va_format = GST_VAAPI_IMAGE_YV12;   break;
+    case GST_VIDEO_FORMAT_I420: va_format = GST_VAAPI_IMAGE_I420;   break;
+    case GST_VIDEO_FORMAT_AYUV: va_format = GST_VAAPI_IMAGE_AYUV;   break;
+    case GST_VIDEO_FORMAT_ARGB: va_format = GST_VAAPI_IMAGE_ARGB;   break;
+    case GST_VIDEO_FORMAT_RGBA: va_format = GST_VAAPI_IMAGE_RGBA;   break;
+    case GST_VIDEO_FORMAT_ABGR: va_format = GST_VAAPI_IMAGE_ABGR;   break;
+    case GST_VIDEO_FORMAT_BGRA: va_format = GST_VAAPI_IMAGE_BGRA;   break;
+    default:                    va_format = (GstVaapiImageFormat)0; break;
+    }
+    return va_format;
+}
+
+/**
+ * gst_vaapi_image_format_get_va_format:
+ * @format: a #GstVaapiImageFormat
+ *
+ * Converts a #GstVaapiImageFormat into the corresponding VA image
+ * format. If no matching VA image format was found, %NULL is returned
+ * and this error must be reported to be fixed.
+ *
+ * Return value: the VA image format, or %NULL if none was found
+ */
+const VAImageFormat *
+gst_vaapi_image_format_get_va_format(GstVaapiImageFormat format)
+{
+    const GstVaapiImageFormatMap * const m = get_map(format);
+
+    return m ? &m->va_format : NULL;
+}
+
+/**
+ * gst_vaapi_image_format_get_caps:
+ * @format: a #GstVaapiImageFormat
+ *
+ * Converts a #GstVaapiImageFormat into the corresponding #GstCaps. If
+ * no matching caps were found, %NULL is returned.
+ *
+ * Return value: the newly allocated #GstCaps, or %NULL if none was found
+ */
+GstCaps *
+gst_vaapi_image_format_get_caps(GstVaapiImageFormat format)
+{
+    const GstVaapiImageFormatMap * const m = get_map(format);
+
+    return m ? gst_caps_from_string(m->caps_str) : NULL;
+}
+
+/**
+ * gst_vaapi_image_format_get_score:
+ * @format: a #GstVaapiImageFormat
+ *
+ * Determines how "native" is this @format. The lower is the returned
+ * score, the best format this is for the underlying hardware.
+ *
+ * Return value: the @format score, or %G_MAXUINT if none was found
+ */
+guint
+gst_vaapi_image_format_get_score(GstVaapiImageFormat format)
+{
+    const GstVaapiImageFormatMap * const m = get_map(format);
+
+    return m ? (m - &gst_vaapi_image_formats[0]) : G_MAXUINT;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiimageformat.h b/gst-libs/gst/vaapi/gstvaapiimageformat.h
new file mode 100644 (file)
index 0000000..56af2a4
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *  gstvaapiimageformat.h - VA image format abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_IMAGE_FORMAT_H
+#define GST_VAAPI_IMAGE_FORMAT_H
+
+#include <gst/gstvalue.h>
+#include <gst/video/video.h>
+
+G_BEGIN_DECLS
+
+typedef enum _GstVaapiImageFormat               GstVaapiImageFormat;
+
+/**
+ * GstVaapiImageFormat:
+ * @GST_VAAPI_IMAGE_NV12:
+ *   planar YUV 4:2:0, 12-bit, 1 plane for Y and 1 plane for UV
+ * @GST_VAAPI_IMAGE_YV12:
+ *   planar YUV 4:2:0, 12-bit, 3 planes for Y V U
+ * @GST_VAAPI_IMAGE_I420:
+ *   planar YUV 4:2:0, 12-bit, 3 planes for Y U V
+ * @GST_VAAPI_IMAGE_AYUV:
+ *   packed YUV 4:4:4, 32-bit, A Y U V, native endian byte-order
+ * @GST_VAAPI_IMAGE_ARGB:
+ *   packed RGB 8:8:8, 32-bit, A R G B
+ * @GST_VAAPI_IMAGE_RGBA:
+ *   packed RGB 8:8:8, 32-bit, R G B A
+ * @GST_VAAPI_IMAGE_ABGR:
+ *   packed RGB 8:8:8, 32-bit, A B G R
+ * @GST_VAAPI_IMAGE_BGRA:
+ *   packed RGB 8:8:8, 32-bit, B G R A
+ *
+ * The set of all image formats for #GstVaapiImage.
+ */
+enum _GstVaapiImageFormat {
+    GST_VAAPI_IMAGE_NV12 = GST_MAKE_FOURCC('N','V','1','2'),
+    GST_VAAPI_IMAGE_YV12 = GST_MAKE_FOURCC('Y','V','1','2'),
+    GST_VAAPI_IMAGE_I420 = GST_MAKE_FOURCC('I','4','2','0'),
+    GST_VAAPI_IMAGE_AYUV = GST_MAKE_FOURCC('A','Y','U','V'),
+    GST_VAAPI_IMAGE_ARGB = GST_MAKE_FOURCC('A','R','G','B'),
+    GST_VAAPI_IMAGE_RGBA = GST_MAKE_FOURCC('R','G','B','A'),
+    GST_VAAPI_IMAGE_ABGR = GST_MAKE_FOURCC('A','B','G','R'),
+    GST_VAAPI_IMAGE_BGRA = GST_MAKE_FOURCC('B','G','R','A'),
+};
+
+gboolean
+gst_vaapi_image_format_is_rgb(GstVaapiImageFormat format);
+
+gboolean
+gst_vaapi_image_format_is_yuv(GstVaapiImageFormat format);
+
+GstVaapiImageFormat
+gst_vaapi_image_format(const VAImageFormat *va_format);
+
+GstVaapiImageFormat
+gst_vaapi_image_format_from_caps(GstCaps *caps);
+
+GstVaapiImageFormat
+gst_vaapi_image_format_from_fourcc(guint32 fourcc);
+
+GstVaapiImageFormat
+gst_vaapi_image_format_from_video(GstVideoFormat format);
+
+const VAImageFormat *
+gst_vaapi_image_format_get_va_format(GstVaapiImageFormat format);
+
+GstCaps *
+gst_vaapi_image_format_get_caps(GstVaapiImageFormat format);
+
+guint
+gst_vaapi_image_format_get_score(GstVaapiImageFormat format);
+
+G_END_DECLS
+
+#endif /* GST_GST_VAAPI_IMAGE_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiimagepool.c b/gst-libs/gst/vaapi/gstvaapiimagepool.c
new file mode 100644 (file)
index 0000000..159cb30
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ *  gstvaapiimagepool.c - Gst VA image pool
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapiimagepool
+ * @short_description: VA image pool
+ */
+
+#include "sysdeps.h"
+#include "gstvaapiimagepool.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(
+    GstVaapiImagePool,
+    gst_vaapi_image_pool,
+    GST_VAAPI_TYPE_VIDEO_POOL);
+
+#define GST_VAAPI_IMAGE_POOL_GET_PRIVATE(obj)                   \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_IMAGE_POOL,    \
+                                 GstVaapiImagePoolPrivate))
+
+struct _GstVaapiImagePoolPrivate {
+    GstVaapiImageFormat format;
+    guint               width;
+    guint               height;
+};
+
+static void
+gst_vaapi_image_pool_set_caps(GstVaapiVideoPool *pool, GstCaps *caps)
+{
+    GstVaapiImagePoolPrivate * const priv = GST_VAAPI_IMAGE_POOL(pool)->priv;
+    GstStructure *structure;
+    gint width, height;
+
+    structure = gst_caps_get_structure(caps, 0);
+    gst_structure_get_int(structure, "width", &width);
+    gst_structure_get_int(structure, "height", &height);
+
+    priv->format        = gst_vaapi_image_format_from_caps(caps);
+    priv->width         = width;
+    priv->height        = height;
+}
+
+gpointer
+gst_vaapi_image_pool_alloc_object(
+    GstVaapiVideoPool *pool,
+    GstVaapiDisplay   *display
+)
+{
+    GstVaapiImagePoolPrivate * const priv = GST_VAAPI_IMAGE_POOL(pool)->priv;
+
+    return gst_vaapi_image_new(display,
+                               priv->format,
+                               priv->width,
+                               priv->height);
+}
+
+static void
+gst_vaapi_image_pool_finalize(GObject *object)
+{
+    G_OBJECT_CLASS(gst_vaapi_image_pool_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_image_pool_class_init(GstVaapiImagePoolClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstVaapiVideoPoolClass * const pool_class = GST_VAAPI_VIDEO_POOL_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiImagePoolPrivate));
+
+    object_class->finalize      = gst_vaapi_image_pool_finalize;
+
+    pool_class->set_caps        = gst_vaapi_image_pool_set_caps;
+    pool_class->alloc_object    = gst_vaapi_image_pool_alloc_object;
+}
+
+static void
+gst_vaapi_image_pool_init(GstVaapiImagePool *pool)
+{
+    GstVaapiImagePoolPrivate *priv = GST_VAAPI_IMAGE_POOL_GET_PRIVATE(pool);
+
+    pool->priv          = priv;
+    priv->format        = 0;
+    priv->width         = 0;
+    priv->height        = 0;
+}
+
+/**
+ * gst_vaapi_image_pool_new:
+ * @display: a #GstVaapiDisplay
+ * @caps: a #GstCaps
+ *
+ * Creates a new #GstVaapiVideoPool of #GstVaapiImage with the
+ * specified dimensions in @caps.
+ *
+ * Return value: the newly allocated #GstVaapiVideoPool
+ */
+GstVaapiVideoPool *
+gst_vaapi_image_pool_new(GstVaapiDisplay *display, GstCaps *caps)
+{
+    return g_object_new(GST_VAAPI_TYPE_IMAGE_POOL,
+                        "display", display,
+                        "caps",    caps,
+                        NULL);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiimagepool.h b/gst-libs/gst/vaapi/gstvaapiimagepool.h
new file mode 100644 (file)
index 0000000..2478c47
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ *  gstvaapiimagepool.h - Gst VA image pool
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_IMAGE_POOL_H
+#define GST_VAAPI_IMAGE_POOL_H
+
+#include <gst/vaapi/gstvaapiimage.h>
+#include <gst/vaapi/gstvaapivideopool.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_IMAGE_POOL \
+    (gst_vaapi_image_pool_get_type())
+
+#define GST_VAAPI_IMAGE_POOL(obj)                               \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_IMAGE_POOL,      \
+                                GstVaapiImagePool))
+
+#define GST_VAAPI_IMAGE_POOL_CLASS(klass)                       \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_IMAGE_POOL,         \
+                             GstVaapiImagePoolClass))
+
+#define GST_VAAPI_IS_IMAGE_POOL(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_IMAGE_POOL))
+
+#define GST_VAAPI_IS_IMAGE_POOL_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_IMAGE_POOL))
+
+#define GST_VAAPI_IMAGE_POOL_GET_CLASS(obj)                     \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_IMAGE_POOL,       \
+                               GstVaapiImagePoolClass))
+
+typedef struct _GstVaapiImagePool               GstVaapiImagePool;
+typedef struct _GstVaapiImagePoolPrivate        GstVaapiImagePoolPrivate;
+typedef struct _GstVaapiImagePoolClass          GstVaapiImagePoolClass;
+
+/**
+ * GstVaapiImagePool:
+ *
+ * A pool of lazily allocated #GstVaapiImage objects.
+ */
+struct _GstVaapiImagePool {
+    /*< private >*/
+    GstVaapiVideoPool parent_instance;
+
+    GstVaapiImagePoolPrivate *priv;
+};
+
+/**
+ * GstVaapiImagePoolClass:
+ *
+ * A pool of lazily allocated #GstVaapiImage objects.
+ */
+struct _GstVaapiImagePoolClass {
+    /*< private >*/
+    GstVaapiVideoPoolClass parent_class;
+};
+
+GType
+gst_vaapi_image_pool_get_type(void) G_GNUC_CONST;
+
+GstVaapiVideoPool *
+gst_vaapi_image_pool_new(GstVaapiDisplay *display, GstCaps *caps);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_IMAGE_POOL_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiobject.c b/gst-libs/gst/vaapi/gstvaapiobject.c
new file mode 100644 (file)
index 0000000..ad3d139
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ *  gstvaapiobject.c - Base VA object
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapiobject
+ * @short_description: Base VA object
+ */
+
+#include "sysdeps.h"
+#include "gstvaapiobject.h"
+#include "gstvaapi_priv.h"
+#include "gstvaapiparamspecs.h"
+#include "gstvaapivalue.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiObject, gst_vaapi_object, G_TYPE_OBJECT);
+
+enum {
+    PROP_0,
+
+    PROP_DISPLAY,
+    PROP_ID
+};
+
+enum {
+    DESTROY,
+
+    LAST_SIGNAL
+};
+
+static guint object_signals[LAST_SIGNAL] = { 0, };
+
+static void
+gst_vaapi_object_dispose(GObject *object)
+{
+    GstVaapiObjectPrivate * const priv = GST_VAAPI_OBJECT(object)->priv;
+
+    if (!priv->is_destroying) {
+        priv->is_destroying = TRUE;
+        g_signal_emit(object, object_signals[DESTROY], 0);
+        priv->is_destroying = FALSE;
+    }
+
+    G_OBJECT_CLASS(gst_vaapi_object_parent_class)->dispose(object);
+}
+
+static void
+gst_vaapi_object_finalize(GObject *object)
+{
+    GstVaapiObjectPrivate * const priv = GST_VAAPI_OBJECT(object)->priv;
+
+    priv->id = GST_VAAPI_ID_NONE;
+
+    g_clear_object(&priv->display);
+
+    G_OBJECT_CLASS(gst_vaapi_object_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_object_set_property(
+    GObject      *gobject,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiObject * const object = GST_VAAPI_OBJECT(gobject);
+
+    switch (prop_id) {
+    case PROP_DISPLAY:
+        object->priv->display = g_object_ref(g_value_get_object(value));
+        break;
+    case PROP_ID:
+        object->priv->id = gst_vaapi_value_get_id(value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_object_get_property(
+    GObject    *gobject,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiObject * const object = GST_VAAPI_OBJECT(gobject);
+
+    switch (prop_id) {
+    case PROP_DISPLAY:
+        g_value_set_object(value, gst_vaapi_object_get_display(object));
+        break;
+    case PROP_ID:
+        gst_vaapi_value_set_id(value, gst_vaapi_object_get_id(object));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_object_class_init(GstVaapiObjectClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiObjectPrivate));
+
+    object_class->dispose      = gst_vaapi_object_dispose;
+    object_class->finalize     = gst_vaapi_object_finalize;
+    object_class->set_property = gst_vaapi_object_set_property;
+    object_class->get_property = gst_vaapi_object_get_property;
+
+    /**
+     * GstVaapiObject:display:
+     *
+     * The #GstVaapiDisplay this object is bound to.
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_DISPLAY,
+         g_param_spec_object("display",
+                             "Display",
+                             "The GstVaapiDisplay this object is bound to",
+                             GST_VAAPI_TYPE_DISPLAY,
+                             G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    /**
+     * GstVaapiObject:id:
+     *
+     * The #GstVaapiID contained in this object.
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_ID,
+         gst_vaapi_param_spec_id("id",
+                                 "ID",
+                                 "The GstVaapiID contained in this object",
+                                 GST_VAAPI_ID_NONE,
+                                 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    /**
+     * GstVaapiObject::destroy:
+     * @object: the object which received the signal
+     *
+     * The ::destroy signal is emitted when an object is destroyed,
+     * when the user released the last reference to @object.
+     */
+    object_signals[DESTROY] = g_signal_new(
+        "destroy",
+        G_TYPE_FROM_CLASS(object_class),
+        G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
+        G_STRUCT_OFFSET(GstVaapiObjectClass, destroy),
+        NULL, NULL,
+        g_cclosure_marshal_VOID__VOID,
+        G_TYPE_NONE, 0
+    );
+}
+
+static void
+gst_vaapi_object_init(GstVaapiObject *object)
+{
+    GstVaapiObjectPrivate *priv = GST_VAAPI_OBJECT_GET_PRIVATE(object);
+
+    object->priv        = priv;
+    priv->display       = NULL;
+    priv->id            = GST_VAAPI_ID_NONE;
+    priv->is_destroying = FALSE;
+}
+
+/**
+ * gst_vaapi_object_get_display:
+ * @object: a #GstVaapiObject
+ *
+ * Returns the #GstVaapiDisplay this @object is bound to.
+ *
+ * Return value: the parent #GstVaapiDisplay object
+ */
+GstVaapiDisplay *
+gst_vaapi_object_get_display(GstVaapiObject *object)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_OBJECT(object), NULL);
+
+    return object->priv->display;
+}
+
+/**
+ * gst_vaapi_object_lock_display:
+ * @object: a #GstVaapiObject
+ *
+ * Locks @object parent display. If display is already locked by
+ * another thread, the current thread will block until display is
+ * unlocked by the other thread.
+ */
+void
+gst_vaapi_object_lock_display(GstVaapiObject *object)
+{
+    g_return_if_fail(GST_VAAPI_IS_OBJECT(object));
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(object);
+}
+
+/**
+ * gst_vaapi_object_unlock_display:
+ * @object: a #GstVaapiObject
+ *
+ * Unlocks @object parent display. If another thread is blocked in a
+ * gst_vaapi_object_lock_display() call, it will be woken and can lock
+ * display itself.
+ */
+void
+gst_vaapi_object_unlock_display(GstVaapiObject *object)
+{
+    g_return_if_fail(GST_VAAPI_IS_OBJECT(object));
+
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(object);
+}
+
+/**
+ * gst_vaapi_object_get_id:
+ * @object: a #GstVaapiObject
+ *
+ * Returns the #GstVaapiID contained in the @object.
+ *
+ * Return value: the #GstVaapiID of the @object
+ */
+GstVaapiID
+gst_vaapi_object_get_id(GstVaapiObject *object)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_OBJECT(object), GST_VAAPI_ID_NONE);
+
+    return object->priv->id;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiobject.h b/gst-libs/gst/vaapi/gstvaapiobject.h
new file mode 100644 (file)
index 0000000..913cac8
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ *  gstvaapiobject.h - Base VA object
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_OBJECT_H
+#define GST_VAAPI_OBJECT_H
+
+#include <gst/vaapi/gstvaapitypes.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_OBJECT \
+    (gst_vaapi_object_get_type())
+
+#define GST_VAAPI_OBJECT(obj)                           \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                  \
+                                GST_VAAPI_TYPE_OBJECT,  \
+                                GstVaapiObject))
+
+#define GST_VAAPI_OBJECT_CLASS(klass)                   \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                   \
+                             GST_VAAPI_TYPE_OBJECT,     \
+                             GstVaapiObjectClass))
+
+#define GST_VAAPI_IS_OBJECT(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_OBJECT))
+
+#define GST_VAAPI_IS_OBJECT_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_OBJECT))
+
+#define GST_VAAPI_OBJECT_GET_CLASS(obj)                 \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                   \
+                               GST_VAAPI_TYPE_OBJECT,   \
+                               GstVaapiObjectClass))
+
+typedef struct _GstVaapiObject                  GstVaapiObject;
+typedef struct _GstVaapiObjectPrivate           GstVaapiObjectPrivate;
+typedef struct _GstVaapiObjectClass             GstVaapiObjectClass;
+
+/**
+ * GstVaapiObject:
+ *
+ * VA object base.
+ */
+struct _GstVaapiObject {
+    /*< private >*/
+    GObject parent_instance;
+
+    GstVaapiObjectPrivate *priv;
+};
+
+/**
+ * GstVaapiObjectClass:
+ * @destroy: signal class handler for #GstVaapiObject::destroy
+ *
+ * VA object base class.
+ */
+struct _GstVaapiObjectClass {
+    /*< private >*/
+    GObjectClass parent_class;
+
+    /*< public >*/
+    void (*destroy)(GstVaapiObject *oject);
+};
+
+GType
+gst_vaapi_object_get_type(void) G_GNUC_CONST;
+
+GstVaapiDisplay *
+gst_vaapi_object_get_display(GstVaapiObject *object);
+
+void
+gst_vaapi_object_lock_display(GstVaapiObject *object);
+
+void
+gst_vaapi_object_unlock_display(GstVaapiObject *object);
+
+GstVaapiID
+gst_vaapi_object_get_id(GstVaapiObject *object);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_OBJECT_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiobject_priv.h b/gst-libs/gst/vaapi/gstvaapiobject_priv.h
new file mode 100644 (file)
index 0000000..aa1b110
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ *  gstvaapiobject_priv.h - Base VA object (private definitions)
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_OBJECT_PRIV_H
+#define GST_VAAPI_OBJECT_PRIV_H
+
+#include <gst/vaapi/gstvaapiobject.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_OBJECT_GET_PRIVATE(obj)                       \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_OBJECT,         \
+                                 GstVaapiObjectPrivate))
+
+#define GST_VAAPI_OBJECT_CAST(object) ((GstVaapiObject *)(object))
+
+/**
+ * GST_VAAPI_OBJECT_DISPLAY:
+ * @object: a #GstVaapiObject
+ *
+ * Macro that evaluates to the #GstVaapiDisplay the @object is bound to.
+ * This is an internal macro that does not do any run-time type check.
+ */
+#define GST_VAAPI_OBJECT_DISPLAY(object) \
+    GST_VAAPI_OBJECT_CAST(object)->priv->display
+
+/**
+ * GST_VAAPI_OBJECT_ID:
+ * @object: a #GstVaapiObject
+ *
+ * Macro that evaluates to the #GstVaapiID contained in @object.
+ * This is an internal macro that does not do any run-time type checks.
+ */
+#define GST_VAAPI_OBJECT_ID(object) \
+    GST_VAAPI_OBJECT_CAST(object)->priv->id
+
+/**
+ * GST_VAAPI_OBJECT_DISPLAY_X11:
+ * @object: a #GstVaapiObject
+ *
+ * Macro that evaluates to the #GstVaapiDisplayX11 the @object is bound to.
+ * This is an internal macro that does not do any run-time type check
+ * and requires #include "gstvaapidisplay_x11_priv.h"
+ */
+#define GST_VAAPI_OBJECT_DISPLAY_X11(object) \
+    GST_VAAPI_DISPLAY_X11_CAST(GST_VAAPI_OBJECT_DISPLAY(object))
+
+/**
+ * GST_VAAPI_OBJECT_DISPLAY_GLX:
+ * @object: a #GstVaapiObject
+ *
+ * Macro that evaluates to the #GstVaapiDisplayGLX the @object is bound to.
+ * This is an internal macro that does not do any run-time type check
+ * and requires #include "gstvaapidisplay_glx_priv.h".
+ */
+#define GST_VAAPI_OBJECT_DISPLAY_GLX(object) \
+    GST_VAAPI_DISPLAY_GLX_CAST(GST_VAAPI_OBJECT_DISPLAY(object))
+
+/**
+ * GST_VAAPI_OBJECT_DISPLAY_WAYLAND:
+ * @object: a #GstVaapiObject
+ *
+ * Macro that evaluates to the #GstVaapiDisplayWayland the @object is
+ * bound to.  This is an internal macro that does not do any run-time
+ * type check and requires #include "gstvaapidisplay_wayland_priv.h"
+ */
+#define GST_VAAPI_OBJECT_DISPLAY_WAYLAND(object) \
+    GST_VAAPI_DISPLAY_WAYLAND_CAST(GST_VAAPI_OBJECT_DISPLAY(object))
+
+/**
+ * GST_VAAPI_OBJECT_VADISPLAY:
+ * @object: a #GstVaapiObject
+ *
+ * Macro that evaluates to the #VADisplay of @display.
+ * This is an internal macro that does not do any run-time type check
+ * and requires #include "gstvaapidisplay_priv.h".
+ */
+#define GST_VAAPI_OBJECT_VADISPLAY(object) \
+    GST_VAAPI_DISPLAY_VADISPLAY(GST_VAAPI_OBJECT_DISPLAY(object))
+
+/**
+ * GST_VAAPI_OBJECT_XDISPLAY:
+ * @object: a #GstVaapiObject
+ *
+ * Macro that evaluates to the underlying X11 #Display of @display.
+ * This is an internal macro that does not do any run-time type check
+ * and requires #include "gstvaapidisplay_x11_priv.h".
+ */
+#define GST_VAAPI_OBJECT_XDISPLAY(object) \
+    GST_VAAPI_DISPLAY_XDISPLAY(GST_VAAPI_OBJECT_DISPLAY(object))
+
+/**
+ * GST_VAAPI_OBJECT_XSCREEN:
+ * @object: a #GstVaapiObject
+ *
+ * Macro that evaluates to the underlying X11 screen of @display.
+ * This is an internal macro that does not do any run-time type check
+ * and requires #include "gstvaapidisplay_x11_priv.h".
+ */
+#define GST_VAAPI_OBJECT_XSCREEN(object) \
+    GST_VAAPI_DISPLAY_XSCREEN(GST_VAAPI_OBJECT_DISPLAY(object))
+
+/**
+ * GST_VAAPI_OBJECT_WL_DISPLAY:
+ * @object: a #GstVaapiObject
+ *
+ * Macro that evaluates to the underlying #wl_display of @display.
+ * This is an internal macro that does not do any run-time type check
+ * and requires #include "gstvaapidisplay_wayland_priv.h".
+ */
+#define GST_VAAPI_OBJECT_WL_DISPLAY(object) \
+    GST_VAAPI_DISPLAY_WL_DISPLAY(GST_VAAPI_OBJECT_DISPLAY(object))
+
+/**
+ * GST_VAAPI_OBJECT_LOCK_DISPLAY:
+ * @object: a #GstVaapiObject
+ *
+ * Macro that locks the #GstVaapiDisplay contained in the @object.
+ * This is an internal macro that does not do any run-time type check.
+ */
+#define GST_VAAPI_OBJECT_LOCK_DISPLAY(object) \
+    GST_VAAPI_DISPLAY_LOCK(GST_VAAPI_OBJECT_DISPLAY(object))
+
+/**
+ * GST_VAAPI_OBJECT_UNLOCK_DISPLAY:
+ * @object: a #GstVaapiObject
+ *
+ * Macro that unlocks the #GstVaapiDisplay contained in the @object.
+ * This is an internal macro that does not do any run-time type check.
+ */
+#define GST_VAAPI_OBJECT_UNLOCK_DISPLAY(object) \
+    GST_VAAPI_DISPLAY_UNLOCK(GST_VAAPI_OBJECT_DISPLAY(object))
+
+/**
+ * GstVaapiObjectPrivate:
+ *
+ * VA object base.
+ */
+struct _GstVaapiObjectPrivate {
+    GstVaapiDisplay    *display;
+    GstVaapiID          id;
+    guint               is_destroying   : 1;
+};
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_OBJECT_PRIV_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiparamspecs.c b/gst-libs/gst/vaapi/gstvaapiparamspecs.c
new file mode 100644 (file)
index 0000000..8905af4
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ *  gstvaapiparamspecs.c - GParamSpecs for some of our types
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapiparamspecs
+ * @short_description: GParamSpecs for some of our types
+ */
+
+#include "sysdeps.h"
+#include "gstvaapiparamspecs.h"
+#include "gstvaapivalue.h"
+
+/* --- GstVaapiParamSpecID --- */
+
+static void
+gst_vaapi_param_id_init(GParamSpec *pspec)
+{
+    GST_VAAPI_PARAM_SPEC_ID(pspec)->default_value = GST_VAAPI_ID_NONE;
+}
+
+static void
+gst_vaapi_param_id_set_default(GParamSpec *pspec, GValue *value)
+{
+    gst_vaapi_value_set_id(value, GST_VAAPI_PARAM_SPEC_ID(pspec)->default_value);
+}
+
+static gboolean
+gst_vaapi_param_id_validate(GParamSpec *pspec, GValue *value)
+{
+    /* Return FALSE if everything is OK, otherwise TRUE */
+    return FALSE;
+}
+
+static gint
+gst_vaapi_param_id_compare(
+    GParamSpec   *pspec,
+    const GValue *value1,
+    const GValue *value2
+)
+{
+    const GstVaapiID v1 = gst_vaapi_value_get_id(value1);
+    const GstVaapiID v2 = gst_vaapi_value_get_id(value2);
+
+    return (v1 < v2 ? -1 : (v1 > v2 ? 1 : 0));
+}
+
+GType
+gst_vaapi_param_spec_id_get_type(void)
+{
+    static GType type;
+
+    if (G_UNLIKELY(type == 0)) {
+        static GParamSpecTypeInfo pspec_info = {
+            sizeof(GstVaapiParamSpecID),        /* instance_size     */
+            0,                                  /* n_preallocs       */
+            gst_vaapi_param_id_init,            /* instance_init     */
+            G_TYPE_INVALID,                     /* value_type        */
+            NULL,                               /* finalize          */
+            gst_vaapi_param_id_set_default,     /* value_set_default */
+            gst_vaapi_param_id_validate,        /* value_validate    */
+            gst_vaapi_param_id_compare,         /* values_cmp        */
+        };
+        pspec_info.value_type = GST_VAAPI_TYPE_ID;
+        type = g_param_type_register_static("GstVaapiParamSpecID", &pspec_info);
+    }
+    return type;
+}
+
+/**
+ * gst_vaapi_param_spec_id:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @default_value: default value
+ * @flags: flags for the property specified
+ *
+ * This function creates an ID GParamSpec for use by #GstVaapiObject
+ * objects. This function is typically used in connection with
+ * g_object_class_install_property() in a GObjects's instance_init
+ * function.
+ *
+ * Return value: a newly created parameter specification
+ */
+GParamSpec *
+gst_vaapi_param_spec_id(
+    const gchar *name,
+    const gchar *nick,
+    const gchar *blurb,
+    GstVaapiID   default_value,
+    GParamFlags  flags
+)
+{
+    GstVaapiParamSpecID *ispec;
+    GParamSpec *pspec;
+    GValue value = { 0, };
+
+    ispec = g_param_spec_internal(
+        GST_VAAPI_TYPE_PARAM_ID,
+        name,
+        nick,
+        blurb,
+        flags
+    );
+    if (!ispec)
+        return NULL;
+
+    ispec->default_value = default_value;
+    pspec = G_PARAM_SPEC(ispec);
+
+    /* Validate default value */
+    g_value_init(&value, GST_VAAPI_TYPE_ID);
+    gst_vaapi_value_set_id(&value, default_value);
+    if (gst_vaapi_param_id_validate(pspec, &value)) {
+        g_param_spec_ref(pspec);
+        g_param_spec_sink(pspec);
+        g_param_spec_unref(pspec);
+        pspec = NULL;
+    }
+    g_value_unset(&value);
+
+    return pspec;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiparamspecs.h b/gst-libs/gst/vaapi/gstvaapiparamspecs.h
new file mode 100644 (file)
index 0000000..5b20149
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *  gstvaapiparamspecs.h - GParamSpecs for some of our types
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_PARAM_SPECS_H
+#define GST_VAAPI_PARAM_SPECS_H
+
+#include <gst/vaapi/gstvaapitypes.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/**
+ * GstVaapiParamSpecID:
+ * @parent_instance: super class
+ * @default_value: default value
+ *
+ * A GParamSpec derived structure that contains the meta data for
+ * #GstVaapiID properties.
+ */
+typedef struct _GstVaapiParamSpecID GstVaapiParamSpecID;
+struct _GstVaapiParamSpecID {
+    GParamSpec  parent_instance;
+
+    GstVaapiID  default_value;
+};
+
+#define GST_VAAPI_TYPE_PARAM_ID \
+    (gst_vaapi_param_spec_id_get_type())
+
+#define GST_VAAPI_IS_PARAM_SPEC_ID(pspec)                       \
+    (G_TYPE_CHECK_INSTANCE_TYPE((pspec),                        \
+                                GST_VAAPI_TYPE_PARAM_ID))
+
+#define GST_VAAPI_PARAM_SPEC_ID(pspec)                          \
+    (G_TYPE_CHECK_INSTANCE_CAST((pspec),                        \
+                                GST_VAAPI_TYPE_PARAM_ID,        \
+                                GstVaapiParamSpecID))
+
+GType
+gst_vaapi_param_spec_id_get_type(void) G_GNUC_CONST;
+
+GParamSpec *
+gst_vaapi_param_spec_id(
+    const gchar *name,
+    const gchar *nick,
+    const gchar *blurb,
+    GstVaapiID   default_value,
+    GParamFlags  flags
+);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_PARAM_SPECS_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiprofile.c b/gst-libs/gst/vaapi/gstvaapiprofile.c
new file mode 100644 (file)
index 0000000..7536c44
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ *  gstvaapiprofile.c - VA profile abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapiprofile
+ * @short_description: VA profile abstraction
+ */
+
+#include "sysdeps.h"
+#include <string.h>
+#include <gst/gstbuffer.h>
+#include "gstvaapicompat.h"
+#include "gstvaapiprofile.h"
+#include "gstvaapiworkarounds.h"
+
+typedef struct _GstVaapiProfileMap              GstVaapiProfileMap;
+typedef struct _GstVaapiEntrypointMap           GstVaapiEntrypointMap;
+
+struct _GstVaapiProfileMap {
+    GstVaapiProfile             profile;
+    VAProfile                   va_profile;
+    const char                 *caps_str;
+    const gchar                *profile_str;
+};
+
+struct _GstVaapiEntrypointMap {
+    GstVaapiEntrypoint          entrypoint;
+    VAEntrypoint                va_entrypoint;
+};
+
+/* Profiles */
+static const GstVaapiProfileMap gst_vaapi_profiles[] = {
+    { GST_VAAPI_PROFILE_MPEG2_SIMPLE, VAProfileMPEG2Simple,
+      "video/mpeg, mpegversion=2", "simple"
+    },
+    { GST_VAAPI_PROFILE_MPEG2_MAIN, VAProfileMPEG2Main,
+      "video/mpeg, mpegversion=2", "main"
+    },
+    { GST_VAAPI_PROFILE_MPEG4_SIMPLE, VAProfileMPEG4Simple,
+      "video/mpeg, mpegversion=4", "simple"
+    },
+    { GST_VAAPI_PROFILE_MPEG4_ADVANCED_SIMPLE, VAProfileMPEG4AdvancedSimple,
+      "video/mpeg, mpegversion=4", "advanced-simple"
+    },
+    { GST_VAAPI_PROFILE_MPEG4_MAIN, VAProfileMPEG4Main,
+      "video/mpeg, mpegversion=4", "main"
+    },
+    { GST_VAAPI_PROFILE_MPEG4_ADVANCED_SIMPLE, VAProfileMPEG4AdvancedSimple,
+      "video/x-divx, divxversion=5", "advanced-simple"
+    },
+    { GST_VAAPI_PROFILE_MPEG4_ADVANCED_SIMPLE, VAProfileMPEG4AdvancedSimple,
+      "video/x-xvid", "advanced-simple"
+    },
+#if VA_CHECK_VERSION(0,30,0)
+    { GST_VAAPI_PROFILE_H263_BASELINE, VAProfileH263Baseline,
+      "video/x-h263, variant=itu, h263version=h263", "baseline"
+    },
+#endif
+    { GST_VAAPI_PROFILE_H264_BASELINE, VAProfileH264Baseline,
+      "video/x-h264", "baseline"
+    },
+    { GST_VAAPI_PROFILE_H264_MAIN, VAProfileH264Main,
+      "video/x-h264", "main"
+    },
+    { GST_VAAPI_PROFILE_H264_HIGH, VAProfileH264High,
+      "video/x-h264", "high"
+    },
+    { GST_VAAPI_PROFILE_VC1_SIMPLE, VAProfileVC1Simple,
+      "video/x-wmv, wmvversion=3", "simple"
+    },
+    { GST_VAAPI_PROFILE_VC1_MAIN, VAProfileVC1Main,
+      "video/x-wmv, wmvversion=3", "main"
+    },
+    { GST_VAAPI_PROFILE_VC1_ADVANCED, VAProfileVC1Advanced,
+      "video/x-wmv, wmvversion=3, format=(fourcc)WVC1", "advanced"
+    },
+#if VA_CHECK_VERSION(0,32,0)
+    { GST_VAAPI_PROFILE_JPEG_BASELINE, VAProfileJPEGBaseline,
+      "image/jpeg", "baseline"
+    },
+#endif
+    { 0, }
+};
+
+/* Entry-points */
+static const GstVaapiEntrypointMap gst_vaapi_entrypoints[] = {
+    { GST_VAAPI_ENTRYPOINT_VLD,          VAEntrypointVLD        },
+    { GST_VAAPI_ENTRYPOINT_IDCT,         VAEntrypointIDCT       },
+    { GST_VAAPI_ENTRYPOINT_MOCO,         VAEntrypointMoComp     },
+#if VA_CHECK_VERSION(0,30,0)
+    { GST_VAAPI_ENTRYPOINT_SLICE_ENCODE, VAEntrypointEncSlice   },
+#endif
+    { 0, }
+};
+
+static const GstVaapiProfileMap *
+get_profiles_map(GstVaapiProfile profile)
+{
+    const GstVaapiProfileMap *m;
+
+    for (m = gst_vaapi_profiles; m->profile; m++)
+        if (m->profile == profile)
+            return m;
+    return NULL;
+}
+
+static const GstVaapiEntrypointMap *
+get_entrypoints_map(GstVaapiEntrypoint entrypoint)
+{
+    const GstVaapiEntrypointMap *m;
+
+    for (m = gst_vaapi_entrypoints; m->entrypoint; m++)
+        if (m->entrypoint == entrypoint)
+            return m;
+    return NULL;
+}
+
+/**
+ * gst_vaapi_profile:
+ * @profile: a #VAProfile
+ *
+ * Converts a VA profile into the corresponding #GstVaapiProfile. If
+ * the profile cannot be represented by #GstVaapiProfile, then zero is
+ * returned.
+ *
+ * Return value: the #GstVaapiProfile describing the @profile
+ */
+GstVaapiProfile
+gst_vaapi_profile(VAProfile profile)
+{
+    const GstVaapiProfileMap *m;
+
+    for (m = gst_vaapi_profiles; m->profile; m++)
+        if (m->va_profile == profile)
+            return m->profile;
+    return 0;
+}
+
+/**
+ * gst_vaapi_profile_from_codec_data:
+ * @codec: a #GstVaapiCodec
+ * @buffer: a #GstBuffer holding code data
+ *
+ * Tries to parse VA profile from @buffer data and @codec information.
+ *
+ * Return value: the #GstVaapiProfile described in @buffer
+ */
+static GstVaapiProfile
+gst_vaapi_profile_from_codec_data_h264(GstBuffer *buffer)
+{
+    /* MPEG-4 Part 15: Advanced Video Coding (AVC) file format */
+    guchar * const buf = GST_BUFFER_DATA(buffer);
+
+    if (buf[0] != 1)    /* configurationVersion = 1 */
+        return 0;
+
+    switch (buf[1]) {   /* AVCProfileIndication */
+    case 66:    return GST_VAAPI_PROFILE_H264_BASELINE;
+    case 77:    return GST_VAAPI_PROFILE_H264_MAIN;
+    case 100:   return GST_VAAPI_PROFILE_H264_HIGH;
+    }
+    return 0;
+}
+
+static GstVaapiProfile
+gst_vaapi_profile_from_codec_data(GstVaapiCodec codec, GstBuffer *buffer)
+{
+    GstVaapiProfile profile;
+
+    if (!codec || !buffer)
+        return 0;
+
+    switch (codec) {
+    case GST_VAAPI_CODEC_H264:
+        profile = gst_vaapi_profile_from_codec_data_h264(buffer);
+        break;
+    default:
+        profile = 0;
+        break;
+    }
+    return profile;
+}
+
+/**
+ * gst_vaapi_profile_from_caps:
+ * @caps: a #GstCaps
+ *
+ * Converts @caps into the corresponding #GstVaapiProfile. If the
+ * profile cannot be represented by #GstVaapiProfile, then zero is
+ * returned.
+ *
+ * Return value: the #GstVaapiProfile describing the @caps
+ */
+GstVaapiProfile
+gst_vaapi_profile_from_caps(GstCaps *caps)
+{
+    const GstVaapiProfileMap *m;
+    GstCaps *caps_test;
+    GstStructure *structure;
+    const gchar *profile_str;
+    GstVaapiProfile profile, best_profile;
+    GstBuffer *codec_data = NULL;
+    const gchar *name;
+    gsize namelen;
+
+    if (!caps)
+        return 0;
+
+    structure = gst_caps_get_structure(caps, 0);
+    if (!structure)
+        return 0;
+
+    name    = gst_structure_get_name(structure);
+    namelen = strlen(name);
+
+    profile_str = gst_structure_get_string(structure, "profile");
+    if (!profile_str) {
+        const GValue *v_codec_data;
+        v_codec_data = gst_structure_get_value(structure, "codec_data");
+        if (v_codec_data)
+            codec_data = gst_value_get_buffer(v_codec_data);
+    }
+
+    profile = 0;
+    best_profile = 0;
+    for (m = gst_vaapi_profiles; !profile && m->profile; m++) {
+        if (strncmp(name, m->caps_str, namelen) != 0)
+            continue;
+        caps_test = gst_caps_from_string(m->caps_str);;
+        if (gst_caps_is_always_compatible(caps, caps_test)) {
+            best_profile = m->profile;
+            if (profile_str && m->profile_str &&
+                strcmp(profile_str, m->profile_str) == 0)
+                profile = best_profile;
+        }
+        if (!profile) {
+            profile = gst_vaapi_profile_from_codec_data(
+                gst_vaapi_profile_get_codec(m->profile),
+                codec_data
+            );
+            if (!profile &&
+                WORKAROUND_QTDEMUX_NO_H263_PROFILES &&
+                strncmp(name, "video/x-h263", namelen) == 0) {
+                /* HACK: qtdemux does not report profiles for h263 */
+                profile = m->profile;
+            }
+        }
+        gst_caps_unref(caps_test);
+    }
+    return profile ? profile : best_profile;
+}
+
+/**
+ * gst_vaapi_profile_get_va_profile:
+ * @profile: a #GstVaapiProfile
+ *
+ * Converts a #GstVaapiProfile into the corresponding VA profile. If
+ * no matching VA profile was found, -1 is returned and this error
+ * must be reported to be fixed.
+ *
+ * Return value: the VA profile, or -1 if none was found
+ */
+VAProfile
+gst_vaapi_profile_get_va_profile(GstVaapiProfile profile)
+{
+    const GstVaapiProfileMap * const m = get_profiles_map(profile);
+
+    return m ? m->va_profile : (VAProfile)-1;
+}
+
+/**
+ * gst_vaapi_profile_get_caps:
+ * @profile: a #GstVaapiProfile
+ *
+ * Converts a #GstVaapiProfile into the corresponding #GstCaps. If no
+ * matching caps were found, %NULL is returned.
+ *
+ * Return value: the newly allocated #GstCaps, or %NULL if none was found
+ */
+GstCaps *
+gst_vaapi_profile_get_caps(GstVaapiProfile profile)
+{
+    const GstVaapiProfileMap *m;
+    GstCaps *out_caps, *caps;
+
+    out_caps = gst_caps_new_empty();
+    if (!out_caps)
+        return NULL;
+
+    for (m = gst_vaapi_profiles; m->profile; m++) {
+        if (m->profile != profile)
+            continue;
+        caps = gst_caps_from_string(m->caps_str);
+        if (!caps)
+            continue;
+        gst_caps_set_simple(
+            caps,
+            "profile", G_TYPE_STRING, m->profile_str,
+            NULL
+        );
+        gst_caps_merge(out_caps, caps);
+    }
+    return out_caps;
+}
+
+/**
+ * gst_vaapi_profile_get_codec:
+ * @profile: a #GstVaapiProfile
+ *
+ * Extracts the #GstVaapiCodec from @profile.
+ *
+ * Return value: the #GstVaapiCodec from @profile
+ */
+GstVaapiCodec
+gst_vaapi_profile_get_codec(GstVaapiProfile profile)
+{
+    GstVaapiCodec codec;
+
+    switch (profile) {
+    case GST_VAAPI_PROFILE_VC1_SIMPLE:
+    case GST_VAAPI_PROFILE_VC1_MAIN:
+        codec = GST_VAAPI_CODEC_WMV3;
+        break;
+    case GST_VAAPI_PROFILE_VC1_ADVANCED:
+        codec = GST_VAAPI_CODEC_VC1;
+        break;
+    case GST_VAAPI_PROFILE_JPEG_BASELINE:
+        codec = GST_VAAPI_CODEC_JPEG;
+        break;
+    default:
+        codec = (guint32)profile & GST_MAKE_FOURCC(0xff,0xff,0xff,0);
+        break;
+    }
+    return codec;
+}
+
+/**
+ * gst_vaapi_entrypoint:
+ * @entrypoint: a #VAEntrypoint
+ *
+ * Converts a VA entry-point into the corresponding #GstVaapiEntrypoint.
+ * If the entry-point cannot be represented by #GstVaapiEntrypoint,
+ * then zero is returned.
+ *
+ * Return value: the #GstVaapiEntrypoint describing the @entrypoint
+ */
+GstVaapiEntrypoint
+gst_vaapi_entrypoint(VAEntrypoint entrypoint)
+{
+    const GstVaapiEntrypointMap *m;
+
+    for (m = gst_vaapi_entrypoints; m->entrypoint; m++)
+        if (m->va_entrypoint == entrypoint)
+            return m->entrypoint;
+    return 0;
+}
+
+/**
+ * gst_vaapi_entrypoint_get_va_entrypoint:
+ * @entrypoint: a #GstVaapiEntrypoint
+ *
+ * Converts a #GstVaapiEntrypoint into the corresponding VA
+ * entry-point. If no matching VA entry-point was found, -1 is
+ * returned and this error must be reported to be fixed.
+ *
+ * Return value: the VA entry-point, or -1 if none was found
+ */
+VAEntrypoint
+gst_vaapi_entrypoint_get_va_entrypoint(GstVaapiEntrypoint entrypoint)
+{
+    const GstVaapiEntrypointMap * const m = get_entrypoints_map(entrypoint);
+
+    return m ? m->va_entrypoint : (VAEntrypoint)-1;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiprofile.h b/gst-libs/gst/vaapi/gstvaapiprofile.h
new file mode 100644 (file)
index 0000000..986c9a2
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ *  gstvaapiprofile.h - VA profile abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_PROFILE_H
+#define GST_VAAPI_PROFILE_H
+
+#include <gst/gstvalue.h>
+
+G_BEGIN_DECLS
+
+typedef enum _GstVaapiCodec                     GstVaapiCodec;
+typedef enum _GstVaapiProfile                   GstVaapiProfile;
+typedef enum _GstVaapiEntrypoint                GstVaapiEntrypoint;
+
+/**
+ * GstVaapiCodec:
+ * @GST_VAAPI_CODEC_MPEG1: MPEG-1 (ISO/IEC 11172)
+ * @GST_VAAPI_CODEC_MPEG2: MPEG-2 (ISO/IEC 13818-2)
+ * @GST_VAAPI_CODEC_MPEG4: MPEG-4 Part 2 (ISO/IEC 14496-2)
+ * @GST_VAAPI_CODEC_H263: H.263
+ * @GST_VAAPI_CODEC_H264: H.264 aka MPEG-4 Part 10 (ISO/IEC 14496-10)
+ * @GST_VAAPI_CODEC_WMV3: Windows Media Video 9. VC-1 Simple or Main profile (SMPTE 421M)
+ * @GST_VAAPI_CODEC_VC1: VC-1 Advanced profile (SMPTE 421M)
+ *
+ * The set of all codecs for #GstVaapiCodec.
+ */
+enum _GstVaapiCodec {
+    GST_VAAPI_CODEC_MPEG1       = GST_MAKE_FOURCC('M','P','1',0),
+    GST_VAAPI_CODEC_MPEG2       = GST_MAKE_FOURCC('M','P','2',0),
+    GST_VAAPI_CODEC_MPEG4       = GST_MAKE_FOURCC('M','P','4',0),
+    GST_VAAPI_CODEC_H263        = GST_MAKE_FOURCC('2','6','3',0),
+    GST_VAAPI_CODEC_H264        = GST_MAKE_FOURCC('2','6','4',0),
+    GST_VAAPI_CODEC_WMV3        = GST_MAKE_FOURCC('W','M','V',0),
+    GST_VAAPI_CODEC_VC1         = GST_MAKE_FOURCC('V','C','1',0),
+    GST_VAAPI_CODEC_JPEG        = GST_MAKE_FOURCC('J','P','G',0),
+};
+
+/**
+ * GST_VAAPI_MAKE_PROFILE:
+ * @codec: the #GstVaapiCodec without the GST_VAAPI_CODEC_ prefix
+ * @sub_id: a non-zero sub-codec id
+ *
+ * Macro that evaluates to the profile composed from @codec and
+ * @sub_id.
+ */
+#define GST_VAAPI_MAKE_PROFILE(codec, sub_id) \
+    (GST_VAAPI_CODEC_##codec | GST_MAKE_FOURCC(0,0,0,sub_id))
+
+/**
+ * GstVaapiProfile:
+ * @GST_VAAPI_PROFILE_UNKNOWN:
+ *   Unknown profile, used for initializers
+ * @GST_VAAPI_PROFILE_MPEG1:
+ *   MPEG-1
+ * @GST_VAAPI_PROFILE_MPEG2_SIMPLE:
+ *   MPEG-2 simple profile
+ * @GST_VAAPI_PROFILE_MPEG2_MAIN:
+ *   MPEG-2 main profile
+ * @GST_VAAPI_PROFILE_MPEG2_HIGH:
+ *   MPEG-2 high profile
+ * @GST_VAAPI_PROFILE_MPEG4_SIMPLE:
+ *   MPEG-4 Part-2 simple profile
+ * @GST_VAAPI_PROFILE_MPEG4_ADVANCED_SIMPLE:
+ *   MPEG-4 Part-2 advanced simple profile
+ * @GST_VAAPI_PROFILE_MPEG4_MAIN:
+ *   MPEG-4 Part-2 main profile
+ * @GST_VAAPI_PROFILE_H263_BASELINE:
+ *   H.263 baseline profile
+ * @GST_VAAPI_PROFILE_H264_BASELINE:
+ *   H.264 (MPEG-4 Part-10) baseline profile
+ * @GST_VAAPI_PROFILE_H264_MAIN:
+ *   H.264 (MPEG-4 Part-10) main profile
+ * @GST_VAAPI_PROFILE_H264_HIGH:
+ *   H.264 (MPEG-4 Part-10) high profile
+ * @GST_VAAPI_PROFILE_VC1_SIMPLE:
+ *   VC-1 simple profile
+ * @GST_VAAPI_PROFILE_VC1_MAIN:
+ *   VC-1 main profile
+ * @GST_VAAPI_PROFILE_VC1_ADVANCED:
+ *   VC-1 advanced profile
+ *
+ * The set of all profiles for #GstVaapiProfile.
+ */
+enum _GstVaapiProfile {
+    GST_VAAPI_PROFILE_UNKNOWN               = 0,
+    GST_VAAPI_PROFILE_MPEG1                 = GST_VAAPI_MAKE_PROFILE(MPEG1,1),
+    GST_VAAPI_PROFILE_MPEG2_SIMPLE          = GST_VAAPI_MAKE_PROFILE(MPEG2,1),
+    GST_VAAPI_PROFILE_MPEG2_MAIN            = GST_VAAPI_MAKE_PROFILE(MPEG2,2),
+    GST_VAAPI_PROFILE_MPEG2_HIGH            = GST_VAAPI_MAKE_PROFILE(MPEG2,3),
+    GST_VAAPI_PROFILE_MPEG4_SIMPLE          = GST_VAAPI_MAKE_PROFILE(MPEG4,1),
+    GST_VAAPI_PROFILE_MPEG4_ADVANCED_SIMPLE = GST_VAAPI_MAKE_PROFILE(MPEG4,2),
+    GST_VAAPI_PROFILE_MPEG4_MAIN            = GST_VAAPI_MAKE_PROFILE(MPEG4,3),
+    GST_VAAPI_PROFILE_H263_BASELINE         = GST_VAAPI_MAKE_PROFILE(H263,1),
+    GST_VAAPI_PROFILE_H264_BASELINE         = GST_VAAPI_MAKE_PROFILE(H264,1),
+    GST_VAAPI_PROFILE_H264_MAIN             = GST_VAAPI_MAKE_PROFILE(H264,2),
+    GST_VAAPI_PROFILE_H264_HIGH             = GST_VAAPI_MAKE_PROFILE(H264,3),
+    GST_VAAPI_PROFILE_VC1_SIMPLE            = GST_VAAPI_MAKE_PROFILE(VC1,1),
+    GST_VAAPI_PROFILE_VC1_MAIN              = GST_VAAPI_MAKE_PROFILE(VC1,2),
+    GST_VAAPI_PROFILE_VC1_ADVANCED          = GST_VAAPI_MAKE_PROFILE(VC1,3),
+    GST_VAAPI_PROFILE_JPEG_BASELINE         = GST_VAAPI_MAKE_PROFILE(JPEG,1),
+};
+
+/**
+ * GstVaapiEntrypoint:
+ * @GST_VAAPI_ENTRYPOINT_VLD: Variable Length Decoding
+ * @GST_VAAPI_ENTRYPOINT_IDCT: Inverse Decrete Cosine Transform
+ * @GST_VAAPI_ENTRYPOINT_MOCO: Motion Compensation
+ * @GST_VAAPI_ENTRYPOINT_SLICE_ENCODE: Encode Slice
+ *
+ * The set of all entrypoints for #GstVaapiEntrypoint
+ */
+enum _GstVaapiEntrypoint {
+    GST_VAAPI_ENTRYPOINT_VLD = 1,
+    GST_VAAPI_ENTRYPOINT_IDCT,
+    GST_VAAPI_ENTRYPOINT_MOCO,
+    GST_VAAPI_ENTRYPOINT_SLICE_ENCODE
+};
+
+GstVaapiProfile
+gst_vaapi_profile(VAProfile profile);
+
+GstVaapiProfile
+gst_vaapi_profile_from_caps(GstCaps *caps);
+
+VAProfile
+gst_vaapi_profile_get_va_profile(GstVaapiProfile profile);
+
+GstCaps *
+gst_vaapi_profile_get_caps(GstVaapiProfile profile);
+
+GstVaapiCodec
+gst_vaapi_profile_get_codec(GstVaapiProfile profile);
+
+GstVaapiEntrypoint
+gst_vaapi_entrypoint(VAEntrypoint entrypoint);
+
+VAEntrypoint
+gst_vaapi_entrypoint_get_va_entrypoint(GstVaapiEntrypoint entrypoint);
+
+G_END_DECLS
+
+#endif /* GST_GST_VAAPI_IMAGE_H */
diff --git a/gst-libs/gst/vaapi/gstvaapisubpicture.c b/gst-libs/gst/vaapi/gstvaapisubpicture.c
new file mode 100644 (file)
index 0000000..cfd7fd3
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ *  gstvaapisubpicture.c - VA subpicture abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapisubpicture
+ * @short_description: VA subpicture abstraction
+ */
+
+#include "sysdeps.h"
+#include <string.h>
+#include "gstvaapicompat.h"
+#include "gstvaapiutils.h"
+#include "gstvaapisubpicture.h"
+#include "gstvaapi_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiSubpicture, gst_vaapi_subpicture, GST_VAAPI_TYPE_OBJECT);
+
+#define GST_VAAPI_SUBPICTURE_GET_PRIVATE(obj)                   \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_SUBPICTURE,    \
+                                 GstVaapiSubpicturePrivate))
+
+struct _GstVaapiSubpicturePrivate {
+    GstVaapiImage      *image;
+};
+
+enum {
+    PROP_0,
+
+    PROP_IMAGE
+};
+
+static void
+gst_vaapi_subpicture_destroy(GstVaapiSubpicture *subpicture)
+{
+    GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(subpicture);
+    GstVaapiSubpicturePrivate * const priv = subpicture->priv;
+    VASubpictureID subpicture_id;
+    VAStatus status;
+
+    subpicture_id = GST_VAAPI_OBJECT_ID(subpicture);
+    GST_DEBUG("subpicture %" GST_VAAPI_ID_FORMAT,
+              GST_VAAPI_ID_ARGS(subpicture_id));
+
+    if (subpicture_id != VA_INVALID_ID) {
+        if (display) {
+            GST_VAAPI_DISPLAY_LOCK(display);
+            status = vaDestroySubpicture(
+                GST_VAAPI_DISPLAY_VADISPLAY(display),
+                subpicture_id
+            );
+            GST_VAAPI_DISPLAY_UNLOCK(display);
+            if (!vaapi_check_status(status, "vaDestroySubpicture()"))
+                g_warning("failed to destroy subpicture %" GST_VAAPI_ID_FORMAT,
+                          GST_VAAPI_ID_ARGS(subpicture_id));
+        }
+        GST_VAAPI_OBJECT_ID(subpicture) = VA_INVALID_ID;
+    }
+
+    g_clear_object(&priv->image);
+}
+
+static gboolean
+gst_vaapi_subpicture_create(GstVaapiSubpicture *subpicture)
+{
+    GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(subpicture);
+    GstVaapiSubpicturePrivate * const priv = subpicture->priv;
+    VASubpictureID subpicture_id;
+    VAStatus status;
+
+    if (!priv->image)
+        return FALSE;
+
+    GST_VAAPI_DISPLAY_LOCK(display);
+    status = vaCreateSubpicture(
+        GST_VAAPI_DISPLAY_VADISPLAY(display),
+        GST_VAAPI_OBJECT_ID(priv->image),
+        &subpicture_id
+    );
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+    if (!vaapi_check_status(status, "vaCreateSubpicture()"))
+        return FALSE;
+
+    GST_DEBUG("subpicture %" GST_VAAPI_ID_FORMAT,
+              GST_VAAPI_ID_ARGS(subpicture_id));
+    GST_VAAPI_OBJECT_ID(subpicture) = subpicture_id;
+    return TRUE;
+}
+
+static void
+gst_vaapi_subpicture_finalize(GObject *object)
+{
+    gst_vaapi_subpicture_destroy(GST_VAAPI_SUBPICTURE(object));
+
+    G_OBJECT_CLASS(gst_vaapi_subpicture_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_subpicture_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiSubpicture * const subpicture = GST_VAAPI_SUBPICTURE(object);
+
+    switch (prop_id) {
+    case PROP_IMAGE:
+        gst_vaapi_subpicture_set_image(subpicture, g_value_get_object(value));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_subpicture_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiSubpicture * const subpicture = GST_VAAPI_SUBPICTURE(object);
+
+    switch (prop_id) {
+    case PROP_IMAGE:
+        g_value_set_object(value, gst_vaapi_subpicture_get_image(subpicture));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_subpicture_class_init(GstVaapiSubpictureClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiSubpicturePrivate));
+
+    object_class->finalize     = gst_vaapi_subpicture_finalize;
+    object_class->set_property = gst_vaapi_subpicture_set_property;
+    object_class->get_property = gst_vaapi_subpicture_get_property;
+
+    /**
+     * GstVaapiSubpicture:image:
+     *
+     * The #GstVaapiImage this subpicture is bound to.
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_IMAGE,
+         g_param_spec_object("image",
+                             "Image",
+                             "The GstVaapiImage this subpicture is bound to",
+                             GST_VAAPI_TYPE_IMAGE,
+                             G_PARAM_READWRITE));
+}
+
+static void
+gst_vaapi_subpicture_init(GstVaapiSubpicture *subpicture)
+{
+    GstVaapiSubpicturePrivate *priv = GST_VAAPI_SUBPICTURE_GET_PRIVATE(subpicture);
+
+    subpicture->priv    = priv;
+    priv->image         = NULL;
+}
+
+/**
+ * gst_vaapi_subpicture_new:
+ * @image: a #GstVaapiImage
+ *
+ * Creates a new #GstVaapiSubpicture with @image as source pixels. The
+ * newly created object holds a reference on @image.
+ *
+ * Return value: the newly allocated #GstVaapiSubpicture object
+ */
+GstVaapiSubpicture *
+gst_vaapi_subpicture_new(GstVaapiImage *image)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL);
+
+    GST_DEBUG("create from image %" GST_VAAPI_ID_FORMAT,
+              GST_VAAPI_ID_ARGS(GST_VAAPI_OBJECT_ID(image)));
+
+    return g_object_new(GST_VAAPI_TYPE_SUBPICTURE,
+                        "display", GST_VAAPI_OBJECT_DISPLAY(image),
+                        "id",      GST_VAAPI_ID(VA_INVALID_ID),
+                        "image",   image,
+                        NULL);
+}
+
+/**
+ * gst_vaapi_subpicture_new_from_overlay_rectangle:
+ * @display: a #GstVaapiDisplay
+ * @rect: a #GstVideoOverlayRectangle
+ *
+ * Helper function that creates a new #GstVaapiSubpicture from a
+ * #GstVideoOverlayRectangle. A new #GstVaapiImage is also created
+ * along the way and attached to the resulting subpicture. The
+ * subpicture holds a unique reference to the underlying image.
+ *
+ * Return value: the newly allocated #GstVaapiSubpicture object
+ */
+GstVaapiSubpicture *
+gst_vaapi_subpicture_new_from_overlay_rectangle(
+    GstVaapiDisplay          *display,
+    GstVideoOverlayRectangle *rect
+)
+{
+    GstVaapiSubpicture *subpicture;
+    GstVaapiImageFormat format;
+    GstVaapiImage *image;
+    GstVaapiImageRaw raw_image;
+    GstBuffer *buffer;
+    guint width, height, stride;
+
+    g_return_val_if_fail(GST_IS_VIDEO_OVERLAY_RECTANGLE(rect), NULL);
+
+    buffer = gst_video_overlay_rectangle_get_pixels_unscaled_argb(
+        rect,
+        &width, &height, &stride,
+        GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE
+    );
+    if (!buffer)
+        return NULL;
+
+    /* XXX: use gst_vaapi_image_format_from_video() */
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+    format = GST_VAAPI_IMAGE_BGRA;
+#else
+    format = GST_VAAPI_IMAGE_ARGB;
+#endif
+    image = gst_vaapi_image_new(display, format, width, height);
+    if (!image)
+        return NULL;
+
+    raw_image.format     = format;
+    raw_image.width      = width;
+    raw_image.height     = height;
+    raw_image.num_planes = 1;
+    raw_image.pixels[0]  = GST_BUFFER_DATA(buffer);
+    raw_image.stride[0]  = stride;
+    if (!gst_vaapi_image_update_from_raw(image, &raw_image, NULL)) {
+        GST_WARNING("could not update VA image with subtitle data");
+        g_object_unref(image);
+        return NULL;
+    }
+
+    subpicture = gst_vaapi_subpicture_new(image);
+    g_object_unref(image);
+    return subpicture;
+}
+
+/**
+ * gst_vaapi_subpicture_get_id:
+ * @subpicture: a #GstVaapiSubpicture
+ *
+ * Returns the underlying VASubpictureID of the @subpicture.
+ *
+ * Return value: the underlying VA subpicture id
+ */
+GstVaapiID
+gst_vaapi_subpicture_get_id(GstVaapiSubpicture *subpicture)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), VA_INVALID_ID);
+
+    return GST_VAAPI_OBJECT_ID(subpicture);
+}
+
+/**
+ * gst_vaapi_subpicture_get_image:
+ * @subpicture: a #GstVaapiSubpicture
+ *
+ * Returns the #GstVaapiImage this @subpicture is bound to.
+ *
+ * Return value: the #GstVaapiImage this @subpicture is bound to
+ */
+GstVaapiImage *
+gst_vaapi_subpicture_get_image(GstVaapiSubpicture *subpicture)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), NULL);
+
+    return subpicture->priv->image;
+}
+
+/**
+ * gst_vaapi_subpicture_set_image:
+ * @subpicture: a #GstVaapiSubpicture
+ * @image: a #GstVaapiImage
+ *
+ * Binds a new #GstVaapiImage to the @subpicture. The reference to the
+ * previous image is released and a new one is acquired on @image.
+ */
+void
+gst_vaapi_subpicture_set_image(
+    GstVaapiSubpicture *subpicture,
+    GstVaapiImage      *image
+)
+{
+    g_return_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture));
+    g_return_if_fail(GST_VAAPI_IS_IMAGE(image));
+
+    gst_vaapi_subpicture_destroy(subpicture);
+
+    subpicture->priv->image = g_object_ref(image);
+    gst_vaapi_subpicture_create(subpicture);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapisubpicture.h b/gst-libs/gst/vaapi/gstvaapisubpicture.h
new file mode 100644 (file)
index 0000000..e7a6dbf
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ *  gstvaapisubpicture.h - VA subpicture abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_SUBPICTURE_H
+#define GST_VAAPI_SUBPICTURE_H
+
+#include <gst/vaapi/gstvaapiobject.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapiimage.h>
+#include <gst/video/video-overlay-composition.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_SUBPICTURE \
+    (gst_vaapi_subpicture_get_type())
+
+#define GST_VAAPI_SUBPICTURE(obj)                               \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_SUBPICTURE,      \
+                                GstVaapiSubpicture))
+
+#define GST_VAAPI_SUBPICTURE_CLASS(klass)                       \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_SUBPICTURE,         \
+                             GstVaapiSubpictureClass))
+
+#define GST_VAAPI_IS_SUBPICTURE(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_SUBPICTURE))
+
+#define GST_VAAPI_IS_SUBPICTURE_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_SUBPICTURE))
+
+#define GST_VAAPI_SUBPICTURE_GET_CLASS(obj)                     \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_SUBPICTURE,       \
+                               GstVaapiSubpictureClass))
+
+typedef struct _GstVaapiSubpicture              GstVaapiSubpicture;
+typedef struct _GstVaapiSubpicturePrivate       GstVaapiSubpicturePrivate;
+typedef struct _GstVaapiSubpictureClass         GstVaapiSubpictureClass;
+
+/**
+ * GstVaapiSubpicture:
+ *
+ * A VA subpicture wrapper
+ */
+struct _GstVaapiSubpicture {
+    /*< private >*/
+    GstVaapiObject parent_instance;
+
+    GstVaapiSubpicturePrivate *priv;
+};
+
+/**
+ * GstVaapiSubpictureClass:
+ *
+ * A VA subpicture wrapper class
+ */
+struct _GstVaapiSubpictureClass {
+    /*< private >*/
+    GstVaapiObjectClass parent_class;
+};
+
+GType
+gst_vaapi_subpicture_get_type(void) G_GNUC_CONST;
+
+GstVaapiSubpicture *
+gst_vaapi_subpicture_new(GstVaapiImage *image);
+
+GstVaapiSubpicture *
+gst_vaapi_subpicture_new_from_overlay_rectangle(
+    GstVaapiDisplay          *display,
+    GstVideoOverlayRectangle *rect
+);
+
+GstVaapiID
+gst_vaapi_subpicture_get_id(GstVaapiSubpicture *subpicture);
+
+GstVaapiImage *
+gst_vaapi_subpicture_get_image(GstVaapiSubpicture *subpicture);
+
+void
+gst_vaapi_subpicture_set_image(
+    GstVaapiSubpicture *subpicture,
+    GstVaapiImage      *image
+);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_SUBPICTURE_H */
diff --git a/gst-libs/gst/vaapi/gstvaapisurface.c b/gst-libs/gst/vaapi/gstvaapisurface.c
new file mode 100644 (file)
index 0000000..18b9559
--- /dev/null
@@ -0,0 +1,942 @@
+/*
+ *  gstvaapisurface.c - VA surface abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapisurface
+ * @short_description: VA surface abstraction
+ */
+
+#include "sysdeps.h"
+#include "gstvaapicompat.h"
+#include "gstvaapiutils.h"
+#include "gstvaapisurface.h"
+#include "gstvaapisurface_priv.h"
+#include "gstvaapicontext.h"
+#include "gstvaapiimage.h"
+#include "gstvaapi_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiSurface, gst_vaapi_surface, GST_VAAPI_TYPE_OBJECT);
+
+#define GST_VAAPI_SURFACE_GET_PRIVATE(obj)                      \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_SURFACE,       \
+                                 GstVaapiSurfacePrivate))
+
+struct _GstVaapiSurfacePrivate {
+    guint               width;
+    guint               height;
+    GstVaapiChromaType  chroma_type;
+    GPtrArray          *subpictures;
+    GstVaapiContext    *parent_context;
+};
+
+enum {
+    PROP_0,
+
+    PROP_WIDTH,
+    PROP_HEIGHT,
+    PROP_CHROMA_TYPE,
+    PROP_PARENT_CONTEXT
+};
+
+static gboolean
+_gst_vaapi_surface_associate_subpicture(
+    GstVaapiSurface         *surface,
+    GstVaapiSubpicture      *subpicture,
+    const GstVaapiRectangle *src_rect,
+    const GstVaapiRectangle *dst_rect
+);
+
+static gboolean
+_gst_vaapi_surface_deassociate_subpicture(
+    GstVaapiSurface    *surface,
+    GstVaapiSubpicture *subpicture
+);
+
+static void
+destroy_subpicture_cb(gpointer subpicture, gpointer surface)
+{
+    _gst_vaapi_surface_deassociate_subpicture(surface, subpicture);
+    g_object_unref(subpicture);
+}
+
+static void
+gst_vaapi_surface_destroy_subpictures(GstVaapiSurface *surface)
+{
+    GstVaapiSurfacePrivate * const priv = surface->priv;
+
+    if (priv->subpictures) {
+        g_ptr_array_foreach(priv->subpictures, destroy_subpicture_cb, surface);
+        g_ptr_array_free(priv->subpictures, TRUE);
+        priv->subpictures = NULL;
+    }
+}
+
+static void
+gst_vaapi_surface_destroy(GstVaapiSurface *surface)
+{
+    GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(surface);
+    VASurfaceID surface_id;
+    VAStatus status;
+
+    surface_id = GST_VAAPI_OBJECT_ID(surface);
+    GST_DEBUG("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(surface_id));
+
+    gst_vaapi_surface_destroy_subpictures(surface);
+    gst_vaapi_surface_set_parent_context(surface, NULL);
+  
+    if (surface_id != VA_INVALID_SURFACE) {
+        GST_VAAPI_DISPLAY_LOCK(display);
+        status = vaDestroySurfaces(
+            GST_VAAPI_DISPLAY_VADISPLAY(display),
+            &surface_id, 1
+        );
+        GST_VAAPI_DISPLAY_UNLOCK(display);
+        if (!vaapi_check_status(status, "vaDestroySurfaces()"))
+            g_warning("failed to destroy surface %" GST_VAAPI_ID_FORMAT,
+                      GST_VAAPI_ID_ARGS(surface_id));
+        GST_VAAPI_OBJECT_ID(surface) = VA_INVALID_SURFACE;
+    }
+}
+
+static gboolean
+gst_vaapi_surface_create(GstVaapiSurface *surface)
+{
+    GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(surface);
+    GstVaapiSurfacePrivate * const priv = surface->priv;
+    VASurfaceID surface_id;
+    VAStatus status;
+    guint format;
+
+    switch (priv->chroma_type) {
+    case GST_VAAPI_CHROMA_TYPE_YUV420:
+        format = VA_RT_FORMAT_YUV420;
+        break;
+    case GST_VAAPI_CHROMA_TYPE_YUV422:
+        format = VA_RT_FORMAT_YUV422;
+        break;
+    case GST_VAAPI_CHROMA_TYPE_YUV444:
+        format = VA_RT_FORMAT_YUV444;
+        break;
+    default:
+        GST_DEBUG("unsupported chroma-type %u\n", priv->chroma_type);
+        return FALSE;
+    }
+
+    GST_VAAPI_DISPLAY_LOCK(display);
+    status = vaCreateSurfaces(
+        GST_VAAPI_DISPLAY_VADISPLAY(display),
+        priv->width,
+        priv->height,
+        format,
+        1, &surface_id
+    );
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+    if (!vaapi_check_status(status, "vaCreateSurfaces()"))
+        return FALSE;
+
+    GST_DEBUG("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(surface_id));
+    GST_VAAPI_OBJECT_ID(surface) = surface_id;
+    return TRUE;
+}
+
+static void
+gst_vaapi_surface_finalize(GObject *object)
+{
+    gst_vaapi_surface_destroy(GST_VAAPI_SURFACE(object));
+
+    G_OBJECT_CLASS(gst_vaapi_surface_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_surface_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiSurface        * const surface = GST_VAAPI_SURFACE(object);
+    GstVaapiSurfacePrivate * const priv    = surface->priv;
+
+    switch (prop_id) {
+    case PROP_WIDTH:
+        priv->width = g_value_get_uint(value);
+        break;
+    case PROP_HEIGHT:
+        priv->height = g_value_get_uint(value);
+        break;
+    case PROP_CHROMA_TYPE:
+        priv->chroma_type = g_value_get_uint(value);
+        break;
+    case PROP_PARENT_CONTEXT:
+        gst_vaapi_surface_set_parent_context(surface, g_value_get_object(value));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_surface_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiSurface * const surface = GST_VAAPI_SURFACE(object);
+
+    switch (prop_id) {
+    case PROP_WIDTH:
+        g_value_set_uint(value, gst_vaapi_surface_get_width(surface));
+        break;
+    case PROP_HEIGHT:
+        g_value_set_uint(value, gst_vaapi_surface_get_height(surface));
+        break;
+    case PROP_CHROMA_TYPE:
+        g_value_set_uint(value, gst_vaapi_surface_get_chroma_type(surface));
+        break;
+    case PROP_PARENT_CONTEXT:
+        g_value_set_object(value, gst_vaapi_surface_get_parent_context(surface));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_surface_constructed(GObject *object)
+{
+    GstVaapiSurface * const surface = GST_VAAPI_SURFACE(object);
+    GstVaapiSurfaceClass * const klass = GST_VAAPI_SURFACE_GET_CLASS(object);
+    GObjectClass *parent_class;
+
+    if (klass->create)
+        klass->create(surface);
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_surface_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+}
+
+static void
+gst_vaapi_surface_class_init(GstVaapiSurfaceClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiSurfacePrivate));
+
+    object_class->finalize     = gst_vaapi_surface_finalize;
+    object_class->set_property = gst_vaapi_surface_set_property;
+    object_class->get_property = gst_vaapi_surface_get_property;
+    object_class->constructed  = gst_vaapi_surface_constructed;
+
+    klass->create = gst_vaapi_surface_create;
+
+    g_object_class_install_property
+        (object_class,
+         PROP_WIDTH,
+         g_param_spec_uint("width",
+                           "Width",
+                           "The width of the surface",
+                           0, G_MAXINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_HEIGHT,
+         g_param_spec_uint("height",
+                           "Height",
+                           "The height of the surface",
+                           0, G_MAXINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_CHROMA_TYPE,
+         g_param_spec_uint("chroma-type",
+                           "Chroma type",
+                           "The chroma type of the surface",
+                           0, G_MAXUINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_PARENT_CONTEXT,
+         g_param_spec_object("parent-context",
+                             "Parent Context",
+                             "The parent context, if any",
+                             GST_VAAPI_TYPE_CONTEXT,
+                             G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gst_vaapi_surface_init(GstVaapiSurface *surface)
+{
+    GstVaapiSurfacePrivate *priv = GST_VAAPI_SURFACE_GET_PRIVATE(surface);
+
+    surface->priv        = priv;
+    priv->width          = 0;
+    priv->height         = 0;
+    priv->chroma_type    = 0;
+    priv->subpictures    = NULL;
+    priv->parent_context = NULL;
+}
+
+/**
+ * gst_vaapi_surface_new:
+ * @display: a #GstVaapiDisplay
+ * @chroma_type: the surface chroma format
+ * @width: the requested surface width
+ * @height: the requested surface height
+ *
+ * Creates a new #GstVaapiSurface with the specified chroma format and
+ * dimensions.
+ *
+ * Return value: the newly allocated #GstVaapiSurface object
+ */
+GstVaapiSurface *
+gst_vaapi_surface_new(
+    GstVaapiDisplay    *display,
+    GstVaapiChromaType  chroma_type,
+    guint               width,
+    guint               height
+)
+{
+    GST_DEBUG("size %ux%u, chroma type 0x%x", width, height, chroma_type);
+
+    return g_object_new(GST_VAAPI_TYPE_SURFACE,
+                        "display",      display,
+                        "id",           GST_VAAPI_ID(VA_INVALID_ID),
+                        "width",        width,
+                        "height",       height,
+                        "chroma-type",  chroma_type,
+                        NULL);
+}
+
+/**
+ * gst_vaapi_surface_get_id:
+ * @surface: a #GstVaapiSurface
+ *
+ * Returns the underlying VASurfaceID of the @surface.
+ *
+ * Return value: the underlying VA surface id
+ */
+GstVaapiID
+gst_vaapi_surface_get_id(GstVaapiSurface *surface)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), VA_INVALID_SURFACE);
+
+    return GST_VAAPI_OBJECT_ID(surface);
+}
+
+/**
+ * gst_vaapi_surface_get_chroma_type:
+ * @surface: a #GstVaapiSurface
+ *
+ * Returns the #GstVaapiChromaType the @surface was created with.
+ *
+ * Return value: the #GstVaapiChromaType
+ */
+GstVaapiChromaType
+gst_vaapi_surface_get_chroma_type(GstVaapiSurface *surface)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), 0);
+
+    return surface->priv->chroma_type;
+}
+
+/**
+ * gst_vaapi_surface_get_width:
+ * @surface: a #GstVaapiSurface
+ *
+ * Returns the @surface width.
+ *
+ * Return value: the surface width, in pixels
+ */
+guint
+gst_vaapi_surface_get_width(GstVaapiSurface *surface)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), 0);
+
+    return surface->priv->width;
+}
+
+/**
+ * gst_vaapi_surface_get_height:
+ * @surface: a #GstVaapiSurface
+ *
+ * Returns the @surface height.
+ *
+ * Return value: the surface height, in pixels.
+ */
+guint
+gst_vaapi_surface_get_height(GstVaapiSurface *surface)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), 0);
+
+    return surface->priv->height;
+}
+
+/**
+ * gst_vaapi_surface_get_size:
+ * @surface: a #GstVaapiSurface
+ * @pwidth: return location for the width, or %NULL
+ * @pheight: return location for the height, or %NULL
+ *
+ * Retrieves the dimensions of a #GstVaapiSurface.
+ */
+void
+gst_vaapi_surface_get_size(
+    GstVaapiSurface *surface,
+    guint           *pwidth,
+    guint           *pheight
+)
+{
+    g_return_if_fail(GST_VAAPI_IS_SURFACE(surface));
+
+    if (pwidth)
+        *pwidth = gst_vaapi_surface_get_width(surface);
+
+    if (pheight)
+        *pheight = gst_vaapi_surface_get_height(surface);
+}
+
+/**
+ * gst_vaapi_surface_set_parent_context:
+ * @surface: a #GstVaapiSurface
+ * @context: a #GstVaapiContext
+ *
+ * Sets new parent context, or clears any parent context if @context
+ * is %NULL. This function owns an extra reference to the context,
+ * which will be released when the surface is destroyed.
+ */
+void
+gst_vaapi_surface_set_parent_context(
+    GstVaapiSurface *surface,
+    GstVaapiContext *context
+)
+{
+    GstVaapiSurfacePrivate *priv;
+
+    g_return_if_fail(GST_VAAPI_IS_SURFACE(surface));
+
+    priv = surface->priv;
+
+    g_clear_object(&priv->parent_context);
+
+    if (context)
+        priv->parent_context = g_object_ref(context);
+}
+
+/**
+ * gst_vaapi_surface_get_parent_context:
+ * @surface: a #GstVaapiSurface
+ *
+ * Retrieves the parent #GstVaapiContext, or %NULL if there is
+ * none. The surface shall still own a reference to the context.
+ * i.e. the caller shall not unreference the returned context object.
+ *
+ * Return value: the parent context, if any.
+ */
+GstVaapiContext *
+gst_vaapi_surface_get_parent_context(GstVaapiSurface *surface)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), NULL);
+
+    return surface->priv->parent_context;
+}
+
+/**
+ * gst_vaapi_surface_derive_image:
+ * @surface: a #GstVaapiSurface
+ *
+ * Derives a #GstVaapiImage from the @surface. This image buffer can
+ * then be mapped/unmapped for direct CPU access. This operation is
+ * only possible if the underlying implementation supports direct
+ * rendering capabilities and internal surface formats that can be
+ * represented with a #GstVaapiImage.
+ *
+ * When the operation is not possible, the function returns %NULL and
+ * the user should then fallback to using gst_vaapi_surface_get_image()
+ * or gst_vaapi_surface_put_image() to accomplish the same task in an
+ * indirect manner (additional copy).
+ *
+ * An image created with gst_vaapi_surface_derive_image() should be
+ * unreferenced when it's no longer needed. The image and image buffer
+ * data structures will be destroyed. However, the surface contents
+ * will remain unchanged until destroyed through the last call to
+ * g_object_unref().
+ *
+ * Return value: the newly allocated #GstVaapiImage object, or %NULL
+ *   on failure
+ */
+GstVaapiImage *
+gst_vaapi_surface_derive_image(GstVaapiSurface *surface)
+{
+    GstVaapiDisplay *display;
+    VAImage va_image;
+    VAStatus status;
+
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), NULL);
+
+    display           = GST_VAAPI_OBJECT_DISPLAY(surface);
+    va_image.image_id = VA_INVALID_ID;
+    va_image.buf      = VA_INVALID_ID;
+
+    GST_VAAPI_DISPLAY_LOCK(display);
+    status = vaDeriveImage(
+        GST_VAAPI_DISPLAY_VADISPLAY(display),
+        GST_VAAPI_OBJECT_ID(surface),
+        &va_image
+    );
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+    if (!vaapi_check_status(status, "vaDeriveImage()"))
+        return NULL;
+    if (va_image.image_id == VA_INVALID_ID || va_image.buf == VA_INVALID_ID)
+        return NULL;
+
+    return gst_vaapi_image_new_with_image(display, &va_image);
+}
+
+/**
+ * gst_vaapi_surface_get_image
+ * @surface: a #GstVaapiSurface
+ * @image: a #GstVaapiImage
+ *
+ * Retrieves surface data into a #GstVaapiImage. The @image must have
+ * a format supported by the @surface.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_surface_get_image(GstVaapiSurface *surface, GstVaapiImage *image)
+{
+    GstVaapiDisplay *display;
+    VAImageID image_id;
+    VAStatus status;
+    guint width, height;
+
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
+
+    display = GST_VAAPI_OBJECT_DISPLAY(surface);
+    if (!display)
+        return FALSE;
+
+    gst_vaapi_image_get_size(image, &width, &height);
+    if (width != surface->priv->width || height != surface->priv->height)
+        return FALSE;
+
+    image_id = GST_VAAPI_OBJECT_ID(image);
+    if (image_id == VA_INVALID_ID)
+        return FALSE;
+
+    GST_VAAPI_DISPLAY_LOCK(display);
+    status = vaGetImage(
+        GST_VAAPI_DISPLAY_VADISPLAY(display),
+        GST_VAAPI_OBJECT_ID(surface),
+        0, 0, width, height,
+        image_id
+    );
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+    if (!vaapi_check_status(status, "vaGetImage()"))
+        return FALSE;
+
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_surface_put_image:
+ * @surface: a #GstVaapiSurface
+ * @image: a #GstVaapiImage
+ *
+ * Copies data from a #GstVaapiImage into a @surface. The @image must
+ * have a format supported by the @surface.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_surface_put_image(GstVaapiSurface *surface, GstVaapiImage *image)
+{
+    GstVaapiDisplay *display;
+    VAImageID image_id;
+    VAStatus status;
+    guint width, height;
+
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
+
+    display = GST_VAAPI_OBJECT_DISPLAY(surface);
+    if (!display)
+        return FALSE;
+
+    gst_vaapi_image_get_size(image, &width, &height);
+    if (width != surface->priv->width || height != surface->priv->height)
+        return FALSE;
+
+    image_id = GST_VAAPI_OBJECT_ID(image);
+    if (image_id == VA_INVALID_ID)
+        return FALSE;
+
+    GST_VAAPI_DISPLAY_LOCK(display);
+    status = vaPutImage(
+        GST_VAAPI_DISPLAY_VADISPLAY(display),
+        GST_VAAPI_OBJECT_ID(surface),
+        image_id,
+        0, 0, width, height,
+        0, 0, width, height
+    );
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+    if (!vaapi_check_status(status, "vaPutImage()"))
+        return FALSE;
+
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_surface_associate_subpicture:
+ * @surface: a #GstVaapiSurface
+ * @subpicture: a #GstVaapiSubpicture
+ * @src_rect: the sub-rectangle of the source subpicture
+ *   image to extract and process. If %NULL, the entire image will be used.
+ * @dst_rect: the sub-rectangle of the destination
+ *   surface into which the image is rendered. If %NULL, the entire
+ *   surface will be used.
+ *
+ * Associates the @subpicture with the @surface. The @src_rect
+ * coordinates and size are relative to the source image bound to
+ * @subpicture. The @dst_rect coordinates and size are relative to the
+ * target @surface. Note that the @surface holds an additional
+ * reference to the @subpicture.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_surface_associate_subpicture(
+    GstVaapiSurface         *surface,
+    GstVaapiSubpicture      *subpicture,
+    const GstVaapiRectangle *src_rect,
+    const GstVaapiRectangle *dst_rect
+)
+{
+    gboolean success;
+
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
+    g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), FALSE);
+
+    if (!surface->priv->subpictures) {
+        surface->priv->subpictures = g_ptr_array_new();
+        if (!surface->priv->subpictures)
+            return FALSE;
+    }
+
+    if (g_ptr_array_remove_fast(surface->priv->subpictures, subpicture)) {
+        success = _gst_vaapi_surface_deassociate_subpicture(surface, subpicture);
+        g_object_unref(subpicture);
+        if (!success)
+            return FALSE;
+    }
+
+    success = _gst_vaapi_surface_associate_subpicture(
+        surface,
+        subpicture,
+        src_rect,
+        dst_rect
+    );
+    if (!success)
+        return FALSE;
+
+    g_ptr_array_add(surface->priv->subpictures, g_object_ref(subpicture));
+    return TRUE;
+}
+
+gboolean
+_gst_vaapi_surface_associate_subpicture(
+    GstVaapiSurface         *surface,
+    GstVaapiSubpicture      *subpicture,
+    const GstVaapiRectangle *src_rect,
+    const GstVaapiRectangle *dst_rect
+)
+{
+    GstVaapiDisplay *display;
+    GstVaapiRectangle src_rect_default, dst_rect_default;
+    GstVaapiImage *image;
+    VASurfaceID surface_id;
+    VAStatus status;
+
+    display = GST_VAAPI_OBJECT_DISPLAY(surface);
+    if (!display)
+        return FALSE;
+
+    surface_id = GST_VAAPI_OBJECT_ID(surface);
+    if (surface_id == VA_INVALID_SURFACE)
+        return FALSE;
+
+    if (!src_rect) {
+        image = gst_vaapi_subpicture_get_image(subpicture);
+        if (!image)
+            return FALSE;
+        src_rect                = &src_rect_default;
+        src_rect_default.x      = 0;
+        src_rect_default.y      = 0;
+        gst_vaapi_image_get_size(
+            image,
+            &src_rect_default.width,
+            &src_rect_default.height
+        );
+    }
+
+    if (!dst_rect) {
+        dst_rect                = &dst_rect_default;
+        dst_rect_default.x      = 0;
+        dst_rect_default.y      = 0;
+        dst_rect_default.width  = surface->priv->width;
+        dst_rect_default.height = surface->priv->height;
+    }
+
+    GST_VAAPI_DISPLAY_LOCK(display);
+    status = vaAssociateSubpicture(
+        GST_VAAPI_DISPLAY_VADISPLAY(display),
+        GST_VAAPI_OBJECT_ID(subpicture),
+        &surface_id, 1,
+        src_rect->x, src_rect->y, src_rect->width, src_rect->height,
+        dst_rect->x, dst_rect->y, dst_rect->width, dst_rect->height,
+        0
+    );
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+    if (!vaapi_check_status(status, "vaAssociateSubpicture()"))
+        return FALSE;
+
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_surface_deassociate_subpicture:
+ * @surface: a #GstVaapiSurface
+ * @subpicture: a #GstVaapiSubpicture
+ *
+ * Deassociates @subpicture from @surface. Other associations are kept.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_surface_deassociate_subpicture(
+    GstVaapiSurface         *surface,
+    GstVaapiSubpicture      *subpicture
+)
+{
+    gboolean success;
+
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
+    g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), FALSE);
+
+    if (!surface->priv->subpictures)
+        return TRUE;
+
+    /* First, check subpicture was really associated with this surface */
+    if (!g_ptr_array_remove_fast(surface->priv->subpictures, subpicture)) {
+        GST_DEBUG("subpicture %" GST_VAAPI_ID_FORMAT " was not bound to "
+                  "surface %" GST_VAAPI_ID_FORMAT,
+                  GST_VAAPI_ID_ARGS(GST_VAAPI_OBJECT_ID(subpicture)),
+                  GST_VAAPI_ID_ARGS(GST_VAAPI_OBJECT_ID(surface)));
+        return TRUE;
+    }
+
+    success = _gst_vaapi_surface_deassociate_subpicture(surface, subpicture);
+    g_object_unref(subpicture);
+    return success;
+}
+
+gboolean
+_gst_vaapi_surface_deassociate_subpicture(
+    GstVaapiSurface         *surface,
+    GstVaapiSubpicture      *subpicture
+)
+{
+    GstVaapiDisplay *display;
+    VASurfaceID surface_id;
+    VAStatus status;
+
+    display = GST_VAAPI_OBJECT_DISPLAY(surface);
+    if (!display)
+        return FALSE;
+
+    surface_id = GST_VAAPI_OBJECT_ID(surface);
+    if (surface_id == VA_INVALID_SURFACE)
+        return FALSE;
+
+    GST_VAAPI_DISPLAY_LOCK(display);
+    status = vaDeassociateSubpicture(
+        GST_VAAPI_DISPLAY_VADISPLAY(display),
+        GST_VAAPI_OBJECT_ID(subpicture),
+        &surface_id, 1
+    );
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+    if (!vaapi_check_status(status, "vaDeassociateSubpicture()"))
+        return FALSE;
+
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_surface_sync:
+ * @surface: a #GstVaapiSurface
+ *
+ * Blocks until all pending operations on the @surface have been
+ * completed.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_surface_sync(GstVaapiSurface *surface)
+{
+    GstVaapiDisplay *display;
+    VAStatus status;
+
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
+
+    display = GST_VAAPI_OBJECT_DISPLAY(surface);
+    if (!display)
+        return FALSE;
+
+    GST_VAAPI_DISPLAY_LOCK(display);
+    status = vaSyncSurface(
+        GST_VAAPI_DISPLAY_VADISPLAY(display),
+        GST_VAAPI_OBJECT_ID(surface)
+    );
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+    if (!vaapi_check_status(status, "vaSyncSurface()"))
+        return FALSE;
+
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_surface_query_status:
+ * @surface: a #GstVaapiSurface
+ * @pstatus: return location for the #GstVaapiSurfaceStatus
+ *
+ * Finds out any pending operations on the @surface. The
+ * #GstVaapiSurfaceStatus flags are returned into @pstatus.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_surface_query_status(
+    GstVaapiSurface       *surface,
+    GstVaapiSurfaceStatus *pstatus
+)
+{
+    VASurfaceStatus surface_status;
+    VAStatus status;
+
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(surface);
+    status = vaQuerySurfaceStatus(
+        GST_VAAPI_OBJECT_VADISPLAY(surface),
+        GST_VAAPI_OBJECT_ID(surface),
+        &surface_status
+    );
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(surface);
+    if (!vaapi_check_status(status, "vaQuerySurfaceStatus()"))
+        return FALSE;
+
+    if (pstatus)
+        *pstatus = to_GstVaapiSurfaceStatus(surface_status);
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_surface_set_subpictures_from_composition:
+ * @surface: a #GstVaapiSurface
+ * @compostion: a #GstVideoOverlayCompositon
+ * @propagate_context: a flag specifying whether to apply composition
+ *     to the parent context, if any
+ *
+ * Helper to update the subpictures from #GstVideoOverlayCompositon. Sending
+ * a NULL composition will clear all the current subpictures. Note that this
+ * method will clear existing subpictures.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_surface_set_subpictures_from_composition(
+    GstVaapiSurface            *surface,
+    GstVideoOverlayComposition *composition,
+    gboolean                    propagate_context
+)
+{
+    GstVaapiDisplay *display;
+    guint n, nb_rectangles;
+
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
+
+    if (propagate_context) {
+        GstVaapiContext * const context = surface->priv->parent_context;
+        if (context)
+            return gst_vaapi_context_apply_composition(context, composition);
+    }
+
+    display = GST_VAAPI_OBJECT_DISPLAY(surface);
+    if (!display)
+        return FALSE;
+
+    /* Clear current subpictures */
+    gst_vaapi_surface_destroy_subpictures(surface);
+
+    if (!composition)
+        return TRUE;
+
+    nb_rectangles = gst_video_overlay_composition_n_rectangles (composition);
+
+    /* Overlay all the rectangles cantained in the overlay composition */
+    for (n = 0; n < nb_rectangles; ++n) {
+        GstVideoOverlayRectangle *rect;
+        GstVaapiRectangle sub_rect;
+        GstVaapiSubpicture *subpicture;
+
+        rect = gst_video_overlay_composition_get_rectangle (composition, n);
+        subpicture = gst_vaapi_subpicture_new_from_overlay_rectangle (display,
+                rect);
+
+        gst_video_overlay_rectangle_get_render_rectangle (rect,
+                (gint *)&sub_rect.x, (gint *)&sub_rect.y,
+                &sub_rect.width, &sub_rect.height);
+
+        if (!gst_vaapi_surface_associate_subpicture (surface, subpicture,
+                    NULL, &sub_rect)) {
+            GST_WARNING ("could not render overlay rectangle %p", rect);
+            g_object_unref (subpicture);
+            return FALSE;
+        }
+        g_object_unref (subpicture);
+    }
+    return TRUE;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapisurface.h b/gst-libs/gst/vaapi/gstvaapisurface.h
new file mode 100644 (file)
index 0000000..f6c269d
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ *  gstvaapisurface.h - VA surface abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_SURFACE_H
+#define GST_VAAPI_SURFACE_H
+
+#include <gst/vaapi/gstvaapiobject.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapiimage.h>
+#include <gst/vaapi/gstvaapisubpicture.h>
+#include <gst/video/gstsurfacebuffer.h>
+#include <gst/video/video-overlay-composition.h>
+
+G_BEGIN_DECLS
+
+typedef enum _GstVaapiChromaType                GstVaapiChromaType;
+typedef enum _GstVaapiSurfaceStatus             GstVaapiSurfaceStatus;
+typedef enum _GstVaapiSurfaceRenderFlags        GstVaapiSurfaceRenderFlags;
+
+/**
+ * GST_VAAPI_SURFACE_CAPS_NAME:
+ *
+ * Generic caps type for VA surfaces.
+ */
+#define GST_VAAPI_SURFACE_CAPS_NAME GST_VIDEO_CAPS_SURFACE
+
+/**
+ * GST_VAAPI_SURFACE_CAPS:
+ *
+ * Generic caps for VA surfaces.
+ */
+#define GST_VAAPI_SURFACE_CAPS                  \
+    GST_VAAPI_SURFACE_CAPS_NAME ", "            \
+    "type = vaapi, "                            \
+    "opengl = (boolean) { true, false }, "      \
+    "width  = (int) [ 1, MAX ], "               \
+    "height = (int) [ 1, MAX ], "               \
+    "framerate = (fraction) [ 0, MAX ]"
+
+#define GST_VAAPI_BUFFER_SHARING_CAPS_NAME "video/x-vaapi-sharing"
+
+#define GST_VAAPI_BUFFER_SHARING_CAPS           \
+    GST_VAAPI_BUFFER_SHARING_CAPS_NAME ", "     \
+    "type = vaapi, "                            \
+    "width  = (int) [ 1, MAX ], "               \
+    "height = (int) [ 1, MAX ], "               \
+    "framerate = (fraction) [ 0, MAX ]"
+
+/**
+ * GstVaapiChromaType:
+ * @GST_VAAPI_CHROMA_TYPE_YUV420: 4:2:0 chroma format
+ * @GST_VAAPI_CHROMA_TYPE_YUV422: 4:2:2 chroma format
+ * @GST_VAAPI_CHROMA_TYPE_YUV444: 4:4:4 chroma format
+ *
+ * The set of all chroma types for #GstVaapiSurface.
+ */
+enum _GstVaapiChromaType {
+    GST_VAAPI_CHROMA_TYPE_YUV420 = 1,
+    GST_VAAPI_CHROMA_TYPE_YUV422,
+    GST_VAAPI_CHROMA_TYPE_YUV444
+};
+
+/**
+ * GstVaapiSurfaceStatus:
+ * @GST_VAAPI_SURFACE_STATUS_IDLE:
+ *   the surface is not being rendered or displayed
+ * @GST_VAAPI_SURFACE_STATUS_RENDERING:
+ *   the surface is used for rendering (decoding to the surface in progress)
+ * @GST_VAAPI_SURFACE_STATUS_DISPLAYING:
+ *   the surface is being displayed to screen
+ * @GST_VAAPI_SURFACE_STATUS_SKIPPED:
+ *   indicates a skipped frame during encode
+ *
+ * The set of all surface status for #GstVaapiSurface.
+ */
+enum _GstVaapiSurfaceStatus {
+    GST_VAAPI_SURFACE_STATUS_IDLE       = 1 << 0,
+    GST_VAAPI_SURFACE_STATUS_RENDERING  = 1 << 1,
+    GST_VAAPI_SURFACE_STATUS_DISPLAYING = 1 << 2,
+    GST_VAAPI_SURFACE_STATUS_SKIPPED    = 1 << 3
+};
+
+/**
+ * GstVaapiSurfaceRenderFlags
+ * @GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD:
+ *   selects the top field of the surface
+ * @GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD:
+ *   selects the bottom field of the surface
+ * @GST_VAAPI_PICTURE_STRUCTURE_FRAME:
+ *   selects the entire surface
+ * @GST_VAAPI_COLOR_STANDARD_ITUR_BT_601:
+ *   uses ITU-R BT.601 standard for color space conversion
+ * @GST_VAAPI_COLOR_STANDARD_ITUR_BT_709:
+ *   uses ITU-R BT.709 standard for color space conversion
+ *
+ * The set of all render flags for gst_vaapi_window_put_surface().
+ */
+enum _GstVaapiSurfaceRenderFlags {
+    GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD       = 1 << 0,
+    GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD    = 1 << 1,
+    GST_VAAPI_PICTURE_STRUCTURE_FRAME           =
+    (
+        GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD |
+        GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD
+    ),
+    GST_VAAPI_COLOR_STANDARD_ITUR_BT_601        = 1 << 2,
+    GST_VAAPI_COLOR_STANDARD_ITUR_BT_709        = 1 << 3,
+};
+
+#define GST_VAAPI_TYPE_SURFACE \
+    (gst_vaapi_surface_get_type())
+
+#define GST_VAAPI_SURFACE(obj)                          \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                  \
+                                GST_VAAPI_TYPE_SURFACE, \
+                                GstVaapiSurface))
+
+#define GST_VAAPI_SURFACE_CLASS(klass)                  \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                   \
+                             GST_VAAPI_TYPE_SURFACE,    \
+                             GstVaapiSurfaceClass))
+
+#define GST_VAAPI_IS_SURFACE(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_SURFACE))
+
+#define GST_VAAPI_IS_SURFACE_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_SURFACE))
+
+#define GST_VAAPI_SURFACE_GET_CLASS(obj)                \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                   \
+                               GST_VAAPI_TYPE_SURFACE,  \
+                               GstVaapiSurfaceClass))
+
+typedef struct _GstVaapiSurface                 GstVaapiSurface;
+typedef struct _GstVaapiSurfacePrivate          GstVaapiSurfacePrivate;
+typedef struct _GstVaapiSurfaceClass            GstVaapiSurfaceClass;
+
+/**
+ * GstVaapiSurface:
+ *
+ * A VA surface wrapper.
+ */
+struct _GstVaapiSurface {
+    /*< private >*/
+    GstVaapiObject parent_instance;
+
+    GstVaapiSurfacePrivate *priv;
+};
+
+/**
+ * GstVaapiSurfaceClass:
+ *
+ * A VA surface wrapper class.
+ */
+struct _GstVaapiSurfaceClass {
+    /*< private >*/
+    GstVaapiObjectClass parent_class;
+
+    gboolean  (*create)(GstVaapiSurface *surface);
+};
+
+GType
+gst_vaapi_surface_get_type(void) G_GNUC_CONST;
+
+GstVaapiSurface *
+gst_vaapi_surface_new(
+    GstVaapiDisplay    *display,
+    GstVaapiChromaType  chroma_type,
+    guint               width,
+    guint               height
+);
+
+GstVaapiID
+gst_vaapi_surface_get_id(GstVaapiSurface *surface);
+
+GstVaapiChromaType
+gst_vaapi_surface_get_chroma_type(GstVaapiSurface *surface);
+
+guint
+gst_vaapi_surface_get_width(GstVaapiSurface *surface);
+
+guint
+gst_vaapi_surface_get_height(GstVaapiSurface *surface);
+
+void
+gst_vaapi_surface_get_size(
+    GstVaapiSurface *surface,
+    guint           *pwidth,
+    guint           *pheight
+);
+
+GstVaapiImage *
+gst_vaapi_surface_derive_image(GstVaapiSurface *surface);
+
+gboolean
+gst_vaapi_surface_get_image(GstVaapiSurface *surface, GstVaapiImage *image);
+
+gboolean
+gst_vaapi_surface_put_image(GstVaapiSurface *surface, GstVaapiImage *image);
+
+gboolean
+gst_vaapi_surface_associate_subpicture(
+    GstVaapiSurface         *surface,
+    GstVaapiSubpicture      *subpicture,
+    const GstVaapiRectangle *src_rect,
+    const GstVaapiRectangle *dst_rect
+);
+
+gboolean
+gst_vaapi_surface_deassociate_subpicture(
+    GstVaapiSurface         *surface,
+    GstVaapiSubpicture      *subpicture
+);
+
+gboolean
+gst_vaapi_surface_sync(GstVaapiSurface *surface);
+
+gboolean
+gst_vaapi_surface_query_status(
+    GstVaapiSurface       *surface,
+    GstVaapiSurfaceStatus *pstatus
+);
+
+gboolean
+gst_vaapi_surface_set_subpictures_from_composition(
+    GstVaapiSurface            *surface,
+    GstVideoOverlayComposition *composition,
+    gboolean                    propagate_context
+);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_SURFACE_H */
diff --git a/gst-libs/gst/vaapi/gstvaapisurface_priv.h b/gst-libs/gst/vaapi/gstvaapisurface_priv.h
new file mode 100644 (file)
index 0000000..0817b29
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ *  gstvaapisurface_priv.h - VA surface abstraction (private data)
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_SURFACE_PRIV_H
+#define GST_VAAPI_SURFACE_PRIV_H
+
+#include <gst/vaapi/gstvaapicontext.h>
+#include <gst/vaapi/gstvaapisurface.h>
+
+G_GNUC_INTERNAL
+void
+gst_vaapi_surface_set_parent_context(
+    GstVaapiSurface *surface,
+    GstVaapiContext *context
+);
+
+G_GNUC_INTERNAL
+GstVaapiContext *
+gst_vaapi_surface_get_parent_context(GstVaapiSurface *surface);
+
+#endif /* GST_VAAPI_SURFACE_PRIV_H */
diff --git a/gst-libs/gst/vaapi/gstvaapisurface_userptr.c b/gst-libs/gst/vaapi/gstvaapisurface_userptr.c
new file mode 100644 (file)
index 0000000..787a80d
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ *  gstvaapisurface_userptr.c - VA surface abstraction for userptr
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapisurface_userptr
+ * @short_description: VA surface abstraction for userptr
+ */
+#include "sysdeps.h"
+#include "gstvaapisurface_userptr.h"
+#include "gstvaapiutils.h"
+#include "gstvaapiobject_priv.h"
+#include "gstvaapidisplay_priv.h"
+
+#include <va/va.h>
+#include <va/va_tpi.h>
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiSurfaceUserPtr, gst_vaapi_surface_userptr, GST_VAAPI_TYPE_SURFACE);
+
+#define GST_VAAPI_SURFACE_USERPTR_GET_PRIVATE(obj)                 \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                            \
+                                 GST_VAAPI_TYPE_SURFACE_USERPTR,   \
+                                 GstVaapiSurfaceUserPtrPrivate))
+
+struct _GstVaapiSurfaceUserPtrPrivate {
+    GstVaapiImageFormat format;
+};
+
+enum {
+    PROP_0,
+
+    PROP_FORMAT
+};
+
+typedef struct _GstVaapiSurfaceUserPtrInfo {
+    guint fourcc;
+    guint datasize;
+    guint y_stride;
+    guint u_stride;
+    guint v_stride;
+    guint y_offset;
+    guint u_offset;
+    guint v_offset;
+} GstVaapiSurfaceUserPtrInfo;
+
+static gboolean
+_get_surface_userptr_info(
+    GstVaapiImageFormat format,
+    guint width,
+    guint height,
+    GstVaapiSurfaceUserPtrInfo *info
+)
+{
+    const VAImageFormat *va_format;
+    guint stride1, stride2;
+    guint height2;
+
+    g_return_val_if_fail(info, FALSE);
+
+    va_format = gst_vaapi_image_format_get_va_format(format);
+    if (!va_format)
+        return FALSE;
+    info->fourcc = va_format->fourcc;
+
+    stride1 = GST_ROUND_UP_4(width);
+    stride2 = GST_ROUND_UP_4((width + 1) / 2);
+    height2 = (height + 1) / 2;
+
+    info->datasize = (stride1 * height) + (stride2 * height2)*2;
+    info->y_stride = stride1;
+    info->y_offset = 0;
+
+    switch (format) {
+    case GST_VAAPI_IMAGE_NV12:
+        info->u_stride = stride1;
+        info->v_stride = stride1;
+        info->u_offset = stride1 * height;
+        info->v_offset = stride1 * height;
+        break;
+
+    case GST_VAAPI_IMAGE_YV12:
+        info->u_stride = stride2;
+        info->v_stride = stride2;
+        info->u_offset = stride1 * height + stride2 * height2;
+        info->v_offset = stride1 * height;
+        break;
+
+    case GST_VAAPI_IMAGE_I420:
+        info->u_stride = stride2;
+        info->v_stride = stride2;
+        info->u_offset = stride1 * height;
+        info->v_offset = stride1 * height + stride2 * height2;
+        break;
+
+    default:
+        return FALSE;
+    }
+    return TRUE;
+}
+
+static gboolean
+gst_vaapi_surface_userptr_create(GstVaapiSurface *base)
+{
+    GstVaapiSurfaceUserPtr * const surface = GST_VAAPI_SURFACE_USERPTR(base);
+    GstVaapiSurfaceUserPtrPrivate * const priv = surface->priv;
+    GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(surface);
+    GstVaapiSurfaceUserPtrInfo info;
+    VASurfaceID surface_id;
+    VAStatus status;
+    guint surface_format;
+    GstVaapiChromaType chroma_type;
+    guint width, height;
+
+    chroma_type = gst_vaapi_surface_get_chroma_type(base);
+    gst_vaapi_surface_get_size(base, &width, &height);
+
+    if (!_get_surface_userptr_info(priv->format, width, height, &info)) {
+        GST_ERROR("surface userptr format error.");
+        return FALSE;
+    }
+
+    switch (chroma_type) {
+    case GST_VAAPI_CHROMA_TYPE_YUV420:
+        surface_format = VA_RT_FORMAT_YUV420;
+        break;
+    case GST_VAAPI_CHROMA_TYPE_YUV422:
+        surface_format = VA_RT_FORMAT_YUV422;
+        break;
+    case GST_VAAPI_CHROMA_TYPE_YUV444:
+        surface_format = VA_RT_FORMAT_YUV444;
+        break;
+    default:
+        GST_DEBUG("unsupported chroma-type %u\n", chroma_type);
+        return FALSE;
+    }
+
+    GST_VAAPI_DISPLAY_LOCK(display);
+    status = vaCreateSurfacesForUserPtr(
+        GST_VAAPI_DISPLAY_VADISPLAY(display),
+        width,
+        height,
+        surface_format,
+        1, &surface_id,
+        info.datasize,
+        info.fourcc,
+        info.y_stride,
+        info.u_stride,
+        info.v_stride,
+        info.y_offset,
+        info.u_offset,
+        info.v_offset);
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+    if (!vaapi_check_status(status, "vaCreateSurfaces()"))
+        return FALSE;
+
+    GST_DEBUG("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(surface_id));
+    GST_VAAPI_OBJECT_ID(surface) = surface_id;
+    return TRUE;
+}
+
+static void
+gst_vaapi_surface_userptr_finalize(GObject *object)
+{
+
+    G_OBJECT_CLASS(gst_vaapi_surface_userptr_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_surface_userptr_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiSurfaceUserPtr        * const surface = GST_VAAPI_SURFACE_USERPTR(object);
+    GstVaapiSurfaceUserPtrPrivate * const priv    = surface->priv;
+
+    switch (prop_id) {
+    case PROP_FORMAT:
+        priv->format = g_value_get_uint(value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_surface_userptr_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiSurfaceUserPtr * const surface = GST_VAAPI_SURFACE_USERPTR(object);
+
+    switch (prop_id) {
+    case PROP_FORMAT:
+        g_value_set_uint(value, gst_vaapi_surface_userptr_get_format(surface));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_surface_userptr_class_init(GstVaapiSurfaceUserPtrClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstVaapiSurfaceClass * const surface_class = GST_VAAPI_SURFACE_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiSurfaceUserPtrPrivate));
+
+    object_class->finalize     = gst_vaapi_surface_userptr_finalize;
+    object_class->set_property = gst_vaapi_surface_userptr_set_property;
+    object_class->get_property = gst_vaapi_surface_userptr_get_property;
+
+    surface_class->create = gst_vaapi_surface_userptr_create;
+
+    g_object_class_install_property
+        (object_class,
+         PROP_FORMAT,
+         g_param_spec_uint("format",
+                           "format",
+                           "The buffer format of surface userptr",
+                           0, G_MAXUINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gst_vaapi_surface_userptr_init(GstVaapiSurfaceUserPtr *surface)
+{
+    GstVaapiSurfaceUserPtrPrivate *priv = GST_VAAPI_SURFACE_USERPTR_GET_PRIVATE(surface);
+
+    surface->priv        = priv;
+    priv->format         = 0;
+}
+
+/**
+ * gst_vaapi_surface_new:
+ * @display: a #GstVaapiDisplay
+ * @chroma_type: the surface chroma format
+ * @format: the fourcc format of the buffer
+ * @width: the requested surface width
+ * @height: the requested surface height
+ *
+ * Creates a new #GstVaapiSurface with the specified chroma format and
+ * dimensions.
+ *
+ * Return value: the newly allocated #GstVaapiSurface object
+ */
+GstVaapiSurfaceUserPtr *
+gst_vaapi_surface_userptr_new(
+    GstVaapiDisplay    *display,
+    GstVaapiChromaType  chroma_type,
+    GstVaapiImageFormat format,
+    guint               width,
+    guint               height
+)
+{
+    GST_DEBUG("size %ux%u, chroma type 0x%x", width, height, chroma_type);
+
+    return g_object_new(GST_VAAPI_TYPE_SURFACE_USERPTR,
+                        "display",      display,
+                        "id",           GST_VAAPI_ID(VA_INVALID_ID),
+                        "width",        width,
+                        "height",       height,
+                        "chroma-type",  chroma_type,
+                        "format",       format,
+                        NULL);
+}
+
+
+GstVaapiImageFormat
+gst_vaapi_surface_userptr_get_format(GstVaapiSurfaceUserPtr *surface)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE_USERPTR(surface), 0);
+
+    return surface->priv->format;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapisurface_userptr.h b/gst-libs/gst/vaapi/gstvaapisurface_userptr.h
new file mode 100644 (file)
index 0000000..564ea5f
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ *  gstvaapisurface_userptr.h - VA surface abstraction for userptr
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_SURFACE_USERPTR_H
+#define GST_VAAPI_SURFACE_USERPTR_H
+
+#include <gst/vaapi/gstvaapiobject.h>
+#include <gst/vaapi/gstvaapisurface.h>
+#include <gst/vaapi/gstvaapiimageformat.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_SURFACE_USERPTR \
+    (gst_vaapi_surface_userptr_get_type())
+
+#define GST_VAAPI_SURFACE_USERPTR(obj)                          \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_SURFACE_USERPTR, \
+                                GstVaapiSurfaceUserPtr))
+
+#define GST_VAAPI_SURFACE_USERPTR_CLASS(klass)                          \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_SURFACE_USERPTR,    \
+                             GstVaapiSurfaceUserPtrClass))
+
+#define GST_VAAPI_IS_SURFACE_USERPTR(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_SURFACE_USERPTR))
+
+#define GST_VAAPI_IS_SURFACE_USERPTR_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_SURFACE_USERPTR))
+
+#define GST_VAAPI_SURFACE_USERPTR_GET_CLASS(obj)                        \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_SURFACE_USERPTR,  \
+                               GstVaapiSurfaceUserPtrClass))
+
+typedef struct _GstVaapiSurfaceUserPtr          GstVaapiSurfaceUserPtr;
+typedef struct _GstVaapiSurfaceUserPtrPrivate   GstVaapiSurfaceUserPtrPrivate;
+typedef struct _GstVaapiSurfaceUserPtrClass     GstVaapiSurfaceUserPtrClass;
+
+/**
+ * GstVaapiSurfaceUserPtr:
+ *
+ * A VA surface userptr wrapper.
+ */
+struct _GstVaapiSurfaceUserPtr {
+    /*< private >*/
+    GstVaapiSurface parent_instance;
+
+    GstVaapiSurfaceUserPtrPrivate *priv;
+};
+
+/**
+ * GstVaapiSurfaceUserPtrClass:
+ *
+ * A VA surface userptr wrapper class.
+ */
+struct _GstVaapiSurfaceUserPtrClass {
+    /*< private >*/
+    GstVaapiSurfaceClass parent_class;
+};
+
+GType
+gst_vaapi_surface_userptr_get_type(void) G_GNUC_CONST;
+
+GstVaapiSurfaceUserPtr *
+gst_vaapi_surface_userptr_new(
+    GstVaapiDisplay    *display,
+    GstVaapiChromaType  chroma_type,
+    GstVaapiImageFormat format,
+    guint               width,
+    guint               height
+);
+
+GstVaapiImageFormat
+gst_vaapi_surface_userptr_get_format(GstVaapiSurfaceUserPtr *surface);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_SURFACE_USERPTR_H */
diff --git a/gst-libs/gst/vaapi/gstvaapisurfacepool.c b/gst-libs/gst/vaapi/gstvaapisurfacepool.c
new file mode 100644 (file)
index 0000000..5bd9196
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ *  gstvaapisurfacepool.c - Gst VA surface pool
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapisurfacepool
+ * @short_description: VA surface pool
+ */
+
+#include "sysdeps.h"
+#include "gstvaapisurfacepool.h"
+#include "gstvaapisurface_userptr.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(
+    GstVaapiSurfacePool,
+    gst_vaapi_surface_pool,
+    GST_VAAPI_TYPE_VIDEO_POOL);
+
+#define GST_VAAPI_SURFACE_POOL_GET_PRIVATE(obj)                 \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_SURFACE_POOL,  \
+                                 GstVaapiSurfacePoolPrivate))
+
+struct _GstVaapiSurfacePoolPrivate {
+    GstVaapiChromaType  chroma_type;
+    guint               width;
+    guint               height;
+    gboolean            is_shared_buffer;
+};
+
+static void
+gst_vaapi_surface_pool_set_caps(GstVaapiVideoPool *pool, GstCaps *caps)
+{
+    GstVaapiSurfacePoolPrivate *priv = GST_VAAPI_SURFACE_POOL(pool)->priv;
+    GstStructure *structure;
+    gint width, height;
+
+    structure = gst_caps_get_structure(caps, 0);
+    gst_structure_get_int(structure, "width", &width);
+    gst_structure_get_int(structure, "height", &height);
+
+    if (gst_structure_has_name(structure, GST_VAAPI_BUFFER_SHARING_CAPS_NAME))
+        priv->is_shared_buffer = TRUE;
+    else
+        priv->is_shared_buffer = FALSE;
+
+    priv->chroma_type   = GST_VAAPI_CHROMA_TYPE_YUV420;
+    priv->width         = width;
+    priv->height        = height;
+}
+
+gpointer
+gst_vaapi_surface_pool_alloc_object(
+    GstVaapiVideoPool *pool,
+    GstVaapiDisplay   *display
+)
+{
+    GstVaapiSurfacePoolPrivate *priv = GST_VAAPI_SURFACE_POOL(pool)->priv;
+
+    if (priv->is_shared_buffer)
+        return gst_vaapi_surface_userptr_new(display,
+                                             priv->chroma_type,
+                                             GST_VAAPI_IMAGE_NV12,
+                                             priv->width,
+                                             priv->height);
+    else
+        return gst_vaapi_surface_new(display,
+                                     priv->chroma_type,
+                                     priv->width,
+                                     priv->height);
+}
+
+static void
+gst_vaapi_surface_pool_finalize(GObject *object)
+{
+    G_OBJECT_CLASS(gst_vaapi_surface_pool_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_surface_pool_class_init(GstVaapiSurfacePoolClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstVaapiVideoPoolClass * const pool_class = GST_VAAPI_VIDEO_POOL_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiSurfacePoolPrivate));
+
+    object_class->finalize      = gst_vaapi_surface_pool_finalize;
+
+    pool_class->set_caps        = gst_vaapi_surface_pool_set_caps;
+    pool_class->alloc_object    = gst_vaapi_surface_pool_alloc_object;
+}
+
+static void
+gst_vaapi_surface_pool_init(GstVaapiSurfacePool *pool)
+{
+    GstVaapiSurfacePoolPrivate *priv = GST_VAAPI_SURFACE_POOL_GET_PRIVATE(pool);
+
+    pool->priv          = priv;
+    priv->chroma_type   = 0;
+    priv->width         = 0;
+    priv->height        = 0;
+    priv->is_shared_buffer = FALSE;
+}
+
+/**
+ * gst_vaapi_surface_pool_new:
+ * @display: a #GstVaapiDisplay
+ * @caps: a #GstCaps
+ *
+ * Creates a new #GstVaapiVideoPool of #GstVaapiSurface with the
+ * specified dimensions in @caps.
+ *
+ * Return value: the newly allocated #GstVaapiVideoPool
+ */
+GstVaapiVideoPool *
+gst_vaapi_surface_pool_new(GstVaapiDisplay *display, GstCaps *caps)
+{
+    return g_object_new(GST_VAAPI_TYPE_SURFACE_POOL,
+                        "display", display,
+                        "caps",    caps,
+                        NULL);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapisurfacepool.h b/gst-libs/gst/vaapi/gstvaapisurfacepool.h
new file mode 100644 (file)
index 0000000..2bb661c
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ *  gstvaapisurfacepool.h - Gst VA surface pool
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_SURFACE_POOL_H
+#define GST_VAAPI_SURFACE_POOL_H
+
+#include <gst/vaapi/gstvaapisurface.h>
+#include <gst/vaapi/gstvaapivideopool.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_SURFACE_POOL \
+    (gst_vaapi_surface_pool_get_type())
+
+#define GST_VAAPI_SURFACE_POOL(obj)                             \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_SURFACE_POOL,    \
+                                GstVaapiSurfacePool))
+
+#define GST_VAAPI_SURFACE_POOL_CLASS(klass)                     \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_SURFACE_POOL,       \
+                             GstVaapiSurfacePoolClass))
+
+#define GST_VAAPI_IS_SURFACE_POOL(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_SURFACE_POOL))
+
+#define GST_VAAPI_IS_SURFACE_POOL_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_SURFACE_POOL))
+
+#define GST_VAAPI_SURFACE_POOL_GET_CLASS(obj)                   \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_SURFACE_POOL,     \
+                               GstVaapiSurfacePoolClass))
+
+typedef struct _GstVaapiSurfacePool             GstVaapiSurfacePool;
+typedef struct _GstVaapiSurfacePoolPrivate      GstVaapiSurfacePoolPrivate;
+typedef struct _GstVaapiSurfacePoolClass        GstVaapiSurfacePoolClass;
+
+/**
+ * GstVaapiSurfacePool:
+ *
+ * A pool of lazily allocated #GstVaapiSurface objects.
+ */
+struct _GstVaapiSurfacePool {
+    /*< private >*/
+    GstVaapiVideoPool parent_instance;
+
+    GstVaapiSurfacePoolPrivate *priv;
+};
+
+/**
+ * GstVaapiSurfacePoolClass:
+ *
+ * A pool of lazily allocated #GstVaapiSurface objects.
+ */
+struct _GstVaapiSurfacePoolClass {
+    /*< private >*/
+    GstVaapiVideoPoolClass parent_class;
+};
+
+GType
+gst_vaapi_surface_pool_get_type(void) G_GNUC_CONST;
+
+GstVaapiVideoPool *
+gst_vaapi_surface_pool_new(GstVaapiDisplay *display, GstCaps *caps);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_SURFACE_POOL_H */
diff --git a/gst-libs/gst/vaapi/gstvaapisurfaceproxy.c b/gst-libs/gst/vaapi/gstvaapisurfaceproxy.c
new file mode 100644 (file)
index 0000000..aa4103e
--- /dev/null
@@ -0,0 +1,431 @@
+/*
+ *  gstvaapisurfaceproxy.c - VA surface proxy
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapisurfaceproxy
+ * @short_description: VA surface proxy
+ */
+
+#include "sysdeps.h"
+#include "gstvaapisurfaceproxy.h"
+#include "gstvaapiobject_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiSurfaceProxy, gst_vaapi_surface_proxy, G_TYPE_OBJECT);
+
+#define GST_VAAPI_SURFACE_PROXY_GET_PRIVATE(obj)                \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_SURFACE_PROXY, \
+                                 GstVaapiSurfaceProxyPrivate))
+
+struct _GstVaapiSurfaceProxyPrivate {
+    GstVaapiContext    *context;
+    GstVaapiSurface    *surface;
+    GstClockTime        timestamp;
+    guint               is_interlaced   : 1;
+    guint               tff             : 1;
+};
+
+enum {
+    PROP_0,
+
+    PROP_CONTEXT,
+    PROP_SURFACE,
+    PROP_TIMESTAMP,
+    PROP_INTERLACED,
+    PROP_TFF
+};
+
+static void
+gst_vaapi_surface_proxy_finalize(GObject *object)
+{
+    GstVaapiSurfaceProxy * const proxy = GST_VAAPI_SURFACE_PROXY(object);
+
+    gst_vaapi_surface_proxy_set_surface(proxy, NULL);
+    gst_vaapi_surface_proxy_set_context(proxy, NULL);
+
+    G_OBJECT_CLASS(gst_vaapi_surface_proxy_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_surface_proxy_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiSurfaceProxy * const proxy = GST_VAAPI_SURFACE_PROXY(object);
+
+    switch (prop_id) {
+    case PROP_CONTEXT:
+        gst_vaapi_surface_proxy_set_context(proxy, g_value_get_pointer(value));
+        break;
+    case PROP_SURFACE:
+        gst_vaapi_surface_proxy_set_surface(proxy, g_value_get_pointer(value));
+        break;
+    case PROP_TIMESTAMP:
+        gst_vaapi_surface_proxy_set_timestamp(proxy, g_value_get_uint64(value));
+        break;
+    case PROP_INTERLACED:
+        gst_vaapi_surface_proxy_set_interlaced(proxy, g_value_get_boolean(value));
+        break;
+    case PROP_TFF:
+        gst_vaapi_surface_proxy_set_tff(proxy, g_value_get_boolean(value));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_surface_proxy_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiSurfaceProxy * const proxy = GST_VAAPI_SURFACE_PROXY(object);
+
+    switch (prop_id) {
+    case PROP_CONTEXT:
+        g_value_set_pointer(value, gst_vaapi_surface_proxy_get_context(proxy));
+        break;
+    case PROP_SURFACE:
+        g_value_set_pointer(value, gst_vaapi_surface_proxy_get_surface(proxy));
+        break;
+    case PROP_TIMESTAMP:
+        g_value_set_uint64(value, gst_vaapi_surface_proxy_get_timestamp(proxy));
+        break;
+    case PROP_INTERLACED:
+        g_value_set_boolean(value, gst_vaapi_surface_proxy_get_interlaced(proxy));
+        break;
+    case PROP_TFF:
+        g_value_set_boolean(value, gst_vaapi_surface_proxy_get_tff(proxy));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_surface_proxy_class_init(GstVaapiSurfaceProxyClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiSurfaceProxyPrivate));
+
+    object_class->finalize     = gst_vaapi_surface_proxy_finalize;
+    object_class->set_property = gst_vaapi_surface_proxy_set_property;
+    object_class->get_property = gst_vaapi_surface_proxy_get_property;
+
+    g_object_class_install_property
+        (object_class,
+         PROP_CONTEXT,
+         g_param_spec_pointer("context",
+                              "Context",
+                              "The context stored in the proxy",
+                              G_PARAM_READWRITE));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_SURFACE,
+         g_param_spec_pointer("surface",
+                              "Surface",
+                              "The surface stored in the proxy",
+                              G_PARAM_READWRITE));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_TIMESTAMP,
+         g_param_spec_uint64("timestamp",
+                             "Timestamp",
+                             "The presentation time of the surface",
+                             0, G_MAXUINT64, GST_CLOCK_TIME_NONE,
+                             G_PARAM_READWRITE));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_INTERLACED,
+         g_param_spec_boolean("interlaced",
+                              "Interlaced",
+                              "Flag indicating whether surface is interlaced",
+                              FALSE,
+                              G_PARAM_READWRITE));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_TFF,
+         g_param_spec_boolean("tff",
+                              "Top-Field-First",
+                              "Flag indicating for interlaced surfaces whether Top Field is First",
+                              FALSE,
+                              G_PARAM_READWRITE));
+}
+
+static void
+gst_vaapi_surface_proxy_init(GstVaapiSurfaceProxy *proxy)
+{ 
+    GstVaapiSurfaceProxyPrivate *priv;
+
+    priv                = GST_VAAPI_SURFACE_PROXY_GET_PRIVATE(proxy);
+    proxy->priv         = priv;
+    priv->context       = NULL;
+    priv->surface       = NULL;
+    priv->timestamp     = GST_CLOCK_TIME_NONE;
+    priv->is_interlaced = FALSE;
+    priv->tff           = FALSE;
+}
+
+/**
+ * gst_vaapi_surface_proxy_new:
+ * @context: a #GstVaapiContext
+ * @surface: a #GstVaapiSurface
+ *
+ * Creates a new #GstVaapiSurfaceProxy with the specified context and
+ * surface.
+ *
+ * Return value: the newly allocated #GstVaapiSurfaceProxy object
+ */
+GstVaapiSurfaceProxy *
+gst_vaapi_surface_proxy_new(GstVaapiContext *context, GstVaapiSurface *surface)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), NULL);
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), NULL);
+
+    return g_object_new(GST_VAAPI_TYPE_SURFACE_PROXY,
+                        "context",  context,
+                        "surface",  surface,
+                        NULL);
+}
+
+/**
+ * gst_vaapi_surface_proxy_get_context:
+ * @proxy: a #GstVaapiSurfaceProxy
+ *
+ * Returns the #GstVaapiContext stored in the @proxy.
+ *
+ * Return value: the #GstVaapiContext
+ */
+GstVaapiContext *
+gst_vaapi_surface_proxy_get_context(GstVaapiSurfaceProxy *proxy)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy), NULL);
+
+    return proxy->priv->context;
+}
+
+/**
+ * gst_vaapi_surface_proxy_set_context:
+ * @proxy: a #GstVaapiSurfaceProxy
+ * @context: the new #GstVaapiContext to be stored in @proxy
+ *
+ * Stores a new @context into the @proxy. The proxy releases the
+ * previous reference, if any, and then holds a reference to the new
+ * @context.
+ */
+void
+gst_vaapi_surface_proxy_set_context(
+    GstVaapiSurfaceProxy *proxy,
+    GstVaapiContext      *context
+)
+{
+    GstVaapiSurfaceProxyPrivate *priv;
+
+    g_return_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy));
+
+    priv = proxy->priv;
+
+    g_clear_object(&priv->context);
+
+    if (context)
+        priv->context = g_object_ref(context);
+}
+
+/**
+ * gst_vaapi_surface_proxy_get_surface:
+ * @proxy: a #GstVaapiSurfaceProxy
+ *
+ * Returns the #GstVaapiSurface stored in the @proxy.
+ *
+ * Return value: the #GstVaapiSurface
+ */
+GstVaapiSurface *
+gst_vaapi_surface_proxy_get_surface(GstVaapiSurfaceProxy *proxy)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy), NULL);
+
+    return proxy->priv->surface;
+}
+
+/**
+ * gst_vaapi_surface_proxy_get_surface_id:
+ * @proxy: a #GstVaapiSurfaceProxy
+ *
+ * Returns the VA surface ID stored in the @proxy.
+ *
+ * Return value: the #GstVaapiID
+ */
+GstVaapiID
+gst_vaapi_surface_proxy_get_surface_id(GstVaapiSurfaceProxy *proxy)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy), GST_VAAPI_ID_NONE);
+    g_return_val_if_fail(proxy->priv->surface != NULL, GST_VAAPI_ID_NONE);
+
+    return GST_VAAPI_OBJECT_ID(proxy->priv->surface);
+}
+
+/**
+ * gst_vaapi_surface_proxy_set_surface:
+ * @proxy: a #GstVaapiSurfaceProxy
+ * @surface: the new #GstVaapiSurface to be stored in @proxy
+ *
+ * Stores a new @surface into the @proxy. The proxy releases the
+ * previous reference, if any, and then holds a reference to the new
+ * @surface.
+ */
+void
+gst_vaapi_surface_proxy_set_surface(
+    GstVaapiSurfaceProxy *proxy,
+    GstVaapiSurface      *surface
+)
+{
+    GstVaapiSurfaceProxyPrivate *priv;
+
+    g_return_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy));
+
+    priv = proxy->priv;
+
+    if (priv->surface) {
+        if (priv->context)
+            gst_vaapi_context_put_surface(priv->context, priv->surface);
+        g_object_unref(priv->surface);
+        priv->surface = NULL;
+    }
+
+    if (surface)
+        priv->surface = g_object_ref(surface);
+}
+
+/**
+ * gst_vaapi_surface_proxy_get_timestamp:
+ * @proxy: a #GstVaapiSurfaceProxy
+ *
+ * Returns the presentation timestamp of the #GstVaapiSurface held by @proxy.
+ *
+ * Return value: the presentation timestamp of the surface, or
+ *   %GST_CLOCK_TIME_NONE is none was set
+ */
+GstClockTime
+gst_vaapi_surface_proxy_get_timestamp(GstVaapiSurfaceProxy *proxy)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy), GST_CLOCK_TIME_NONE);
+
+    return proxy->priv->timestamp;
+}
+
+/**
+ * gst_vaapi_surface_proxy_set_timestamp:
+ * @proxy: a #GstVaapiSurfaceProxy
+ * @timestamp: the new presentation timestamp as a #GstClockTime
+ *
+ * Sets the presentation timestamp of the @proxy surface to @timestamp.
+ */
+void
+gst_vaapi_surface_proxy_set_timestamp(
+    GstVaapiSurfaceProxy *proxy,
+    GstClockTime          timestamp
+)
+{
+    g_return_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy));
+
+    proxy->priv->timestamp = timestamp;
+}
+
+/**
+ * gst_vaapi_surface_proxy_get_interlaced:
+ * @proxy: a #GstVaapiSurfaceProxy
+ *
+ * Returns whether the @proxy holds an interlaced #GstVaapiSurface or not.
+ *
+ * Return value: %TRUE if the underlying surface is interlaced, %FALSE
+ *     otherwise.
+ */
+gboolean
+gst_vaapi_surface_proxy_get_interlaced(GstVaapiSurfaceProxy *proxy)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy), FALSE);
+
+    return proxy->priv->is_interlaced;
+}
+
+/**
+ * gst_vaapi_surface_proxy_set_interlaced:
+ * @proxy: a #GstVaapiSurfaceProxy
+ * @b: a boolean value
+ *
+ * Sets whether the underlying #GstVaapiSurface for @proxy is interlaced
+ * or not.
+ */
+void
+gst_vaapi_surface_proxy_set_interlaced(GstVaapiSurfaceProxy *proxy, gboolean b)
+{
+    g_return_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy));
+
+    proxy->priv->is_interlaced = b;
+}
+
+/**
+ * gst_vaapi_surface_proxy_get_tff:
+ * @proxy: a #GstVaapiSurfaceProxy
+ *
+ * Returns the TFF flag of the #GstVaapiSurface held by @proxy.
+ *
+ * Return value: the TFF flag of the surface
+ */
+gboolean
+gst_vaapi_surface_proxy_get_tff(GstVaapiSurfaceProxy *proxy)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy), FALSE);
+
+    return proxy->priv->is_interlaced && proxy->priv->tff;
+}
+
+/**
+ * gst_vaapi_surface_proxy_set_tff:
+ * @proxy: a #GstVaapiSurfaceProxy
+ * @tff: the new value of the TFF flag
+ *
+ * Sets the TFF flag of the @proxy surface to @tff.
+ */
+void
+gst_vaapi_surface_proxy_set_tff(GstVaapiSurfaceProxy *proxy, gboolean tff)
+{
+    g_return_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy));
+
+    proxy->priv->tff = tff;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapisurfaceproxy.h b/gst-libs/gst/vaapi/gstvaapisurfaceproxy.h
new file mode 100644 (file)
index 0000000..35e38f7
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ *  gstvaapisurfaceproxy.h - VA surface proxy
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_SURFACE_PROXY_H
+#define GST_VAAPI_SURFACE_PROXY_H
+
+#include <glib-object.h>
+#include <gst/vaapi/gstvaapicontext.h>
+#include <gst/vaapi/gstvaapisurface.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_SURFACE_PROXY \
+    (gst_vaapi_surface_proxy_get_type())
+
+#define GST_VAAPI_SURFACE_PROXY(obj)                            \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_SURFACE_PROXY,   \
+                                GstVaapiSurfaceProxy))
+
+#define GST_VAAPI_SURFACE_PROXY_CLASS(klass)                    \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_SURFACE_PROXY,      \
+                             GstVaapiSurfaceProxyClass))
+
+#define GST_VAAPI_IS_SURFACE_PROXY(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_SURFACE_PROXY))
+
+#define GST_VAAPI_IS_SURFACE_PROXY_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_SURFACE_PROXY))
+
+#define GST_VAAPI_SURFACE_PROXY_GET_CLASS(obj)                  \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_SURFACE_PROXY,    \
+                               GstVaapiSurfaceProxyClass))
+
+/**
+ * GST_VAAPI_SURFACE_PROXY_SURFACE:
+ * @surface: a #GstVaapiSurfaceProxy
+ *
+ * Macro that evaluates to the #GstVaapiSurface of @surface.
+ */
+#define GST_VAAPI_SURFACE_PROXY_SURFACE(surface) \
+    gst_vaapi_surface_proxy_get_surface(surface)
+
+/**
+ * GST_VAAPI_SURFACE_PROXY_TIMESTAMP:
+ * @surface: a #GstVaapiSurfaceProxy
+ *
+ * Macro that evaluates to the @surface timestamp, or
+ * %GST_CLOCK_TIME_NONE if none was set.
+ */
+#define GST_VAAPI_SURFACE_PROXY_TIMESTAMP(surface) \
+    gst_vaapi_surface_proxy_get_timestamp(surface)
+
+/**
+ * GST_VAAPI_SURFACE_PROXY_INTERLACED:
+ * @surface: a #GstVaapiSurfaceProxy
+ *
+ * Macro that evaluates to %TRUE if the @surface is interlaced.
+ */
+#define GST_VAAPI_SURFACE_PROXY_INTERLACED(surface) \
+    gst_vaapi_surface_proxy_get_interlaced(surface)
+
+/**
+ * GST_VAAPI_SURFACE_PROXY_TFF:
+ * @surface: a #GstVaapiSurfaceProxy
+ *
+ * Macro that evaluates to the tff flag of the @surface
+ */
+#define GST_VAAPI_SURFACE_PROXY_TFF(surface) \
+    gst_vaapi_surface_proxy_get_tff(surface)
+
+typedef struct _GstVaapiSurfaceProxy            GstVaapiSurfaceProxy;
+typedef struct _GstVaapiSurfaceProxyPrivate     GstVaapiSurfaceProxyPrivate;
+typedef struct _GstVaapiSurfaceProxyClass       GstVaapiSurfaceProxyClass;
+
+/**
+ * GstVaapiSurfaceProxy:
+ *
+ * A wrapper around a VA surface and context.
+ */
+struct _GstVaapiSurfaceProxy {
+    /*< private >*/
+    GObject parent_instance;
+
+    GstVaapiSurfaceProxyPrivate *priv;
+};
+
+/**
+ * GstVaapiSurfaceProxyClass:
+ *
+ * A wrapper around a VA surface and context.
+ */
+struct _GstVaapiSurfaceProxyClass {
+    /*< private >*/
+    GObjectClass parent_class;
+};
+
+GType
+gst_vaapi_surface_proxy_get_type(void) G_GNUC_CONST;
+
+GstVaapiSurfaceProxy *
+gst_vaapi_surface_proxy_new(GstVaapiContext *context, GstVaapiSurface *surface);
+
+GstVaapiContext *
+gst_vaapi_surface_proxy_get_context(GstVaapiSurfaceProxy *proxy);
+
+void
+gst_vaapi_surface_proxy_set_context(
+    GstVaapiSurfaceProxy *proxy,
+    GstVaapiContext      *context
+);
+
+GstVaapiSurface *
+gst_vaapi_surface_proxy_get_surface(GstVaapiSurfaceProxy *proxy);
+
+GstVaapiID
+gst_vaapi_surface_proxy_get_surface_id(GstVaapiSurfaceProxy *proxy);
+
+void
+gst_vaapi_surface_proxy_set_surface(
+    GstVaapiSurfaceProxy *proxy,
+    GstVaapiSurface      *surface
+);
+
+GstClockTime
+gst_vaapi_surface_proxy_get_timestamp(GstVaapiSurfaceProxy *proxy);
+
+void
+gst_vaapi_surface_proxy_set_timestamp(
+    GstVaapiSurfaceProxy *proxy,
+    GstClockTime          timestamp
+);
+
+gboolean
+gst_vaapi_surface_proxy_get_interlaced(GstVaapiSurfaceProxy *proxy);
+
+void
+gst_vaapi_surface_proxy_set_interlaced(GstVaapiSurfaceProxy *proxy, gboolean b);
+
+gboolean
+gst_vaapi_surface_proxy_get_tff(GstVaapiSurfaceProxy *proxy);
+
+void
+gst_vaapi_surface_proxy_set_tff(GstVaapiSurfaceProxy *proxy, gboolean tff);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_SURFACE_PROXY_H */
diff --git a/gst-libs/gst/vaapi/gstvaapitexture.c b/gst-libs/gst/vaapi/gstvaapitexture.c
new file mode 100644 (file)
index 0000000..97025f2
--- /dev/null
@@ -0,0 +1,683 @@
+/*
+ *  gstvaapitexture.c - VA texture abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapitexture
+ * @short_description: VA/GLX texture abstraction
+ */
+
+#include "sysdeps.h"
+#include "gstvaapitexture.h"
+#include "gstvaapicompat.h"
+#include "gstvaapiutils.h"
+#include "gstvaapiutils_glx.h"
+#include "gstvaapidisplay_glx.h"
+#include "gstvaapi_priv.h"
+#include "gstvaapidisplay_x11_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiTexture, gst_vaapi_texture, GST_VAAPI_TYPE_OBJECT);
+
+#define GST_VAAPI_TEXTURE_GET_PRIVATE(obj)                      \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_TEXTURE,        \
+                                 GstVaapiTexturePrivate))
+
+struct _GstVaapiTexturePrivate {
+    GLenum               target;
+    GLenum               format;
+    guint                width;
+    guint                height;
+    GLContextState      *gl_context;
+    void                *gl_surface;
+    GLPixmapObject      *pixo;
+    GLFramebufferObject *fbo;
+    guint                foreign_texture : 1;
+    guint                is_constructed  : 1;
+};
+
+enum {
+    PROP_0,
+
+    PROP_TARGET,
+    PROP_FORMAT,
+    PROP_WIDTH,
+    PROP_HEIGHT
+};
+
+static void
+_gst_vaapi_texture_destroy_objects(GstVaapiTexture *texture)
+{
+    GstVaapiTexturePrivate * const priv = texture->priv;
+
+#if USE_VAAPI_GLX
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(texture);
+    if (priv->gl_surface) {
+        vaDestroySurfaceGLX(
+            GST_VAAPI_OBJECT_VADISPLAY(texture),
+            priv->gl_surface
+        );
+        priv->gl_surface = NULL;
+    }
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(texture);
+#else
+    GLContextState old_cs;
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(texture);
+    if (priv->gl_context)
+        gl_set_current_context(priv->gl_context, &old_cs);
+
+    if (priv->fbo) {
+        gl_destroy_framebuffer_object(priv->fbo);
+        priv->fbo = NULL;
+    }
+
+    if (priv->pixo) {
+        gl_destroy_pixmap_object(priv->pixo);
+        priv->pixo = NULL;
+    }
+
+    if (priv->gl_context) {
+        gl_set_current_context(&old_cs, NULL);
+        gl_destroy_context(priv->gl_context);
+        priv->gl_context = NULL;
+    }
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(texture);
+#endif
+}
+
+static void
+gst_vaapi_texture_destroy(GstVaapiTexture *texture)
+{
+    GstVaapiTexturePrivate * const priv = texture->priv;
+    const GLuint texture_id = GST_VAAPI_OBJECT_ID(texture);
+
+    _gst_vaapi_texture_destroy_objects(texture);
+
+    if (texture_id) {
+        if (!priv->foreign_texture)
+            glDeleteTextures(1, &texture_id);
+        GST_VAAPI_OBJECT_ID(texture) = 0;
+    }
+}
+
+static gboolean
+_gst_vaapi_texture_create_objects(GstVaapiTexture *texture, GLuint texture_id)
+{
+    GstVaapiTexturePrivate * const priv = texture->priv;
+    gboolean success = FALSE;
+
+#if USE_VAAPI_GLX
+    VAStatus status;
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(texture);
+    status = vaCreateSurfaceGLX(
+        GST_VAAPI_OBJECT_VADISPLAY(texture),
+        priv->target,
+        texture_id,
+        &priv->gl_surface
+    );
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(texture);
+    success = vaapi_check_status(status, "vaCreateSurfaceGLX()");
+#else
+    GLContextState old_cs;
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(texture);
+    gl_get_current_context(&old_cs);
+    priv->gl_context = gl_create_context(
+        GST_VAAPI_OBJECT_XDISPLAY(texture),
+        GST_VAAPI_OBJECT_XSCREEN(texture),
+        &old_cs
+    );
+    if (!priv->gl_context || !gl_set_current_context(priv->gl_context, NULL))
+        goto end;
+
+    priv->pixo = gl_create_pixmap_object(
+        GST_VAAPI_OBJECT_XDISPLAY(texture),
+        priv->width,
+        priv->height
+    );
+    if (!priv->pixo)
+        goto end;
+
+    priv->fbo = gl_create_framebuffer_object(
+        priv->target,
+        texture_id,
+        priv->width,
+        priv->height
+    );
+    if (priv->fbo)
+        success = TRUE;
+end:
+    gl_set_current_context(&old_cs, NULL);
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(texture);
+#endif
+    return success;
+}
+
+static gboolean
+gst_vaapi_texture_create(GstVaapiTexture *texture)
+{
+    GstVaapiTexturePrivate * const priv = texture->priv;
+    GLuint texture_id;
+
+    if (priv->foreign_texture)
+        texture_id = GST_VAAPI_OBJECT_ID(texture);
+    else {
+        GST_VAAPI_OBJECT_LOCK_DISPLAY(texture);
+        texture_id = gl_create_texture(
+            priv->target,
+            priv->format,
+            priv->width,
+            priv->height
+        );
+        GST_VAAPI_OBJECT_UNLOCK_DISPLAY(texture);
+        if (!texture_id)
+            return FALSE;
+        GST_VAAPI_OBJECT_ID(texture) = texture_id;
+    }
+
+    return _gst_vaapi_texture_create_objects(texture, texture_id);
+}
+
+static void
+gst_vaapi_texture_finalize(GObject *object)
+{
+    gst_vaapi_texture_destroy(GST_VAAPI_TEXTURE(object));
+
+    G_OBJECT_CLASS(gst_vaapi_texture_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_texture_constructed(GObject *object)
+{
+    GstVaapiTexture * const texture = GST_VAAPI_TEXTURE(object);
+    GObjectClass *parent_class;
+
+    texture->priv->foreign_texture = GST_VAAPI_OBJECT_ID(texture) != 0;
+    texture->priv->is_constructed  = gst_vaapi_texture_create(texture);
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_texture_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+}
+
+static void
+gst_vaapi_texture_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiTexture * const texture = GST_VAAPI_TEXTURE(object);
+
+    switch (prop_id) {
+    case PROP_TARGET:
+        texture->priv->target = g_value_get_uint(value);
+        break;
+    case PROP_FORMAT:
+        texture->priv->format = g_value_get_uint(value);
+        break;
+    case PROP_WIDTH:
+        texture->priv->width = g_value_get_uint(value);
+        break;
+    case PROP_HEIGHT:
+        texture->priv->height = g_value_get_uint(value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_texture_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiTexture * const texture = GST_VAAPI_TEXTURE(object);
+
+    switch (prop_id) {
+    case PROP_TARGET:
+        g_value_set_uint(value, gst_vaapi_texture_get_target(texture));
+        break;
+    case PROP_FORMAT:
+        g_value_set_uint(value, gst_vaapi_texture_get_format(texture));
+        break;
+    case PROP_WIDTH:
+        g_value_set_uint(value, gst_vaapi_texture_get_width(texture));
+        break;
+    case PROP_HEIGHT:
+        g_value_set_uint(value, gst_vaapi_texture_get_height(texture));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_texture_class_init(GstVaapiTextureClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiTexturePrivate));
+
+    object_class->finalize     = gst_vaapi_texture_finalize;
+    object_class->set_property = gst_vaapi_texture_set_property;
+    object_class->get_property = gst_vaapi_texture_get_property;
+    object_class->constructed  = gst_vaapi_texture_constructed;
+
+    g_object_class_install_property
+        (object_class,
+         PROP_TARGET,
+         g_param_spec_uint("target",
+                           "Target",
+                           "The texture target",
+                           0, G_MAXUINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_FORMAT,
+         g_param_spec_uint("format",
+                           "Format",
+                           "The texture format",
+                           0, G_MAXUINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_WIDTH,
+         g_param_spec_uint("width",
+                           "width",
+                           "The texture width",
+                           0, G_MAXUINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_HEIGHT,
+         g_param_spec_uint("height",
+                           "height",
+                           "The texture height",
+                           0, G_MAXUINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gst_vaapi_texture_init(GstVaapiTexture *texture)
+{
+    GstVaapiTexturePrivate *priv = GST_VAAPI_TEXTURE_GET_PRIVATE(texture);
+
+    texture->priv               = priv;
+    priv->target                = GL_NONE;
+    priv->format                = GL_NONE;
+    priv->width                 = 0;
+    priv->height                = 0;
+    priv->gl_context            = NULL;
+    priv->gl_surface            = NULL;
+    priv->pixo                  = NULL;
+    priv->fbo                   = NULL;
+    priv->foreign_texture       = FALSE;
+    priv->is_constructed        = FALSE;
+}
+
+/**
+ * gst_vaapi_texture_new:
+ * @display: a #GstVaapiDisplay
+ * @target: the target to which the texture is bound
+ * @format: the format of the pixel data
+ * @width: the requested width, in pixels
+ * @height: the requested height, in pixels
+ *
+ * Creates a texture with the specified dimensions, @target and
+ * @format. Note that only GL_TEXTURE_2D @target and GL_RGBA or
+ * GL_BGRA formats are supported at this time.
+ *
+ * The application shall maintain the live GL context itself. That is,
+ * gst_vaapi_window_glx_make_current() must be called beforehand, or
+ * any other function like glXMakeCurrent() if the context is managed
+ * outside of this library.
+ *
+ * Return value: the newly created #GstVaapiTexture object
+ */
+GstVaapiTexture *
+gst_vaapi_texture_new(
+    GstVaapiDisplay *display,
+    GLenum           target,
+    GLenum           format,
+    guint            width,
+    guint            height
+)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+
+    return g_object_new(GST_VAAPI_TYPE_TEXTURE,
+                        "display", display,
+                        "id",      GST_VAAPI_ID(0),
+                        "target",  target,
+                        "format",  format,
+                        "width",   width,
+                        "height",  height,
+                        NULL);
+}
+
+/**
+ * gst_vaapi_texture_new_with_texture:
+ * @display: a #GstVaapiDisplay
+ * @texture: the foreign GL texture name to use
+ * @target: the target to which the texture is bound
+ * @format: the format of the pixel data
+ *
+ * Creates a texture from an existing GL texture, with the specified
+ * @target and @format. Note that only GL_TEXTURE_2D @target and
+ * GL_RGBA or GL_BGRA formats are supported at this time. The
+ * dimensions will be retrieved from the @texture.
+ *
+ * The application shall maintain the live GL context itself. That is,
+ * gst_vaapi_window_glx_make_current() must be called beforehand, or
+ * any other function like glXMakeCurrent() if the context is managed
+ * outside of this library.
+ *
+ * Return value: the newly created #GstVaapiTexture object
+ */
+GstVaapiTexture *
+gst_vaapi_texture_new_with_texture(
+    GstVaapiDisplay *display,
+    GLuint           texture,
+    GLenum           target,
+    GLenum           format
+)
+{
+    guint width, height, border_width;
+    GLTextureState ts;
+    gboolean success;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+
+    /* Check texture dimensions */
+    GST_VAAPI_DISPLAY_LOCK(display);
+    success = gl_bind_texture(&ts, target, texture);
+    if (success) {
+        if (!gl_get_texture_param(target, GL_TEXTURE_WIDTH,  &width)  ||
+            !gl_get_texture_param(target, GL_TEXTURE_HEIGHT, &height) ||
+            !gl_get_texture_param(target, GL_TEXTURE_BORDER, &border_width))
+            success = FALSE;
+        gl_unbind_texture(&ts);
+    }
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+    if (!success)
+        return NULL;
+
+    width  -= 2 * border_width;
+    height -= 2 * border_width;
+    if (width == 0 || height == 0)
+        return NULL;
+
+    return g_object_new(GST_VAAPI_TYPE_TEXTURE,
+                        "display", display,
+                        "id",      GST_VAAPI_ID(texture),
+                        "target",  target,
+                        "format",  format,
+                        "width",   width,
+                        "height",  height,
+                        NULL);
+}
+
+/**
+ * gst_vaapi_texture_get_id:
+ * @texture: a #GstVaapiTexture
+ *
+ * Returns the underlying texture id of the @texture.
+ *
+ * Return value: the underlying texture id of the @texture
+ */
+GLuint
+gst_vaapi_texture_get_id(GstVaapiTexture *texture)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_TEXTURE(texture), 0);
+
+    return GST_VAAPI_OBJECT_ID(texture);
+}
+
+/**
+ * gst_vaapi_texture_get_target:
+ * @texture: a #GstVaapiTexture
+ *
+ * Returns the @texture target type
+ *
+ * Return value: the texture target
+ */
+GLenum
+gst_vaapi_texture_get_target(GstVaapiTexture *texture)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_TEXTURE(texture), GL_NONE);
+    g_return_val_if_fail(texture->priv->is_constructed, GL_NONE);
+
+    return texture->priv->target;
+}
+
+/**
+ * gst_vaapi_texture_get_format
+ * @texture: a #GstVaapiTexture
+ *
+ * Returns the @texture format
+ *
+ * Return value: the texture format
+ */
+GLenum
+gst_vaapi_texture_get_format(GstVaapiTexture *texture)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_TEXTURE(texture), GL_NONE);
+    g_return_val_if_fail(texture->priv->is_constructed, GL_NONE);
+
+    return texture->priv->format;
+}
+
+/**
+ * gst_vaapi_texture_get_width:
+ * @texture: a #GstVaapiTexture
+ *
+ * Returns the @texture width.
+ *
+ * Return value: the texture width, in pixels
+ */
+guint
+gst_vaapi_texture_get_width(GstVaapiTexture *texture)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_TEXTURE(texture), 0);
+    g_return_val_if_fail(texture->priv->is_constructed, 0);
+
+    return texture->priv->width;
+}
+
+/**
+ * gst_vaapi_texture_get_height:
+ * @texture: a #GstVaapiTexture
+ *
+ * Returns the @texture height.
+ *
+ * Return value: the texture height, in pixels.
+ */
+guint
+gst_vaapi_texture_get_height(GstVaapiTexture *texture)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_TEXTURE(texture), 0);
+    g_return_val_if_fail(texture->priv->is_constructed, 0);
+
+    return texture->priv->height;
+}
+
+/**
+ * gst_vaapi_texture_get_size:
+ * @texture: a #GstVaapiTexture
+ * @pwidth: return location for the width, or %NULL
+ * @pheight: return location for the height, or %NULL
+ *
+ * Retrieves the dimensions of a #GstVaapiTexture.
+ */
+void
+gst_vaapi_texture_get_size(
+    GstVaapiTexture *texture,
+    guint           *pwidth,
+    guint           *pheight
+)
+{
+    g_return_if_fail(GST_VAAPI_IS_TEXTURE(texture));
+    g_return_if_fail(texture->priv->is_constructed);
+
+    if (pwidth)
+        *pwidth = texture->priv->width;
+
+    if (pheight)
+        *pheight = texture->priv->height;
+}
+
+/**
+ * gst_vaapi_texture_put_surface:
+ * @texture: a #GstVaapiTexture
+ * @surface: a #GstVaapiSurface
+ * @flags: postprocessing flags. See #GstVaapiTextureRenderFlags
+ *
+ * Renders the @surface into the Ã texture. The @flags specify how
+ * de-interlacing (if needed), color space conversion, scaling and
+ * other postprocessing transformations are performed.
+ *
+ * Return value: %TRUE on success
+ */
+static gboolean
+_gst_vaapi_texture_put_surface(
+    GstVaapiTexture *texture,
+    GstVaapiSurface *surface,
+    guint            flags
+)
+{
+    GstVaapiTexturePrivate * const priv = texture->priv;
+    VAStatus status;
+
+#if USE_VAAPI_GLX
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(texture);
+    status = vaCopySurfaceGLX(
+        GST_VAAPI_OBJECT_VADISPLAY(texture),
+        priv->gl_surface,
+        GST_VAAPI_OBJECT_ID(surface),
+        from_GstVaapiSurfaceRenderFlags(flags)
+    );
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(texture);
+    if (!vaapi_check_status(status, "vaCopySurfaceGLX()"))
+        return FALSE;
+#else
+    guint surface_width, surface_height;
+    GLContextState old_cs;
+    gboolean success = FALSE;
+
+    gst_vaapi_surface_get_size(surface, &surface_width, &surface_height);
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(texture);
+    status = vaPutSurface(
+        GST_VAAPI_OBJECT_VADISPLAY(texture),
+        GST_VAAPI_OBJECT_ID(surface),
+        priv->pixo->pixmap,
+        0, 0, surface_width, surface_height,
+        0, 0, priv->width, priv->height,
+        NULL, 0,
+        from_GstVaapiSurfaceRenderFlags(flags)
+    );
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(texture);
+    if (!vaapi_check_status(status, "vaPutSurface() [TFP]"))
+        return FALSE;
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(texture);
+    if (priv->gl_context) {
+        success = gl_set_current_context(priv->gl_context, &old_cs);
+        if (!success)
+            goto end;
+    }
+
+    success = gl_bind_framebuffer_object(priv->fbo);
+    if (!success) {
+        GST_DEBUG("could not bind FBO");
+        goto out_reset_context;
+    }
+
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(texture);
+    success = gst_vaapi_surface_sync(surface);
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(texture);
+    if (!success) {
+        GST_DEBUG("could not render surface to pixmap");
+        goto out_unbind_fbo;
+    }
+
+    success = gl_bind_pixmap_object(priv->pixo);
+    if (!success) {
+        GST_DEBUG("could not bind GLX pixmap");
+        goto out_unbind_fbo;
+    }
+
+    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+    glBegin(GL_QUADS);
+    {
+        glTexCoord2f(0.0f, 0.0f); glVertex2i(0,           0           );
+        glTexCoord2f(0.0f, 1.0f); glVertex2i(0,           priv->height);
+        glTexCoord2f(1.0f, 1.0f); glVertex2i(priv->width, priv->height);
+        glTexCoord2f(1.0f, 0.0f); glVertex2i(priv->width, 0           );
+    }
+    glEnd();
+
+    success = gl_unbind_pixmap_object(priv->pixo);
+    if (!success) {
+        GST_DEBUG("could not release GLX pixmap");
+        goto out_unbind_fbo;
+    }
+
+out_unbind_fbo:
+    if (!gl_unbind_framebuffer_object(priv->fbo))
+        success = FALSE;
+out_reset_context:
+    if (priv->gl_context && !gl_set_current_context(&old_cs, NULL))
+        success = FALSE;
+end:
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(texture);
+    return success;
+#endif
+    return TRUE;
+}
+
+gboolean
+gst_vaapi_texture_put_surface(
+    GstVaapiTexture *texture,
+    GstVaapiSurface *surface,
+    guint            flags
+)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_TEXTURE(texture), FALSE);
+    g_return_val_if_fail(texture->priv->is_constructed, FALSE);
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
+
+    return _gst_vaapi_texture_put_surface(texture, surface, flags);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapitexture.h b/gst-libs/gst/vaapi/gstvaapitexture.h
new file mode 100644 (file)
index 0000000..4f8f3ce
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ *  gstvaapitexture.h - VA texture abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_TEXTURE_H
+#define GST_VAAPI_TEXTURE_H
+
+#include <GL/gl.h>
+#include <gst/vaapi/gstvaapitypes.h>
+#include <gst/vaapi/gstvaapiobject.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapisurface.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_TEXTURE \
+    (gst_vaapi_texture_get_type())
+
+#define GST_VAAPI_TEXTURE(obj)                          \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                  \
+                                GST_VAAPI_TYPE_TEXTURE, \
+                                GstVaapiTexture))
+
+#define GST_VAAPI_TEXTURE_CLASS(klass)                  \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                   \
+                             GST_VAAPI_TYPE_TEXTURE,    \
+                             GstVaapiTextureClass))
+
+#define GST_VAAPI_IS_TEXTURE(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_TEXTURE))
+
+#define GST_VAAPI_IS_TEXTURE_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_TEXTURE))
+
+#define GST_VAAPI_TEXTURE_GET_CLASS(obj)                \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                   \
+                               GST_VAAPI_TYPE_TEXTURE,  \
+                               GstVaapiTextureClass))
+
+typedef struct _GstVaapiTexture                 GstVaapiTexture;
+typedef struct _GstVaapiTexturePrivate          GstVaapiTexturePrivate;
+typedef struct _GstVaapiTextureClass            GstVaapiTextureClass;
+
+/**
+ * GstVaapiTexture:
+ *
+ * Base class for system-dependent textures.
+ */
+struct _GstVaapiTexture {
+    /*< private >*/
+    GstVaapiObject parent_instance;
+
+    GstVaapiTexturePrivate *priv;
+};
+
+/**
+ * GstVaapiTextureClass:
+ *
+ * Base class for system-dependent textures.
+ */
+struct _GstVaapiTextureClass {
+    /*< private >*/
+    GstVaapiObjectClass parent_class;
+};
+
+GType
+gst_vaapi_texture_get_type(void) G_GNUC_CONST;
+
+GstVaapiTexture *
+gst_vaapi_texture_new(
+    GstVaapiDisplay *display,
+    GLenum           target,
+    GLenum           format,
+    guint            width,
+    guint            height
+);
+
+GstVaapiTexture *
+gst_vaapi_texture_new_with_texture(
+    GstVaapiDisplay *display,
+    GLuint           texture,
+    GLenum           target,
+    GLenum           format
+);
+
+GLuint
+gst_vaapi_texture_get_id(GstVaapiTexture *texture);
+
+GLenum
+gst_vaapi_texture_get_target(GstVaapiTexture *texture);
+
+GLenum
+gst_vaapi_texture_get_format(GstVaapiTexture *texture);
+
+guint
+gst_vaapi_texture_get_width(GstVaapiTexture *texture);
+
+guint
+gst_vaapi_texture_get_height(GstVaapiTexture *texture);
+
+void
+gst_vaapi_texture_get_size(
+    GstVaapiTexture *texture,
+    guint           *pwidth,
+    guint           *pheight
+);
+
+gboolean
+gst_vaapi_texture_put_surface(
+    GstVaapiTexture *texture,
+    GstVaapiSurface *surface,
+    guint            flags
+);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_TEXTURE_H */
diff --git a/gst-libs/gst/vaapi/gstvaapitypes.h b/gst-libs/gst/vaapi/gstvaapitypes.h
new file mode 100644 (file)
index 0000000..08c0bd1
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ *  gstvaapitypes.h - Basic types
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_TYPES_H
+#define GST_VAAPI_TYPES_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/**
+ * GstVaapiID:
+ *
+ * An integer large enough to hold a generic VA id or a pointer
+ * wherever necessary.
+ */
+#if defined(GLIB_SIZEOF_VOID_P)
+# define GST_VAAPI_TYPE_ID_SIZE GLIB_SIZEOF_VOID_P
+#elif G_MAXULONG == 0xffffffff
+# define GST_VAAPI_TYPE_ID_SIZE 4
+#elif G_MAXULONG == 0xffffffffffffffffull
+# define GST_VAAPI_TYPE_ID_SIZE 8
+#else
+# error "could not determine size of GstVaapiID"
+#endif
+#if GST_VAAPI_TYPE_ID_SIZE == 4
+typedef guint32 GstVaapiID;
+#elif GST_VAAPI_TYPE_ID_SIZE == 8
+typedef guint64 GstVaapiID;
+#else
+# error "unsupported value for GST_VAAPI_TYPE_ID_SIZE"
+#endif
+
+/**
+ * GST_VAAPI_ID:
+ * @id: an arbitrary integer value
+ *
+ * Macro that creates a #GstVaapiID from @id.
+ */
+#define GST_VAAPI_ID(id) ((GstVaapiID)(id))
+
+/**
+ * GST_VAAPI_ID_NONE:
+ *
+ * Macro that evaluates to the default #GstVaapiID value.
+ */
+#define GST_VAAPI_ID_NONE GST_VAAPI_ID(0)
+
+/**
+ * GST_VAAPI_ID_FORMAT:
+ *
+ * Can be used together with #GST_VAAPI_ID_ARGS to properly output an
+ * integer value in a printf()-style text message.
+ * <informalexample>
+ * <programlisting>
+ * printf("id: %" GST_VAAPI_ID_FORMAT "\n", GST_VAAPI_ID_ARGS(id));
+ * </programlisting>
+ * </informalexample>
+ */
+#define GST_VAAPI_ID_FORMAT "p"
+
+/**
+ * GST_VAAPI_ID_ARGS:
+ * @id: a #GstVaapiID
+ *
+ * Can be used together with #GST_VAAPI_ID_FORMAT to properly output
+ * an integer value in a printf()-style text message.
+ */
+#define GST_VAAPI_ID_ARGS(id) GUINT_TO_POINTER(id)
+
+/**
+ * GstVaapiPoint:
+ * @x: X coordinate
+ * @y: Y coordinate
+ *
+ * A location within a surface.
+ */
+typedef struct _GstVaapiPoint GstVaapiPoint;
+struct _GstVaapiPoint {
+    guint32 x;
+    guint32 y;
+};
+
+/**
+ * GstVaapiRectangle:
+ * @x: X coordinate
+ * @y: Y coordinate
+ * @width: region width
+ * @height: region height
+ *
+ * A rectangle region within a surface.
+ */
+typedef struct _GstVaapiRectangle GstVaapiRectangle;
+struct _GstVaapiRectangle {
+    guint32 x;
+    guint32 y;
+    guint32 width;
+    guint32 height;
+};
+
+/**
+ * GstVaapiRenderMode:
+ * @GST_VAAPI_RENDER_MODE_OVERLAY: in this mode, the VA display
+ *   backend renders surfaces with an overlay engine. This means that
+ *   the surface that is currently displayed shall not be re-used
+ *   right away for decoding. i.e. it needs to be retained further,
+ *   until the next surface is to be displayed.
+ * @GST_VAAPI_RENDER_MODE_TEXTURE: in this modem the VA display
+ *   backend renders surfaces with a textured blit (GPU/3D engine).
+ *   This means that the surface is copied to some intermediate
+ *   backing store, or back buffer of a frame buffer, and is free to
+ *   be re-used right away for decoding.
+ */
+typedef enum _GstVaapiRenderMode GstVaapiRenderMode;
+enum _GstVaapiRenderMode {
+    GST_VAAPI_RENDER_MODE_OVERLAY = 1,
+    GST_VAAPI_RENDER_MODE_TEXTURE
+};
+
+/**
+ * GstVaapiRotation:
+ * @GST_VAAPI_ROTATION_0: the VA display is not rotated.
+ * @GST_VAAPI_ROTATION_90: the VA display is rotated by 90°, clockwise.
+ * @GST_VAAPI_ROTATION_180: the VA display is rotated by 180°, clockwise.
+ * @GST_VAAPI_ROTATION_270: the VA display is rotated by 270°, clockwise.
+ */
+typedef enum _GstVaapiRotation GstVaapiRotation;
+enum _GstVaapiRotation {
+    GST_VAAPI_ROTATION_0   = 0,
+    GST_VAAPI_ROTATION_90  = 90,
+    GST_VAAPI_ROTATION_180 = 180,
+    GST_VAAPI_ROTATION_270 = 270,
+};
+
+/**
+ * GstVaapiRateControl:
+ * @GST_VAAPI_RATECONTROL_NONE: None rate control
+ * @GST_VAAPI_RATECONTROL_CBR: Constant rate control
+ * @GST_VAAPI_RATECONTROL_VBR: Variable bitrate control
+ * @GST_VAAPI_RATECONTROL_VCM: Video conference mode
+ * @GST_VAAPI_RATECONTROL_CQP: Variable bitrate control
+ * @GST_VAAPI_RATECONTROL_VBR_CONSTRAINED: Variable bitrate control with peak rate higher than average bitrate
+ *
+ * The set of all rate-controls for #GstVaapiRateControl, only worked on encoders
+ */
+typedef enum {
+    GST_VAAPI_RATECONTROL_NONE = 0,
+    GST_VAAPI_RATECONTROL_CBR,
+    GST_VAAPI_RATECONTROL_VBR,
+    GST_VAAPI_RATECONTROL_VCM,
+    GST_VAAPI_RATECONTROL_CQP,
+    GST_VAAPI_RATECONTROL_VBR_CONSTRAINED,
+} GstVaapiRateControl;
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_TYPES_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiutils.c b/gst-libs/gst/vaapi/gstvaapiutils.c
new file mode 100644 (file)
index 0000000..55cefe7
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ *  gstvaapiutils.c - VA-API utilities
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "sysdeps.h"
+#include "gstvaapicompat.h"
+#include "gstvaapiutils.h"
+#include "gstvaapisurface.h"
+#include <stdio.h>
+#include <stdarg.h>
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+#define CONCAT(a, b)    CONCAT_(a, b)
+#define CONCAT_(a, b)   a##b
+#define STRINGIFY(x)    STRINGIFY_(x)
+#define STRINGIFY_(x)   #x
+#define STRCASEP(p, x)  STRCASE(CONCAT(p, x))
+#define STRCASE(x)      case x: return STRINGIFY(x)
+
+/* Check VA status for success or print out an error */
+gboolean
+vaapi_check_status(VAStatus status, const char *msg)
+{
+    if (status != VA_STATUS_SUCCESS) {
+        GST_DEBUG("%s: %s", msg, vaErrorStr(status));
+        return FALSE;
+    }
+    return TRUE;
+}
+
+/* Maps VA buffer */
+void *
+vaapi_map_buffer(VADisplay dpy, VABufferID buf_id)
+{
+    VAStatus status;
+    void *data = NULL;
+
+    status = vaMapBuffer(dpy, buf_id, &data);
+    if (!vaapi_check_status(status, "vaMapBuffer()"))
+        return NULL;
+    return data;
+}
+
+/* Unmaps VA buffer */
+void
+vaapi_unmap_buffer(VADisplay dpy, VABufferID buf_id, void **pbuf)
+{
+    VAStatus status;
+
+    if (pbuf)
+        *pbuf = NULL;
+
+    status = vaUnmapBuffer(dpy, buf_id);
+    if (!vaapi_check_status(status, "vaUnmapBuffer()"))
+        return;
+}
+
+/* Creates and maps VA buffer */
+gboolean
+vaapi_create_buffer(
+    VADisplay     dpy,
+    VAContextID   ctx,
+    int           type,
+    unsigned int  size,
+    gconstpointer buf,
+    VABufferID   *buf_id_ptr,
+    gpointer     *mapped_data
+)
+{
+    VABufferID buf_id;
+    VAStatus status;
+    gpointer data = (gpointer)buf;
+
+    status = vaCreateBuffer(dpy, ctx, type, size, 1, data, &buf_id);
+    if (!vaapi_check_status(status, "vaCreateBuffer()"))
+        return FALSE;
+
+    if (mapped_data) {
+        data = vaapi_map_buffer(dpy, buf_id);
+        if (!data)
+            goto error;
+        *mapped_data = data;
+    }
+
+    *buf_id_ptr = buf_id;
+    return TRUE;
+
+error:
+    vaapi_destroy_buffer(dpy, &buf_id);
+    return FALSE;
+}
+
+/* Destroy VA buffer */
+void
+vaapi_destroy_buffer(VADisplay dpy, VABufferID *buf_id_ptr)
+{
+    if (!buf_id_ptr || *buf_id_ptr == VA_INVALID_ID)
+        return;
+
+    vaDestroyBuffer(dpy, *buf_id_ptr);
+    *buf_id_ptr = VA_INVALID_ID;
+}
+
+/* Return a string representation of a VAProfile */
+const char *string_of_VAProfile(VAProfile profile)
+{
+    switch (profile) {
+#define MAP(profile) \
+        STRCASEP(VAProfile, profile)
+        MAP(MPEG2Simple);
+        MAP(MPEG2Main);
+        MAP(MPEG4Simple);
+        MAP(MPEG4AdvancedSimple);
+        MAP(MPEG4Main);
+#if VA_CHECK_VERSION(0,32,0)
+        MAP(JPEGBaseline);
+        MAP(H263Baseline);
+        MAP(H264ConstrainedBaseline);
+#endif
+        MAP(H264Baseline);
+        MAP(H264Main);
+        MAP(H264High);
+        MAP(VC1Simple);
+        MAP(VC1Main);
+        MAP(VC1Advanced);
+#undef MAP
+    default: break;
+    }
+    return "<unknown>";
+}
+
+/* Return a string representation of a VAEntrypoint */
+const char *string_of_VAEntrypoint(VAEntrypoint entrypoint)
+{
+    switch (entrypoint) {
+#define MAP(entrypoint) \
+        STRCASEP(VAEntrypoint, entrypoint)
+        MAP(VLD);
+        MAP(IZZ);
+        MAP(IDCT);
+        MAP(MoComp);
+        MAP(Deblocking);
+#undef MAP
+    default: break;
+    }
+    return "<unknown>";
+}
+
+/* Return a string representation of a VADisplayAttributeType */
+const char *
+string_of_VADisplayAttributeType(VADisplayAttribType attribute_type)
+{
+    switch (attribute_type) {
+#define MAP(attribute_type) \
+        STRCASEP(VADisplayAttrib, attribute_type)
+        MAP(Brightness);
+        MAP(Contrast);
+        MAP(Hue);
+        MAP(Saturation);
+        MAP(BackgroundColor);
+#if !VA_CHECK_VERSION(0,34,0)
+        MAP(DirectSurface);
+#endif
+        MAP(Rotation);
+        MAP(OutofLoopDeblock);
+#if VA_CHECK_VERSION(0,31,1) && !VA_CHECK_VERSION(0,34,0)
+        MAP(BLEBlackMode);
+        MAP(BLEWhiteMode);
+        MAP(BlueStretch);
+        MAP(SkinColorCorrection);
+#endif
+        MAP(CSCMatrix);
+        MAP(BlendColor);
+        MAP(OverlayAutoPaintColorKey);
+        MAP(OverlayColorKey);
+        MAP(RenderMode);
+        MAP(RenderDevice);
+        MAP(RenderRect);
+#undef MAP
+    default: break;
+    }
+    return "<unknown>";
+}
+
+/**
+ * from_GstVaapiSurfaceRenderFlags:
+ * @flags: the #GstVaapiSurfaceRenderFlags
+ *
+ * Converts #GstVaapiSurfaceRenderFlags to flags suitable for
+ * vaPutSurface().
+ */
+guint
+from_GstVaapiSurfaceRenderFlags(guint flags)
+{
+    guint va_fields = 0, va_csc = 0;
+
+    if (flags & GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD)
+        va_fields |= VA_TOP_FIELD;
+    if (flags & GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD)
+        va_fields |= VA_BOTTOM_FIELD;
+    if ((va_fields ^ (VA_TOP_FIELD|VA_BOTTOM_FIELD)) == 0)
+        va_fields  = VA_FRAME_PICTURE;
+
+#ifdef VA_SRC_BT601
+    if (flags & GST_VAAPI_COLOR_STANDARD_ITUR_BT_601)
+        va_csc = VA_SRC_BT601;
+#endif
+#ifdef VA_SRC_BT709
+    if (flags & GST_VAAPI_COLOR_STANDARD_ITUR_BT_709)
+        va_csc = VA_SRC_BT709;
+#endif
+
+    return va_fields|va_csc;
+}
+
+/**
+ * to_GstVaapiSurfaceStatus:
+ * @flags: the #GstVaapiSurfaceStatus flags to translate
+ *
+ * Converts vaQuerySurfaceStatus() @flags to #GstVaapiSurfaceStatus
+ * flags.
+ *
+ * Return value: the #GstVaapiSurfaceStatus flags
+ */
+guint
+to_GstVaapiSurfaceStatus(guint va_flags)
+{
+    guint flags;
+    const guint va_flags_mask = (VASurfaceReady|
+                                 VASurfaceRendering|
+                                 VASurfaceDisplaying);
+
+    /* Check for core status */
+    switch (va_flags & va_flags_mask) {
+    case VASurfaceReady:
+        flags = GST_VAAPI_SURFACE_STATUS_IDLE;
+        break;
+    case VASurfaceRendering:
+        flags = GST_VAAPI_SURFACE_STATUS_RENDERING;
+        break;
+    case VASurfaceDisplaying:
+        flags = GST_VAAPI_SURFACE_STATUS_DISPLAYING;
+        break;
+    default:
+        flags = 0;
+        break;
+    }
+
+    /* Check for encoder status */
+#if VA_CHECK_VERSION(0,30,0)
+    if (va_flags & VASurfaceSkipped)
+        flags |= GST_VAAPI_SURFACE_STATUS_SKIPPED;
+#endif
+    return flags;
+}
+
+/* Translate GstVaapiRotation value to VA-API rotation value */
+guint
+from_GstVaapiRotation(guint value)
+{
+    switch (value) {
+    case GST_VAAPI_ROTATION_0:   return VA_ROTATION_NONE;
+    case GST_VAAPI_ROTATION_90:  return VA_ROTATION_90;
+    case GST_VAAPI_ROTATION_180: return VA_ROTATION_180;
+    case GST_VAAPI_ROTATION_270: return VA_ROTATION_270;
+    }
+    GST_ERROR("unsupported GstVaapiRotation value %d", value);
+    return VA_ROTATION_NONE;
+}
+
+/* Translate VA-API rotation value to GstVaapiRotation value */
+guint
+to_GstVaapiRotation(guint value)
+{
+    switch (value) {
+    case VA_ROTATION_NONE: return GST_VAAPI_ROTATION_0;
+    case VA_ROTATION_90:   return GST_VAAPI_ROTATION_90;
+    case VA_ROTATION_180:  return GST_VAAPI_ROTATION_180;
+    case VA_ROTATION_270:  return GST_VAAPI_ROTATION_270;
+    }
+    GST_ERROR("unsupported VA-API rotation value %d", value);
+    return GST_VAAPI_ROTATION_0;
+}
+
+guint
+from_GstVaapiRateControl(guint value)
+{
+    switch (value) {
+    case GST_VAAPI_RATECONTROL_NONE:   return VA_RC_NONE;
+    case GST_VAAPI_RATECONTROL_CBR:  return VA_RC_CBR;
+    case GST_VAAPI_RATECONTROL_VBR: return VA_RC_VBR;
+    case GST_VAAPI_RATECONTROL_VCM: return VA_RC_VCM;
+#if VA_CHECK_VERSION(0,34,0)
+    case GST_VAAPI_RATECONTROL_CQP: return VA_RC_CQP;
+    case GST_VAAPI_RATECONTROL_VBR_CONSTRAINED: return VA_RC_VBR_CONSTRAINED;
+#endif
+    }
+    GST_ERROR("unsupported GstVaapiRateControl value %d", value);
+    return VA_RC_NONE;
+}
+
+guint
+to_GstVaapiRateControl(guint value)
+{
+    switch (value) {
+    case VA_RC_NONE: return GST_VAAPI_RATECONTROL_NONE;
+    case VA_RC_CBR:   return GST_VAAPI_RATECONTROL_CBR;
+    case VA_RC_VBR:  return GST_VAAPI_RATECONTROL_VBR;
+    case VA_RC_VCM:  return GST_VAAPI_RATECONTROL_VCM;
+#if VA_CHECK_VERSION(0,34,0)
+    case VA_RC_CQP: return GST_VAAPI_RATECONTROL_CQP;
+    case VA_RC_VBR_CONSTRAINED: return GST_VAAPI_RATECONTROL_VBR_CONSTRAINED;
+#endif
+    }
+    GST_ERROR("unsupported VA-API Rate Control value %d", value);
+    return GST_VAAPI_RATECONTROL_NONE;
+}
+
+const char *
+string_of_VARateControl(guint rate_control)
+{
+    switch (rate_control) {
+    case VA_RC_NONE: return "VA_RC_NONE";
+    case VA_RC_CBR: return "VA_RC_CBR";
+    case VA_RC_VBR: return "VA_RC_VBR";
+    case VA_RC_VCM: return "VA_RC_VCM";
+#if VA_CHECK_VERSION(0,34,0)
+    case VA_RC_CQP: return "VA_RC_CQP";
+    case VA_RC_VBR_CONSTRAINED: return "VA_RC_VBR_CONSTRAINED";
+#endif
+    default: break;
+    }
+    return "<unknown>";
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiutils.h b/gst-libs/gst/vaapi/gstvaapiutils.h
new file mode 100644 (file)
index 0000000..1a3fbf2
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ *  gstvaapiutils.h - VA-API utilities
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_UTILS_H
+#define GST_VAAPI_UTILS_H
+
+#include "config.h"
+#include <glib.h>
+#include <va/va.h>
+
+/** Check VA status for success or print out an error */
+G_GNUC_INTERNAL
+gboolean
+vaapi_check_status(VAStatus status, const char *msg);
+
+/** Maps VA buffer */
+G_GNUC_INTERNAL
+void *
+vaapi_map_buffer(VADisplay dpy, VABufferID buf_id);
+
+/** Unmaps VA buffer */
+G_GNUC_INTERNAL
+void
+vaapi_unmap_buffer(VADisplay dpy, VABufferID buf_id, void **pbuf);
+
+/** Creates and maps VA buffer */
+G_GNUC_INTERNAL
+gboolean
+vaapi_create_buffer(
+    VADisplay     dpy,
+    VAContextID   ctx,
+    int           type,
+    unsigned int  size,
+    gconstpointer data,
+    VABufferID   *buf_id,
+    gpointer     *mapped_data
+);
+
+/** Destroy VA buffer */
+G_GNUC_INTERNAL
+void
+vaapi_destroy_buffer(VADisplay dpy, VABufferID *buf_id);
+
+/** Return a string representation of a VAProfile */
+G_GNUC_INTERNAL
+const char *string_of_VAProfile(VAProfile profile);
+
+/** Return a string representation of a VAEntrypoint */
+G_GNUC_INTERNAL
+const char *string_of_VAEntrypoint(VAEntrypoint entrypoint);
+
+/* Return a string representation of a VADisplayAttributeType */
+G_GNUC_INTERNAL
+const char *
+string_of_VADisplayAttributeType(VADisplayAttribType attribute_type);
+
+G_GNUC_INTERNAL
+guint
+from_GstVaapiSurfaceRenderFlags(guint flags);
+
+G_GNUC_INTERNAL
+guint
+to_GstVaapiSurfaceStatus(guint va_flags);
+
+G_GNUC_INTERNAL
+guint
+from_GstVaapiRotation(guint value);
+
+G_GNUC_INTERNAL
+guint
+to_GstVaapiRotation(guint value);
+
+G_GNUC_INTERNAL
+guint
+from_GstVaapiRateControl(guint value);
+
+G_GNUC_INTERNAL
+guint
+to_GstVaapiRateControl(guint value);
+
+G_GNUC_INTERNAL
+const char *
+string_of_VARateControl(guint rate_control);
+
+#endif /* GST_VAAPI_UTILS_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiutils_glx.c b/gst-libs/gst/vaapi/gstvaapiutils_glx.c
new file mode 100644 (file)
index 0000000..3821181
--- /dev/null
@@ -0,0 +1,1192 @@
+/*
+ *  gstvaapiutils_glx.c - GLX utilties
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#define _GNU_SOURCE 1 /* RTLD_DEFAULT */
+#include "sysdeps.h"
+#include <string.h>
+#include <math.h>
+#include <dlfcn.h>
+#include "gstvaapiutils_glx.h"
+#include "gstvaapiutils_x11.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+/** Lookup for substring NAME in string EXT using SEP as separators */
+static gboolean
+find_string(const char *name, const char *ext, const char *sep)
+{
+    const char *end;
+    int name_len, n;
+
+    if (!name || !ext)
+        return FALSE;
+
+    end = ext + strlen(ext);
+    name_len = strlen(name);
+    while (ext < end) {
+        n = strcspn(ext, sep);
+        if (n == name_len && strncmp(name, ext, n) == 0)
+            return TRUE;
+        ext += (n + 1);
+    }
+    return FALSE;
+}
+
+/**
+ * gl_get_error_string:
+ * @error: an OpenGL error enumeration
+ *
+ * Retrieves the string representation the OpenGL @error.
+ *
+ * Return error: the static string representing the OpenGL @error
+ */
+const char *
+gl_get_error_string(GLenum error)
+{
+    switch (error) {
+#define MAP(id, str) \
+        case id: return str " (" #id ")"
+        MAP(GL_NO_ERROR,                "no error");
+        MAP(GL_INVALID_ENUM,            "invalid enumerant");
+        MAP(GL_INVALID_VALUE,           "invalid value");
+        MAP(GL_INVALID_OPERATION,       "invalid operation");
+        MAP(GL_STACK_OVERFLOW,          "stack overflow");
+        MAP(GL_STACK_UNDERFLOW,         "stack underflow");
+        MAP(GL_OUT_OF_MEMORY,           "out of memory");
+#ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
+        MAP(GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+            "invalid framebuffer operation");
+#endif
+#undef MAP
+    default: break;
+    };
+    return "<unknown>";
+}
+
+/**
+ * gl_purge_errors:
+ *
+ * Purges all OpenGL errors. This function is generally useful to
+ * clear up the pending errors prior to calling gl_check_error().
+ */
+void
+gl_purge_errors(void)
+{
+    while (glGetError() != GL_NO_ERROR)
+        ; /* nothing */
+}
+
+/**
+ * gl_check_error:
+ *
+ * Checks whether there is any OpenGL error pending.
+ *
+ * Return value: %TRUE if an error was encountered
+ */
+gboolean
+gl_check_error(void)
+{
+    GLenum error;
+    gboolean has_errors = FALSE;
+
+    while ((error = glGetError()) != GL_NO_ERROR) {
+        GST_DEBUG("glError: %s caught", gl_get_error_string(error));
+        has_errors = TRUE;
+    }
+    return has_errors;
+}
+
+/**
+ * gl_get_param:
+ * @param: the parameter name
+ * @pval: return location for the value
+ *
+ * This function is a wrapper around glGetIntegerv() that does extra
+ * error checking.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gl_get_param(GLenum param, guint *pval)
+{
+    GLint val;
+
+    gl_purge_errors();
+    glGetIntegerv(param, &val);
+    if (gl_check_error())
+        return FALSE;
+
+    if (pval)
+        *pval = val;
+    return TRUE;
+}
+
+/**
+ * gl_get_texture_param:
+ * @target: the target to which the texture is bound
+ * @param: the parameter name
+ * @pval: return location for the value
+ *
+ * This function is a wrapper around glGetTexLevelParameteriv() that
+ * does extra error checking.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gl_get_texture_param(GLenum target, GLenum param, guint *pval)
+{
+    GLint val;
+
+    gl_purge_errors();
+    glGetTexLevelParameteriv(target, 0, param, &val);
+    if (gl_check_error())
+        return FALSE;
+
+    if (pval)
+        *pval = val;
+    return TRUE;
+}
+
+/**
+ * gl_get_texture_binding:
+ * @target: a texture target
+ *
+ * Determines the texture binding type for the specified target.
+ *
+ * Return value: texture binding type for @target
+ */
+static GLenum
+gl_get_texture_binding(GLenum target)
+{
+    GLenum binding;
+
+    switch (target) {
+    case GL_TEXTURE_1D:
+        binding = GL_TEXTURE_BINDING_1D;
+        break;
+    case GL_TEXTURE_2D:
+        binding = GL_TEXTURE_BINDING_2D;
+        break;
+    case GL_TEXTURE_3D:
+        binding = GL_TEXTURE_BINDING_3D;
+        break;
+    case GL_TEXTURE_RECTANGLE_ARB:
+        binding = GL_TEXTURE_BINDING_RECTANGLE_ARB;
+        break;
+    default:
+        binding = 0;
+        break;
+    }
+    return binding;
+}
+
+/**
+ * gl_set_bgcolor:
+ * @color: the requested RGB color
+ *
+ * Sets background color to the RGB @color. This basically is a
+ * wrapper around glClearColor().
+ */
+void
+gl_set_bgcolor(guint32 color)
+{
+    glClearColor(
+        ((color >> 16) & 0xff) / 255.0f,
+        ((color >>  8) & 0xff) / 255.0f,
+        ( color        & 0xff) / 255.0f,
+        1.0f
+    );
+}
+
+/**
+ * gl_perspective:
+ * @fovy: the field of view angle, in degrees, in the y direction
+ * @aspect: the aspect ratio that determines the field of view in the
+ *   x direction.  The aspect ratio is the ratio of x (width) to y
+ *   (height)
+ * @zNear: the distance from the viewer to the near clipping plane
+ *   (always positive)
+ * @zFar: the distance from the viewer to the far clipping plane
+ *   (always positive)
+ *
+ * Specified a viewing frustum into the world coordinate system. This
+ * basically is the Mesa implementation of gluPerspective().
+ */
+static void
+gl_perspective(GLdouble fovy, GLdouble aspect, GLdouble near_val, GLdouble far_val)
+{
+    GLdouble left, right, top, bottom;
+
+    /* Source (Q 9.085):
+       <http://www.opengl.org/resources/faq/technical/transformations.htm> */
+    top    = tan(fovy * M_PI / 360.0) * near_val;
+    bottom = -top;
+    left   = aspect * bottom;
+    right  = aspect * top;
+    glFrustum(left, right, bottom, top, near_val, far_val);
+}
+
+/**
+ * gl_resize:
+ * @width: the requested width, in pixels
+ * @height: the requested height, in pixels
+ *
+ * Resizes the OpenGL viewport to the specified dimensions, using an
+ * orthogonal projection. (0,0) represents the top-left corner of the
+ * window.
+ */
+void
+gl_resize(guint width, guint height)
+{
+#define FOVY     60.0f
+#define ASPECT   1.0f
+#define Z_NEAR   0.1f
+#define Z_FAR    100.0f
+#define Z_CAMERA 0.869f
+
+    glViewport(0, 0, width, height);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    gl_perspective(FOVY, ASPECT, Z_NEAR, Z_FAR);
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+
+    glTranslatef(-0.5f, -0.5f, -Z_CAMERA);
+    glScalef(1.0f/width, -1.0f/height, 1.0f/width);
+    glTranslatef(0.0f, -1.0f*height, 0.0f);
+}
+
+/**
+ * gl_create_context:
+ * @dpy: an X11 #Display
+ * @screen: the associated screen of @dpy
+ * @parent: the parent #GLContextState, or %NULL if none is to be used
+ *
+ * Creates a GLX context sharing textures and displays lists with
+ * @parent, if not %NULL.
+ *
+ * Return value: the newly created GLX context
+ */
+GLContextState *
+gl_create_context(Display *dpy, int screen, GLContextState *parent)
+{
+    GLContextState *cs;
+    GLXFBConfig *fbconfigs = NULL;
+    int fbconfig_id, val, n, n_fbconfigs;
+    Status status;
+
+    static GLint fbconfig_attrs[] = {
+        GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+        GLX_RENDER_TYPE,   GLX_RGBA_BIT,
+        GLX_DOUBLEBUFFER,  True,
+        GLX_RED_SIZE,      8,
+        GLX_GREEN_SIZE,    8, 
+        GLX_BLUE_SIZE,     8,
+        None
+    };
+
+    cs = malloc(sizeof(*cs));
+    if (!cs)
+        goto error;
+
+    if (parent) {
+        cs->display     = parent->display;
+        cs->window      = parent->window;
+        screen          = DefaultScreen(parent->display);
+    }
+    else {
+        cs->display     = dpy;
+        cs->window      = None;
+    }
+    cs->visual          = NULL;
+    cs->context         = NULL;
+    cs->swapped_buffers = FALSE;
+
+    if (parent && parent->context) {
+        status = glXQueryContext(
+            parent->display,
+            parent->context,
+            GLX_FBCONFIG_ID, &fbconfig_id
+        );
+        if (status != Success)
+            goto error;
+
+        if (fbconfig_id == GLX_DONT_CARE)
+            goto choose_fbconfig;
+
+        fbconfigs = glXGetFBConfigs(parent->display, screen, &n_fbconfigs);
+        if (!fbconfigs)
+            goto error;
+
+        /* Find out a GLXFBConfig compatible with the parent context */
+        for (n = 0; n < n_fbconfigs; n++) {
+            status = glXGetFBConfigAttrib(
+                parent->display,
+                fbconfigs[n],
+                GLX_FBCONFIG_ID, &val
+            );
+            if (status == Success && val == fbconfig_id)
+                break;
+        }
+        if (n == n_fbconfigs)
+            goto error;
+    }
+    else {
+    choose_fbconfig:
+        fbconfigs = glXChooseFBConfig(
+            cs->display,
+            screen,
+            fbconfig_attrs, &n_fbconfigs
+        );
+        if (!fbconfigs)
+            goto error;
+
+        /* Select the first one */
+        n = 0;
+    }
+
+    cs->visual  = glXGetVisualFromFBConfig(cs->display, fbconfigs[n]);
+    cs->context = glXCreateNewContext(
+        cs->display,
+        fbconfigs[n],
+        GLX_RGBA_TYPE,
+        parent ? parent->context : NULL,
+        True
+    );
+    if (cs->context)
+        goto end;
+
+error:
+    gl_destroy_context(cs);
+    cs = NULL;
+end:
+    if (fbconfigs)
+        XFree(fbconfigs);
+    return cs;
+}
+
+/**
+ * gl_destroy_context:
+ * @cs: a #GLContextState
+ *
+ * Destroys the GLX context @cs
+ */
+void
+gl_destroy_context(GLContextState *cs)
+{
+    if (!cs)
+        return;
+
+    if (cs->visual) {
+        XFree(cs->visual);
+        cs->visual = NULL;
+    }
+
+    if (cs->display && cs->context) {
+        if (glXGetCurrentContext() == cs->context) {
+            /* XXX: if buffers were never swapped, the application
+               will crash later with the NVIDIA driver */
+            if (!cs->swapped_buffers)
+                gl_swap_buffers(cs);
+            glXMakeCurrent(cs->display, None, NULL);
+        }
+        glXDestroyContext(cs->display, cs->context);
+        cs->display = NULL;
+        cs->context = NULL;
+    }
+    free(cs);
+}
+
+/**
+ * gl_get_current_context:
+ * @cs: return location to the current #GLContextState
+ *
+ * Retrieves the current GLX context, display and drawable packed into
+ * the #GLContextState struct.
+ */
+void
+gl_get_current_context(GLContextState *cs)
+{
+    cs->display = glXGetCurrentDisplay();
+    cs->window  = glXGetCurrentDrawable();
+    cs->context = glXGetCurrentContext();
+}
+
+/**
+ * gl_set_current_context:
+ * @new_cs: the requested new #GLContextState
+ * @old_cs: return location to the context that was previously current
+ *
+ * Makes the @new_cs GLX context the current GLX rendering context of
+ * the calling thread, replacing the previously current context if
+ * there was one.
+ *
+ * If @old_cs is non %NULL, the previously current GLX context and
+ * window are recorded.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gl_set_current_context(GLContextState *new_cs, GLContextState *old_cs)
+{
+    /* If display is NULL, this could be that new_cs was retrieved from
+       gl_get_current_context() with none set previously. If that case,
+       the other fields are also NULL and we don't return an error */
+    if (!new_cs->display)
+        return !new_cs->window && !new_cs->context;
+
+    if (old_cs) {
+        if (old_cs == new_cs)
+            return TRUE;
+        gl_get_current_context(old_cs);
+        if (old_cs->display == new_cs->display &&
+            old_cs->window  == new_cs->window  &&
+            old_cs->context == new_cs->context)
+            return TRUE;
+    }
+    return glXMakeCurrent(new_cs->display, new_cs->window, new_cs->context);
+}
+
+/**
+ * gl_swap_buffers:
+ * @cs: a #GLContextState
+ *
+ * Promotes the contents of the back buffer of the @win window to
+ * become the contents of the front buffer. This simply is wrapper
+ * around glXSwapBuffers().
+ */
+void
+gl_swap_buffers(GLContextState *cs)
+{
+    glXSwapBuffers(cs->display, cs->window);
+    cs->swapped_buffers = TRUE;
+}
+
+/**
+ * gl_bind_texture:
+ * @ts: a #GLTextureState
+ * @target: the target to which the texture is bound
+ * @texture: the name of a texture
+ *
+ * Binds @texture to the specified @target, while recording the
+ * previous state in @ts.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gl_bind_texture(GLTextureState *ts, GLenum target, GLuint texture)
+{
+    GLenum binding;
+
+    ts->target = target;
+
+    if (glIsEnabled(target)) {
+        binding = gl_get_texture_binding(target);
+        if (!binding)
+            return FALSE;
+        if (!gl_get_param(binding, &ts->old_texture))
+            return FALSE;
+        ts->was_enabled = TRUE;
+        ts->was_bound   = texture == ts->old_texture;
+        if (ts->was_bound)
+            return TRUE;
+    }
+    else {
+        glEnable(target);
+        ts->old_texture = 0;
+        ts->was_enabled = FALSE;
+        ts->was_bound   = FALSE;
+    }
+
+    gl_purge_errors();
+    glBindTexture(target, texture);
+    if (gl_check_error())
+        return FALSE;
+    return TRUE;
+}
+
+/**
+ * gl_unbind_texture:
+ * @ts: a #GLTextureState
+ *
+ * Rebinds the texture that was previously bound and recorded in @ts.
+ */
+void
+gl_unbind_texture(GLTextureState *ts)
+{
+    if (!ts->was_bound && ts->old_texture)
+        glBindTexture(ts->target, ts->old_texture);
+    if (!ts->was_enabled)
+        glDisable(ts->target);
+}
+
+/**
+ * gl_create_texture:
+ * @target: the target to which the texture is bound
+ * @format: the format of the pixel data
+ * @width: the requested width, in pixels
+ * @height: the requested height, in pixels
+ *
+ * Creates a texture with the specified dimensions and @format. The
+ * internal format will be automatically derived from @format.
+ *
+ * Return value: the newly created texture name
+ */
+GLuint
+gl_create_texture(GLenum target, GLenum format, guint width, guint height)
+{
+    GLenum internal_format;
+    GLuint texture;
+    GLTextureState ts;
+    guint bytes_per_component;
+
+    internal_format = format;
+    switch (format) {
+    case GL_LUMINANCE:
+        bytes_per_component = 1;
+        break;
+    case GL_LUMINANCE_ALPHA:
+        bytes_per_component = 2;
+        break;
+    case GL_RGBA:
+    case GL_BGRA:
+        internal_format = GL_RGBA;
+        bytes_per_component = 4;
+        break;
+    default:
+        bytes_per_component = 0;
+        break;
+    }
+    g_assert(bytes_per_component > 0);
+
+    glGenTextures(1, &texture);
+    if (!gl_bind_texture(&ts, target, texture))
+        return 0;
+    glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, bytes_per_component);
+    glTexImage2D(
+        target,
+        0,
+        internal_format,
+        width, height,
+        0,
+        format,
+        GL_UNSIGNED_BYTE,
+        NULL
+    );
+    gl_unbind_texture(&ts);
+    return texture;
+}
+
+/**
+ * get_proc_address:
+ * @name: the name of the OpenGL extension function to lookup
+ *
+ * Returns the specified OpenGL extension function
+ *
+ * Return value: the OpenGL extension matching @name, or %NULL if none
+ *   was found
+ */
+typedef void (*GLFuncPtr)(void);
+typedef GLFuncPtr (*GLXGetProcAddressProc)(const char *);
+
+static GLFuncPtr
+get_proc_address_default(const char *name)
+{
+    return NULL;
+}
+
+static GLXGetProcAddressProc
+get_proc_address_func(void)
+{
+    GLXGetProcAddressProc get_proc_func;
+
+    dlerror();
+    get_proc_func = (GLXGetProcAddressProc)
+        dlsym(RTLD_DEFAULT, "glXGetProcAddress");
+    if (!dlerror())
+        return get_proc_func;
+
+    get_proc_func = (GLXGetProcAddressProc)
+        dlsym(RTLD_DEFAULT, "glXGetProcAddressARB");
+    if (!dlerror())
+        return get_proc_func;
+
+    return get_proc_address_default;
+}
+
+static inline GLFuncPtr
+get_proc_address(const char *name)
+{
+    static GLXGetProcAddressProc get_proc_func = NULL;
+    if (!get_proc_func)
+        get_proc_func = get_proc_address_func();
+    return get_proc_func(name);
+}
+
+/**
+ * gl_init_vtable:
+ *
+ * Initializes the global #GLVTable.
+ *
+ * Return value: the #GLVTable filled in with OpenGL extensions, or
+ *   %NULL on error.
+ */
+static GLVTable gl_vtable_static;
+
+static GLVTable *
+gl_init_vtable(void)
+{
+    GLVTable * const gl_vtable = &gl_vtable_static;
+    const gchar *gl_extensions = (const gchar *)glGetString(GL_EXTENSIONS);
+    gboolean has_extension;
+
+    /* GLX_EXT_texture_from_pixmap */
+    gl_vtable->glx_create_pixmap = (PFNGLXCREATEPIXMAPPROC)
+        get_proc_address("glXCreatePixmap");
+    if (!gl_vtable->glx_create_pixmap)
+        return NULL;
+    gl_vtable->glx_destroy_pixmap = (PFNGLXDESTROYPIXMAPPROC)
+        get_proc_address("glXDestroyPixmap");
+    if (!gl_vtable->glx_destroy_pixmap)
+        return NULL;
+    gl_vtable->glx_bind_tex_image = (PFNGLXBINDTEXIMAGEEXTPROC)
+        get_proc_address("glXBindTexImageEXT");
+    if (!gl_vtable->glx_bind_tex_image)
+        return NULL;
+    gl_vtable->glx_release_tex_image = (PFNGLXRELEASETEXIMAGEEXTPROC)
+        get_proc_address("glXReleaseTexImageEXT");
+    if (!gl_vtable->glx_release_tex_image)
+        return NULL;
+
+    /* GL_ARB_framebuffer_object */
+    has_extension = (
+        find_string("GL_ARB_framebuffer_object", gl_extensions, " ") ||
+        find_string("GL_EXT_framebuffer_object", gl_extensions, " ")
+    );
+    if (has_extension) {
+        gl_vtable->gl_gen_framebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC)
+            get_proc_address("glGenFramebuffersEXT");
+        if (!gl_vtable->gl_gen_framebuffers)
+            return NULL;
+        gl_vtable->gl_delete_framebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC)
+            get_proc_address("glDeleteFramebuffersEXT");
+        if (!gl_vtable->gl_delete_framebuffers)
+            return NULL;
+        gl_vtable->gl_bind_framebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC)
+            get_proc_address("glBindFramebufferEXT");
+        if (!gl_vtable->gl_bind_framebuffer)
+            return NULL;
+        gl_vtable->gl_gen_renderbuffers = (PFNGLGENRENDERBUFFERSEXTPROC)
+            get_proc_address("glGenRenderbuffersEXT");
+        if (!gl_vtable->gl_gen_renderbuffers)
+            return NULL;
+        gl_vtable->gl_delete_renderbuffers = (PFNGLDELETERENDERBUFFERSEXTPROC)
+            get_proc_address("glDeleteRenderbuffersEXT");
+        if (!gl_vtable->gl_delete_renderbuffers)
+            return NULL;
+        gl_vtable->gl_bind_renderbuffer = (PFNGLBINDRENDERBUFFEREXTPROC)
+            get_proc_address("glBindRenderbufferEXT");
+        if (!gl_vtable->gl_bind_renderbuffer)
+            return NULL;
+        gl_vtable->gl_renderbuffer_storage = (PFNGLRENDERBUFFERSTORAGEEXTPROC)
+            get_proc_address("glRenderbufferStorageEXT");
+        if (!gl_vtable->gl_renderbuffer_storage)
+            return NULL;
+        gl_vtable->gl_framebuffer_renderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)
+            get_proc_address("glFramebufferRenderbufferEXT");
+        if (!gl_vtable->gl_framebuffer_renderbuffer)
+            return NULL;
+        gl_vtable->gl_framebuffer_texture_2d = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
+            get_proc_address("glFramebufferTexture2DEXT");
+        if (!gl_vtable->gl_framebuffer_texture_2d)
+            return NULL;
+        gl_vtable->gl_check_framebuffer_status = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
+            get_proc_address("glCheckFramebufferStatusEXT");
+        if (!gl_vtable->gl_check_framebuffer_status)
+            return NULL;
+        gl_vtable->has_framebuffer_object = TRUE;
+    }
+
+    /* GL_ARB_fragment_program */
+    has_extension = (
+        find_string("GL_ARB_fragment_program", gl_extensions, " ")
+    );
+    if (has_extension) {
+        gl_vtable->gl_gen_programs = (PFNGLGENPROGRAMSARBPROC)
+            get_proc_address("glGenProgramsARB");
+        if (!gl_vtable->gl_gen_programs)
+            return NULL;
+        gl_vtable->gl_delete_programs = (PFNGLDELETEPROGRAMSARBPROC)
+            get_proc_address("glDeleteProgramsARB");
+        if (!gl_vtable->gl_delete_programs)
+            return NULL;
+        gl_vtable->gl_bind_program = (PFNGLBINDPROGRAMARBPROC)
+            get_proc_address("glBindProgramARB");
+        if (!gl_vtable->gl_bind_program)
+            return NULL;
+        gl_vtable->gl_program_string = (PFNGLPROGRAMSTRINGARBPROC)
+            get_proc_address("glProgramStringARB");
+        if (!gl_vtable->gl_program_string)
+            return NULL;
+        gl_vtable->gl_get_program_iv = (PFNGLGETPROGRAMIVARBPROC)
+            get_proc_address("glGetProgramivARB");
+        if (!gl_vtable->gl_get_program_iv)
+            return NULL;
+        gl_vtable->gl_program_local_parameter_4fv = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)
+            get_proc_address("glProgramLocalParameter4fvARB");
+        if (!gl_vtable->gl_program_local_parameter_4fv)
+            return NULL;
+        gl_vtable->has_fragment_program = TRUE;
+    }
+
+    /* GL_ARB_multitexture */
+    has_extension = (
+        find_string("GL_ARB_multitexture", gl_extensions, " ")
+    );
+    if (has_extension) {
+        gl_vtable->gl_active_texture = (PFNGLACTIVETEXTUREPROC)
+            get_proc_address("glActiveTextureARB");
+        if (!gl_vtable->gl_active_texture)
+            return NULL;
+        gl_vtable->gl_multi_tex_coord_2f = (PFNGLMULTITEXCOORD2FPROC)
+            get_proc_address("glMultiTexCoord2fARB");
+        if (!gl_vtable->gl_multi_tex_coord_2f)
+            return NULL;
+        gl_vtable->has_multitexture = TRUE;
+    }
+    return gl_vtable;
+}
+
+/**
+ * gl_get_vtable:
+ *
+ * Retrieves a VTable for OpenGL extensions.
+ *
+ * Return value: VTable for OpenGL extensions
+ */
+GLVTable *
+gl_get_vtable(void)
+{
+    static GStaticMutex mutex          = G_STATIC_MUTEX_INIT;
+    static gboolean     gl_vtable_init = TRUE;
+    static GLVTable    *gl_vtable      = NULL;
+
+    g_static_mutex_lock(&mutex);
+    if (gl_vtable_init) {
+        gl_vtable_init = FALSE;
+        gl_vtable      = gl_init_vtable();
+    }
+    g_static_mutex_unlock(&mutex);
+    return gl_vtable;
+}
+
+/**
+ * gl_create_pixmap_object:
+ * @dpy: an X11 #Display
+ * @width: the request width, in pixels
+ * @height: the request height, in pixels
+ *
+ * Creates a #GLPixmapObject of the specified dimensions. This
+ * requires the GLX_EXT_texture_from_pixmap extension.
+ *
+ * Return value: the newly created #GLPixmapObject object
+ */
+GLPixmapObject *
+gl_create_pixmap_object(Display *dpy, guint width, guint height)
+{
+    GLVTable * const    gl_vtable = gl_get_vtable();
+    GLPixmapObject     *pixo;
+    GLXFBConfig        *fbconfig;
+    int                 screen;
+    Window              rootwin;
+    XWindowAttributes   wattr;
+    int                *attr;
+    int                 n_fbconfig_attrs;
+
+    int fbconfig_attrs[32] = {
+        GLX_DRAWABLE_TYPE,      GLX_PIXMAP_BIT,
+        GLX_DOUBLEBUFFER,       GL_FALSE,
+        GLX_RENDER_TYPE,        GLX_RGBA_BIT,
+        GLX_X_RENDERABLE,       GL_TRUE,
+        GLX_Y_INVERTED_EXT,     GL_TRUE,
+        GLX_RED_SIZE,           8,
+        GLX_GREEN_SIZE,         8,
+        GLX_BLUE_SIZE,          8,
+        GL_NONE,
+    };
+
+    int pixmap_attrs[10] = {
+        GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
+        GLX_MIPMAP_TEXTURE_EXT, GL_FALSE,
+        GL_NONE,
+    };
+
+    if (!gl_vtable)
+        return NULL;
+
+    screen  = DefaultScreen(dpy);
+    rootwin = RootWindow(dpy, screen);
+
+    /* XXX: this won't work for different displays */
+    if (!gl_vtable->has_texture_from_pixmap) {
+        const char *glx_extensions = glXQueryExtensionsString(dpy, screen);
+        if (!glx_extensions)
+            return NULL;
+        if (!find_string("GLX_EXT_texture_from_pixmap", glx_extensions, " "))
+            return NULL;
+        gl_vtable->has_texture_from_pixmap = TRUE;
+    }
+
+    pixo = calloc(1, sizeof(*pixo));
+    if (!pixo)
+        return NULL;
+
+    pixo->dpy           = dpy;
+    pixo->width         = width;
+    pixo->height        = height;
+    pixo->pixmap        = None;
+    pixo->glx_pixmap    = None;
+    pixo->is_bound      = FALSE;
+
+    XGetWindowAttributes(dpy, rootwin, &wattr);
+    pixo->pixmap  = XCreatePixmap(dpy, rootwin, width, height, wattr.depth);
+    if (!pixo->pixmap)
+        goto error;
+
+    /* Initialize FBConfig attributes */
+    for (attr = fbconfig_attrs; *attr != GL_NONE; attr += 2)
+        ;
+    *attr++ = GLX_DEPTH_SIZE;                 *attr++ = wattr.depth;
+    if (wattr.depth == 32) {
+    *attr++ = GLX_ALPHA_SIZE;                 *attr++ = 8;
+    *attr++ = GLX_BIND_TO_TEXTURE_RGBA_EXT;   *attr++ = GL_TRUE;
+    }
+    else {
+    *attr++ = GLX_BIND_TO_TEXTURE_RGB_EXT;    *attr++ = GL_TRUE;
+    }
+    *attr++ = GL_NONE;
+
+    fbconfig = glXChooseFBConfig(
+        dpy,
+        screen,
+        fbconfig_attrs, &n_fbconfig_attrs
+    );
+    if (!fbconfig)
+        goto error;
+
+    /* Initialize GLX Pixmap attributes */
+    for (attr = pixmap_attrs; *attr != GL_NONE; attr += 2)
+        ;
+    *attr++ = GLX_TEXTURE_FORMAT_EXT;
+    if (wattr.depth == 32)
+    *attr++ = GLX_TEXTURE_FORMAT_RGBA_EXT;
+    else
+    *attr++ = GLX_TEXTURE_FORMAT_RGB_EXT;
+    *attr++ = GL_NONE;
+
+    x11_trap_errors();
+    pixo->glx_pixmap = gl_vtable->glx_create_pixmap(
+        dpy,
+        fbconfig[0],
+        pixo->pixmap,
+        pixmap_attrs
+    );
+    free(fbconfig);
+    if (x11_untrap_errors() != 0)
+        goto error;
+
+    pixo->target = GL_TEXTURE_2D;
+    glGenTextures(1, &pixo->texture);
+    if (!gl_bind_texture(&pixo->old_texture, pixo->target, pixo->texture))
+        goto error;
+    glTexParameteri(pixo->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(pixo->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    gl_unbind_texture(&pixo->old_texture);
+    return pixo;
+
+error:
+    gl_destroy_pixmap_object(pixo);
+    return NULL;
+}
+
+/**
+ * gl_destroy_pixmap_object:
+ * @pixo: a #GLPixmapObject
+ *
+ * Destroys the #GLPixmapObject object.
+ */
+void
+gl_destroy_pixmap_object(GLPixmapObject *pixo)
+{
+    GLVTable * const gl_vtable = gl_get_vtable();
+
+    if (!pixo)
+        return;
+
+    gl_unbind_pixmap_object(pixo);
+
+    if (pixo->texture) {
+        glDeleteTextures(1, &pixo->texture);
+        pixo->texture = 0;
+    }
+
+    if (pixo->glx_pixmap) {
+        gl_vtable->glx_destroy_pixmap(pixo->dpy, pixo->glx_pixmap);
+        pixo->glx_pixmap = None;
+    }
+
+    if (pixo->pixmap) {
+        XFreePixmap(pixo->dpy, pixo->pixmap);
+        pixo->pixmap = None;
+    }
+    free(pixo);
+}
+
+/**
+ * gl_bind_pixmap_object:
+ * @pixo: a #GLPixmapObject
+ *
+ * Defines a two-dimensional texture image. The texture image is taken
+ * from the @pixo pixmap and need not be copied. The texture target,
+ * format and size are derived from attributes of the @pixo pixmap.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gl_bind_pixmap_object(GLPixmapObject *pixo)
+{
+    GLVTable * const gl_vtable = gl_get_vtable();
+
+    if (pixo->is_bound)
+        return TRUE;
+
+    if (!gl_bind_texture(&pixo->old_texture, pixo->target, pixo->texture))
+        return FALSE;
+
+    x11_trap_errors();
+    gl_vtable->glx_bind_tex_image(
+        pixo->dpy,
+        pixo->glx_pixmap,
+        GLX_FRONT_LEFT_EXT,
+        NULL
+    );
+    XSync(pixo->dpy, False);
+    if (x11_untrap_errors() != 0) {
+        GST_DEBUG("failed to bind pixmap");
+        return FALSE;
+    }
+
+    pixo->is_bound = TRUE;
+    return TRUE;
+}
+
+/**
+ * gl_unbind_pixmap_object:
+ * @pixo: a #GLPixmapObject
+ *
+ * Releases a color buffers that is being used as a texture.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gl_unbind_pixmap_object(GLPixmapObject *pixo)
+{
+    GLVTable * const gl_vtable = gl_get_vtable();
+
+    if (!pixo->is_bound)
+        return TRUE;
+
+    x11_trap_errors();
+    gl_vtable->glx_release_tex_image(
+        pixo->dpy,
+        pixo->glx_pixmap,
+        GLX_FRONT_LEFT_EXT
+    );
+    XSync(pixo->dpy, False);
+    if (x11_untrap_errors() != 0) {
+        GST_DEBUG("failed to release pixmap");
+        return FALSE;
+    }
+
+    gl_unbind_texture(&pixo->old_texture);
+
+    pixo->is_bound = FALSE;
+    return TRUE;
+}
+
+/**
+ * gl_create_framebuffer_object:
+ * @target: the target to which the texture is bound
+ * @texture: the GL texture to hold the framebuffer
+ * @width: the requested width, in pixels
+ * @height: the requested height, in pixels
+ *
+ * Creates an FBO with the specified texture and size.
+ *
+ * Return value: the newly created #GLFramebufferObject, or %NULL if
+ *   an error occurred
+ */
+GLFramebufferObject *
+gl_create_framebuffer_object(
+    GLenum target,
+    GLuint texture,
+    guint  width,
+    guint  height
+)
+{
+    GLVTable * const gl_vtable = gl_get_vtable();
+    GLFramebufferObject *fbo;
+    GLenum status;
+
+    if (!gl_vtable || !gl_vtable->has_framebuffer_object)
+        return NULL;
+
+    /* XXX: we only support GL_TEXTURE_2D at this time */
+    if (target != GL_TEXTURE_2D)
+        return NULL;
+
+    fbo = calloc(1, sizeof(*fbo));
+    if (!fbo)
+        return NULL;
+
+    fbo->width          = width;
+    fbo->height         = height;
+    fbo->fbo            = 0;
+    fbo->old_fbo        = 0;
+    fbo->is_bound       = FALSE;
+
+    gl_get_param(GL_FRAMEBUFFER_BINDING, &fbo->old_fbo);
+    gl_vtable->gl_gen_framebuffers(1, &fbo->fbo);
+    gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->fbo);
+    gl_vtable->gl_framebuffer_texture_2d(
+        GL_FRAMEBUFFER_EXT,
+        GL_COLOR_ATTACHMENT0_EXT,
+        target, texture,
+        0
+    );
+
+    status = gl_vtable->gl_check_framebuffer_status(GL_DRAW_FRAMEBUFFER_EXT);
+    gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->old_fbo);
+    if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
+        goto error;
+    return fbo;
+
+error:
+    gl_destroy_framebuffer_object(fbo);
+    return NULL;
+}
+
+/**
+ * gl_destroy_framebuffer_object:
+ * @fbo: a #GLFramebufferObject
+ *
+ * Destroys the @fbo object.
+ */
+void
+gl_destroy_framebuffer_object(GLFramebufferObject *fbo)
+{
+    GLVTable * const gl_vtable = gl_get_vtable();
+
+    if (!fbo)
+        return;
+
+    gl_unbind_framebuffer_object(fbo);
+
+    if (fbo->fbo) {
+        gl_vtable->gl_delete_framebuffers(1, &fbo->fbo);
+        fbo->fbo = 0;
+    }
+    free(fbo);
+}
+
+/**
+ * gl_bind_framebuffer_object:
+ * @fbo: a #GLFramebufferObject
+ *
+ * Binds @fbo object.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gl_bind_framebuffer_object(GLFramebufferObject *fbo)
+{
+    GLVTable * const gl_vtable = gl_get_vtable();
+    const guint width  = fbo->width;
+    const guint height = fbo->height;
+
+    const guint attribs = (GL_VIEWPORT_BIT|
+                           GL_CURRENT_BIT|
+                           GL_ENABLE_BIT|
+                           GL_TEXTURE_BIT|
+                           GL_COLOR_BUFFER_BIT);
+
+    if (fbo->is_bound)
+        return TRUE;
+
+    gl_get_param(GL_FRAMEBUFFER_BINDING, &fbo->old_fbo);
+    gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->fbo);
+    glPushAttrib(attribs);
+    glMatrixMode(GL_PROJECTION);
+    glPushMatrix();
+    glLoadIdentity();
+    glMatrixMode(GL_MODELVIEW);
+    glPushMatrix();
+    glLoadIdentity();
+    glViewport(0, 0, width, height);
+    glTranslatef(-1.0f, -1.0f, 0.0f);
+    glScalef(2.0f / width, 2.0f / height, 1.0f);
+
+    fbo->is_bound = TRUE;
+    return TRUE;
+}
+
+/**
+ * gl_unbind_framebuffer_object:
+ * @fbo: a #GLFramebufferObject
+ *
+ * Releases @fbo object.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gl_unbind_framebuffer_object(GLFramebufferObject *fbo)
+{
+    GLVTable * const gl_vtable = gl_get_vtable();
+
+    if (!fbo->is_bound)
+        return TRUE;
+
+    glPopAttrib();
+    glMatrixMode(GL_PROJECTION);
+    glPopMatrix();
+    glMatrixMode(GL_MODELVIEW);
+    glPopMatrix();
+    gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->old_fbo);
+
+    fbo->is_bound = FALSE;
+    return TRUE;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiutils_glx.h b/gst-libs/gst/vaapi/gstvaapiutils_glx.h
new file mode 100644 (file)
index 0000000..c9a4983
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ *  gstvaapiutils_glx.h - GLX utilties
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_UTILS_GLX_H
+#define GST_VAAPI_UTILS_GLX_H
+
+#include "config.h"
+#include <GL/gl.h>
+#include <GL/glext.h>
+#include <GL/glx.h>
+#include <GL/glxext.h>
+#include <glib.h>
+
+#if GLX_GLXEXT_VERSION < 18
+typedef void (*PFNGLXBINDTEXIMAGEEXTPROC)(Display *, GLXDrawable, int, const int *);
+typedef void (*PFNGLXRELEASETEXIMAGEEXTPROC)(Display *, GLXDrawable, int);
+#endif
+
+#if GLX_GLXEXT_VERSION < 27
+/* XXX: this is not exactly that version but this is the only means to
+   make sure we have the correct <GL/glx.h> with those signatures */
+typedef GLXPixmap (*PFNGLXCREATEPIXMAPPROC)(Display *, GLXFBConfig, Pixmap, const int *);
+typedef void (*PFNGLXDESTROYPIXMAPPROC)(Display *, GLXPixmap);
+#endif
+
+#ifndef GL_FRAMEBUFFER_BINDING
+#define GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_EXT
+#endif
+
+G_GNUC_INTERNAL
+const char *
+gl_get_error_string(GLenum error);
+
+G_GNUC_INTERNAL
+void
+gl_purge_errors(void);
+
+G_GNUC_INTERNAL
+gboolean
+gl_check_error(void);
+
+G_GNUC_INTERNAL
+gboolean
+gl_get_param(GLenum param, guint *pval);
+
+G_GNUC_INTERNAL
+gboolean
+gl_get_texture_param(GLenum target, GLenum param, guint *pval);
+
+G_GNUC_INTERNAL
+void
+gl_set_bgcolor(guint32 color);
+
+G_GNUC_INTERNAL
+void
+gl_resize(guint width, guint height);
+
+typedef struct _GLContextState GLContextState;
+struct _GLContextState {
+    Display     *display;
+    Window       window;
+    XVisualInfo *visual;
+    GLXContext   context;
+    guint        swapped_buffers : 1;
+};
+
+G_GNUC_INTERNAL
+GLContextState *
+gl_create_context(Display *dpy, int screen, GLContextState *parent);
+
+G_GNUC_INTERNAL
+void
+gl_destroy_context(GLContextState *cs);
+
+G_GNUC_INTERNAL
+void
+gl_get_current_context(GLContextState *cs);
+
+G_GNUC_INTERNAL
+gboolean
+gl_set_current_context(GLContextState *new_cs, GLContextState *old_cs);
+
+G_GNUC_INTERNAL
+void
+gl_swap_buffers(GLContextState *cs);
+
+typedef struct _GLTextureState GLTextureState;
+struct _GLTextureState {
+    GLenum      target;
+    GLuint      old_texture;
+    guint       was_enabled     : 1;
+    guint       was_bound       : 1;
+};
+
+G_GNUC_INTERNAL
+gboolean
+gl_bind_texture(GLTextureState *ts, GLenum target, GLuint texture);
+
+G_GNUC_INTERNAL
+void
+gl_unbind_texture(GLTextureState *ts);
+
+G_GNUC_INTERNAL
+GLuint
+gl_create_texture(GLenum target, GLenum format, guint width, guint height);
+
+typedef struct _GLVTable GLVTable;
+struct _GLVTable {
+    PFNGLXCREATEPIXMAPPROC              glx_create_pixmap;
+    PFNGLXDESTROYPIXMAPPROC             glx_destroy_pixmap;
+    PFNGLXBINDTEXIMAGEEXTPROC           glx_bind_tex_image;
+    PFNGLXRELEASETEXIMAGEEXTPROC        glx_release_tex_image;
+    PFNGLGENFRAMEBUFFERSEXTPROC         gl_gen_framebuffers;
+    PFNGLDELETEFRAMEBUFFERSEXTPROC      gl_delete_framebuffers;
+    PFNGLBINDFRAMEBUFFEREXTPROC         gl_bind_framebuffer;
+    PFNGLGENRENDERBUFFERSEXTPROC        gl_gen_renderbuffers;
+    PFNGLDELETERENDERBUFFERSEXTPROC     gl_delete_renderbuffers;
+    PFNGLBINDRENDERBUFFEREXTPROC        gl_bind_renderbuffer;
+    PFNGLRENDERBUFFERSTORAGEEXTPROC     gl_renderbuffer_storage;
+    PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC gl_framebuffer_renderbuffer;
+    PFNGLFRAMEBUFFERTEXTURE2DEXTPROC    gl_framebuffer_texture_2d;
+    PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC  gl_check_framebuffer_status;
+    PFNGLGENPROGRAMSARBPROC             gl_gen_programs;
+    PFNGLDELETEPROGRAMSARBPROC          gl_delete_programs;
+    PFNGLBINDPROGRAMARBPROC             gl_bind_program;
+    PFNGLPROGRAMSTRINGARBPROC           gl_program_string;
+    PFNGLGETPROGRAMIVARBPROC            gl_get_program_iv;
+    PFNGLPROGRAMLOCALPARAMETER4FVARBPROC gl_program_local_parameter_4fv;
+    PFNGLACTIVETEXTUREPROC              gl_active_texture;
+    PFNGLMULTITEXCOORD2FPROC            gl_multi_tex_coord_2f;
+    guint                               has_texture_from_pixmap : 1;
+    guint                               has_framebuffer_object  : 1;
+    guint                               has_fragment_program    : 1;
+    guint                               has_multitexture        : 1;
+};
+
+G_GNUC_INTERNAL
+GLVTable *
+gl_get_vtable(void);
+
+typedef struct _GLPixmapObject GLPixmapObject;
+struct _GLPixmapObject {
+    Display        *dpy;
+    GLenum          target;
+    GLuint          texture;
+    GLTextureState  old_texture;
+    guint           width;
+    guint           height;
+    Pixmap          pixmap;
+    GLXPixmap       glx_pixmap;
+    guint           is_bound    : 1;
+};
+
+G_GNUC_INTERNAL
+GLPixmapObject *
+gl_create_pixmap_object(Display *dpy, guint width, guint height);
+
+G_GNUC_INTERNAL
+void
+gl_destroy_pixmap_object(GLPixmapObject *pixo);
+
+G_GNUC_INTERNAL
+gboolean
+gl_bind_pixmap_object(GLPixmapObject *pixo);
+
+G_GNUC_INTERNAL
+gboolean
+gl_unbind_pixmap_object(GLPixmapObject *pixo);
+
+typedef struct _GLFramebufferObject GLFramebufferObject;
+struct _GLFramebufferObject {
+    guint           width;
+    guint           height;
+    GLuint          fbo;
+    GLuint          old_fbo;
+    guint           is_bound    : 1;
+};
+
+G_GNUC_INTERNAL
+GLFramebufferObject *
+gl_create_framebuffer_object(
+    GLenum target,
+    GLuint texture,
+    guint  width,
+    guint  height
+);
+
+G_GNUC_INTERNAL
+void
+gl_destroy_framebuffer_object(GLFramebufferObject *fbo);
+
+G_GNUC_INTERNAL
+gboolean
+gl_bind_framebuffer_object(GLFramebufferObject *fbo);
+
+G_GNUC_INTERNAL
+gboolean
+gl_unbind_framebuffer_object(GLFramebufferObject *fbo);
+
+#endif /* GST_VAAPI_UTILS_GLX_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiutils_x11.c b/gst-libs/gst/vaapi/gstvaapiutils_x11.c
new file mode 100644 (file)
index 0000000..abc58b8
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ *  gstvaapiutils_x11.c - X11 utilties
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "sysdeps.h"
+#include <glib.h>
+#include <X11/Xutil.h>
+#include "gstvaapiutils_x11.h"
+
+// X error trap
+static int x11_error_code = 0;
+static int (*old_error_handler)(Display *, XErrorEvent *);
+
+static int error_handler(Display *dpy, XErrorEvent *error)
+{
+    x11_error_code = error->error_code;
+    return 0;
+}
+
+void x11_trap_errors(void)
+{
+    x11_error_code    = 0;
+    old_error_handler = XSetErrorHandler(error_handler);
+}
+
+int x11_untrap_errors(void)
+{
+    XSetErrorHandler(old_error_handler);
+    return x11_error_code;
+}
+
+// X window management
+static const int x11_event_mask = (KeyPressMask |
+                                   KeyReleaseMask |
+                                   ButtonPressMask |
+                                   ButtonReleaseMask |
+                                   PointerMotionMask |
+                                   EnterWindowMask |
+                                   ExposureMask |
+                                   StructureNotifyMask);
+
+/**
+ * x11_create_window:
+ * @dpy: an X11 #Display
+ * @w: the requested width, in pixels
+ * @h: the requested height, in pixels
+ * @vis: the request visual
+ * @cmap: the request colormap
+ *
+ * Creates a border-less window with the specified dimensions. If @vis
+ * is %NULL, the default visual for @display will be used. If @cmap is
+ * %None, no specific colormap will be bound to the window. Also note
+ * the default background color is black.
+ *
+ * Return value: the newly created X #Window.
+ */
+Window
+x11_create_window(Display *dpy, guint w, guint h, Visual *vis, Colormap cmap)
+{
+    Window rootwin, win;
+    int screen, depth;
+    XSetWindowAttributes xswa;
+    unsigned long xswa_mask;
+    XWindowAttributes wattr;
+    unsigned long black_pixel;
+
+    screen      = DefaultScreen(dpy);
+    rootwin     = RootWindow(dpy, screen);
+    black_pixel = BlackPixel(dpy, screen);
+
+    if (!vis)
+        vis = DefaultVisual(dpy, screen);
+
+    XGetWindowAttributes(dpy, rootwin, &wattr);
+    depth = wattr.depth;
+    if (depth != 15 && depth != 16 && depth != 24 && depth != 32)
+        depth = 24;
+
+    xswa_mask             = CWBorderPixel | CWBackPixel;
+    xswa.border_pixel     = black_pixel;
+    xswa.background_pixel = black_pixel;
+
+    if (cmap) {
+        xswa_mask        |= CWColormap;
+        xswa.colormap     = cmap;
+    }
+
+    win = XCreateWindow(
+        dpy,
+        rootwin,
+        0, 0, w, h,
+        0,
+        depth,
+        InputOutput,
+        vis,
+        xswa_mask, &xswa
+    );
+    if (!win)
+        return None;
+
+    XSelectInput(dpy, win, x11_event_mask);
+    return win;
+}
+
+gboolean
+x11_get_geometry(
+    Display    *dpy,
+    Drawable    drawable,
+    gint       *px,
+    gint       *py,
+    guint      *pwidth,
+    guint      *pheight
+)
+{
+    Window rootwin;
+    int x, y;
+    guint width, height, border_width, depth;
+
+    x11_trap_errors();
+    XGetGeometry(
+        dpy,
+        drawable,
+        &rootwin,
+        &x, &y, &width, &height,
+        &border_width,
+        &depth
+    );
+    if (x11_untrap_errors())
+        return FALSE;
+
+    if (px)      *px      = x;
+    if (py)      *py      = y;
+    if (pwidth)  *pwidth  = width;
+    if (pheight) *pheight = height;
+    return TRUE;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiutils_x11.h b/gst-libs/gst/vaapi/gstvaapiutils_x11.h
new file mode 100644 (file)
index 0000000..090b403
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *  gstvaapiutils_x11.h - X11 utilties
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_UTILS_X11_H
+#define GST_VAAPI_UTILS_X11_H
+
+#include "config.h"
+#include <X11/Xlib.h>
+#include <glib.h>
+
+G_GNUC_INTERNAL
+void
+x11_trap_errors(void);
+
+G_GNUC_INTERNAL
+int
+x11_untrap_errors(void);
+
+G_GNUC_INTERNAL
+Window
+x11_create_window(Display *dpy, guint w, guint h, Visual *vis, Colormap cmap);
+
+G_GNUC_INTERNAL
+gboolean
+x11_get_geometry(
+    Display    *dpy,
+    Drawable    drawable,
+    gint       *px,
+    gint       *py,
+    guint      *pwidth,
+    guint      *pheight
+);
+
+#endif /* GST_VAAPI_UTILS_X11_H */
diff --git a/gst-libs/gst/vaapi/gstvaapivalue.c b/gst-libs/gst/vaapi/gstvaapivalue.c
new file mode 100644 (file)
index 0000000..9bd97c3
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ *  gstvaapivalue.c - GValue implementations specific to VA-API
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapivalue
+ * @short_description: GValue implementations specific to VA-API
+ */
+
+#include "sysdeps.h"
+#include <gobject/gvaluecollector.h>
+#include "gstvaapivalue.h"
+
+static GTypeInfo gst_vaapi_type_info = {
+    0,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    0,
+    0,
+    NULL,
+    NULL,
+};
+
+static GTypeFundamentalInfo gst_vaapi_type_finfo = {
+    0
+};
+
+#define GST_VAAPI_TYPE_DEFINE(type, name)                               \
+GType gst_vaapi_ ## type ## _get_type(void)                             \
+{                                                                       \
+    static GType gst_vaapi_ ## type ## _type = 0;                       \
+                                                                        \
+    if (G_UNLIKELY(gst_vaapi_ ## type ## _type == 0)) {                 \
+        gst_vaapi_type_info.value_table =                               \
+            &gst_vaapi_ ## type ## _value_table;                        \
+        gst_vaapi_ ## type ## _type = g_type_register_fundamental(      \
+            g_type_fundamental_next(),                                  \
+            name,                                                       \
+            &gst_vaapi_type_info,                                       \
+            &gst_vaapi_type_finfo,                                      \
+            0                                                           \
+        );                                                              \
+    }                                                                   \
+    return gst_vaapi_ ## type ## _type;                                 \
+}
+
+/* --- GstVaapiID --- */
+
+#if GST_VAAPI_TYPE_ID_SIZE == 4
+# define GST_VAAPI_VALUE_ID_(cvalue)    ((cvalue).v_int)
+# define GST_VAAPI_VALUE_ID_CFORMAT     "i"
+#elif GST_VAAPI_TYPE_ID_SIZE == 8
+# define GST_VAAPI_VALUE_ID_(cvalue)    ((cvalue).v_int64)
+# define GST_VAAPI_VALUE_ID_CFORMAT     "q"
+#else
+# error "unsupported GstVaapiID size"
+#endif
+#define GST_VAAPI_VALUE_ID(value)       GST_VAAPI_VALUE_ID_((value)->data[0])
+
+static void
+gst_vaapi_value_id_init(GValue *value)
+{
+    GST_VAAPI_VALUE_ID(value) = 0;
+}
+
+static void
+gst_vaapi_value_id_copy(const GValue *src_value, GValue *dst_value)
+{
+    GST_VAAPI_VALUE_ID(dst_value) = GST_VAAPI_VALUE_ID(src_value);
+}
+
+static gchar *
+gst_vaapi_value_id_collect(
+    GValue      *value,
+    guint        n_collect_values,
+    GTypeCValue *collect_values,
+    guint        collect_flags
+)
+{
+    GST_VAAPI_VALUE_ID(value) = GST_VAAPI_VALUE_ID_(collect_values[0]);
+
+    return NULL;
+}
+
+static gchar *
+gst_vaapi_value_id_lcopy(
+    const GValue *value,
+    guint         n_collect_values,
+    GTypeCValue  *collect_values,
+    guint         collect_flags
+)
+{
+    GstVaapiID *id_p = collect_values[0].v_pointer;
+
+    if (!id_p)
+        return g_strdup_printf("value location for `%s' passed as NULL",
+                               G_VALUE_TYPE_NAME(value));
+
+    *id_p = GST_VAAPI_VALUE_ID(value);
+    return NULL;
+}
+
+static const GTypeValueTable gst_vaapi_id_value_table = {
+    gst_vaapi_value_id_init,
+    NULL,
+    gst_vaapi_value_id_copy,
+    NULL,
+    GST_VAAPI_VALUE_ID_CFORMAT,
+    gst_vaapi_value_id_collect,
+    "p",
+    gst_vaapi_value_id_lcopy
+};
+
+GST_VAAPI_TYPE_DEFINE(id, "GstVaapiID");
+
+/**
+ * gst_vaapi_value_get_id:
+ * @value: a GValue initialized to #GstVaapiID
+ *
+ * Gets the integer contained in @value.
+ *
+ * Return value: the integer contained in @value
+ */
+GstVaapiID
+gst_vaapi_value_get_id(const GValue *value)
+{
+    g_return_val_if_fail(GST_VAAPI_VALUE_HOLDS_ID(value), 0);
+
+    return GST_VAAPI_VALUE_ID(value);
+}
+
+/**
+ * gst_vaapi_value_set_id:
+ * @value: a GValue initialized to #GstVaapiID
+ * @id: a #GstVaapiID
+ *
+ * Sets the integer contained in @id to @value.
+ */
+void
+gst_vaapi_value_set_id(GValue *value, GstVaapiID id)
+{
+    g_return_if_fail(GST_VAAPI_VALUE_HOLDS_ID(value));
+
+    GST_VAAPI_VALUE_ID(value) = id;
+}
+
+/* --- GstVaapiRenderMode --- */
+
+GType
+gst_vaapi_render_mode_get_type(void)
+{
+    static GType render_mode_type = 0;
+
+    static const GEnumValue render_modes[] = {
+        { GST_VAAPI_RENDER_MODE_OVERLAY,
+          "Overlay render mode", "overlay" },
+        { GST_VAAPI_RENDER_MODE_TEXTURE,
+          "Textured-blit render mode", "texture" },
+        { 0, NULL, NULL }
+    };
+
+    if (!render_mode_type) {
+        render_mode_type =
+            g_enum_register_static("GstVaapiRenderMode", render_modes);
+    }
+    return render_mode_type;
+}
+
+/* --- GstVaapiRotation --- */
+
+GType
+gst_vaapi_rotation_get_type(void)
+{
+    static GType g_type = 0;
+
+    static const GEnumValue rotation_values[] = {
+        { GST_VAAPI_ROTATION_0,
+          "Unrotated mode", "0" },
+        { GST_VAAPI_ROTATION_90,
+          "Rotated by 90°, clockwise", "90" },
+        { GST_VAAPI_ROTATION_180,
+          "Rotated by 180°, clockwise", "180" },
+        { GST_VAAPI_ROTATION_270,
+          "Rotated by 270°, clockwise", "270" },
+        { 0, NULL, NULL },
+    };
+
+    if (!g_type)
+        g_type = g_enum_register_static("GstVaapiRotation", rotation_values);
+    return g_type;
+}
+
+/* --- GstVaapiRateControl --- */
+
+GType
+gst_vaapi_rate_control_get_type(void)
+{
+    static GType g_type = 0;
+
+    static const GEnumValue rate_control_values[] = {
+        { GST_VAAPI_RATECONTROL_NONE,
+          "None rate control mode", "none" },
+        { GST_VAAPI_RATECONTROL_CBR,
+          "Constant bitrate control mode", "cbr" },
+        { GST_VAAPI_RATECONTROL_VBR,
+          "Variable bitrate control mode", "vbr" },
+        { GST_VAAPI_RATECONTROL_VCM,
+          "Video conference mode", "vcm" },
+        { GST_VAAPI_RATECONTROL_CQP,
+          "Constant QP mode", "cqp" },
+        { GST_VAAPI_RATECONTROL_VBR_CONSTRAINED,
+          "Variable bitrate control with peak rate higher than average bitrate",
+          "vbr_constrain" },
+        { 0, NULL, NULL },
+    };
+
+    if (!g_type)
+        g_type = g_enum_register_static("GstVaapiRateControl", rate_control_values);
+    return g_type;
+
+}
diff --git a/gst-libs/gst/vaapi/gstvaapivalue.h b/gst-libs/gst/vaapi/gstvaapivalue.h
new file mode 100644 (file)
index 0000000..cb45ad0
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *  gstvaapivalue.h - GValue implementations specific to VA-API
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_VALUE_H
+#define GST_VAAPI_VALUE_H
+
+#include <glib-object.h>
+#include <gst/vaapi/gstvaapitypes.h>
+
+G_BEGIN_DECLS
+
+/**
+ * GST_VAAPI_TYPE_ID:
+ *
+ * A #GValue type that represents a VA identifier.
+ *
+ * Return value: the #GType of GstVaapiID
+ */
+#define GST_VAAPI_TYPE_ID gst_vaapi_id_get_type()
+
+/**
+ * GST_VAAPI_VALUE_HOLDS_ID:
+ * @x: the #GValue to check
+ *
+ * Checks if the given #GValue contains a #GstVaapiID value.
+ */
+#define GST_VAAPI_VALUE_HOLDS_ID(x) (G_VALUE_HOLDS((x), GST_VAAPI_TYPE_ID))
+
+/**
+ * GST_VAAPI_TYPE_RENDER_MODE:
+ *
+ * A #GstVaapiRenderMode type that represents the VA display backend
+ * rendering mode: overlay (2D engine) or textured-blit (3D engine).
+ *
+ * Return value: the #GType of GstVaapiRenderMode
+ */
+#define GST_VAAPI_TYPE_RENDER_MODE gst_vaapi_render_mode_get_type()
+
+/**
+ * GST_VAAPI_TYPE_ROTATION:
+ *
+ * A type that represents the VA display rotation.
+ *
+ * Return value: the #GType of GstVaapiRotation
+ */
+#define GST_VAAPI_TYPE_ROTATION gst_vaapi_rotation_get_type()
+
+/**
+ * GST_VAAPI_TYPE_RATE_CONTROL:
+ *
+ * A type that represents the VA rate control.
+ *
+ * Return value: the #GType of GstVaapiRateControl
+ */
+#define GST_VAAPI_TYPE_RATE_CONTROL gst_vaapi_rate_control_get_type()
+
+GType
+gst_vaapi_id_get_type(void) G_GNUC_CONST;
+
+GstVaapiID
+gst_vaapi_value_get_id(const GValue *value);
+
+void
+gst_vaapi_value_set_id(GValue *value, GstVaapiID id);
+
+GType
+gst_vaapi_render_mode_get_type(void) G_GNUC_CONST;
+
+GType
+gst_vaapi_rotation_get_type(void) G_GNUC_CONST;
+
+GType
+gst_vaapi_rate_control_get_type(void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_VALUE_H */
diff --git a/gst-libs/gst/vaapi/gstvaapivideobuffer.c b/gst-libs/gst/vaapi/gstvaapivideobuffer.c
new file mode 100644 (file)
index 0000000..488d473
--- /dev/null
@@ -0,0 +1,665 @@
+/*
+ *  gstvaapivideobuffer.c - Gst VA video buffer
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapivideobuffer
+ * @short_description: VA video buffer for GStreamer
+ */
+
+#include "sysdeps.h"
+#include "gstvaapivideobuffer.h"
+#include "gstvaapivideobuffer_priv.h"
+#include "gstvaapiimagepool.h"
+#include "gstvaapisurfacepool.h"
+#include "gstvaapiobject_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiVideoBuffer, gst_vaapi_video_buffer, GST_TYPE_SURFACE_BUFFER);
+
+#define GST_VAAPI_VIDEO_BUFFER_GET_PRIVATE(obj)                 \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_VIDEO_BUFFER,  \
+                                 GstVaapiVideoBufferPrivate))
+
+struct _GstVaapiVideoBufferPrivate {
+    GstVaapiDisplay            *display;
+    GstVaapiVideoPool          *image_pool;
+    GstVaapiImage              *image;
+    GstVaapiVideoPool          *surface_pool;
+    GstVaapiSurface            *surface;
+    GstVaapiSurfaceProxy       *proxy;
+    GstBuffer                  *buffer;
+    guint                       render_flags;
+};
+
+static void
+set_display(GstVaapiVideoBuffer *buffer, GstVaapiDisplay *display)
+{
+    GstVaapiVideoBufferPrivate * const priv = buffer->priv;
+
+    g_clear_object(&priv->display);
+
+    if (display)
+        priv->display = g_object_ref(display);
+}
+
+static inline void
+set_image(GstVaapiVideoBuffer *buffer, GstVaapiImage *image)
+{
+    buffer->priv->image = g_object_ref(image);
+    set_display(buffer, GST_VAAPI_OBJECT_DISPLAY(image));
+}
+
+static inline void
+set_surface(GstVaapiVideoBuffer *buffer, GstVaapiSurface *surface)
+{
+    buffer->priv->surface = g_object_ref(surface);
+    set_display(buffer, GST_VAAPI_OBJECT_DISPLAY(surface));
+}
+
+static void
+gst_vaapi_video_buffer_destroy_image(GstVaapiVideoBuffer *buffer)
+{
+    GstVaapiVideoBufferPrivate * const priv = buffer->priv;
+
+    if (priv->image) {
+        if (priv->image_pool)
+            gst_vaapi_video_pool_put_object(priv->image_pool, priv->image);
+        g_object_unref(priv->image);
+        priv->image = NULL;
+    }
+
+    g_clear_object(&priv->image_pool);
+}
+
+static void
+gst_vaapi_video_buffer_destroy_surface(GstVaapiVideoBuffer *buffer)
+{
+    GstVaapiVideoBufferPrivate * const priv = buffer->priv;
+
+    g_clear_object(&priv->proxy);
+
+    if (priv->surface) {
+        if (priv->surface_pool)
+            gst_vaapi_video_pool_put_object(priv->surface_pool, priv->surface);
+        g_object_unref(priv->surface);
+        priv->surface = NULL;
+    }
+
+    g_clear_object(&priv->surface_pool);
+
+    if (priv->buffer) {
+        gst_buffer_unref(priv->buffer);
+        priv->buffer = NULL;
+    }
+}
+
+static void
+gst_vaapi_video_buffer_finalize(GstMiniObject *object)
+{
+    GstVaapiVideoBuffer * const buffer = GST_VAAPI_VIDEO_BUFFER(object);
+    GstMiniObjectClass *parent_class;
+
+    gst_vaapi_video_buffer_destroy_image(buffer);
+    gst_vaapi_video_buffer_destroy_surface(buffer);
+
+    set_display(buffer, NULL);
+
+    parent_class = GST_MINI_OBJECT_CLASS(gst_vaapi_video_buffer_parent_class);
+    if (parent_class->finalize)
+        parent_class->finalize(object);
+}
+
+static void
+gst_vaapi_video_buffer_class_init(GstVaapiVideoBufferClass *klass)
+{
+    GstMiniObjectClass * const object_class = GST_MINI_OBJECT_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiVideoBufferPrivate));
+
+    object_class->finalize = gst_vaapi_video_buffer_finalize;
+}
+
+static void
+gst_vaapi_video_buffer_init(GstVaapiVideoBuffer *buffer)
+{
+    GstVaapiVideoBufferPrivate *priv;
+
+    priv                = GST_VAAPI_VIDEO_BUFFER_GET_PRIVATE(buffer);
+    buffer->priv        = priv;
+    priv->display       = NULL;
+    priv->image_pool    = NULL;
+    priv->image         = NULL;
+    priv->surface_pool  = NULL;
+    priv->surface       = NULL;
+    priv->proxy         = NULL;
+    priv->buffer        = NULL;
+    priv->render_flags  = 0;
+}
+
+static inline gboolean
+gst_vaapi_video_buffer_is_a(GstBuffer *buffer, GType type)
+{
+    return G_TYPE_CHECK_INSTANCE_TYPE(buffer, type);
+}
+
+static inline gpointer
+_gst_vaapi_video_buffer_typed_new(GType type)
+{
+    g_return_val_if_fail(g_type_is_a(type, GST_VAAPI_TYPE_VIDEO_BUFFER), NULL);
+
+    return gst_mini_object_new(type);
+}
+
+/**
+ * gst_vaapi_video_buffer_typed_new:
+ * @display: a #GstVaapiDisplay
+ *
+ * Creates an empty #GstBuffer. The caller is responsible for completing
+ * the initialization of the buffer with the gst_vaapi_video_buffer_set_*()
+ * functions.
+ *
+ * This function shall only be called from within gstreamer-vaapi
+ * plugin elements.
+ *
+ * Return value: the newly allocated #GstBuffer, or %NULL or error
+ */
+GstBuffer *
+gst_vaapi_video_buffer_typed_new(GType type, GstVaapiDisplay *display)
+{
+    GstBuffer *buffer;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+
+    buffer = _gst_vaapi_video_buffer_typed_new(type);
+    if (!buffer)
+        return NULL;
+
+    set_display(GST_VAAPI_VIDEO_BUFFER(buffer), display);
+    return buffer;
+}
+
+/**
+ * gst_vaapi_video_buffer_typed_new_from_pool:
+ * @pool: a #GstVaapiVideoPool
+ *
+ * Creates a #GstBuffer with a video object allocated from a @pool.
+ * Only #GstVaapiSurfacePool and #GstVaapiImagePool pools are supported.
+ *
+ * The buffer is destroyed through the last call to gst_buffer_unref()
+ * and the video objects are pushed back to their respective pools.
+ *
+ * Return value: the newly allocated #GstBuffer, or %NULL on error
+ */
+GstBuffer *
+gst_vaapi_video_buffer_typed_new_from_pool(GType type, GstVaapiVideoPool *pool)
+{
+    GstVaapiVideoBuffer *buffer;
+    gboolean is_image_pool, is_surface_pool;
+
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool), NULL);
+
+    is_image_pool   = GST_VAAPI_IS_IMAGE_POOL(pool);
+    is_surface_pool = GST_VAAPI_IS_SURFACE_POOL(pool);
+
+    if (!is_image_pool && !is_surface_pool)
+        return NULL;
+
+    buffer = _gst_vaapi_video_buffer_typed_new(type);
+    if (buffer &&
+        ((is_image_pool &&
+          gst_vaapi_video_buffer_set_image_from_pool(buffer, pool)) ||
+         (is_surface_pool &&
+          gst_vaapi_video_buffer_set_surface_from_pool(buffer, pool)))) {
+        set_display(buffer, gst_vaapi_video_pool_get_display(pool));
+        return GST_BUFFER(buffer);
+    }
+
+    gst_mini_object_unref(GST_MINI_OBJECT(buffer));
+    return NULL;
+}
+
+/**
+ * gst_vaapi_video_buffer_typed_new_from_buffer:
+ * @buffer: a #GstBuffer
+ *
+ * Creates a #GstBuffer with video objects bound to @buffer video
+ * objects, if any.
+ *
+ * This function shall only be called from within gstreamer-vaapi
+ * plugin elements.
+ *
+ * Return value: the newly allocated #GstBuffer, or %NULL on error
+ */
+GstBuffer *
+gst_vaapi_video_buffer_typed_new_from_buffer(GType type, GstBuffer *buffer)
+{
+    GstVaapiVideoBuffer *inbuf, *outbuf;
+
+    if (!gst_vaapi_video_buffer_is_a(buffer, type)) {
+        if (!buffer->parent ||
+            !gst_vaapi_video_buffer_is_a(buffer->parent, type))
+            return NULL;
+        buffer = buffer->parent;
+    }
+    inbuf = GST_VAAPI_VIDEO_BUFFER(buffer);
+
+    outbuf = _gst_vaapi_video_buffer_typed_new(type);
+    if (!outbuf)
+        return NULL;
+
+    if (inbuf->priv->image)
+        gst_vaapi_video_buffer_set_image(outbuf, inbuf->priv->image);
+    if (inbuf->priv->surface)
+        gst_vaapi_video_buffer_set_surface(outbuf, inbuf->priv->surface);
+    if (inbuf->priv->proxy)
+        gst_vaapi_video_buffer_set_surface_proxy(outbuf, inbuf->priv->proxy);
+
+    outbuf->priv->buffer = gst_buffer_ref(buffer);
+    return GST_BUFFER(outbuf);
+}
+
+/**
+ * gst_vaapi_video_buffer_typed_new_with_image:
+ * @image: a #GstVaapiImage
+ *
+ * Creates a #GstBuffer with the specified @image. The resulting
+ * buffer holds an additional reference to the @image.
+ *
+ * This function shall only be called from within gstreamer-vaapi
+ * plugin elements.
+ *
+ * Return value: the newly allocated #GstBuffer, or %NULL on error
+ */
+GstBuffer *
+gst_vaapi_video_buffer_typed_new_with_image(GType type, GstVaapiImage *image)
+{
+    GstVaapiVideoBuffer *buffer;
+
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL);
+
+    buffer = _gst_vaapi_video_buffer_typed_new(type);
+    if (buffer)
+        gst_vaapi_video_buffer_set_image(buffer, image);
+    return GST_BUFFER(buffer);
+}
+
+/**
+ * gst_vaapi_video_buffer_typed_new_with_surface:
+ * @surface: a #GstVaapiSurface
+ *
+ * Creates a #GstBuffer with the specified @surface. The resulting
+ * buffer holds an additional reference to the @surface.
+ *
+ * This function shall only be called from within gstreamer-vaapi
+ * plugin elements.
+ *
+ * Return value: the newly allocated #GstBuffer, or %NULL on error
+ */
+GstBuffer *
+gst_vaapi_video_buffer_typed_new_with_surface(
+    GType            type,
+    GstVaapiSurface *surface
+)
+{
+    GstVaapiVideoBuffer *buffer;
+
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), NULL);
+
+    buffer = _gst_vaapi_video_buffer_typed_new(type);
+    if (buffer)
+        gst_vaapi_video_buffer_set_surface(buffer, surface);
+    return GST_BUFFER(buffer);
+}
+
+/**
+ * gst_vaapi_video_buffer_typed_new_with_surface_proxy:
+ * @proxy: a #GstVaapiSurfaceProxy
+ *
+ * Creates a #GstBuffer with the specified surface @proxy. The
+ * resulting buffer holds an additional reference to the @proxy.
+ *
+ * This function shall only be called from within gstreamer-vaapi
+ * plugin elements.
+ *
+ * Return value: the newly allocated #GstBuffer, or %NULL on error
+ */
+GstBuffer *
+gst_vaapi_video_buffer_typed_new_with_surface_proxy(
+    GType                 type,
+    GstVaapiSurfaceProxy *proxy
+)
+{
+    GstVaapiVideoBuffer *buffer;
+
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy), NULL);
+
+    buffer = _gst_vaapi_video_buffer_typed_new(type);
+    if (buffer)
+        gst_vaapi_video_buffer_set_surface_proxy(buffer, proxy);
+    return GST_BUFFER(buffer);
+}
+
+/**
+ * gst_vaapi_video_buffer_get_display:
+ * @buffer: a #GstVaapiVideoBuffer
+ *
+ * Retrieves the #GstVaapiDisplay the @buffer is bound to. The @buffer
+ * owns the returned #GstVaapiDisplay object so the caller is
+ * responsible for calling g_object_ref() when needed.
+ *
+ * Return value: the #GstVaapiDisplay the @buffer is bound to
+ */
+GstVaapiDisplay *
+gst_vaapi_video_buffer_get_display(GstVaapiVideoBuffer *buffer)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer), NULL);
+
+    return buffer->priv->display;
+}
+
+/**
+ * gst_vaapi_video_buffer_get_image:
+ * @buffer: a #GstVaapiVideoBuffer
+ *
+ * Retrieves the #GstVaapiImage bound to the @buffer. The @buffer owns
+ * the #GstVaapiImage so the caller is responsible for calling
+ * g_object_ref() when needed.
+ *
+ * Return value: the #GstVaapiImage bound to the @buffer, or %NULL if
+ *   there is none
+ */
+GstVaapiImage *
+gst_vaapi_video_buffer_get_image(GstVaapiVideoBuffer *buffer)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer), NULL);
+
+    return buffer->priv->image;
+}
+
+/**
+ * gst_vaapi_video_buffer_set_image:
+ * @buffer: a #GstVaapiVideoBuffer
+ * @image: a #GstVaapiImage
+ *
+ * Binds @image to the @buffer. If the @buffer contains another image
+ * previously allocated from a pool, it's pushed back to its parent
+ * pool and the pool is also released.
+ */
+void
+gst_vaapi_video_buffer_set_image(
+    GstVaapiVideoBuffer *buffer,
+    GstVaapiImage       *image
+)
+{
+    g_return_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer));
+    g_return_if_fail(GST_VAAPI_IS_IMAGE(image));
+
+    gst_vaapi_video_buffer_destroy_image(buffer);
+
+    if (image)
+        set_image(buffer, image);
+}
+
+/**
+ * gst_vaapi_video_buffer_set_image_from_pool
+ * @buffer: a #GstVaapiVideoBuffer
+ * @pool: a #GstVaapiVideoPool
+ *
+ * Binds a newly allocated video object from the @pool. The @pool
+ * shall be of type #GstVaapiImagePool. Previously allocated objects
+ * are released and returned to their parent pools, if any.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_video_buffer_set_image_from_pool(
+    GstVaapiVideoBuffer *buffer,
+    GstVaapiVideoPool   *pool
+)
+{
+    GstVaapiImage *image;
+
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer), FALSE);
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE_POOL(pool), FALSE);
+
+    gst_vaapi_video_buffer_destroy_image(buffer);
+
+    if (pool) {
+        image = gst_vaapi_video_pool_get_object(pool);
+        if (!image)
+            return FALSE;
+        set_image(buffer, image);
+        buffer->priv->image_pool = g_object_ref(pool);
+    }
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_video_buffer_get_surface:
+ * @buffer: a #GstVaapiVideoBuffer
+ *
+ * Retrieves the #GstVaapiSurface bound to the @buffer. The @buffer
+ * owns the #GstVaapiSurface so the caller is responsible for calling
+ * g_object_ref() when needed.
+ *
+ * Return value: the #GstVaapiSurface bound to the @buffer, or %NULL if
+ *   there is none
+ */
+GstVaapiSurface *
+gst_vaapi_video_buffer_get_surface(GstVaapiVideoBuffer *buffer)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer), NULL);
+
+    return buffer->priv->surface;
+}
+
+/**
+ * gst_vaapi_video_buffer_set_surface:
+ * @buffer: a #GstVaapiVideoBuffer
+ * @surface: a #GstVaapiSurface
+ *
+ * Binds @surface to the @buffer. If the @buffer contains another
+ * surface previously allocated from a pool, it's pushed back to its
+ * parent pool and the pool is also released.
+ */
+void
+gst_vaapi_video_buffer_set_surface(
+    GstVaapiVideoBuffer *buffer,
+    GstVaapiSurface     *surface
+)
+{
+    g_return_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer));
+    g_return_if_fail(GST_VAAPI_IS_SURFACE(surface));
+
+    gst_vaapi_video_buffer_destroy_surface(buffer);
+
+    if (surface)
+        set_surface(buffer, surface);
+}
+
+/**
+ * gst_vaapi_video_buffer_set_surface_from_pool
+ * @buffer: a #GstVaapiVideoBuffer
+ * @pool: a #GstVaapiVideoPool
+ *
+ * Binds a newly allocated video object from the @pool. The @pool
+ * shall be of type #GstVaapiSurfacePool. Previously allocated objects
+ * are released and returned to their parent pools, if any.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_video_buffer_set_surface_from_pool(
+    GstVaapiVideoBuffer *buffer,
+    GstVaapiVideoPool   *pool
+)
+{
+    GstVaapiSurface *surface;
+
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer), FALSE);
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE_POOL(pool), FALSE);
+
+    gst_vaapi_video_buffer_destroy_surface(buffer);
+
+    if (pool) {
+        surface = gst_vaapi_video_pool_get_object(pool);
+        if (!surface)
+            return FALSE;
+        set_surface(buffer, surface);
+        buffer->priv->surface_pool = g_object_ref(pool);
+    }
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_video_buffer_get_surface_proxy:
+ * @buffer: a #GstVaapiVideoBuffer
+ *
+ * Retrieves the #GstVaapiSurfaceProxy bound to the @buffer. The @buffer
+ * owns the #GstVaapiSurfaceProxy so the caller is responsible for calling
+ * g_object_ref() when needed.
+ *
+ * Return value: the #GstVaapiSurfaceProxy bound to the @buffer, or
+ *   %NULL if there is none
+ */
+GstVaapiSurfaceProxy *
+gst_vaapi_video_buffer_get_surface_proxy(GstVaapiVideoBuffer *buffer)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer), NULL);
+
+    return buffer->priv->proxy;
+}
+
+/**
+ * gst_vaapi_video_buffer_set_surface_proxy:
+ * @buffer: a #GstVaapiVideoBuffer
+ * @proxy: a #GstVaapiSurfaceProxy
+ *
+ * Binds surface @proxy to the @buffer. If the @buffer contains another
+ * surface previously allocated from a pool, it's pushed back to its
+ * parent pool and the pool is also released.
+ */
+void
+gst_vaapi_video_buffer_set_surface_proxy(
+    GstVaapiVideoBuffer  *buffer,
+    GstVaapiSurfaceProxy *proxy
+)
+{
+    GstVaapiSurface *surface;
+
+    g_return_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer));
+    g_return_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy));
+
+    gst_vaapi_video_buffer_destroy_surface(buffer);
+
+    if (proxy) {
+        surface = GST_VAAPI_SURFACE_PROXY_SURFACE(proxy);
+        if (!surface)
+            return;
+        set_surface(buffer, surface);
+        buffer->priv->proxy = g_object_ref(proxy);
+    }
+}
+
+/**
+ * gst_vaapi_video_buffer_get_render_flags:
+ * @buffer: a #GstVaapiVideoBuffer
+ *
+ * Retrieves the surface render flags bound to the @buffer.
+ *
+ * Return value: a combination for #GstVaapiSurfaceRenderFlags
+ */
+guint
+gst_vaapi_video_buffer_get_render_flags(GstVaapiVideoBuffer *buffer)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer), 0);
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(buffer->priv->surface), 0);
+
+    return buffer->priv->render_flags;
+}
+
+/**
+ * gst_vaapi_video_buffer_set_render_flags:
+ * @buffer: a #GstVaapiVideoBuffer
+ * @flags: a set of surface render flags
+ *
+ * Sets #GstVaapiSurfaceRenderFlags to the @buffer.
+ */
+void
+gst_vaapi_video_buffer_set_render_flags(GstVaapiVideoBuffer *buffer, guint flags)
+{
+    g_return_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer));
+    g_return_if_fail(GST_VAAPI_IS_SURFACE(buffer->priv->surface));
+
+    buffer->priv->render_flags = flags;
+}
+
+/**
+ * gst_vaapi_video_buffer_ensure_pointer:
+ * @buffer: a #GstVaapiVideoBuffer
+ *
+ * Maps image data buffer to #GstBuffer of @buffer.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_video_buffer_ensure_pointer(GstVaapiVideoBuffer *buffer)
+{
+    GstVaapiVideoBufferPrivate * const priv = buffer->priv;
+    GstVaapiImage *image = NULL;
+    gboolean is_image_derived = FALSE;
+    gboolean ret = FALSE;
+
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer), FALSE);
+    g_return_val_if_fail (priv->image || priv->surface, FALSE);
+
+    if (!priv->image) {
+        image = gst_vaapi_surface_derive_image(priv->surface);
+        g_return_val_if_fail(image, FALSE);
+        is_image_derived = TRUE;
+    } else {
+        image = priv->image;
+        is_image_derived = FALSE;
+    }
+
+    if (!gst_vaapi_image_map(image))
+        goto end;
+
+    if(!gst_vaapi_image_ensure_mapped_buffer(image))
+        goto end;
+
+    GST_BUFFER_DATA(buffer) = gst_vaapi_image_get_plane(image, 0);
+    GST_BUFFER_SIZE(buffer) = gst_vaapi_image_get_data_size(image);
+
+    if (!gst_vaapi_image_unmap(image))
+        goto end;
+
+    ret = TRUE;
+
+end:
+    if (image && is_image_derived)
+        g_object_unref(image);
+    return ret;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapivideobuffer.h b/gst-libs/gst/vaapi/gstvaapivideobuffer.h
new file mode 100644 (file)
index 0000000..0161240
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ *  gstvaapivideobuffer.h - Gstreamer/VA video buffer
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_VIDEO_BUFFER_H
+#define GST_VAAPI_VIDEO_BUFFER_H
+
+#include <gst/video/gstsurfacebuffer.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapiimage.h>
+#include <gst/vaapi/gstvaapisurface.h>
+#include <gst/vaapi/gstvaapisurfaceproxy.h>
+#include <gst/vaapi/gstvaapivideopool.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_VIDEO_BUFFER \
+    (gst_vaapi_video_buffer_get_type())
+
+#define GST_VAAPI_VIDEO_BUFFER(obj)                             \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_VIDEO_BUFFER,    \
+                                GstVaapiVideoBuffer))
+
+#define GST_VAAPI_VIDEO_BUFFER_CLASS(klass)                     \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_VIDEO_BUFFER,       \
+                             GstVaapiVideoBufferClass))
+
+#define GST_VAAPI_IS_VIDEO_BUFFER(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_VIDEO_BUFFER))
+
+#define GST_VAAPI_IS_VIDEO_BUFFER_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_VIDEO_BUFFER))
+
+#define GST_VAAPI_VIDEO_BUFFER_GET_CLASS(obj)                   \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_VIDEO_BUFFER,     \
+                               GstVaapiVideoBufferClass))
+
+typedef struct _GstVaapiVideoBuffer             GstVaapiVideoBuffer;
+typedef struct _GstVaapiVideoBufferPrivate      GstVaapiVideoBufferPrivate;
+typedef struct _GstVaapiVideoBufferClass        GstVaapiVideoBufferClass;
+
+/**
+ * GstVaapiVideoBuffer:
+ *
+ * A #GstBuffer holding video objects (#GstVaapiSurface and #GstVaapiImage).
+ */
+struct _GstVaapiVideoBuffer {
+    /*< private >*/
+    GstSurfaceBuffer parent_instance;
+
+    GstVaapiVideoBufferPrivate *priv;
+};
+
+/**
+ * GstVaapiVideoBufferClass:
+ *
+ * A #GstBuffer holding video objects
+ */
+struct _GstVaapiVideoBufferClass {
+    /*< private >*/
+    GstSurfaceBufferClass parent_class;
+};
+
+GType
+gst_vaapi_video_buffer_get_type(void) G_GNUC_CONST;
+
+GstVaapiDisplay *
+gst_vaapi_video_buffer_get_display(GstVaapiVideoBuffer *buffer);
+
+GstVaapiImage *
+gst_vaapi_video_buffer_get_image(GstVaapiVideoBuffer *buffer);
+
+void
+gst_vaapi_video_buffer_set_image(
+    GstVaapiVideoBuffer *buffer,
+    GstVaapiImage       *image
+);
+
+gboolean
+gst_vaapi_video_buffer_set_image_from_pool(
+    GstVaapiVideoBuffer *buffer,
+    GstVaapiVideoPool   *pool
+);
+
+GstVaapiSurface *
+gst_vaapi_video_buffer_get_surface(GstVaapiVideoBuffer *buffer);
+
+void
+gst_vaapi_video_buffer_set_surface(
+    GstVaapiVideoBuffer *buffer,
+    GstVaapiSurface     *surface
+);
+
+gboolean
+gst_vaapi_video_buffer_set_surface_from_pool(
+    GstVaapiVideoBuffer *buffer,
+    GstVaapiVideoPool   *pool
+);
+
+GstVaapiSurfaceProxy *
+gst_vaapi_video_buffer_get_surface_proxy(GstVaapiVideoBuffer *buffer);
+
+void
+gst_vaapi_video_buffer_set_surface_proxy(
+    GstVaapiVideoBuffer  *buffer,
+    GstVaapiSurfaceProxy *proxy
+);
+
+guint
+gst_vaapi_video_buffer_get_render_flags(GstVaapiVideoBuffer *buffer);
+
+void
+gst_vaapi_video_buffer_set_render_flags(GstVaapiVideoBuffer *buffer, guint flags);
+
+gboolean
+gst_vaapi_video_buffer_ensure_pointer(GstVaapiVideoBuffer *buffer);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_VIDEO_BUFFER_H */
diff --git a/gst-libs/gst/vaapi/gstvaapivideobuffer_glx.c b/gst-libs/gst/vaapi/gstvaapivideobuffer_glx.c
new file mode 100644 (file)
index 0000000..c531f79
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *  gstvaapivideobuffer_glx.c - Gst VA video buffer
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Copyright (C) 2011 Collabora Ltd.
+ *    Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapivideobufferglx
+ * @short_description: VA video buffer for GStreamer with GLX support
+ */
+
+#include "sysdeps.h"
+#include "gstvaapivideobuffer_glx.h"
+#include "gstvaapivideoconverter_glx.h"
+#include "gstvaapivideopool.h"
+#include "gstvaapivideobuffer_priv.h"
+#include "gstvaapidisplay_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiVideoBufferGLX,
+              gst_vaapi_video_buffer_glx,
+              GST_VAAPI_TYPE_VIDEO_BUFFER);
+
+static void
+gst_vaapi_video_buffer_glx_class_init(GstVaapiVideoBufferGLXClass *klass)
+{
+    GstSurfaceBufferClass * const surface_class =
+        GST_SURFACE_BUFFER_CLASS(klass);
+
+    surface_class->create_converter = gst_vaapi_video_converter_glx_new;
+}
+
+static void
+gst_vaapi_video_buffer_glx_init(GstVaapiVideoBufferGLX *buffer)
+{
+}
diff --git a/gst-libs/gst/vaapi/gstvaapivideobuffer_glx.h b/gst-libs/gst/vaapi/gstvaapivideobuffer_glx.h
new file mode 100644 (file)
index 0000000..0dbe065
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ *  gstvaapivideobuffer_glx.h - Gstreamer/VA video buffer
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Copyright (C) 2011 Collabora Ltd.
+ *    Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_VIDEO_BUFFER_GLX_H
+#define GST_VAAPI_VIDEO_BUFFER_GLX_H
+
+#include <gst/vaapi/gstvaapidisplay_glx.h>
+#include <gst/vaapi/gstvaapivideobuffer.h>
+#include <gst/vaapi/gstvaapivideopool.h>
+#include <gst/video/gstsurfacebuffer.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_VIDEO_BUFFER_GLX \
+    (gst_vaapi_video_buffer_glx_get_type())
+
+#define GST_VAAPI_VIDEO_BUFFER_GLX(obj)                                 \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                                  \
+                                GST_VAAPI_TYPE_VIDEO_BUFFER_GLX,        \
+                                GstVaapiVideoBufferGLX))
+
+#define GST_VAAPI_VIDEO_BUFFER_GLX_CLASS(klass)                 \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_VIDEO_BUFFER_GLX,   \
+                             GstVaapiVideoBufferGLXClass))
+
+#define GST_VAAPI_IS_VIDEO_BUFFER_GLX(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_VIDEO_BUFFER_GLX))
+
+#define GST_VAAPI_IS_VIDEO_BUFFER_GLX_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_VIDEO_BUFFER_GLX))
+
+#define GST_VAAPI_VIDEO_BUFFER_GLX_GET_CLASS(obj)               \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_VIDEO_BUFFER_GLX, \
+                               GstVaapiVideoBufferGLXClass))
+
+typedef struct _GstVaapiVideoBufferGLX             GstVaapiVideoBufferGLX;
+typedef struct _GstVaapiVideoBufferGLXClass        GstVaapiVideoBufferGLXClass;
+
+/**
+ * GstVaapiVideoBufferGLX:
+ *
+ * A #GstBuffer holding video objects (#GstVaapiSurface and #GstVaapiImage).
+ */
+struct _GstVaapiVideoBufferGLX {
+    /*< private >*/
+    GstVaapiVideoBuffer parent_instance;
+};
+
+/**
+ * GstVaapiVideoBufferGLXClass:
+ *
+ * A #GstBuffer holding video objects
+ */
+struct _GstVaapiVideoBufferGLXClass {
+    /*< private >*/
+    GstVaapiVideoBufferClass parent_class;
+};
+
+GType      gst_vaapi_video_buffer_glx_get_type        (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_VIDEO_BUFFER_GLX_H */
diff --git a/gst-libs/gst/vaapi/gstvaapivideobuffer_priv.h b/gst-libs/gst/vaapi/gstvaapivideobuffer_priv.h
new file mode 100644 (file)
index 0000000..a08edbd
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *  gstvaapivideobuffer_priv.h - Gstreamer/VA video buffer (private interface)
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Copyright (C) 2011 Collabora Ltd.
+ *    Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_VIDEO_BUFFER_PRIV_H
+#define GST_VAAPI_VIDEO_BUFFER_PRIV_H
+
+#include <gst/vaapi/gstvaapivideobuffer.h>
+
+G_BEGIN_DECLS
+
+/* Private API for gstreamer-vaapi plugin elements only */
+
+GstBuffer *
+gst_vaapi_video_buffer_typed_new(GType type, GstVaapiDisplay *display);
+
+GstBuffer *
+gst_vaapi_video_buffer_typed_new_from_pool(GType type, GstVaapiVideoPool *pool);
+
+GstBuffer *
+gst_vaapi_video_buffer_typed_new_from_buffer(GType type, GstBuffer *buffer);
+
+GstBuffer *
+gst_vaapi_video_buffer_typed_new_with_image(GType type, GstVaapiImage *image);
+
+GstBuffer *
+gst_vaapi_video_buffer_typed_new_with_surface(
+    GType            type,
+    GstVaapiSurface *surface
+);
+
+GstBuffer *
+gst_vaapi_video_buffer_typed_new_with_surface_proxy(
+    GType                 type,
+    GstVaapiSurfaceProxy *proxy
+);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_VIDEO_BUFFER_PRIV_H */
diff --git a/gst-libs/gst/vaapi/gstvaapivideoconverter_glx.c b/gst-libs/gst/vaapi/gstvaapivideoconverter_glx.c
new file mode 100644 (file)
index 0000000..0ea968f
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ *  gstvaapivideoconverter_glx.c - Gst VA video converter
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Copyright (C) 2011 Collabora Ltd.
+ *    Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "sysdeps.h"
+#include <string.h>
+#include "gstvaapivideoconverter_glx.h"
+#include "gstvaapivideobuffer.h"
+#include "gstvaapitexture.h"
+
+static void gst_vaapi_video_converter_glx_iface_init (GstSurfaceConverterInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GstVaapiVideoConverterGLX, gst_vaapi_video_converter_glx,
+                         G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GST_TYPE_SURFACE_CONVERTER,
+                                                gst_vaapi_video_converter_glx_iface_init));
+
+struct _GstVaapiVideoConverterGLXPrivate {
+    GstVaapiTexture *texture;
+};
+
+static void
+gst_vaapi_video_converter_glx_dispose(GObject *object)
+{
+    GstVaapiVideoConverterGLXPrivate *priv =
+      GST_VAAPI_VIDEO_CONVERTER_GLX (object)->priv;
+
+    g_clear_object(&priv->texture);
+
+    G_OBJECT_CLASS (gst_vaapi_video_converter_glx_parent_class)->dispose (object);
+}
+
+static void
+gst_vaapi_video_converter_glx_class_init(GstVaapiVideoConverterGLXClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    g_type_class_add_private (klass, sizeof (GstVaapiVideoConverterGLXPrivate));
+    object_class->dispose = gst_vaapi_video_converter_glx_dispose;
+}
+
+static void
+gst_vaapi_video_converter_glx_init(GstVaapiVideoConverterGLX *buffer)
+{
+    buffer->priv = G_TYPE_INSTANCE_GET_PRIVATE(buffer,
+                                               GST_VAAPI_TYPE_VIDEO_CONVERTER,
+                                               GstVaapiVideoConverterGLXPrivate);
+}
+
+static void
+gst_vaapi_video_converter_glx_iface_init (GstSurfaceConverterInterface *iface) {
+  iface->upload = gst_vaapi_video_converter_glx_upload;
+}
+
+/**
+ * gst_vaapi_video_converter_glx_new:
+ * @surface: the #GstSurfaceBuffer
+ * @type: type of the target buffer (must be "opengl")
+ * @dest: target of the conversion (must be GL texture id)
+ *
+ * Creates an empty #GstBuffer. The caller is responsible for
+ * completing the initialization of the buffer with the
+ * gst_vaapi_video_converter_glx_set_*() functions.
+ *
+ * Return value: the newly allocated #GstBuffer, or %NULL on error
+ */
+GstSurfaceConverter *
+gst_vaapi_video_converter_glx_new(GstSurfaceBuffer *surface, const gchar *type,
+    GValue *dest)
+{
+    GstVaapiVideoBuffer *buffer = GST_VAAPI_VIDEO_BUFFER (surface);
+    GstVaapiDisplay *display = gst_vaapi_video_buffer_get_display (buffer);
+    GstVaapiTexture *texture;
+    GstVaapiVideoConverterGLX *converter = NULL;
+
+    /* We only support Open GL texture conversion */
+    if (strcmp(type, "opengl") || !G_VALUE_HOLDS_UINT (dest))
+        return NULL;
+
+    /* FIXME Should we assume target and format ? */
+    texture = gst_vaapi_texture_new_with_texture (display,
+                                                  g_value_get_uint (dest),
+                                                  GL_TEXTURE_2D,
+                                                  GL_BGRA);
+
+    if (texture) {
+      converter = g_object_new (GST_VAAPI_TYPE_VIDEO_CONVERTER, NULL);
+      converter->priv->texture = texture;
+    }
+
+    return GST_SURFACE_CONVERTER (converter);
+}
+
+gboolean
+gst_vaapi_video_converter_glx_upload (GstSurfaceConverter *converter,
+    GstSurfaceBuffer *buffer)
+{
+  GstVaapiVideoConverterGLXPrivate *priv =
+    GST_VAAPI_VIDEO_CONVERTER_GLX (converter)->priv;
+  GstVaapiVideoBuffer * const vbuffer = GST_VAAPI_VIDEO_BUFFER (buffer);
+  GstVaapiSurface *surface = gst_vaapi_video_buffer_get_surface (vbuffer);
+  GstVaapiDisplay *new_dpy, *old_dpy;
+  GstVideoOverlayComposition * const composition =
+    gst_video_buffer_get_overlay_composition (GST_BUFFER (buffer));
+
+  new_dpy = gst_vaapi_object_get_display (GST_VAAPI_OBJECT (surface));
+  old_dpy = gst_vaapi_object_get_display (GST_VAAPI_OBJECT (priv->texture));
+
+  if (old_dpy != new_dpy) {
+    guint texture = gst_vaapi_texture_get_id (priv->texture);
+    g_object_unref (priv->texture);
+    priv->texture = gst_vaapi_texture_new_with_texture (new_dpy,
+                                                        texture,
+                                                        GL_TEXTURE_2D,
+                                                        GL_BGRA);
+  }
+
+  if (!gst_vaapi_surface_set_subpictures_from_composition (surface,
+           composition, TRUE))
+        GST_WARNING ("could not update subtitles");
+
+  return gst_vaapi_texture_put_surface (priv->texture, surface,
+      gst_vaapi_video_buffer_get_render_flags (vbuffer));
+}
diff --git a/gst-libs/gst/vaapi/gstvaapivideoconverter_glx.h b/gst-libs/gst/vaapi/gstvaapivideoconverter_glx.h
new file mode 100644 (file)
index 0000000..0215444
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *  gstvaapivideoconverter_glx.h - Gstreamer/VA video converter
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Copyright (C) 2011 Collabora Ltd.
+ *    Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_VIDEO_CONVERTER_GLX_H
+#define GST_VAAPI_VIDEO_CONVERTER_GLX_H
+
+#include <gst/video/gstsurfaceconverter.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_VIDEO_CONVERTER                (gst_vaapi_video_converter_glx_get_type ())
+#define GST_VAAPI_VIDEO_CONVERTER_GLX(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_VAAPI_TYPE_VIDEO_CONVERTER, GstVaapiVideoConverterGLX))
+#define GST_VAAPI_VIDEO_CONVERTER_GLX_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GST_VAAPI_TYPE_VIDEO_CONVERTER, GstVaapiVideoConverterGLXClass))
+#define GST_VAAPI_IS_VIDEO_CONVERTER(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_VAAPI_TYPE_VIDEO_CONVERTER))
+#define GST_VAAPI_IS_VIDEO_CONVERTER_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_VAAPI_TYPE_VIDEO_CONVERTER))
+#define GST_VAAPI_VIDEO_CONVERTER_GLX_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_VAAPI_TYPE_VIDEO_CONVERTER, GstVaapiVideoConverterGLXClass))
+
+typedef struct _GstVaapiVideoConverterGLX             GstVaapiVideoConverterGLX;
+typedef struct _GstVaapiVideoConverterGLXPrivate      GstVaapiVideoConverterGLXPrivate;
+typedef struct _GstVaapiVideoConverterGLXClass        GstVaapiVideoConverterGLXClass;
+
+/**
+ * GstVaapiVideoConverterGLX:
+ *
+ * Converter to transform VA buffers into GL textures.
+ */
+struct _GstVaapiVideoConverterGLX {
+    /*< private >*/
+    GObject parent_instance;
+
+    GstVaapiVideoConverterGLXPrivate *priv;
+};
+
+/**
+ * GstVaapiVideoConverterGLXClass:
+ *
+ * Converter to transform VA buffers into GL textures.
+ */
+struct _GstVaapiVideoConverterGLXClass {
+    /*< private >*/
+    GObjectClass parent_class;
+};
+
+GType                 gst_vaapi_video_converter_glx_get_type (void) G_GNUC_CONST;
+
+GstSurfaceConverter  *gst_vaapi_video_converter_glx_new      (GstSurfaceBuffer *buffer,
+                                                              const gchar      *type,
+                                                              GValue           *dest);
+
+gboolean              gst_vaapi_video_converter_glx_upload   (GstSurfaceConverter *self,
+                                                              GstSurfaceBuffer *buffer);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_VIDEO_CONVERTER_GLX_H */
diff --git a/gst-libs/gst/vaapi/gstvaapivideopool.c b/gst-libs/gst/vaapi/gstvaapivideopool.c
new file mode 100644 (file)
index 0000000..f05ba00
--- /dev/null
@@ -0,0 +1,516 @@
+/*
+ *  gstvaapivideopool.c - Video object pool abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapivideopool
+ * @short_description: Video object pool abstraction
+ */
+
+#include "sysdeps.h"
+#include "gstvaapivideopool.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiVideoPool, gst_vaapi_video_pool, G_TYPE_OBJECT);
+
+#define GST_VAAPI_VIDEO_POOL_GET_PRIVATE(obj)                   \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_VIDEO_POOL,    \
+                                 GstVaapiVideoPoolPrivate))
+
+#define VAAPI_VIDEO_POOL_LOCK(mutex)    g_static_rec_mutex_lock(mutex)
+#define VAAPI_VIDEO_POOL_UNLOCK(mutex)  g_static_rec_mutex_unlock(mutex)
+
+
+struct _GstVaapiVideoPoolPrivate {
+    GstVaapiDisplay    *display;
+    GQueue              free_objects;
+    GList              *used_objects;
+    GstCaps            *caps;
+    guint               used_count;
+    guint               capacity;
+
+    GStaticRecMutex     mutex;
+};
+
+enum {
+    PROP_0,
+
+    PROP_DISPLAY,
+    PROP_CAPS,
+    PROP_CAPACITY
+};
+
+static void
+gst_vaapi_video_pool_set_caps(GstVaapiVideoPool *pool, GstCaps *caps);
+
+static inline gpointer
+gst_vaapi_video_pool_alloc_object(GstVaapiVideoPool *pool)
+{
+    GstVaapiVideoPoolClass * const klass = GST_VAAPI_VIDEO_POOL_GET_CLASS(pool);
+
+    return klass->alloc_object(pool, pool->priv->display);
+}
+
+static void
+gst_vaapi_video_pool_clear(GstVaapiVideoPool *pool)
+{
+    GstVaapiVideoPoolPrivate * const priv = pool->priv;
+    gpointer object;
+    GList *list, *next;
+
+    for (list = priv->used_objects; list; list = next) {
+        next = list->next;
+        g_object_unref(list->data);
+        g_list_free_1(list);
+    }
+    priv->used_objects = NULL;
+
+    while ((object = g_queue_pop_head(&priv->free_objects)))
+        g_object_unref(object);
+}
+
+static void
+gst_vaapi_video_pool_destroy(GstVaapiVideoPool *pool)
+{
+    GstVaapiVideoPoolPrivate * const priv = pool->priv;
+
+    gst_vaapi_video_pool_clear(pool);
+
+    if (priv->caps) {
+        gst_caps_unref(priv->caps);
+        priv->caps = NULL;
+    }
+
+    g_clear_object(&priv->display);
+}
+
+static void
+gst_vaapi_video_pool_finalize(GObject *object)
+{
+    gst_vaapi_video_pool_destroy(GST_VAAPI_VIDEO_POOL(object));
+
+    G_OBJECT_CLASS(gst_vaapi_video_pool_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_video_pool_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiVideoPool * const pool = GST_VAAPI_VIDEO_POOL(object);
+
+    switch (prop_id) {
+    case PROP_DISPLAY:
+        pool->priv->display = g_object_ref(g_value_get_object(value));
+        break;
+    case PROP_CAPS:
+        gst_vaapi_video_pool_set_caps(pool, g_value_get_pointer(value));
+        break;
+    case PROP_CAPACITY:
+        gst_vaapi_video_pool_set_capacity(pool, g_value_get_uint(value));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_video_pool_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiVideoPool * const pool = GST_VAAPI_VIDEO_POOL(object);
+
+    switch (prop_id) {
+    case PROP_DISPLAY:
+        g_value_set_object(value, gst_vaapi_video_pool_get_display(pool));
+        break;
+    case PROP_CAPS:
+        g_value_set_pointer(value, gst_vaapi_video_pool_get_caps(pool));
+        break;
+    case PROP_CAPACITY:
+        g_value_set_uint(value, gst_vaapi_video_pool_get_capacity(pool));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_video_pool_class_init(GstVaapiVideoPoolClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiVideoPoolPrivate));
+
+    object_class->finalize      = gst_vaapi_video_pool_finalize;
+    object_class->set_property  = gst_vaapi_video_pool_set_property;
+    object_class->get_property  = gst_vaapi_video_pool_get_property;
+
+    /**
+     * GstVaapiVideoPool:display:
+     *
+     * The #GstVaapiDisplay this pool is bound to.
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_DISPLAY,
+         g_param_spec_object("display",
+                             "Display",
+                             "The GstVaapiDisplay this pool is bound to",
+                             GST_VAAPI_TYPE_DISPLAY,
+                             G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    /**
+     * GstVaapiVidePool:caps:
+     *
+     * The video object capabilities represented as a #GstCaps. This
+     * shall hold at least the "width" and "height" properties.
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_CAPS,
+         g_param_spec_pointer("caps",
+                              "caps",
+                              "The video object capabilities",
+                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    /**
+     * GstVaapiVidePool:capacity:
+     *
+     * The maximum number of objects in the pool. Or zero, the pool
+     * will allocate as many objects as possible.
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_CAPACITY,
+         g_param_spec_uint("capacity",
+                           "capacity",
+                           "The maximum number of objects in the pool",
+                           0, G_MAXUINT32, 0,
+                           G_PARAM_READWRITE));
+}
+
+static void
+gst_vaapi_video_pool_init(GstVaapiVideoPool *pool)
+{
+    GstVaapiVideoPoolPrivate *priv = GST_VAAPI_VIDEO_POOL_GET_PRIVATE(pool);
+
+    pool->priv          = priv;
+    priv->display       = NULL;
+    priv->used_objects  = NULL;
+    priv->caps          = NULL;
+    priv->used_count    = 0;
+    priv->capacity      = 0;
+
+    g_queue_init(&priv->free_objects);
+    g_static_rec_mutex_init(&priv->mutex);
+}
+
+/**
+ * gst_vaapi_video_pool_get_display:
+ * @pool: a #GstVaapiVideoPool
+ *
+ * Retrieves the #GstVaapiDisplay the @pool is bound to. The @pool
+ * owns the returned object and it shall not be unref'ed.
+ *
+ * Return value: the #GstVaapiDisplay the @pool is bound to
+ */
+GstVaapiDisplay *
+gst_vaapi_video_pool_get_display(GstVaapiVideoPool *pool)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool), NULL);
+
+    return pool->priv->display;
+}
+
+/**
+ * gst_vaapi_video_pool_get_caps:
+ * @pool: a #GstVaapiVideoPool
+ *
+ * Retrieves the #GstCaps the @pool was created with. The @pool owns
+ * the returned object and it shall not be unref'ed.
+ *
+ * Return value: the #GstCaps the @pool was created with
+ */
+GstCaps *
+gst_vaapi_video_pool_get_caps(GstVaapiVideoPool *pool)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool), NULL);
+
+    return pool->priv->caps;
+}
+
+/*
+ * gst_vaapi_video_pool_set_caps:
+ * @pool: a #GstVaapiVideoPool
+ * @caps: a #GstCaps
+ *
+ * Binds new @caps to the @pool and notify the sub-classes.
+ */
+void
+gst_vaapi_video_pool_set_caps(GstVaapiVideoPool *pool, GstCaps *caps)
+{
+    GstVaapiVideoPoolClass * const klass = GST_VAAPI_VIDEO_POOL_GET_CLASS(pool);
+
+    pool->priv->caps = gst_caps_ref(caps);
+
+    if (klass->set_caps)
+        klass->set_caps(pool, caps);
+}
+
+/**
+ * gst_vaapi_video_pool_get_object:
+ * @pool: a #GstVaapiVideoPool
+ *
+ * Retrieves a new object from the @pool, or allocates a new one if
+ * none was found. The @pool holds a reference on the returned object
+ * and thus shall be released through gst_vaapi_video_pool_put_object()
+ * when it's no longer needed.
+ *
+ * Return value: a possibly newly allocated object, or %NULL on error
+ */
+gpointer
+gst_vaapi_video_pool_get_object(GstVaapiVideoPool *pool)
+{
+    GstVaapiVideoPoolPrivate *priv;
+    gpointer object = NULL;
+
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool), NULL);
+
+    priv = pool->priv;
+
+    VAAPI_VIDEO_POOL_LOCK(&priv->mutex);
+    if (priv->capacity && priv->used_count >= priv->capacity)
+        goto end;
+
+    object = g_queue_pop_head(&priv->free_objects);
+    if (!object) {
+        VAAPI_VIDEO_POOL_UNLOCK(&priv->mutex);
+        object = gst_vaapi_video_pool_alloc_object(pool);
+        VAAPI_VIDEO_POOL_LOCK(&priv->mutex);
+        if (!object)
+            goto end;
+    }
+
+    ++priv->used_count;
+    priv->used_objects = g_list_prepend(priv->used_objects, object);
+    g_object_ref(object);
+
+  end:
+    VAAPI_VIDEO_POOL_UNLOCK(&priv->mutex);
+    return object;
+}
+
+/**
+ * gst_vaapi_video_pool_put_object:
+ * @pool: a #GstVaapiVideoPool
+ * @object: the object to add back to the pool
+ *
+ * Pushes the @object back into the pool. The @object shall be
+ * obtained from the @pool through gst_vaapi_video_pool_get_object().
+ * Calling this function with an arbitrary object yields undefined
+ * behaviour.
+ */
+void
+gst_vaapi_video_pool_put_object(GstVaapiVideoPool *pool, gpointer object)
+{
+    GstVaapiVideoPoolPrivate *priv;
+    GList *elem;
+
+    g_return_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool));
+    g_return_if_fail(G_IS_OBJECT(object));
+
+    priv = pool->priv;
+
+    VAAPI_VIDEO_POOL_LOCK(&priv->mutex);
+    elem = g_list_find(priv->used_objects, object);
+    if (!elem)
+        goto end;
+
+    g_object_unref(object);
+    --priv->used_count;
+    priv->used_objects = g_list_delete_link(priv->used_objects, elem);
+    g_queue_push_tail(&priv->free_objects, object);
+
+  end:
+    VAAPI_VIDEO_POOL_UNLOCK(&priv->mutex);
+}
+
+/**
+ * gst_vaapi_video_pool_add_object:
+ * @pool: a #GstVaapiVideoPool
+ * @object: the object to add to the pool
+ *
+ * Adds the @object to the pool. The pool then holds a reference on
+ * the @object. This operation does not change the capacity of the
+ * pool.
+ *
+ * Return value: %TRUE on success.
+ */
+gboolean
+gst_vaapi_video_pool_add_object(GstVaapiVideoPool *pool, gpointer object)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool), FALSE);
+    g_return_val_if_fail(G_IS_OBJECT(object), FALSE);
+
+    VAAPI_VIDEO_POOL_LOCK(&pool->priv->mutex);
+    g_queue_push_tail(&pool->priv->free_objects, g_object_ref(object));
+    VAAPI_VIDEO_POOL_UNLOCK(&pool->priv->mutex);
+
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_video_pool_add_objects:
+ * @pool: a #GstVaapiVideoPool
+ * @objects: a #GPtrArray of objects
+ *
+ * Adds the @objects to the pool. The pool then holds a reference on
+ * the @objects. This operation does not change the capacity of the
+ * pool and is just a wrapper around gst_vaapi_video_pool_add_object().
+ *
+ * Return value: %TRUE on success.
+ */
+gboolean
+gst_vaapi_video_pool_add_objects(GstVaapiVideoPool *pool, GPtrArray *objects)
+{
+    guint i;
+
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool), FALSE);
+
+    for (i = 0; i < objects->len; i++) {
+        gpointer const object = g_ptr_array_index(objects, i);
+        if (!gst_vaapi_video_pool_add_object(pool, object))
+            return FALSE;
+    }
+    return TRUE;
+}
+
+/**
+ * gst_vaapi_video_pool_get_size:
+ * @pool: a #GstVaapiVideoPool
+ *
+ * Returns the number of free objects available in the pool.
+ *
+ * Return value: number of free objects in the pool
+ */
+guint
+gst_vaapi_video_pool_get_size(GstVaapiVideoPool *pool)
+{
+    guint size;
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool), 0);
+
+
+    VAAPI_VIDEO_POOL_LOCK(&pool->priv->mutex);
+    size = g_queue_get_length(&pool->priv->free_objects);
+    VAAPI_VIDEO_POOL_UNLOCK(&pool->priv->mutex);
+    return size;
+}
+
+/**
+ * gst_vaapi_video_pool_reserve:
+ * @pool: a #GstVaapiVideoPool
+ * @n: the number of objects to pre-allocate
+ *
+ * Pre-allocates up to @n objects in the pool. If @n is less than or
+ * equal to the number of free and used objects in the pool, this call
+ * has no effect. Otherwise, it is a request for allocation of
+ * additional objects.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_video_pool_reserve(GstVaapiVideoPool *pool, guint n)
+{
+    guint i, num_allocated;
+    gboolean ret = TRUE;
+
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool), 0);
+
+    VAAPI_VIDEO_POOL_LOCK(&pool->priv->mutex);
+
+    num_allocated = gst_vaapi_video_pool_get_size(pool) + pool->priv->used_count;
+    if (n < num_allocated)
+        goto end;
+
+    if ((n -= num_allocated) > pool->priv->capacity)
+        n = pool->priv->capacity;
+
+    for (i = num_allocated; i < n; i++) {
+        gpointer const object = gst_vaapi_video_pool_alloc_object(pool);
+        if (!object) {
+            ret = FALSE;
+            goto end;
+        }
+        g_queue_push_tail(&pool->priv->free_objects, object);
+    }
+    ret = TRUE;
+  end:
+    VAAPI_VIDEO_POOL_UNLOCK(&pool->priv->mutex);
+    return ret;
+}
+
+/**
+ * gst_vaapi_video_pool_get_capacity:
+ * @pool: a #GstVaapiVideoPool
+ *
+ * Returns the maximum number of objects in the pool. i.e. the maximum
+ * number of objects that can be returned by gst_vaapi_video_pool_get_object().
+ *
+ * Return value: the capacity of the pool
+ */
+guint
+gst_vaapi_video_pool_get_capacity(GstVaapiVideoPool *pool)
+{
+    guint capacity;
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool), 0);
+    VAAPI_VIDEO_POOL_LOCK(&pool->priv->mutex);
+    capacity = pool->priv->capacity;
+    VAAPI_VIDEO_POOL_UNLOCK(&pool->priv->mutex);
+    return capacity;
+}
+
+/**
+ * gst_vaapi_video_pool_set_capacity:
+ * @pool: a #GstVaapiVideoPool
+ * @capacity: the maximal capacity of the pool
+ *
+ * Sets the maximum number of objects that can be allocated in the pool.
+ */
+void
+gst_vaapi_video_pool_set_capacity(GstVaapiVideoPool *pool, guint capacity)
+{
+    g_return_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool));
+    VAAPI_VIDEO_POOL_LOCK(&pool->priv->mutex);
+    pool->priv->capacity = capacity;
+    VAAPI_VIDEO_POOL_UNLOCK(&pool->priv->mutex);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapivideopool.h b/gst-libs/gst/vaapi/gstvaapivideopool.h
new file mode 100644 (file)
index 0000000..f2fdb5e
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ *  gstvaapivideopool.h - Video object pool abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_VIDEO_POOL_H
+#define GST_VAAPI_VIDEO_POOL_H
+
+#include <glib.h>
+#include <gst/gstcaps.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_VIDEO_POOL \
+    (gst_vaapi_video_pool_get_type())
+
+#define GST_VAAPI_VIDEO_POOL(obj)                               \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_VIDEO_POOL,      \
+                                GstVaapiVideoPool))
+
+#define GST_VAAPI_VIDEO_POOL_CLASS(klass)                       \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_VIDEO_POOL,         \
+                             GstVaapiVideoPoolClass))
+
+#define GST_VAAPI_IS_VIDEO_POOL(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_VIDEO_POOL))
+
+#define GST_VAAPI_IS_VIDEO_POOL_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_VIDEO_POOL))
+
+#define GST_VAAPI_VIDEO_POOL_GET_CLASS(obj)                     \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_VIDEO_POOL,       \
+                               GstVaapiVideoPoolClass))
+
+typedef struct _GstVaapiVideoPool               GstVaapiVideoPool;
+typedef struct _GstVaapiVideoPoolPrivate        GstVaapiVideoPoolPrivate;
+typedef struct _GstVaapiVideoPoolClass          GstVaapiVideoPoolClass;
+
+/**
+ * GstVaapiVideoPool:
+ *
+ * A pool of lazily allocated video objects. e.g. surfaces, images.
+ */
+struct _GstVaapiVideoPool {
+    /*< private >*/
+    GObject parent_instance;
+
+    GstVaapiVideoPoolPrivate *priv;
+};
+
+/**
+ * GstVaapiVideoPoolClass:
+ * @set_caps: virtual function for notifying the subclass of the
+ *   negotiated caps
+ * @alloc_object: virtual function for allocating a video pool object
+ *
+ * A pool base class used to hold video objects. e.g. surfaces, images.
+ */
+struct _GstVaapiVideoPoolClass {
+    /*< private >*/
+    GObjectClass parent_class;
+
+    /*< public >*/
+    void     (*set_caps)    (GstVaapiVideoPool *pool, GstCaps *caps);
+    gpointer (*alloc_object)(GstVaapiVideoPool *pool, GstVaapiDisplay *display);
+};
+
+GType
+gst_vaapi_video_pool_get_type(void) G_GNUC_CONST;
+
+GstVaapiDisplay *
+gst_vaapi_video_pool_get_display(GstVaapiVideoPool *pool);
+
+GstCaps *
+gst_vaapi_video_pool_get_caps(GstVaapiVideoPool *pool);
+
+gpointer
+gst_vaapi_video_pool_get_object(GstVaapiVideoPool *pool);
+
+void
+gst_vaapi_video_pool_put_object(GstVaapiVideoPool *pool, gpointer object);
+
+gboolean
+gst_vaapi_video_pool_add_object(GstVaapiVideoPool *pool, gpointer object);
+
+gboolean
+gst_vaapi_video_pool_add_objects(GstVaapiVideoPool *pool, GPtrArray *objects);
+
+guint
+gst_vaapi_video_pool_get_size(GstVaapiVideoPool *pool);
+
+gboolean
+gst_vaapi_video_pool_reserve(GstVaapiVideoPool *pool, guint n);
+
+guint
+gst_vaapi_video_pool_get_capacity(GstVaapiVideoPool *pool);
+
+void
+gst_vaapi_video_pool_set_capacity(GstVaapiVideoPool *pool, guint capacity);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_VIDEO_POOL_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiwindow.c b/gst-libs/gst/vaapi/gstvaapiwindow.c
new file mode 100644 (file)
index 0000000..56ef8ed
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ *  gstvaapiwindow.c - VA window abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapiwindow
+ * @short_description: VA window abstraction
+ */
+
+#include "sysdeps.h"
+#include "gstvaapiwindow.h"
+#include "gstvaapi_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiWindow, gst_vaapi_window, GST_VAAPI_TYPE_OBJECT);
+
+#define GST_VAAPI_WINDOW_GET_PRIVATE(obj)                       \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_WINDOW,         \
+                                 GstVaapiWindowPrivate))
+
+struct _GstVaapiWindowPrivate {
+    guint               width;
+    guint               height;
+    guint               display_width;
+    guint               display_height;
+    gboolean            is_constructed          : 1;
+    guint               is_fullscreen           : 1;
+    guint               check_geometry          : 1;
+};
+
+enum {
+    PROP_0,
+
+    PROP_WIDTH,
+    PROP_HEIGHT,
+    PROP_FULLSCREEN
+};
+
+static void
+gst_vaapi_window_ensure_size(GstVaapiWindow *window)
+{
+    GstVaapiWindowPrivate * const priv = window->priv;
+    GstVaapiWindowClass * const klass  = GST_VAAPI_WINDOW_GET_CLASS(window);
+
+    if (!priv->check_geometry)
+        return;
+
+    if (klass->get_geometry)
+        klass->get_geometry(window, NULL, NULL, &priv->width, &priv->height);
+
+    priv->check_geometry = FALSE;
+    priv->is_fullscreen  = (priv->width  == priv->display_width &&
+                            priv->height == priv->display_height);
+}
+
+static void
+gst_vaapi_window_destroy(GstVaapiWindow *window)
+{
+    GST_VAAPI_WINDOW_GET_CLASS(window)->destroy(window);
+}
+
+static gboolean
+gst_vaapi_window_create(GstVaapiWindow *window)
+{
+    GstVaapiWindowPrivate * const priv = window->priv;
+    guint width, height;
+
+    width  = priv->width;
+    height = priv->height;
+
+    gst_vaapi_display_get_size(
+        GST_VAAPI_OBJECT_DISPLAY(window),
+        &priv->display_width,
+        &priv->display_height
+    );
+
+    if (!GST_VAAPI_WINDOW_GET_CLASS(window)->create(window, &width, &height))
+        return FALSE;
+
+    if (width != priv->width || height != priv->height) {
+        GST_DEBUG("backend resized window to %ux%u", width, height);
+        priv->width  = width;
+        priv->height = height;
+    }
+    return TRUE;
+}
+
+static void
+gst_vaapi_window_finalize(GObject *object)
+{
+    gst_vaapi_window_destroy(GST_VAAPI_WINDOW(object));
+
+    G_OBJECT_CLASS(gst_vaapi_window_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_window_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiWindow * const window = GST_VAAPI_WINDOW(object);
+
+    switch (prop_id) {
+    case PROP_WIDTH:
+        gst_vaapi_window_set_width(window, g_value_get_uint(value));
+        break;
+    case PROP_HEIGHT:
+        gst_vaapi_window_set_height(window, g_value_get_uint(value));
+        break;
+    case PROP_FULLSCREEN:
+        gst_vaapi_window_set_fullscreen(window, g_value_get_boolean(value));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_window_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiWindow * const window = GST_VAAPI_WINDOW(object);
+
+    switch (prop_id) {
+    case PROP_WIDTH:
+        g_value_set_uint(value, gst_vaapi_window_get_width(window));
+        break;
+    case PROP_HEIGHT:
+        g_value_set_uint(value, gst_vaapi_window_get_height(window));
+        break;
+    case PROP_FULLSCREEN:
+        g_value_set_boolean(value, window->priv->is_fullscreen);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_window_constructed(GObject *object)
+{
+    GstVaapiWindow * const window = GST_VAAPI_WINDOW(object);
+    GObjectClass *parent_class;
+
+    window->priv->is_constructed = gst_vaapi_window_create(window);
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_window_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+}
+
+static void
+gst_vaapi_window_class_init(GstVaapiWindowClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiWindowPrivate));
+
+    object_class->finalize     = gst_vaapi_window_finalize;
+    object_class->set_property = gst_vaapi_window_set_property;
+    object_class->get_property = gst_vaapi_window_get_property;
+    object_class->constructed  = gst_vaapi_window_constructed;
+
+    g_object_class_install_property
+        (object_class,
+         PROP_WIDTH,
+         g_param_spec_uint("width",
+                           "Width",
+                           "The window width",
+                           1, G_MAXUINT32, 1,
+                           G_PARAM_READWRITE));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_HEIGHT,
+         g_param_spec_uint("height",
+                           "height",
+                           "The window height",
+                           1, G_MAXUINT32, 1,
+                           G_PARAM_READWRITE));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_FULLSCREEN,
+         g_param_spec_boolean("fullscreen",
+                              "Fullscreen",
+                              "The fullscreen state of the window",
+                              FALSE,
+                              G_PARAM_READWRITE));
+}
+
+static void
+gst_vaapi_window_init(GstVaapiWindow *window)
+{
+    GstVaapiWindowPrivate *priv = GST_VAAPI_WINDOW_GET_PRIVATE(window);
+
+    window->priv                = priv;
+    priv->width                 = 1;
+    priv->height                = 1;
+    priv->is_constructed        = FALSE;
+    priv->is_fullscreen         = FALSE;
+    priv->check_geometry        = FALSE;
+}
+
+/**
+ * gst_vaapi_window_get_display:
+ * @window: a #GstVaapiWindow
+ *
+ * Returns the #GstVaapiDisplay this @window is bound to.
+ *
+ * Return value: the parent #GstVaapiDisplay object
+ */
+GstVaapiDisplay *
+gst_vaapi_window_get_display(GstVaapiWindow *window)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_WINDOW(window), NULL);
+
+    return GST_VAAPI_OBJECT_DISPLAY(window);
+}
+
+/**
+ * gst_vaapi_window_show:
+ * @window: a #GstVaapiWindow
+ *
+ * Flags a window to be displayed. Any window that is not shown will
+ * not appear on the screen.
+ */
+void
+gst_vaapi_window_show(GstVaapiWindow *window)
+{
+    g_return_if_fail(GST_VAAPI_IS_WINDOW(window));
+    g_return_if_fail(window->priv->is_constructed);
+
+    GST_VAAPI_WINDOW_GET_CLASS(window)->show(window);
+    window->priv->check_geometry = TRUE;
+}
+
+/**
+ * gst_vaapi_window_hide:
+ * @window: a #GstVaapiWindow
+ *
+ * Reverses the effects of gst_vaapi_window_show(), causing the window
+ * to be hidden (invisible to the user).
+ */
+void
+gst_vaapi_window_hide(GstVaapiWindow *window)
+{
+    g_return_if_fail(GST_VAAPI_IS_WINDOW(window));
+    g_return_if_fail(window->priv->is_constructed);
+
+    GST_VAAPI_WINDOW_GET_CLASS(window)->hide(window);
+}
+
+/**
+ * gst_vaapi_window_get_fullscreen:
+ * @window: a #GstVaapiWindow
+ *
+ * Retrieves whether the @window is fullscreen or not
+ *
+ * Return value: %TRUE if the window is fullscreen
+ */
+gboolean
+gst_vaapi_window_get_fullscreen(GstVaapiWindow *window)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_WINDOW(window), FALSE);
+
+    gst_vaapi_window_ensure_size(window);
+
+    return window->priv->is_fullscreen;
+}
+
+/**
+ * gst_vaapi_window_set_fullscreen:
+ * @window: a #GstVaapiWindow
+ * @fullscreen: %TRUE to request window to get fullscreen
+ *
+ * Requests to place the @window in fullscreen or unfullscreen states.
+ */
+void
+gst_vaapi_window_set_fullscreen(GstVaapiWindow *window, gboolean fullscreen)
+{
+    GstVaapiWindowClass *klass;
+
+    g_return_if_fail(GST_VAAPI_IS_WINDOW(window));
+
+    klass = GST_VAAPI_WINDOW_GET_CLASS(window);
+
+    if (window->priv->is_fullscreen != fullscreen &&
+        klass->set_fullscreen && klass->set_fullscreen(window, fullscreen)) {
+        window->priv->is_fullscreen  = fullscreen;
+        window->priv->check_geometry = TRUE;
+    }
+}
+
+/**
+ * gst_vaapi_window_get_width:
+ * @window: a #GstVaapiWindow
+ *
+ * Retrieves the width of a #GstVaapiWindow.
+ *
+ * Return value: the width of the @window, in pixels
+ */
+guint
+gst_vaapi_window_get_width(GstVaapiWindow *window)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_WINDOW(window), 0);
+    g_return_val_if_fail(window->priv->is_constructed, 0);
+
+    gst_vaapi_window_ensure_size(window);
+
+    return window->priv->width;
+}
+
+/**
+ * gst_vaapi_window_get_height:
+ * @window: a #GstVaapiWindow
+ *
+ * Retrieves the height of a #GstVaapiWindow
+ *
+ * Return value: the height of the @window, in pixels
+ */
+guint
+gst_vaapi_window_get_height(GstVaapiWindow *window)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_WINDOW(window), 0);
+    g_return_val_if_fail(window->priv->is_constructed, 0);
+
+    gst_vaapi_window_ensure_size(window);
+
+    return window->priv->height;
+}
+
+/**
+ * gst_vaapi_window_get_size:
+ * @window: a #GstVaapiWindow
+ * @pwidth: return location for the width, or %NULL
+ * @pheight: return location for the height, or %NULL
+ *
+ * Retrieves the dimensions of a #GstVaapiWindow.
+ */
+void
+gst_vaapi_window_get_size(GstVaapiWindow *window, guint *pwidth, guint *pheight)
+{
+    g_return_if_fail(GST_VAAPI_IS_WINDOW(window));
+    g_return_if_fail(window->priv->is_constructed);
+
+    gst_vaapi_window_ensure_size(window);
+
+    if (pwidth)
+        *pwidth = window->priv->width;
+
+    if (pheight)
+        *pheight = window->priv->height;
+}
+
+/**
+ * gst_vaapi_window_set_width:
+ * @window: a #GstVaapiWindow
+ * @width: requested new width for the window, in pixels
+ *
+ * Resizes the @window to match the specified @width.
+ */
+void
+gst_vaapi_window_set_width(GstVaapiWindow *window, guint width)
+{
+    g_return_if_fail(GST_VAAPI_IS_WINDOW(window));
+
+    gst_vaapi_window_set_size(window, width, window->priv->height);
+}
+
+/**
+ * gst_vaapi_window_set_height:
+ * @window: a #GstVaapiWindow
+ * @height: requested new height for the window, in pixels
+ *
+ * Resizes the @window to match the specified @height.
+ */
+void
+gst_vaapi_window_set_height(GstVaapiWindow *window, guint height)
+{
+    g_return_if_fail(GST_VAAPI_IS_WINDOW(window));
+
+    gst_vaapi_window_set_size(window, window->priv->width, height);
+}
+
+/**
+ * gst_vaapi_window_set_size:
+ * @window: a #GstVaapiWindow
+ * @width: requested new width for the window, in pixels
+ * @height: requested new height for the window, in pixels
+ *
+ * Resizes the @window to match the specified @width and @height.
+ */
+void
+gst_vaapi_window_set_size(GstVaapiWindow *window, guint width, guint height)
+{
+    g_return_if_fail(GST_VAAPI_IS_WINDOW(window));
+
+    if (width == window->priv->width && height == window->priv->height)
+        return;
+
+    window->priv->width  = width;
+    window->priv->height = height;
+
+    if (window->priv->is_constructed)
+        GST_VAAPI_WINDOW_GET_CLASS(window)->resize(window, width, height);
+}
+
+static inline void
+get_surface_rect(GstVaapiSurface *surface, GstVaapiRectangle *rect)
+{
+    guint width, height;
+
+    gst_vaapi_surface_get_size(surface, &width, &height);
+    rect->x      = 0;
+    rect->y      = 0;
+    rect->width  = width;
+    rect->height = height;
+}
+
+static inline void
+get_window_rect(GstVaapiWindow *window, GstVaapiRectangle *rect)
+{
+    guint width, height;
+
+    gst_vaapi_window_get_size(window, &width, &height);
+    rect->x      = 0;
+    rect->y      = 0;
+    rect->width  = width;
+    rect->height = height;
+}
+
+/**
+ * gst_vaapi_window_put_surface:
+ * @window: a #GstVaapiWindow
+ * @surface: a #GstVaapiSurface
+ * @src_rect: the sub-rectangle of the source surface to
+ *   extract and process. If %NULL, the entire surface will be used.
+ * @dst_rect: the sub-rectangle of the destination
+ *   window into which the surface is rendered. If %NULL, the entire
+ *   window will be used.
+ * @flags: postprocessing flags. See #GstVaapiSurfaceRenderFlags
+ *
+ * Renders the @surface region specified by @src_rect into the @window
+ * region specified by @dst_rect. The @flags specify how de-interlacing
+ * (if needed), color space conversion, scaling and other postprocessing
+ * transformations are performed.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_window_put_surface(
+    GstVaapiWindow          *window,
+    GstVaapiSurface         *surface,
+    const GstVaapiRectangle *src_rect,
+    const GstVaapiRectangle *dst_rect,
+    guint                    flags
+)
+{
+    GstVaapiWindowClass *klass;
+    GstVaapiRectangle src_rect_default, dst_rect_default;
+
+    g_return_val_if_fail(GST_VAAPI_IS_WINDOW(window), FALSE);
+    g_return_val_if_fail(window->priv->is_constructed, FALSE);
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
+
+    klass = GST_VAAPI_WINDOW_GET_CLASS(window);
+    if (!klass->render)
+        return FALSE;
+
+    if (!src_rect) {
+        src_rect = &src_rect_default;
+        get_surface_rect(surface, &src_rect_default);
+    }
+
+    if (!dst_rect) {
+        dst_rect = &dst_rect_default;
+        get_window_rect(window, &dst_rect_default);
+    }
+
+    return klass->render(window, surface, src_rect, dst_rect, flags);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiwindow.h b/gst-libs/gst/vaapi/gstvaapiwindow.h
new file mode 100644 (file)
index 0000000..5fdaf81
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *  gstvaapiwindow.h - VA window abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_WINDOW_H
+#define GST_VAAPI_WINDOW_H
+
+#include <gst/video/gstvideosink.h>
+#include <gst/vaapi/gstvaapitypes.h>
+#include <gst/vaapi/gstvaapiobject.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapisurface.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_WINDOW \
+    (gst_vaapi_window_get_type())
+
+#define GST_VAAPI_WINDOW(obj)                           \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                  \
+                                GST_VAAPI_TYPE_WINDOW,  \
+                                GstVaapiWindow))
+
+#define GST_VAAPI_WINDOW_CLASS(klass)                   \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                   \
+                             GST_VAAPI_TYPE_WINDOW,     \
+                             GstVaapiWindowClass))
+
+#define GST_VAAPI_IS_WINDOW(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_WINDOW))
+
+#define GST_VAAPI_IS_WINDOW_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_WINDOW))
+
+#define GST_VAAPI_WINDOW_GET_CLASS(obj)                 \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                   \
+                               GST_VAAPI_TYPE_WINDOW,   \
+                               GstVaapiWindowClass))
+
+typedef struct _GstVaapiWindow                  GstVaapiWindow;
+typedef struct _GstVaapiWindowPrivate           GstVaapiWindowPrivate;
+typedef struct _GstVaapiWindowClass             GstVaapiWindowClass;
+
+/**
+ * GstVaapiWindow:
+ *
+ * Base class for system-dependent windows.
+ */
+struct _GstVaapiWindow {
+    /*< private >*/
+    GstVaapiObject parent_instance;
+
+    GstVaapiWindowPrivate *priv;
+};
+
+/**
+ * GstVaapiWindowClass:
+ * @create: virtual function to create a window with width and height
+ * @destroy: virtual function to destroy a window
+ * @show: virtual function to show (map) a window
+ * @hide: virtual function to hide (unmap) a window
+ * @set_fullscreen: virtual function to change window fullscreen state
+ * @resize: virtual function to resize a window
+ * @render: virtual function to render a #GstVaapiSurface into a window
+ *
+ * Base class for system-dependent windows.
+ */
+struct _GstVaapiWindowClass {
+    /*< private >*/
+    GstVaapiObjectClass parent_class;
+
+    /*< public >*/
+    gboolean    (*create) (GstVaapiWindow *window, guint *width, guint *height);
+    void        (*destroy)(GstVaapiWindow *window);
+    gboolean    (*show)   (GstVaapiWindow *window);
+    gboolean    (*hide)   (GstVaapiWindow *window);
+    gboolean    (*get_geometry)  (GstVaapiWindow *window,
+                                  gint *px, gint *py,
+                                  guint *pwidth, guint *pheight);
+    gboolean    (*set_fullscreen)(GstVaapiWindow *window, gboolean fullscreen);
+    gboolean    (*resize) (GstVaapiWindow *window, guint width, guint height);
+    gboolean    (*render) (GstVaapiWindow *window,
+                           GstVaapiSurface *surface,
+                           const GstVaapiRectangle *src_rect,
+                           const GstVaapiRectangle *dst_rect,
+                           guint flags);
+};
+
+GType
+gst_vaapi_window_get_type(void) G_GNUC_CONST;
+
+GstVaapiDisplay *
+gst_vaapi_window_get_display(GstVaapiWindow *window);
+
+void
+gst_vaapi_window_show(GstVaapiWindow *window);
+
+void
+gst_vaapi_window_hide(GstVaapiWindow *window);
+
+gboolean
+gst_vaapi_window_get_fullscreen(GstVaapiWindow *window);
+
+void
+gst_vaapi_window_set_fullscreen(GstVaapiWindow *window, gboolean fullscreen);
+
+guint
+gst_vaapi_window_get_width(GstVaapiWindow *window);
+
+guint
+gst_vaapi_window_get_height(GstVaapiWindow *window);
+
+void
+gst_vaapi_window_get_size(GstVaapiWindow *window, guint *pwidth, guint *pheight);
+
+void
+gst_vaapi_window_set_width(GstVaapiWindow *window, guint width);
+
+void
+gst_vaapi_window_set_height(GstVaapiWindow *window, guint height);
+
+void
+gst_vaapi_window_set_size(GstVaapiWindow *window, guint width, guint height);
+
+gboolean
+gst_vaapi_window_put_surface(
+    GstVaapiWindow          *window,
+    GstVaapiSurface         *surface,
+    const GstVaapiRectangle *src_rect,
+    const GstVaapiRectangle *dst_rect,
+    guint                    flags
+);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_WINDOW_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiwindow_drm.c b/gst-libs/gst/vaapi/gstvaapiwindow_drm.c
new file mode 100644 (file)
index 0000000..6303480
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ *  gstvaapiwindow_drm.c - VA/DRM window abstraction
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapiwindow_drm
+ * @short_description: VA/DRM dummy window abstraction
+ */
+
+#include "sysdeps.h"
+#include "gstvaapiwindow_drm.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiWindowDRM,
+              gst_vaapi_window_drm,
+              GST_VAAPI_TYPE_WINDOW);
+
+static gboolean
+gst_vaapi_window_drm_show(GstVaapiWindow *window)
+{
+    return TRUE;
+}
+
+static gboolean
+gst_vaapi_window_drm_hide(GstVaapiWindow *window)
+{
+    return TRUE;
+}
+
+static gboolean
+gst_vaapi_window_drm_create(
+    GstVaapiWindow *window,
+    guint          *width,
+    guint          *height
+)
+{
+    return TRUE;
+}
+
+static void
+gst_vaapi_window_drm_destroy(GstVaapiWindow * window)
+{
+}
+
+static gboolean
+gst_vaapi_window_drm_resize(
+    GstVaapiWindow * window,
+    guint            width,
+    guint            height
+)
+{
+    return TRUE;
+}
+
+static gboolean
+gst_vaapi_window_drm_render(
+    GstVaapiWindow          *window,
+    GstVaapiSurface         *surface,
+    const GstVaapiRectangle *src_rect,
+    const GstVaapiRectangle *dst_rect,
+    guint                    flags
+)
+{
+    return TRUE;
+}
+
+static void
+gst_vaapi_window_drm_finalize(GObject *object)
+{
+    G_OBJECT_CLASS(gst_vaapi_window_drm_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_window_drm_constructed(GObject *object)
+{
+    GObjectClass *parent_class;
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_window_drm_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+}
+
+static void
+gst_vaapi_window_drm_class_init(GstVaapiWindowDRMClass * klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstVaapiWindowClass * const window_class = GST_VAAPI_WINDOW_CLASS(klass);
+
+    object_class->finalize      = gst_vaapi_window_drm_finalize;
+    object_class->constructed   = gst_vaapi_window_drm_constructed;
+
+    window_class->create        = gst_vaapi_window_drm_create;
+    window_class->destroy       = gst_vaapi_window_drm_destroy;
+    window_class->show          = gst_vaapi_window_drm_show;
+    window_class->hide          = gst_vaapi_window_drm_hide;
+    window_class->render        = gst_vaapi_window_drm_render;
+    window_class->resize        = gst_vaapi_window_drm_resize;
+}
+
+static void
+gst_vaapi_window_drm_init(GstVaapiWindowDRM * window)
+{
+}
+
+/**
+ * gst_vaapi_window_drm_new:
+ * @display: a #GstVaapiDisplay
+ * @width: the requested window width, in pixels (unused)
+ * @height: the requested windo height, in pixels (unused)
+ *
+ * Creates a dummy window. The window will be attached to the @display.
+ * All rendering functions will return success since VA/DRM is a
+ * renderless API.
+ *
+ * Note: this dummy window object is only necessary to fulfill cases
+ * where the client application wants to automatically determine the
+ * best display to use for the current system. As such, it provides
+ * utility functions with the same API (function arguments) to help
+ * implement uniform function tables.
+ *
+ * Return value: the newly allocated #GstVaapiWindow object
+ */
+GstVaapiWindow *
+gst_vaapi_window_drm_new(
+    GstVaapiDisplay *display,
+    guint            width,
+    guint            height
+)
+{
+    GST_DEBUG("new window, size %ux%u", width, height);
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+    g_return_val_if_fail(width  > 0, NULL);
+    g_return_val_if_fail(height > 0, NULL);
+
+    return g_object_new(GST_VAAPI_TYPE_WINDOW_DRM,
+                        "display", display,
+                        "id",      GST_VAAPI_ID(0),
+                        "width",   width,
+                        "height",  height,
+                        NULL);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiwindow_drm.h b/gst-libs/gst/vaapi/gstvaapiwindow_drm.h
new file mode 100644 (file)
index 0000000..47e053a
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ *  gstvaapiwindow_drm.h - VA/DRM window abstraction
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_WINDOW_DRM_H
+#define GST_VAAPI_WINDOW_DRM_H
+
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapiwindow.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_WINDOW_DRM \
+    (gst_vaapi_window_drm_get_type())
+
+#define GST_VAAPI_WINDOW_DRM(obj)                               \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_WINDOW_DRM,      \
+                                GstVaapiWindowDRM))
+
+#define GST_VAAPI_WINDOW_DRM_CLASS(klass)                       \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_WINDOW_DRM,         \
+                             GstVaapiWindowDRMClass))
+
+#define GST_VAAPI_IS_WINDOW_DRM(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_WINDOW_DRM))
+
+#define GST_VAAPI_IS_WINDOW_DRM_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_WINDOW_DRM))
+
+#define GST_VAAPI_WINDOW_DRM_GET_CLASS(obj)                     \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_WINDOW_DRM,       \
+                               GstVaapiWindowDRMClass))
+
+typedef struct _GstVaapiWindowDRM               GstVaapiWindowDRM;
+typedef struct _GstVaapiWindowDRMClass          GstVaapiWindowDRMClass;
+
+/**
+ * GstVaapiWindowDRM:
+ *
+ * A dummy DRM window abstraction.
+ */
+struct _GstVaapiWindowDRM {
+    /*< private >*/
+    GstVaapiWindow parent_instance;
+};
+
+/**
+ * GstVaapiWindowDRMClass:
+ *
+ * A DRM window class.
+ */
+struct _GstVaapiWindowDRMClass {
+    /*< private >*/
+    GstVaapiWindowClass parent_class;
+};
+
+GType
+gst_vaapi_window_drm_get_type(void) G_GNUC_CONST;
+
+GstVaapiWindow *
+gst_vaapi_window_drm_new(GstVaapiDisplay *display, guint width, guint height);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_WINDOW_DRM_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiwindow_glx.c b/gst-libs/gst/vaapi/gstvaapiwindow_glx.c
new file mode 100644 (file)
index 0000000..45c040d
--- /dev/null
@@ -0,0 +1,604 @@
+/*
+ *  gstvaapiwindow_glx.c - VA/GLX window abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapiwindow_glx
+ * @short_description: VA/GLX window abstraction
+ */
+
+#include "sysdeps.h"
+#include "gstvaapiwindow_glx.h"
+#include "gstvaapidisplay_x11.h"
+#include "gstvaapidisplay_x11_priv.h"
+#include "gstvaapiutils_x11.h"
+#include "gstvaapiutils_glx.h"
+#include "gstvaapi_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiWindowGLX,
+              gst_vaapi_window_glx,
+              GST_VAAPI_TYPE_WINDOW_X11);
+
+#define GST_VAAPI_WINDOW_GLX_GET_PRIVATE(obj)                   \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_WINDOW_GLX,     \
+                                 GstVaapiWindowGLXPrivate))
+
+struct _GstVaapiWindowGLXPrivate {
+    Colormap            cmap;
+    GLContextState     *gl_context;
+    guint               is_constructed  : 1;
+    guint               foreign_window  : 1;
+};
+
+enum {
+    PROP_0,
+
+    PROP_GLX_CONTEXT
+};
+
+/* Fill rectangle coords with capped bounds */
+static inline void
+fill_rect(
+    GstVaapiRectangle       *dst_rect,
+    const GstVaapiRectangle *src_rect,
+    guint                    width,
+    guint                    height
+)
+{
+    if (src_rect) {
+        dst_rect->x = src_rect->x > 0 ? src_rect->x : 0;
+        dst_rect->y = src_rect->y > 0 ? src_rect->y : 0;
+        if (src_rect->x + src_rect->width < width)
+            dst_rect->width = src_rect->width;
+        else
+            dst_rect->width = width - dst_rect->x;
+        if (src_rect->y + src_rect->height < height)
+            dst_rect->height = src_rect->height;
+        else
+            dst_rect->height = height - dst_rect->y;
+    }
+    else {
+        dst_rect->x      = 0;
+        dst_rect->y      = 0;
+        dst_rect->width  = width;
+        dst_rect->height = height;
+    }
+}
+
+static void
+_gst_vaapi_window_glx_destroy_context(GstVaapiWindowGLX *window)
+{
+    GstVaapiWindowGLXPrivate * const priv = window->priv;
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+    if (priv->gl_context) {
+        gl_destroy_context(priv->gl_context);
+        priv->gl_context = NULL;
+    }
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+}
+
+static gboolean
+_gst_vaapi_window_glx_create_context(
+    GstVaapiWindowGLX *window,
+    GLXContext         foreign_context
+)
+{
+    GstVaapiWindowGLXPrivate * const priv = window->priv;
+    Display * const                  dpy  = GST_VAAPI_OBJECT_XDISPLAY(window);
+    GLContextState                   parent_cs;
+
+    parent_cs.display = dpy;
+    parent_cs.window  = None;
+    parent_cs.context = foreign_context;
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+    priv->gl_context = gl_create_context(
+        dpy,
+        GST_VAAPI_OBJECT_XSCREEN(window),
+        &parent_cs
+    );
+    if (!priv->gl_context) {
+        GST_DEBUG("could not create GLX context");
+        goto end;
+    }
+
+    if (!glXIsDirect(dpy, priv->gl_context->context)) {
+        GST_DEBUG("could not create a direct-rendering GLX context");
+        goto out_destroy_context;
+    }
+    goto end;
+
+out_destroy_context:
+    gl_destroy_context(priv->gl_context);
+    priv->gl_context = NULL;
+end:
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+    return priv->gl_context != NULL;
+}
+
+static gboolean
+_gst_vaapi_window_glx_ensure_context(
+    GstVaapiWindowGLX *window,
+    GLXContext         foreign_context
+)
+{
+    GstVaapiWindowGLXPrivate * const priv = window->priv;
+
+    if (priv->gl_context) {
+        if (!foreign_context || foreign_context == priv->gl_context->context)
+            return TRUE;
+        _gst_vaapi_window_glx_destroy_context(window);
+    }
+    return _gst_vaapi_window_glx_create_context(window, foreign_context);
+}
+
+static gboolean
+gst_vaapi_window_glx_ensure_context(
+    GstVaapiWindowGLX *window,
+    GLXContext         foreign_context
+)
+{
+    GstVaapiWindowGLXPrivate * const priv = window->priv;
+    GLContextState old_cs;
+    guint width, height;
+
+    if (!_gst_vaapi_window_glx_ensure_context(window, foreign_context))
+        return FALSE;
+
+    priv->gl_context->window = GST_VAAPI_OBJECT_ID(window);
+    if (!gl_set_current_context(priv->gl_context, &old_cs)) {
+        GST_DEBUG("could not make newly created GLX context current");
+        return FALSE;
+    }
+
+    glDisable(GL_DEPTH_TEST);
+    glDepthMask(GL_FALSE);
+    glDisable(GL_CULL_FACE);
+    glDrawBuffer(GL_BACK);
+    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+    gst_vaapi_window_get_size(GST_VAAPI_WINDOW(window), &width, &height);
+    gl_resize(width, height);
+
+    gl_set_bgcolor(0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    gl_set_current_context(&old_cs, NULL);
+    return TRUE;
+}
+
+static Visual *
+gst_vaapi_window_glx_get_visual(GstVaapiWindow *window)
+{
+    GstVaapiWindowGLX * const glx_window = GST_VAAPI_WINDOW_GLX(window);
+
+    if (!_gst_vaapi_window_glx_ensure_context(glx_window, NULL))
+        return NULL;
+    return glx_window->priv->gl_context->visual->visual;
+}
+
+static void
+gst_vaapi_window_glx_destroy_colormap(GstVaapiWindowGLX *window)
+{
+    GstVaapiWindowGLXPrivate * const priv = window->priv;
+    Display * const                  dpy  = GST_VAAPI_OBJECT_XDISPLAY(window);
+
+    if (priv->cmap) {
+        if (!priv->foreign_window) {
+            GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+            XFreeColormap(dpy, priv->cmap);
+            GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+        }
+        priv->cmap = None;
+    }
+}
+
+static Colormap
+gst_vaapi_window_glx_create_colormap(GstVaapiWindowGLX *window)
+{
+    GstVaapiWindowGLXPrivate * const priv = window->priv;
+    Display * const                  dpy  = GST_VAAPI_OBJECT_XDISPLAY(window);
+    int                              screen;
+    XWindowAttributes                wattr;
+    gboolean                         success = FALSE;
+
+    if (!priv->cmap) {
+        if (!priv->foreign_window) {
+            if (!_gst_vaapi_window_glx_ensure_context(window, NULL))
+                return None;
+            GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+            x11_trap_errors();
+            /* XXX: add a GstVaapiDisplayX11:x11-screen property? */
+            screen     = GST_VAAPI_OBJECT_XSCREEN(window);
+            priv->cmap = XCreateColormap(
+                dpy,
+                RootWindow(dpy, screen),
+                priv->gl_context->visual->visual,
+                AllocNone
+            );
+            success = x11_untrap_errors() == 0;
+            GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+        }
+        else {
+            GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+            x11_trap_errors();
+            XGetWindowAttributes(dpy, GST_VAAPI_OBJECT_ID(window), &wattr);
+            priv->cmap = wattr.colormap;
+            success = x11_untrap_errors() == 0;
+            GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+        }
+        if (!success)
+            return None;
+    }
+    return priv->cmap;
+}
+
+static Colormap
+gst_vaapi_window_glx_get_colormap(GstVaapiWindow *window)
+{
+    return gst_vaapi_window_glx_create_colormap(GST_VAAPI_WINDOW_GLX(window));
+}
+
+static gboolean
+gst_vaapi_window_glx_resize(GstVaapiWindow *window, guint width, guint height)
+{
+    GstVaapiWindowGLXPrivate * const priv = GST_VAAPI_WINDOW_GLX(window)->priv;
+    Display * const                  dpy  = GST_VAAPI_OBJECT_XDISPLAY(window);
+    GLContextState                   old_cs;
+
+    if (!GST_VAAPI_WINDOW_CLASS(gst_vaapi_window_glx_parent_class)->
+        resize(window, width, height))
+        return FALSE;
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+    XSync(dpy, False); /* make sure resize completed */
+    if (gl_set_current_context(priv->gl_context, &old_cs)) {
+        gl_resize(width, height);
+        gl_set_current_context(&old_cs, NULL);
+    }
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+    return TRUE;
+}
+
+static void
+gst_vaapi_window_glx_finalize(GObject *object)
+{
+    GstVaapiWindowGLX * const window = GST_VAAPI_WINDOW_GLX(object);
+
+    _gst_vaapi_window_glx_destroy_context(window);
+    gst_vaapi_window_glx_destroy_colormap(window);
+
+    G_OBJECT_CLASS(gst_vaapi_window_glx_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_window_glx_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiWindowGLX * const window = GST_VAAPI_WINDOW_GLX(object);
+
+    switch (prop_id) {
+    case PROP_GLX_CONTEXT:
+        gst_vaapi_window_glx_set_context(window, g_value_get_pointer(value));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_window_glx_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiWindowGLX * const window = GST_VAAPI_WINDOW_GLX(object);
+
+    switch (prop_id) {
+    case PROP_GLX_CONTEXT:
+        g_value_set_pointer(value, gst_vaapi_window_glx_get_context(window));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_window_glx_constructed(GObject *object)
+{
+    GstVaapiWindowGLXPrivate * const priv = GST_VAAPI_WINDOW_GLX(object)->priv;
+    GObjectClass *parent_class;
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_window_glx_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+
+    priv->foreign_window =
+        gst_vaapi_window_x11_is_foreign_xid(GST_VAAPI_WINDOW_X11(object));
+
+    priv->is_constructed =
+        gst_vaapi_window_glx_ensure_context(GST_VAAPI_WINDOW_GLX(object), NULL);
+}
+
+static void
+gst_vaapi_window_glx_class_init(GstVaapiWindowGLXClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstVaapiWindowClass * const win_class = GST_VAAPI_WINDOW_CLASS(klass);
+    GstVaapiWindowX11Class * const xwin_class = GST_VAAPI_WINDOW_X11_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiWindowGLXPrivate));
+
+    object_class->finalize      = gst_vaapi_window_glx_finalize;
+    object_class->set_property  = gst_vaapi_window_glx_set_property;
+    object_class->get_property  = gst_vaapi_window_glx_get_property;
+    object_class->constructed   = gst_vaapi_window_glx_constructed;
+
+    win_class->resize           = gst_vaapi_window_glx_resize;
+    xwin_class->get_visual      = gst_vaapi_window_glx_get_visual;
+    xwin_class->get_colormap    = gst_vaapi_window_glx_get_colormap;
+
+    /**
+     * GstVaapiDisplayGLX:glx-context:
+     *
+     * The GLX context that was created by gst_vaapi_window_glx_new()
+     * or that was bound from gst_vaapi_window_glx_set_context().
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_GLX_CONTEXT,
+         g_param_spec_pointer("glx-context",
+                              "GLX context",
+                              "GLX context",
+                              G_PARAM_READWRITE));
+}
+
+static void
+gst_vaapi_window_glx_init(GstVaapiWindowGLX *window)
+{
+    GstVaapiWindowGLXPrivate *priv = GST_VAAPI_WINDOW_GLX_GET_PRIVATE(window);
+
+    window->priv                = priv;
+    priv->cmap                  = None;
+    priv->gl_context            = NULL;
+    priv->is_constructed        = FALSE;
+    priv->foreign_window        = FALSE;
+}
+
+/**
+ * gst_vaapi_window_glx_new:
+ * @display: a #GstVaapiDisplay
+ * @width: the requested window width, in pixels
+ * @height: the requested windo height, in pixels
+ *
+ * Creates a window with the specified @width and @height. The window
+ * will be attached to the @display and remains invisible to the user
+ * until gst_vaapi_window_show() is called.
+ *
+ * Return value: the newly allocated #GstVaapiWindow object
+ */
+GstVaapiWindow *
+gst_vaapi_window_glx_new(GstVaapiDisplay *display, guint width, guint height)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+    g_return_val_if_fail(width  > 0, NULL);
+    g_return_val_if_fail(height > 0, NULL);
+
+    return g_object_new(GST_VAAPI_TYPE_WINDOW_GLX,
+                        "display", display,
+                        "id",      GST_VAAPI_ID(None),
+                        "width",   width,
+                        "height",  height,
+                        NULL);
+}
+
+/**
+ * gst_vaapi_window_glx_new_with_xid:
+ * @display: a #GstVaapiDisplay
+ * @xid: an X11 #Window id
+ *
+ * Creates a #GstVaapiWindow using the X11 #Window @xid. The caller
+ * still owns the window and must call XDestroyWindow() when all
+ * #GstVaapiWindow references are released. Doing so too early can
+ * yield undefined behaviour.
+ *
+ * Return value: the newly allocated #GstVaapiWindow object
+ */
+GstVaapiWindow *
+gst_vaapi_window_glx_new_with_xid(GstVaapiDisplay *display, Window xid)
+{
+    GST_DEBUG("new window from xid 0x%08x", xid);
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+    g_return_val_if_fail(xid != None, NULL);
+
+    return g_object_new(GST_VAAPI_TYPE_WINDOW_GLX,
+                        "display", display,
+                        "id",      GST_VAAPI_ID(xid),
+                        NULL);
+}
+
+/**
+ * gst_vaapi_window_glx_get_context:
+ * @window: a #GstVaapiWindowGLX
+ *
+ * Returns the #GLXContext bound to the @window.
+ *
+ * Return value: the #GLXContext bound to the @window
+ */
+GLXContext
+gst_vaapi_window_glx_get_context(GstVaapiWindowGLX *window)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_WINDOW_GLX(window), NULL);
+    g_return_val_if_fail(window->priv->is_constructed, FALSE);
+
+    return window->priv->gl_context->context;
+}
+
+/**
+ * gst_vaapi_window_glx_set_context:
+ * @window: a #GstVaapiWindowGLX
+ * @ctx: a GLX context
+ *
+ * Binds GLX context @ctx to @window. If @ctx is non %NULL, the caller
+ * is responsible to making sure it has compatible visual with that of
+ * the underlying X window. If @ctx is %NULL, a new context is created
+ * and the @window owns it.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_window_glx_set_context(GstVaapiWindowGLX *window, GLXContext ctx)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_WINDOW_GLX(window), FALSE);
+    g_return_val_if_fail(window->priv->is_constructed, FALSE);
+
+    return gst_vaapi_window_glx_ensure_context(window, ctx);
+}
+
+/**
+ * gst_vaapi_window_glx_make_current:
+ * @window: a #GstVaapiWindowGLX
+ *
+ * Makes the @window GLX context the current GLX rendering context of
+ * the calling thread, replacing the previously current context if
+ * there was one.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_window_glx_make_current(GstVaapiWindowGLX *window)
+{
+    gboolean success;
+
+    g_return_val_if_fail(GST_VAAPI_IS_WINDOW_GLX(window), FALSE);
+    g_return_val_if_fail(window->priv->is_constructed, FALSE);
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+    success = gl_set_current_context(window->priv->gl_context, NULL);
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+    return success;
+}
+
+/**
+ * gst_vaapi_window_glx_swap_buffers:
+ * @window: a #GstVaapiWindowGLX
+ *
+ * Promotes the contents of the back buffer of @window to become the
+ * contents of the front buffer of @window. This simply is wrapper
+ * around glXSwapBuffers().
+ */
+void
+gst_vaapi_window_glx_swap_buffers(GstVaapiWindowGLX *window)
+{
+    g_return_if_fail(GST_VAAPI_IS_WINDOW_GLX(window));
+    g_return_if_fail(window->priv->is_constructed);
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+    gl_swap_buffers(window->priv->gl_context);
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+}
+
+/**
+ * gst_vaapi_window_glx_put_texture:
+ * @window: a #GstVaapiWindowGLX
+ * @texture: a #GstVaapiTexture
+ * @src_rect: the sub-rectangle of the source texture to
+ *   extract and process. If %NULL, the entire texture will be used.
+ * @dst_rect: the sub-rectangle of the destination
+ *   window into which the texture is rendered. If %NULL, the entire
+ *   window will be used.
+ *
+ * Renders the @texture region specified by @src_rect into the @window
+ * region specified by @dst_rect.
+ *
+ * NOTE: only GL_TEXTURE_2D textures are supported at this time.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_window_glx_put_texture(
+    GstVaapiWindowGLX       *window,
+    GstVaapiTexture         *texture,
+    const GstVaapiRectangle *src_rect,
+    const GstVaapiRectangle *dst_rect
+)
+{
+    GstVaapiRectangle tmp_src_rect, tmp_dst_rect;
+    GLTextureState ts;
+    GLenum tex_target;
+    GLuint tex_id;
+    guint tex_width, tex_height;
+    guint win_width, win_height;
+
+    g_return_val_if_fail(GST_VAAPI_IS_WINDOW_GLX(window), FALSE);
+    g_return_val_if_fail(GST_VAAPI_IS_TEXTURE(texture), FALSE);
+
+    gst_vaapi_texture_get_size(texture, &tex_width, &tex_height);
+    fill_rect(&tmp_src_rect, src_rect, tex_width, tex_height);
+    src_rect = &tmp_src_rect;
+
+    gst_vaapi_window_get_size(GST_VAAPI_WINDOW(window), &win_width, &win_height);
+    fill_rect(&tmp_dst_rect, dst_rect, win_width, win_height);
+    dst_rect = &tmp_dst_rect;
+
+    /* XXX: only GL_TEXTURE_2D textures are supported at this time */
+    tex_target = gst_vaapi_texture_get_target(texture);
+    if (tex_target != GL_TEXTURE_2D)
+        return FALSE;
+
+    tex_id = gst_vaapi_texture_get_id(texture);
+    if (!gl_bind_texture(&ts, tex_target, tex_id))
+        return FALSE;
+    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+    glPushMatrix();
+    glTranslatef((GLfloat)dst_rect->x, (GLfloat)dst_rect->y, 0.0f);
+    glBegin(GL_QUADS);
+    {
+        const float tx1 = (float)src_rect->x / tex_width;
+        const float tx2 = (float)(src_rect->x + src_rect->width) / tex_width;
+        const float ty1 = (float)src_rect->y / tex_height;
+        const float ty2 = (float)(src_rect->y + src_rect->height) / tex_height;
+        const guint w   = dst_rect->width;
+        const guint h   = dst_rect->height;
+        glTexCoord2f(tx1, ty1); glVertex2i(0, 0);
+        glTexCoord2f(tx1, ty2); glVertex2i(0, h);
+        glTexCoord2f(tx2, ty2); glVertex2i(w, h);
+        glTexCoord2f(tx2, ty1); glVertex2i(w, 0);
+    }
+    glEnd();
+    glPopMatrix();
+    gl_unbind_texture(&ts);
+    return TRUE;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiwindow_glx.h b/gst-libs/gst/vaapi/gstvaapiwindow_glx.h
new file mode 100644 (file)
index 0000000..5547355
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ *  gstvaapiwindow_glx.h - VA/GLX window abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_WINDOW_GLX_H
+#define GST_VAAPI_WINDOW_GLX_H
+
+#include <GL/glx.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapiwindow_x11.h>
+#include <gst/vaapi/gstvaapitexture.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_WINDOW_GLX \
+    (gst_vaapi_window_glx_get_type())
+
+#define GST_VAAPI_WINDOW_GLX(obj)                               \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_WINDOW_GLX,      \
+                                GstVaapiWindowGLX))
+
+#define GST_VAAPI_WINDOW_GLX_CLASS(klass)                       \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_WINDOW_GLX,         \
+                             GstVaapiWindowGLXClass))
+
+#define GST_VAAPI_IS_WINDOW_GLX(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_WINDOW_GLX))
+
+#define GST_VAAPI_IS_WINDOW_GLX_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_WINDOW_GLX))
+
+#define GST_VAAPI_WINDOW_GLX_GET_CLASS(obj)                     \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_WINDOW_GLX,       \
+                               GstVaapiWindowGLXClass))
+
+typedef struct _GstVaapiWindowGLX               GstVaapiWindowGLX;
+typedef struct _GstVaapiWindowGLXPrivate        GstVaapiWindowGLXPrivate;
+typedef struct _GstVaapiWindowGLXClass          GstVaapiWindowGLXClass;
+
+/**
+ * GstVaapiWindowGLX:
+ *
+ * An X11 #Window suitable for GLX rendering.
+ */
+struct _GstVaapiWindowGLX {
+    /*< private >*/
+    GstVaapiWindowX11 parent_instance;
+
+    GstVaapiWindowGLXPrivate *priv;
+};
+
+/**
+ * GstVaapiWindowGLXClass:
+ *
+ * An X11 #Window suitable for GLX rendering.
+ */
+struct _GstVaapiWindowGLXClass {
+    /*< private >*/
+    GstVaapiWindowX11Class parent_class;
+};
+
+GType
+gst_vaapi_window_glx_get_type(void) G_GNUC_CONST;
+
+GstVaapiWindow *
+gst_vaapi_window_glx_new(GstVaapiDisplay *display, guint width, guint height);
+
+GstVaapiWindow *
+gst_vaapi_window_glx_new_with_xid(GstVaapiDisplay *display, Window xid);
+
+GLXContext
+gst_vaapi_window_glx_get_context(GstVaapiWindowGLX *window);
+
+gboolean
+gst_vaapi_window_glx_set_context(GstVaapiWindowGLX *window, GLXContext ctx);
+
+gboolean
+gst_vaapi_window_glx_make_current(GstVaapiWindowGLX *window);
+
+void
+gst_vaapi_window_glx_swap_buffers(GstVaapiWindowGLX *window);
+
+gboolean
+gst_vaapi_window_glx_put_texture(
+    GstVaapiWindowGLX       *window,
+    GstVaapiTexture         *texture,
+    const GstVaapiRectangle *src_rect,
+    const GstVaapiRectangle *dst_rect
+);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_WINDOW_GLX_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiwindow_wayland.c b/gst-libs/gst/vaapi/gstvaapiwindow_wayland.c
new file mode 100644 (file)
index 0000000..5925fe4
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ *  gstvaapiwindow_wayland.c - VA/Wayland window abstraction
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapiwindow_wayland
+ * @short_description: VA/Wayland window abstraction
+ */
+
+#include "sysdeps.h"
+#include <string.h>
+#include "gstvaapicompat.h"
+#include "gstvaapiwindow_wayland.h"
+#include "gstvaapidisplay_wayland.h"
+#include "gstvaapidisplay_wayland_priv.h"
+#include "gstvaapiutils.h"
+#include "gstvaapi_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiWindowWayland,
+              gst_vaapi_window_wayland,
+              GST_VAAPI_TYPE_WINDOW);
+
+#define GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE(obj)               \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_WINDOW_WAYLAND, \
+                                 GstVaapiWindowWaylandPrivate))
+
+struct _GstVaapiWindowWaylandPrivate {
+    struct wl_shell_surface    *shell_surface;
+    struct wl_surface          *surface;
+    struct wl_buffer           *buffer;
+    guint                       redraw_pending  : 1;
+};
+
+static gboolean
+gst_vaapi_window_wayland_show(GstVaapiWindow *window)
+{
+    GST_WARNING("unimplemented GstVaapiWindowWayland::show()");
+
+    return TRUE;
+}
+
+static gboolean
+gst_vaapi_window_wayland_hide(GstVaapiWindow *window)
+{
+    GST_WARNING("unimplemented GstVaapiWindowWayland::hide()");
+
+    return TRUE;
+}
+
+static void
+handle_ping(void *data, struct wl_shell_surface *shell_surface,
+            uint32_t serial)
+{
+    wl_shell_surface_pong(shell_surface, serial);
+}
+
+static void
+handle_configure(void *data, struct wl_shell_surface *shell_surface,
+                 uint32_t edges, int32_t width, int32_t height)
+{
+}
+
+static void
+handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
+{
+}
+
+static const struct wl_shell_surface_listener shell_surface_listener = {
+    handle_ping,
+    handle_configure,
+    handle_popup_done
+};
+
+static gboolean
+gst_vaapi_window_wayland_create(
+    GstVaapiWindow *window,
+    guint          *width,
+    guint          *height
+)
+{
+    GstVaapiWindowWaylandPrivate * const priv =
+        GST_VAAPI_WINDOW_WAYLAND(window)->priv;
+    GstVaapiDisplayWaylandPrivate * const priv_display =
+        GST_VAAPI_OBJECT_DISPLAY_WAYLAND(window)->priv;
+
+    GST_DEBUG("create window, size %ux%u", *width, *height);
+
+    g_return_val_if_fail(priv_display->compositor != NULL, FALSE);
+    g_return_val_if_fail(priv_display->shell != NULL, FALSE);
+
+    priv->surface = wl_compositor_create_surface(priv_display->compositor);
+    if (!priv->surface)
+        return FALSE;
+
+    priv->shell_surface =
+        wl_shell_get_shell_surface(priv_display->shell, priv->surface);
+    if (!priv->shell_surface)
+        return FALSE;
+
+    wl_shell_surface_add_listener(priv->shell_surface,
+                                  &shell_surface_listener, priv);
+    wl_shell_surface_set_toplevel(priv->shell_surface);
+    wl_shell_surface_set_fullscreen(
+        priv->shell_surface,
+        WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE,
+        0,
+        NULL
+    );
+
+    priv->redraw_pending = FALSE;
+    return TRUE;
+}
+
+static void
+gst_vaapi_window_wayland_destroy(GstVaapiWindow * window)
+{
+    GstVaapiWindowWaylandPrivate * const priv =
+        GST_VAAPI_WINDOW_WAYLAND(window)->priv;
+
+    if (priv->shell_surface) {
+       wl_shell_surface_destroy(priv->shell_surface);
+        priv->shell_surface = NULL;
+    }
+
+    if (priv->surface) {
+        wl_surface_destroy(priv->surface);
+        priv->surface = NULL;
+    }
+
+    if (priv->buffer) {
+       wl_buffer_destroy(priv->buffer);
+        priv->buffer = NULL;
+    }
+}
+
+static gboolean
+gst_vaapi_window_wayland_resize(
+    GstVaapiWindow * window,
+    guint            width,
+    guint            height
+)
+{
+    GST_DEBUG("resize window, new size %ux%u", width, height);
+    return TRUE;
+}
+
+static void
+frame_redraw_callback(void *data, struct wl_callback *callback, uint32_t time)
+{
+    GstVaapiWindowWaylandPrivate * const priv = data;
+
+    priv->redraw_pending = FALSE;
+    wl_buffer_destroy(priv->buffer);
+    priv->buffer = NULL;
+    wl_callback_destroy(callback);
+}
+
+static const struct wl_callback_listener frame_callback_listener = {
+    frame_redraw_callback
+};
+
+static gboolean
+gst_vaapi_window_wayland_render(
+    GstVaapiWindow          *window,
+    GstVaapiSurface         *surface,
+    const GstVaapiRectangle *src_rect,
+    const GstVaapiRectangle *dst_rect,
+    guint                    flags
+)
+{
+    GstVaapiWindowWaylandPrivate * const priv =
+        GST_VAAPI_WINDOW_WAYLAND(window)->priv;
+    GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(window);
+    struct wl_display * const wl_display = GST_VAAPI_OBJECT_WL_DISPLAY(window);
+    struct wl_buffer *buffer;
+    struct wl_callback *callback;
+    guint width, height, va_flags;
+    VASurfaceID surface_id;
+    VAStatus status;
+
+    /* XXX: use VPP to support unusual source and destination rectangles */
+    gst_vaapi_surface_get_size(surface, &width, &height);
+    if (src_rect->x      != 0     ||
+        src_rect->y      != 0     ||
+        src_rect->width  != width ||
+        src_rect->height != height) {
+        GST_ERROR("unsupported source rectangle for rendering");
+        return FALSE;
+    }
+
+    if (0 && (dst_rect->width != width || dst_rect->height != height)) {
+        GST_ERROR("unsupported target rectangle for rendering");
+        return FALSE;
+    }
+
+    surface_id = GST_VAAPI_OBJECT_ID(surface);
+    if (surface_id == VA_INVALID_ID)
+        return FALSE;
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+
+    /* Wait for the previous frame to complete redraw */
+    if (priv->redraw_pending) 
+       wl_display_iterate(wl_display, WL_DISPLAY_READABLE);
+
+    /* XXX: use VA/VPP for other filters */
+    va_flags = from_GstVaapiSurfaceRenderFlags(flags);
+    status = vaGetSurfaceBufferWl(
+        GST_VAAPI_DISPLAY_VADISPLAY(display),
+        surface_id,
+        va_flags & (VA_TOP_FIELD|VA_BOTTOM_FIELD),
+        &buffer
+    );
+    if (status == VA_STATUS_ERROR_FLAG_NOT_SUPPORTED) {
+        /* XXX: de-interlacing flags not supported, try with VPP? */
+        status = vaGetSurfaceBufferWl(
+            GST_VAAPI_DISPLAY_VADISPLAY(display),
+            surface_id,
+            VA_FRAME_PICTURE,
+            &buffer
+        );
+    }
+    if (!vaapi_check_status(status, "vaGetSurfaceBufferWl()"))
+        return FALSE;
+
+    /* XXX: attach to the specified target rectangle */
+    wl_surface_attach(priv->surface, buffer, 0, 0);
+    wl_surface_damage(priv->surface, 0, 0, width, height);
+
+    wl_display_iterate(wl_display, WL_DISPLAY_WRITABLE);
+    priv->redraw_pending = TRUE;
+    priv->buffer = buffer;
+
+    callback = wl_surface_frame(priv->surface);
+    wl_callback_add_listener(callback, &frame_callback_listener, priv);
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+    return TRUE;
+}
+
+static void
+gst_vaapi_window_wayland_finalize(GObject *object)
+{
+    G_OBJECT_CLASS(gst_vaapi_window_wayland_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_window_wayland_constructed(GObject *object)
+{
+    GObjectClass *parent_class;
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_window_wayland_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+}
+
+static void
+gst_vaapi_window_wayland_class_init(GstVaapiWindowWaylandClass * klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstVaapiWindowClass * const window_class = GST_VAAPI_WINDOW_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiWindowWaylandPrivate));
+
+    object_class->finalize      = gst_vaapi_window_wayland_finalize;
+    object_class->constructed   = gst_vaapi_window_wayland_constructed;
+
+    window_class->create        = gst_vaapi_window_wayland_create;
+    window_class->destroy       = gst_vaapi_window_wayland_destroy;
+    window_class->show          = gst_vaapi_window_wayland_show;
+    window_class->hide          = gst_vaapi_window_wayland_hide;
+    window_class->render        = gst_vaapi_window_wayland_render;
+    window_class->resize        = gst_vaapi_window_wayland_resize;
+}
+
+static void
+gst_vaapi_window_wayland_init(GstVaapiWindowWayland * window)
+{
+    GstVaapiWindowWaylandPrivate *priv =
+        GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE(window);
+
+    window->priv         = priv;
+    priv->shell_surface  = NULL;
+    priv->surface        = NULL;
+    priv->buffer         = NULL;
+    priv->redraw_pending = FALSE;
+}
+
+/**
+ * gst_vaapi_window_wayland_new:
+ * @display: a #GstVaapiDisplay
+ * @width: the requested window width, in pixels
+ * @height: the requested windo height, in pixels
+ *
+ * Creates a window with the specified @width and @height. The window
+ * will be attached to the @display and remains invisible to the user
+ * until gst_vaapi_window_show() is called.
+ *
+ * Return value: the newly allocated #GstVaapiWindow object
+ */
+GstVaapiWindow *
+gst_vaapi_window_wayland_new(
+    GstVaapiDisplay *display,
+    guint            width,
+    guint            height
+)
+{
+    GST_DEBUG("new window, size %ux%u", width, height);
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+    g_return_val_if_fail(width  > 0, NULL);
+    g_return_val_if_fail(height > 0, NULL);
+
+    return g_object_new(GST_VAAPI_TYPE_WINDOW_WAYLAND,
+                        "display", display,
+                        "id",      GST_VAAPI_ID(0),
+                        "width",   width,
+                        "height",  height,
+                        NULL);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiwindow_wayland.h b/gst-libs/gst/vaapi/gstvaapiwindow_wayland.h
new file mode 100644 (file)
index 0000000..d711fb7
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ *  gstvaapiwindow_wayland.h - VA/Wayland window abstraction
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_WINDOW_WAYLAND_H
+#define GST_VAAPI_WINDOW_WAYLAND_H
+
+#include <wayland-client.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapiwindow.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_WINDOW_WAYLAND \
+    (gst_vaapi_window_wayland_get_type())
+
+#define GST_VAAPI_WINDOW_WAYLAND(obj)                           \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_WINDOW_WAYLAND,  \
+                                GstVaapiWindowWayland))
+
+#define GST_VAAPI_WINDOW_WAYLAND_CLASS(klass)                   \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_WINDOW_WAYLAND,     \
+                             GstVaapiWindowWaylandClass))
+
+#define GST_VAAPI_IS_WINDOW_WAYLAND(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_WINDOW_WAYLAND))
+
+#define GST_VAAPI_IS_WINDOW_WAYLAND_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_WINDOW_WAYLAND))
+
+#define GST_VAAPI_WINDOW_WAYLAND_GET_CLASS(obj)                 \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_WINDOW_WAYLAND,   \
+                               GstVaapiWindowWaylandClass))
+
+typedef struct _GstVaapiWindowWayland           GstVaapiWindowWayland;
+typedef struct _GstVaapiWindowWaylandPrivate    GstVaapiWindowWaylandPrivate;
+typedef struct _GstVaapiWindowWaylandClass      GstVaapiWindowWaylandClass;
+
+/**
+ * GstVaapiWindowWayland:
+ *
+ * A Wayland window abstraction.
+ */
+struct _GstVaapiWindowWayland {
+    /*< private >*/
+    GstVaapiWindow parent_instance;
+
+    GstVaapiWindowWaylandPrivate *priv;
+};
+
+/**
+ * GstVaapiWindowWaylandClass:
+ *
+ * An Wayland #Window wrapper class.
+ */
+struct _GstVaapiWindowWaylandClass {
+    /*< private >*/
+    GstVaapiWindowClass parent_class;
+};
+
+GType
+gst_vaapi_window_wayland_get_type(void) G_GNUC_CONST;
+
+GstVaapiWindow *
+gst_vaapi_window_wayland_new(GstVaapiDisplay *display, guint width, guint height);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_WINDOW_WAYLAND_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiwindow_x11.c b/gst-libs/gst/vaapi/gstvaapiwindow_x11.c
new file mode 100644 (file)
index 0000000..a936813
--- /dev/null
@@ -0,0 +1,625 @@
+/*
+ *  gstvaapiwindow_x11.c - VA/X11 window abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapiwindow_x11
+ * @short_description: VA/X11 window abstraction
+ */
+
+#include "sysdeps.h"
+#include <string.h>
+#include <X11/Xatom.h>
+#include "gstvaapicompat.h"
+#include "gstvaapiwindow_x11.h"
+#include "gstvaapidisplay_x11.h"
+#include "gstvaapidisplay_x11_priv.h"
+#include "gstvaapiutils.h"
+#include "gstvaapiutils_x11.h"
+#include "gstvaapi_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiWindowX11, gst_vaapi_window_x11, GST_VAAPI_TYPE_WINDOW);
+
+#define GST_VAAPI_WINDOW_X11_GET_PRIVATE(obj)                   \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_WINDOW_X11,     \
+                                 GstVaapiWindowX11Private))
+
+struct _GstVaapiWindowX11Private {
+    Atom                atom_NET_WM_STATE;
+    Atom                atom_NET_WM_STATE_FULLSCREEN;
+    guint               create_window           : 1;
+    guint               is_mapped               : 1;
+    guint               fullscreen_on_map       : 1;
+    guint               is_pixmap               : 1;
+};
+/*
+  * is_pixmap will be used by _create(), but _new_with_xid() doesn't have
+  * a chance to set the flag, so add this flag here.
+  * TODO, we'd better add is_pixmap flag to base class: GstVaapiWindow
+*/
+
+static gboolean _is_pixmap = FALSE;
+
+#define _NET_WM_STATE_REMOVE    0 /* remove/unset property */
+#define _NET_WM_STATE_ADD       1 /* add/set property      */
+#define _NET_WM_STATE_TOGGLE    2 /* toggle property       */
+
+static void
+send_wmspec_change_state(GstVaapiWindowX11 *window, Atom state, gboolean add)
+{
+    GstVaapiWindowX11Private * const priv = window->priv;
+    Display * const dpy = GST_VAAPI_OBJECT_XDISPLAY(window);
+    XClientMessageEvent xclient;
+
+    memset(&xclient, 0, sizeof(xclient));
+
+    xclient.type         = ClientMessage;
+    xclient.window       = GST_VAAPI_OBJECT_ID(window);
+    xclient.message_type = priv->atom_NET_WM_STATE;
+    xclient.format       = 32;
+
+    xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
+    xclient.data.l[1] = state;
+    xclient.data.l[2] = 0;
+    xclient.data.l[3] = 0;
+    xclient.data.l[4] = 0;
+
+    XSendEvent(
+        dpy,
+        DefaultRootWindow(dpy),
+        False,
+        SubstructureRedirectMask|SubstructureNotifyMask,
+        (XEvent *)&xclient
+    );
+}
+
+static void
+wait_event(GstVaapiWindow *window, int type)
+{
+    Display * const     dpy = GST_VAAPI_OBJECT_XDISPLAY(window);
+    const Window        xid = GST_VAAPI_OBJECT_ID(window);
+    XEvent              e;
+    Bool                got_event;
+
+    for (;;) {
+        GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+        got_event = XCheckTypedWindowEvent(dpy, xid, type, &e);
+        GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+        if (got_event)
+            break;
+        g_usleep(10);
+    }
+}
+
+static gboolean
+timed_wait_event(GstVaapiWindow *window, int type, guint64 end_time, XEvent *e)
+{
+    Display * const     dpy = GST_VAAPI_OBJECT_XDISPLAY(window);
+    const Window        xid = GST_VAAPI_OBJECT_ID(window);
+    XEvent              tmp_event;
+    GTimeVal            now;
+    guint64             now_time;
+    Bool                got_event;
+
+    if (!e)
+        e = &tmp_event;
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+    got_event = XCheckTypedWindowEvent(dpy, xid, type, e);
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+    if (got_event)
+        return TRUE;
+
+    do {
+        g_usleep(10);
+        GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+        got_event = XCheckTypedWindowEvent(dpy, xid, type, e);
+        GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+        if (got_event)
+            return TRUE;
+        g_get_current_time(&now);
+        now_time = (guint64)now.tv_sec * 1000000 + now.tv_usec;
+    } while (now_time < end_time);
+    return FALSE;
+}
+
+static gboolean
+gst_vaapi_window_x11_show(GstVaapiWindow *window)
+{
+    GstVaapiWindowX11Private * const priv = GST_VAAPI_WINDOW_X11(window)->priv;
+    Display * const                  dpy  = GST_VAAPI_OBJECT_XDISPLAY(window);
+    const Window                     xid  = GST_VAAPI_OBJECT_ID(window);
+    XWindowAttributes                wattr;
+    gboolean                         has_errors;
+
+    if (priv->is_mapped)
+        return TRUE;
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+    x11_trap_errors();
+    if (!priv->create_window) {
+        XGetWindowAttributes(dpy, xid, &wattr);
+        if (!(wattr.your_event_mask & StructureNotifyMask))
+            XSelectInput(dpy, xid, StructureNotifyMask);
+    }
+    XMapWindow(dpy, xid);
+    has_errors = x11_untrap_errors() != 0;
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+
+    if (!has_errors) {
+        wait_event(window, MapNotify);
+        if (!priv->create_window &&
+            !(wattr.your_event_mask & StructureNotifyMask)) {
+            GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+            x11_trap_errors();
+            XSelectInput(dpy, xid, wattr.your_event_mask);
+            has_errors = x11_untrap_errors() != 0;
+            GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+        }
+        priv->is_mapped = TRUE;
+
+        if (priv->fullscreen_on_map)
+            gst_vaapi_window_set_fullscreen(window, TRUE);
+    }
+    return !has_errors;
+}
+
+static gboolean
+gst_vaapi_window_x11_hide(GstVaapiWindow *window)
+{
+    GstVaapiWindowX11Private * const priv = GST_VAAPI_WINDOW_X11(window)->priv;
+    Display * const                  dpy  = GST_VAAPI_OBJECT_XDISPLAY(window);
+    const Window                     xid  = GST_VAAPI_OBJECT_ID(window);
+    XWindowAttributes                wattr;
+    gboolean                         has_errors;
+
+    if (!priv->is_mapped)
+        return TRUE;
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+    x11_trap_errors();
+    if (!priv->create_window) {
+        XGetWindowAttributes(dpy, xid, &wattr);
+        if (!(wattr.your_event_mask & StructureNotifyMask))
+            XSelectInput(dpy, xid, StructureNotifyMask);
+    }
+    XUnmapWindow(dpy, xid);
+    has_errors = x11_untrap_errors() != 0;
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+
+    if (!has_errors) {
+        wait_event(window, UnmapNotify);
+        if (!priv->create_window &&
+            !(wattr.your_event_mask & StructureNotifyMask)) {
+            GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+            x11_trap_errors();
+            XSelectInput(dpy, xid, wattr.your_event_mask);
+            has_errors = x11_untrap_errors() != 0;
+            GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+        }
+        priv->is_mapped = FALSE;
+    }
+    return !has_errors;
+}
+
+static gboolean
+gst_vaapi_window_x11_create(GstVaapiWindow *window, guint *width, guint *height)
+{
+    GstVaapiWindowX11Private * const priv = GST_VAAPI_WINDOW_X11(window)->priv;
+    Display * const                  dpy  = GST_VAAPI_OBJECT_XDISPLAY(window);
+    Window                           xid  = GST_VAAPI_OBJECT_ID(window);
+    Visual                          *vis  = NULL;
+    Colormap                         cmap = None;
+    GstVaapiWindowX11Class          *klass;
+    XWindowAttributes                wattr;
+    Atom                             atoms[2];
+    gboolean                         ok;
+
+    static const char *atom_names[2] = {
+        "_NET_WM_STATE",
+        "_NET_WM_STATE_FULLSCREEN",
+    };
+
+    if (!priv->create_window && xid) {
+        GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+        if (_is_pixmap) {
+            priv->is_mapped = TRUE;
+        }
+        else {
+            XGetWindowAttributes(dpy, xid, &wattr);
+            priv->is_mapped = wattr.map_state == IsViewable;
+        }
+        ok = x11_get_geometry(dpy, xid, NULL, NULL, width, height);
+        GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+        return ok;
+    }
+
+    klass = GST_VAAPI_WINDOW_X11_GET_CLASS(window);
+    if (klass) {
+        if (klass->get_visual)
+            vis = klass->get_visual(window);
+        if (klass->get_colormap)
+            cmap = klass->get_colormap(window);
+    }
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+    XInternAtoms(
+        dpy,
+        (char **)atom_names, G_N_ELEMENTS(atom_names),
+        False,
+        atoms
+    );
+    priv->atom_NET_WM_STATE            = atoms[0];
+    priv->atom_NET_WM_STATE_FULLSCREEN = atoms[1];
+
+    xid = x11_create_window(dpy, *width, *height, vis, cmap);
+    if (xid)
+        XRaiseWindow(dpy, xid);
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+
+    GST_DEBUG("xid %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(xid));
+    GST_VAAPI_OBJECT_ID(window) = xid;
+    return xid != None;
+}
+
+static void
+gst_vaapi_window_x11_destroy(GstVaapiWindow *window)
+{
+    GstVaapiWindowX11Private * const priv = GST_VAAPI_WINDOW_X11(window)->priv;
+    Display * const                  dpy  = GST_VAAPI_OBJECT_XDISPLAY(window);
+    const Window                     xid  = GST_VAAPI_OBJECT_ID(window);
+
+    if (xid) {
+        if (priv->create_window) {
+            GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+            XDestroyWindow(dpy, xid);
+            GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+        }
+        GST_VAAPI_OBJECT_ID(window) = None;
+    }
+}
+
+static gboolean
+gst_vaapi_window_x11_get_geometry(
+    GstVaapiWindow *window,
+    gint           *px,
+    gint           *py,
+    guint          *pwidth,
+    guint          *pheight)
+{
+    Display * const     dpy = GST_VAAPI_OBJECT_XDISPLAY(window);
+    const Window        xid = GST_VAAPI_OBJECT_ID(window);
+
+    return x11_get_geometry(dpy, xid, px, py, pwidth, pheight);
+}
+
+static gboolean
+gst_vaapi_window_x11_set_fullscreen(GstVaapiWindow *window, gboolean fullscreen)
+{
+    GstVaapiWindowX11Private * const priv = GST_VAAPI_WINDOW_X11(window)->priv;
+    Display * const                  dpy  = GST_VAAPI_OBJECT_XDISPLAY(window);
+    const Window                     xid  = GST_VAAPI_OBJECT_ID(window);
+    XEvent e;
+    guint width, height;
+    gboolean has_errors;
+    GTimeVal now;
+    guint64 end_time;
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+    x11_trap_errors();
+    if (fullscreen) {
+        if (!priv->is_mapped) {
+            priv->fullscreen_on_map = TRUE;
+
+            XChangeProperty(
+                dpy,
+                xid,
+                priv->atom_NET_WM_STATE, XA_ATOM, 32,
+                PropModeReplace,
+                (unsigned char *)&priv->atom_NET_WM_STATE_FULLSCREEN, 1
+            );
+        }
+        else {
+            send_wmspec_change_state(
+                GST_VAAPI_WINDOW_X11(window),
+                priv->atom_NET_WM_STATE_FULLSCREEN,
+                TRUE
+            );
+        }
+    }
+    else {
+        if (!priv->is_mapped) {
+            priv->fullscreen_on_map = FALSE;
+
+            XDeleteProperty(
+                dpy,
+                xid,
+                priv->atom_NET_WM_STATE
+            );
+        }
+        else {
+            send_wmspec_change_state(
+                GST_VAAPI_WINDOW_X11(window),
+                priv->atom_NET_WM_STATE_FULLSCREEN,
+                FALSE
+            );
+        }
+    }
+    XSync(dpy, False);
+    has_errors = x11_untrap_errors() != 0;
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+    if (has_errors)
+        return FALSE;
+
+    /* Try to wait for the completion of the fullscreen mode switch */
+    if (priv->create_window && priv->is_mapped) {
+        const guint DELAY = 100000; /* 100 ms */
+        g_get_current_time(&now);
+        end_time = DELAY + ((guint64)now.tv_sec * 1000000 + now.tv_usec);
+        while (timed_wait_event(window, ConfigureNotify, end_time, &e)) {
+            if (fullscreen) {
+                gst_vaapi_display_get_size(
+                    GST_VAAPI_OBJECT_DISPLAY(window),
+                    &width,
+                    &height
+                );
+                if (e.xconfigure.width == width && e.xconfigure.height == height)
+                    return TRUE;
+            }
+            else {
+                gst_vaapi_window_get_size(window, &width, &height);
+                if (e.xconfigure.width != width || e.xconfigure.height != height)
+                    return TRUE;
+            }
+        }
+    }
+    return FALSE;
+}
+
+static gboolean
+gst_vaapi_window_x11_resize(GstVaapiWindow *window, guint width, guint height)
+{
+    gboolean has_errors;
+
+    if (!GST_VAAPI_OBJECT_ID(window))
+        return FALSE;
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+    x11_trap_errors();
+    XResizeWindow(
+        GST_VAAPI_OBJECT_XDISPLAY(window),
+        GST_VAAPI_OBJECT_ID(window),
+        width,
+        height
+    );
+    has_errors = x11_untrap_errors() != 0;
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+    return !has_errors;
+}
+
+static gboolean
+gst_vaapi_window_x11_render(
+    GstVaapiWindow          *window,
+    GstVaapiSurface         *surface,
+    const GstVaapiRectangle *src_rect,
+    const GstVaapiRectangle *dst_rect,
+    guint                    flags
+)
+{
+    VASurfaceID surface_id;
+    VAStatus status;
+
+    surface_id = GST_VAAPI_OBJECT_ID(surface);
+    if (surface_id == VA_INVALID_ID)
+        return FALSE;
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+    status = vaPutSurface(
+        GST_VAAPI_OBJECT_VADISPLAY(window),
+        surface_id,
+        GST_VAAPI_OBJECT_ID(window),
+        src_rect->x,
+        src_rect->y,
+        src_rect->width,
+        src_rect->height,
+        dst_rect->x,
+        dst_rect->y,
+        dst_rect->width,
+        dst_rect->height,
+        NULL, 0,
+        from_GstVaapiSurfaceRenderFlags(flags)
+    );
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+    if (!vaapi_check_status(status, "vaPutSurface()"))
+        return FALSE;
+
+    return TRUE;
+}
+
+static void
+gst_vaapi_window_x11_finalize(GObject *object)
+{
+    G_OBJECT_CLASS(gst_vaapi_window_x11_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_window_x11_constructed(GObject *object)
+{
+    GstVaapiWindowX11 * const window = GST_VAAPI_WINDOW_X11(object);
+    GObjectClass *parent_class;
+
+    window->priv->create_window = GST_VAAPI_OBJECT_ID(object) == None;
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_window_x11_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+}
+
+static void
+gst_vaapi_window_x11_class_init(GstVaapiWindowX11Class *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstVaapiWindowClass * const window_class = GST_VAAPI_WINDOW_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiWindowX11Private));
+
+    object_class->finalize       = gst_vaapi_window_x11_finalize;
+    object_class->constructed    = gst_vaapi_window_x11_constructed;
+
+    window_class->create         = gst_vaapi_window_x11_create;
+    window_class->destroy        = gst_vaapi_window_x11_destroy;
+    window_class->show           = gst_vaapi_window_x11_show;
+    window_class->hide           = gst_vaapi_window_x11_hide;
+    window_class->get_geometry   = gst_vaapi_window_x11_get_geometry;
+    window_class->set_fullscreen = gst_vaapi_window_x11_set_fullscreen;
+    window_class->resize         = gst_vaapi_window_x11_resize;
+    window_class->render         = gst_vaapi_window_x11_render;
+}
+
+static void
+gst_vaapi_window_x11_init(GstVaapiWindowX11 *window)
+{
+    GstVaapiWindowX11Private *priv = GST_VAAPI_WINDOW_X11_GET_PRIVATE(window);
+
+    window->priv                = priv;
+    priv->create_window         = TRUE;
+    priv->is_mapped             = FALSE;
+    priv->fullscreen_on_map     = FALSE;
+    priv->is_pixmap             = FALSE;
+}
+
+/**
+ * gst_vaapi_window_x11_new:
+ * @display: a #GstVaapiDisplay
+ * @width: the requested window width, in pixels
+ * @height: the requested windo height, in pixels
+ *
+ * Creates a window with the specified @width and @height. The window
+ * will be attached to the @display and remains invisible to the user
+ * until gst_vaapi_window_show() is called.
+ *
+ * Return value: the newly allocated #GstVaapiWindow object
+ */
+GstVaapiWindow *
+gst_vaapi_window_x11_new(GstVaapiDisplay *display, guint width, guint height)
+{
+    GST_DEBUG("new window, size %ux%u", width, height);
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+    g_return_val_if_fail(width  > 0, NULL);
+    g_return_val_if_fail(height > 0, NULL);
+
+    return g_object_new(GST_VAAPI_TYPE_WINDOW_X11,
+                        "display", display,
+                        "id",      GST_VAAPI_ID(None),
+                        "width",   width,
+                        "height",  height,
+                        NULL);
+}
+
+/**
+ * gst_vaapi_window_x11_new_with_xid:
+ * @display: a #GstVaapiDisplay
+ * @xid: an X11 #Window id
+ *
+ * Creates a #GstVaapiWindow using the X11 #Window @xid. The caller
+ * still owns the window and must call XDestroyWindow() when all
+ * #GstVaapiWindow references are released. Doing so too early can
+ * yield undefined behaviour.
+ *
+ * Return value: the newly allocated #GstVaapiWindow object
+ */
+GstVaapiWindow *
+gst_vaapi_window_x11_new_with_xid(GstVaapiDisplay *display, Window xid, gboolean is_pixmap)
+{
+    GstVaapiWindow * window = NULL;
+    GST_DEBUG("new window from xid 0x%08x", xid);
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+    g_return_val_if_fail(xid != None, NULL);
+
+    _is_pixmap = is_pixmap;
+    window = g_object_new(GST_VAAPI_TYPE_WINDOW_X11,
+                        "display", display,
+                        "id",      GST_VAAPI_ID(xid),
+                        NULL);
+
+    if (window) {
+        GstVaapiWindowX11Private *priv = GST_VAAPI_WINDOW_X11_GET_PRIVATE(window);
+        priv->is_pixmap = is_pixmap;
+    }
+
+    return window;
+}
+
+/**
+ * gst_vaapi_window_x11_get_xid:
+ * @window: a #GstVaapiWindowX11
+ *
+ * Returns the underlying X11 #Window that was created by
+ * gst_vaapi_window_x11_new() or that was bound with
+ * gst_vaapi_window_x11_new_with_xid().
+ *
+ * Return value: the underlying X11 #Window bound to @window.
+ */
+Window
+gst_vaapi_window_x11_get_xid(GstVaapiWindowX11 *window)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_WINDOW_X11(window), None);
+
+    return GST_VAAPI_OBJECT_ID(window);
+}
+
+/**
+ * gst_vaapi_window_x11_is_foreign_xid:
+ * @window: a #GstVaapiWindowX11
+ *
+ * Checks whether the @window XID was created by gst_vaapi_window_x11_new() or bound with gst_vaapi_window_x11_new_with_xid().
+ *
+ * Return value: %TRUE if the underlying X window is owned by the
+ *   caller (foreign window)
+ */
+gboolean
+gst_vaapi_window_x11_is_foreign_xid(GstVaapiWindowX11 *window)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_WINDOW_X11(window), FALSE);
+
+    return !window->priv->create_window;
+}
+
+/**
+ * gst_vaapi_window_x11_is_pixmap:
+ * @window: a #GstVaapiWindowX11
+ *
+ * Checks whether the @window XID is Pixmap or Window
+ *
+ * Return value: %TRUE if the underlying X Drawble is Pixmap
+ */
+gboolean
+gst_vaapi_window_x11_is_pixmap(GstVaapiWindowX11 *window)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_WINDOW_X11(window), FALSE);
+
+    return window->priv->is_pixmap;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiwindow_x11.h b/gst-libs/gst/vaapi/gstvaapiwindow_x11.h
new file mode 100644 (file)
index 0000000..b5ea9ff
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ *  gstvaapiwindow_x11.h - VA/X11 window abstraction
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_WINDOW_X11_H
+#define GST_VAAPI_WINDOW_X11_H
+
+#include <X11/Xlib.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapiwindow.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_WINDOW_X11 \
+    (gst_vaapi_window_x11_get_type())
+
+#define GST_VAAPI_WINDOW_X11(obj)                               \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                          \
+                                GST_VAAPI_TYPE_WINDOW_X11,      \
+                                GstVaapiWindowX11))
+
+#define GST_VAAPI_WINDOW_X11_CLASS(klass)                       \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                           \
+                             GST_VAAPI_TYPE_WINDOW_X11,         \
+                             GstVaapiWindowX11Class))
+
+#define GST_VAAPI_IS_WINDOW_X11(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_WINDOW_X11))
+
+#define GST_VAAPI_IS_WINDOW_X11_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_WINDOW_X11))
+
+#define GST_VAAPI_WINDOW_X11_GET_CLASS(obj)                     \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                           \
+                               GST_VAAPI_TYPE_WINDOW_X11,       \
+                               GstVaapiWindowX11Class))
+
+/**
+ * GST_VAAPI_WINDOW_XWINDOW:
+ * @window: a #GstVaapiWindow
+ *
+ * Macro that evaluates to the underlying X11 #Window of @window
+ */
+#define GST_VAAPI_WINDOW_XWINDOW(window) \
+    gst_vaapi_window_x11_get_xid(GST_VAAPI_WINDOW_X11(window))
+
+typedef struct _GstVaapiWindowX11               GstVaapiWindowX11;
+typedef struct _GstVaapiWindowX11Private        GstVaapiWindowX11Private;
+typedef struct _GstVaapiWindowX11Class          GstVaapiWindowX11Class;
+
+/**
+ * GstVaapiWindowX11:
+ *
+ * An X11 #Window wrapper.
+ */
+struct _GstVaapiWindowX11 {
+    /*< private >*/
+    GstVaapiWindow parent_instance;
+
+    GstVaapiWindowX11Private *priv;
+};
+
+/**
+ * GstVaapiWindowX11Class:
+ * @get_visual: virtual function to get the desired visual used to
+ *   create the window
+ * @get_colormap: virtual function to get the desired colormap used to
+ *   create the window
+ *
+ * An X11 #Window wrapper class.
+ */
+struct _GstVaapiWindowX11Class {
+    /*< private >*/
+    GstVaapiWindowClass parent_class;
+
+    Visual *  (*get_visual)     (GstVaapiWindow *window);
+    Colormap  (*get_colormap)   (GstVaapiWindow *window);
+};
+
+GType
+gst_vaapi_window_x11_get_type(void) G_GNUC_CONST;
+
+GstVaapiWindow *
+gst_vaapi_window_x11_new(GstVaapiDisplay *display, guint width, guint height);
+
+GstVaapiWindow *
+gst_vaapi_window_x11_new_with_xid(GstVaapiDisplay *display, Window xid, gboolean is_pixmap);
+
+Window
+gst_vaapi_window_x11_get_xid(GstVaapiWindowX11 *window);
+
+gboolean
+gst_vaapi_window_x11_is_foreign_xid(GstVaapiWindowX11 *window);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_WINDOW_X11_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiworkarounds.h b/gst-libs/gst/vaapi/gstvaapiworkarounds.h
new file mode 100644 (file)
index 0000000..a7276f4
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ *  gstvaapiworkaround.h - GStreamer/VA workarounds
+ *
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_WORKAROUNDS_H
+#define GST_VAAPI_WORKAROUNDS_H
+
+G_BEGIN_DECLS
+
+/*
+ * Workaround to expose H.263 Baseline decode profile for drivers that
+ * support MPEG-4:2 Simple profile decoding.
+ */
+#define WORKAROUND_H263_BASELINE_DECODE_PROFILE (1)
+
+/*
+ * Workaround for qtdemux that does not report profiles for
+ * video/x-h263. Assume H.263 Baseline profile in this case.
+ */
+#define WORKAROUND_QTDEMUX_NO_H263_PROFILES (1)
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_WORKAROUNDS_H */
diff --git a/gst-libs/gst/vaapi/sysdeps.h b/gst-libs/gst/vaapi/sysdeps.h
new file mode 100644 (file)
index 0000000..c8be890
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  sysdeps.h - System-dependent definitions
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef SYSDEPS_H
+#define SYSDEPS_H
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "glibcompat.h"
+
+#endif /* SYSDEPS_H */
diff --git a/gst/Makefile.am b/gst/Makefile.am
new file mode 100644 (file)
index 0000000..37d365d
--- /dev/null
@@ -0,0 +1,4 @@
+SUBDIRS = vaapi
+
+# Extra clean files so that maintainer-clean removes *everything*
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/gst/vaapi/Makefile.am b/gst/vaapi/Makefile.am
new file mode 100644 (file)
index 0000000..ebe46bb
--- /dev/null
@@ -0,0 +1,91 @@
+plugin_LTLIBRARIES = libgstvaapi.la
+
+libgstvaapi_CFLAGS = \
+       $(LIBVA_CFLAGS)                 \
+       -DGST_USE_UNSTABLE_API          \
+       -I$(top_srcdir)/gst-libs        \
+       -I$(top_builddir)/gst-libs      \
+       $(NULL)
+
+libgstvaapi_LIBS =
+
+if USE_DRM
+libgstvaapi_LIBS += \
+       $(top_builddir)/gst-libs/gst/vaapi/libgstvaapi-drm-$(GST_MAJORMINOR).la
+endif
+
+if USE_X11
+libgstvaapi_LIBS += \
+       $(top_builddir)/gst-libs/gst/vaapi/libgstvaapi-x11-$(GST_MAJORMINOR).la
+endif
+
+if USE_GLX
+libgstvaapi_LIBS += \
+       $(top_builddir)/gst-libs/gst/vaapi/libgstvaapi-glx-$(GST_MAJORMINOR).la
+endif
+
+if USE_WAYLAND
+libgstvaapi_LIBS += \
+       $(top_builddir)/gst-libs/gst/vaapi/libgstvaapi-wayland-$(GST_MAJORMINOR).la
+endif
+
+libgstvaapi_la_SOURCES =       \
+       gstvaapi.c              \
+       gstvaapidecode.c        \
+       gstvaapidownload.c      \
+       gstvaapipluginbuffer.c  \
+       gstvaapipluginutil.c    \
+       gstvaapipostproc.c      \
+       gstvaapisink.c          \
+       gstvaapiupload.c        \
+       $(NULL)
+
+noinst_HEADERS =               \
+       gstvaapidecode.h        \
+       gstvaapidownload.h      \
+       gstvaapipluginbuffer.h  \
+       gstvaapipluginutil.h    \
+       gstvaapipostproc.h      \
+       gstvaapisink.h          \
+       gstvaapiupload.h        \
+       $(NULL)
+
+if USE_ENCODERS
+libgstvaapi_la_SOURCES +=    \
+    gstvaapiencode.c    \
+    gstvaapiencode_h264.c \
+    gstvaapiencode_h263.c \
+    gstvaapiencode_mpeg4.c \
+       $(NULL)
+
+noinst_HEADERS +=        \
+    gstvaapiencode.h    \
+    gstvaapiencode_h264.h \
+    gstvaapiencode_h263.h \
+    gstvaapiencode_mpeg4.h \
+       $(NULL)
+endif
+
+libgstvaapi_la_CFLAGS =        \
+       $(libgstvaapi_CFLAGS)   \
+       $(GST_CFLAGS)           \
+       $(GST_BASE_CFLAGS)      \
+       $(GST_VIDEO_CFLAGS)     \
+       $(GST_INTERFACES_CFLAGS) \
+       $(GST_BASEVIDEO_CFLAGS) \
+       $(GST_PLUGINS_BASE_CFLAGS)
+
+libgstvaapi_la_LIBADD =        \
+       $(libgstvaapi_LIBS)     \
+       $(GST_LIBS)             \
+       $(GST_BASE_LIBS)        \
+       $(GST_VIDEO_LIBS)       \
+       $(GST_INTERFACES_LIBS)  \
+       $(GST_BASEVIDEO_LIBS)   \
+       $(GST_PLUGINS_BASE_LIBS)
+
+libgstvaapi_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstvaapi_la_LIBTOOLFLAGS = --tag=disable-static
+
+# Extra clean files so that maintainer-clean removes *everything*
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/gst/vaapi/gstvaapi.c b/gst/vaapi/gstvaapi.c
new file mode 100644 (file)
index 0000000..4bd442b
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *  gstvaapi.c - VA-API element registration
+ *
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *  Copyright (C) 2011 Collabora Ltd.
+ *    Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; 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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gst/gst.h>
+
+#include "gstvaapidownload.h"
+#include "gstvaapiupload.h"
+#include "gstvaapidecode.h"
+#include "gstvaapipostproc.h"
+#include "gstvaapisink.h"
+
+#if USE_ENCODERS
+#include "gstvaapiencode.h"
+#include "gstvaapiencode_h264.h"
+#include "gstvaapiencode_h263.h"
+#include "gstvaapiencode_mpeg4.h"
+
+/*  encoder plugin register*/
+static gboolean
+vaapi_encoder_plugins_init (GstPlugin * plugin)
+{
+  gboolean ret = TRUE;
+
+  ret &= gst_element_register (plugin, "vaapiencodeh264", GST_RANK_PRIMARY,
+      GST_TYPE_VAAPI_ENCODE_H264);
+  ret &= gst_element_register (plugin, "vaapiencodeh263", GST_RANK_PRIMARY,
+      GST_TYPE_VAAPI_ENCODE_H263);
+  ret &= gst_element_register (plugin, "vaapiencodempeg4", GST_RANK_PRIMARY,
+      GST_TYPE_VAAPI_ENCODE_MPEG4);
+  return ret;
+}
+#endif
+
+static gboolean
+plugin_init (GstPlugin *plugin)
+{
+    gst_element_register(plugin, "vaapidownload",
+                         GST_RANK_SECONDARY,
+                         GST_TYPE_VAAPIDOWNLOAD);
+    gst_element_register(plugin, "vaapiupload",
+                         GST_RANK_PRIMARY,
+                         GST_TYPE_VAAPIUPLOAD);
+    gst_element_register(plugin, "vaapidecode",
+                         GST_RANK_PRIMARY,
+                         GST_TYPE_VAAPIDECODE);
+    gst_element_register(plugin, "vaapipostproc",
+                         GST_RANK_PRIMARY,
+                         GST_TYPE_VAAPIPOSTPROC);
+    gst_element_register(plugin, "vaapisink",
+                         GST_RANK_PRIMARY,
+                         GST_TYPE_VAAPISINK);
+#if USE_ENCODERS
+    return vaapi_encoder_plugins_init(plugin);
+#endif
+    return TRUE;
+}
+
+GST_PLUGIN_DEFINE(
+    GST_VERSION_MAJOR, GST_VERSION_MINOR,
+    "vaapi",
+    "VA-API based elements",
+    plugin_init,
+    PACKAGE_VERSION,
+    "LGPL",
+    PACKAGE,
+    PACKAGE_BUGREPORT);
diff --git a/gst/vaapi/gstvaapidecode.c b/gst/vaapi/gstvaapidecode.c
new file mode 100644 (file)
index 0000000..3647d4c
--- /dev/null
@@ -0,0 +1,790 @@
+/*
+ *  gstvaapidecode.c - VA-API video decoder
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+*/
+
+/**
+ * SECTION:gstvaapidecode
+ * @short_description: A VA-API based video decoder
+ *
+ * vaapidecode decodes from raw bitstreams to surfaces suitable for
+ * the vaapisink element.
+ */
+
+#include "config.h"
+
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapivideobuffer.h>
+#include <gst/video/videocontext.h>
+
+#include "gstvaapidecode.h"
+#include "gstvaapipluginutil.h"
+#include "gstvaapipluginbuffer.h"
+
+#include <gst/vaapi/gstvaapidecoder_h264.h>
+#include <gst/vaapi/gstvaapidecoder_jpeg.h>
+#include <gst/vaapi/gstvaapidecoder_mpeg2.h>
+#include <gst/vaapi/gstvaapidecoder_mpeg4.h>
+#include <gst/vaapi/gstvaapidecoder_vc1.h>
+
+#define GST_PLUGIN_NAME "vaapidecode"
+#define GST_PLUGIN_DESC "A VA-API based video decoder"
+
+GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapidecode);
+#define GST_CAT_DEFAULT gst_debug_vaapidecode
+
+/* ElementFactory information */
+static const GstElementDetails gst_vaapidecode_details =
+    GST_ELEMENT_DETAILS(
+        "VA-API decoder",
+        "Codec/Decoder/Video",
+        GST_PLUGIN_DESC,
+        "Gwenole Beauchesne <gwenole.beauchesne@intel.com>");
+
+/* Default templates */
+#define GST_CAPS_CODEC(CODEC) CODEC "; "
+
+static const char gst_vaapidecode_sink_caps_str[] =
+    GST_CAPS_CODEC("video/mpeg, mpegversion=2, systemstream=(boolean)false")
+    GST_CAPS_CODEC("video/mpeg, mpegversion=4")
+    GST_CAPS_CODEC("video/x-divx")
+    GST_CAPS_CODEC("video/x-xvid")
+    GST_CAPS_CODEC("video/x-h263")
+    GST_CAPS_CODEC("video/x-h264")
+    GST_CAPS_CODEC("video/x-wmv")
+    GST_CAPS_CODEC("image/jpeg")
+    ;
+
+static const char gst_vaapidecode_src_caps_str[] =
+    GST_VAAPI_SURFACE_CAPS;
+
+static GstStaticPadTemplate gst_vaapidecode_sink_factory =
+    GST_STATIC_PAD_TEMPLATE(
+        "sink",
+        GST_PAD_SINK,
+        GST_PAD_ALWAYS,
+        GST_STATIC_CAPS(gst_vaapidecode_sink_caps_str));
+
+static GstStaticPadTemplate gst_vaapidecode_src_factory =
+    GST_STATIC_PAD_TEMPLATE(
+        "src",
+        GST_PAD_SRC,
+        GST_PAD_ALWAYS,
+        GST_STATIC_CAPS(gst_vaapidecode_src_caps_str));
+
+static void
+gst_vaapidecode_implements_iface_init(GstImplementsInterfaceClass *iface);
+
+static void
+gst_video_context_interface_init(GstVideoContextInterface *iface);
+
+#define GstVideoContextClass GstVideoContextInterface
+G_DEFINE_TYPE_WITH_CODE(
+    GstVaapiDecode,
+    gst_vaapidecode,
+    GST_TYPE_ELEMENT,
+    G_IMPLEMENT_INTERFACE(GST_TYPE_IMPLEMENTS_INTERFACE,
+                          gst_vaapidecode_implements_iface_init);
+    G_IMPLEMENT_INTERFACE(GST_TYPE_VIDEO_CONTEXT,
+                          gst_video_context_interface_init));
+
+static gboolean
+gst_vaapidecode_update_src_caps(GstVaapiDecode *decode, GstCaps *caps);
+
+static void
+gst_vaapi_decoder_notify_caps(GObject *obj, GParamSpec *pspec, void *user_data)
+{
+    GstVaapiDecode * const decode = GST_VAAPIDECODE(user_data);
+    GstCaps *caps;
+
+    g_assert(decode->decoder == GST_VAAPI_DECODER(obj));
+
+    caps = gst_vaapi_decoder_get_caps(decode->decoder);
+    gst_vaapidecode_update_src_caps(decode, caps);
+}
+
+static inline gboolean
+gst_vaapidecode_update_sink_caps(GstVaapiDecode *decode, GstCaps *caps)
+{
+    if (decode->sinkpad_caps)
+        gst_caps_unref(decode->sinkpad_caps);
+    decode->sinkpad_caps = gst_caps_ref(caps);
+    return TRUE;
+}
+
+static gboolean
+gst_vaapidecode_update_src_caps(GstVaapiDecode *decode, GstCaps *caps)
+{
+    GstCaps *other_caps;
+    GstStructure *structure;
+    const GValue *v_width, *v_height, *v_framerate, *v_par, *v_interlaced;
+    gboolean success;
+
+    if (!decode->srcpad_caps) {
+        decode->srcpad_caps = gst_caps_from_string(GST_VAAPI_SURFACE_CAPS_NAME);
+        if (!decode->srcpad_caps)
+            return FALSE;
+    }
+
+    structure    = gst_caps_get_structure(caps, 0);
+    v_width      = gst_structure_get_value(structure, "width");
+    v_height     = gst_structure_get_value(structure, "height");
+    v_framerate  = gst_structure_get_value(structure, "framerate");
+    v_par        = gst_structure_get_value(structure, "pixel-aspect-ratio");
+    v_interlaced = gst_structure_get_value(structure, "interlaced");
+
+    structure = gst_caps_get_structure(decode->srcpad_caps, 0);
+    if (v_width && v_height) {
+        gst_structure_set_value(structure, "width", v_width);
+        gst_structure_set_value(structure, "height", v_height);
+    }
+    if (v_framerate)
+        gst_structure_set_value(structure, "framerate", v_framerate);
+    if (v_par)
+        gst_structure_set_value(structure, "pixel-aspect-ratio", v_par);
+    if (v_interlaced)
+        gst_structure_set_value(structure, "interlaced", v_interlaced);
+
+    gst_structure_set(structure, "type", G_TYPE_STRING, "vaapi", NULL);
+    gst_structure_set(structure, "opengl", G_TYPE_BOOLEAN, USE_GLX, NULL);
+
+    other_caps = gst_caps_copy(decode->srcpad_caps);
+    success = gst_pad_set_caps(decode->srcpad, other_caps);
+    gst_caps_unref(other_caps);
+    return success;
+}
+
+static void
+gst_vaapidecode_release(GstVaapiDecode *decode, GObject *dead_object)
+{
+    g_mutex_lock(decode->decoder_mutex);
+    g_cond_signal(decode->decoder_ready);
+    g_mutex_unlock(decode->decoder_mutex);
+}
+
+static gboolean
+gst_vaapidecode_is_valid_time(GstVaapiDecode *decode, gint64 time)
+{
+    if (decode->segment.format != GST_FORMAT_TIME)
+        return TRUE;
+    if (decode->segment.stop != -1 && time != -1 && time > decode->segment.stop)
+        return FALSE;
+    if (decode->segment.start != -1 && time != -1 && time < decode->segment.start)
+        return FALSE;
+
+    return TRUE;
+}
+
+static GstFlowReturn
+gst_vaapidecode_step(GstVaapiDecode *decode)
+{
+    GstVaapiSurfaceProxy *proxy;
+    GstVaapiDecoderStatus status;
+    GstBuffer *buffer;
+    GstClockTime timestamp;
+    GstFlowReturn ret;
+    guint tries;
+
+    for (;;) {
+        tries = 0;
+    again:
+        proxy = gst_vaapi_decoder_get_surface(decode->decoder, &status);
+        if (!proxy) {
+            if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE) {
+                /* Wait for a VA surface to be displayed and free'd */
+                if (++tries > 100)
+                    goto error_decode_timeout;
+                GTimeVal timeout;
+                g_get_current_time(&timeout);
+                g_time_val_add(&timeout, 10000); /* 10 ms each step */
+                g_mutex_lock(decode->decoder_mutex);
+                g_cond_timed_wait(
+                    decode->decoder_ready,
+                    decode->decoder_mutex,
+                    &timeout
+                );
+                g_mutex_unlock(decode->decoder_mutex);
+                goto again;
+            }
+            if (status != GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA)
+                goto error_decode;
+            /* More data is needed */
+            break;
+        }
+
+        timestamp = GST_VAAPI_SURFACE_PROXY_TIMESTAMP(proxy);
+        if (GST_CLOCK_TIME_IS_VALID(timestamp) &&
+            !gst_vaapidecode_is_valid_time(decode, (gint64)timestamp)) {
+            g_object_unref(proxy);
+            continue;
+        }
+
+        g_object_weak_ref(
+            G_OBJECT(proxy),
+            (GWeakNotify)gst_vaapidecode_release,
+            decode
+        );
+
+        buffer = gst_vaapi_video_buffer_new(decode->display);
+        if (!buffer)
+            goto error_create_buffer;
+
+        GST_BUFFER_TIMESTAMP(buffer) = timestamp;
+        gst_buffer_set_caps(buffer, GST_PAD_CAPS(decode->srcpad));
+
+        if (GST_VAAPI_SURFACE_PROXY_TFF(proxy))
+            GST_BUFFER_FLAG_SET(buffer, GST_VIDEO_BUFFER_TFF);
+
+        gst_vaapi_video_buffer_set_surface_proxy(
+            GST_VAAPI_VIDEO_BUFFER(buffer),
+            proxy
+        );
+
+        ret = gst_pad_push(decode->srcpad, buffer);
+        if (ret != GST_FLOW_OK)
+            goto error_commit_buffer;
+
+        g_object_unref(proxy);
+    }
+    return GST_FLOW_OK;
+
+    /* ERRORS */
+error_decode_timeout:
+    {
+        GST_DEBUG("decode timeout. Decoder required a VA surface but none "
+                  "got available within one second");
+        return GST_FLOW_UNEXPECTED;
+    }
+error_decode:
+    {
+        GST_DEBUG("decode error %d", status);
+        switch (status) {
+        case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC:
+        case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE:
+        case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT:
+            ret = GST_FLOW_NOT_SUPPORTED;
+            break;
+        default:
+            ret = GST_FLOW_UNEXPECTED;
+            break;
+        }
+        return ret;
+    }
+error_create_buffer:
+    {
+        const GstVaapiID surface_id =
+            gst_vaapi_surface_get_id(GST_VAAPI_SURFACE_PROXY_SURFACE(proxy));
+
+        GST_DEBUG("video sink failed to create video buffer for proxy'ed "
+                  "surface %" GST_VAAPI_ID_FORMAT " (error %d)",
+                  GST_VAAPI_ID_ARGS(surface_id), ret);
+        g_object_unref(proxy);
+        return GST_FLOW_UNEXPECTED;
+    }
+error_commit_buffer:
+    {
+        GST_DEBUG("video sink rejected the video buffer (error %d)", ret);
+        g_object_unref(proxy);
+        return GST_FLOW_UNEXPECTED;
+    }
+}
+
+static inline gboolean
+gst_vaapidecode_ensure_display(GstVaapiDecode *decode)
+{
+    return gst_vaapi_ensure_display(decode, GST_VAAPI_DISPLAY_TYPE_ANY,
+        &decode->display);
+}
+
+static gboolean
+gst_vaapidecode_create(GstVaapiDecode *decode, GstCaps *caps)
+{
+    GstVaapiDisplay *dpy;
+    GstStructure *structure;
+    int version;
+
+    if (!gst_vaapidecode_ensure_display(decode))
+        return FALSE;
+    dpy = decode->display;
+
+    decode->decoder_mutex = g_mutex_new();
+    if (!decode->decoder_mutex)
+        return FALSE;
+
+    decode->decoder_ready = g_cond_new();
+    if (!decode->decoder_ready)
+        return FALSE;
+
+    structure = gst_caps_get_structure(caps, 0);
+    if (!structure)
+        return FALSE;
+
+    if (gst_structure_has_name(structure, "video/x-h264"))
+        decode->decoder = gst_vaapi_decoder_h264_new(dpy, caps);
+    else if (gst_structure_has_name(structure, "video/mpeg")) {
+        if (!gst_structure_get_int(structure, "mpegversion", &version))
+            return FALSE;
+        if (version == 2)
+            decode->decoder = gst_vaapi_decoder_mpeg2_new(dpy, caps);
+        else if (version == 4)
+            decode->decoder = gst_vaapi_decoder_mpeg4_new(dpy, caps);
+    }
+    else if (gst_structure_has_name(structure, "video/x-wmv"))
+        decode->decoder = gst_vaapi_decoder_vc1_new(dpy, caps);
+    else if (gst_structure_has_name(structure, "video/x-h263") ||
+             gst_structure_has_name(structure, "video/x-divx") ||
+             gst_structure_has_name(structure, "video/x-xvid"))
+        decode->decoder = gst_vaapi_decoder_mpeg4_new(dpy, caps);
+#if USE_JPEG_DECODER
+    else if (gst_structure_has_name(structure, "image/jpeg"))
+        decode->decoder = gst_vaapi_decoder_jpeg_new(dpy, caps);
+#endif
+    if (!decode->decoder)
+        return FALSE;
+
+    g_signal_connect(
+        G_OBJECT(decode->decoder),
+        "notify::caps",
+        G_CALLBACK(gst_vaapi_decoder_notify_caps),
+        decode
+    );
+
+    decode->decoder_caps = gst_caps_ref(caps);
+    return TRUE;
+}
+
+static void
+gst_vaapidecode_destroy(GstVaapiDecode *decode)
+{
+    if (decode->decoder) {
+        gst_vaapi_decoder_put_buffer(decode->decoder, NULL);
+        g_object_unref(decode->decoder);
+        decode->decoder = NULL;
+    }
+
+    if (decode->decoder_caps) {
+        gst_caps_unref(decode->decoder_caps);
+        decode->decoder_caps = NULL;
+    }
+
+    if (decode->decoder_ready) {
+        gst_vaapidecode_release(decode, NULL);
+        g_cond_free(decode->decoder_ready);
+        decode->decoder_ready = NULL;
+    }
+
+    if (decode->decoder_mutex) {
+        g_mutex_free(decode->decoder_mutex);
+        decode->decoder_mutex = NULL;
+    }
+}
+
+static gboolean
+gst_vaapidecode_reset(GstVaapiDecode *decode, GstCaps *caps)
+{
+    if (decode->decoder &&
+        decode->decoder_caps &&
+        gst_caps_is_always_compatible(caps, decode->decoder_caps))
+        return TRUE;
+
+    gst_vaapidecode_destroy(decode);
+    return gst_vaapidecode_create(decode, caps);
+}
+
+static void
+gst_vaapidecode_configure_segment(
+    GstVaapiDecode *decode,
+    GstEvent *event
+)
+{
+    gboolean update;
+    gdouble rate, applied_rate;
+    GstFormat format;
+    gint64 start, stop, time;
+
+    gst_event_parse_new_segment_full(event, &update, &rate, &applied_rate,
+                                     &format, &start, &stop, &time);
+    if (format == GST_FORMAT_TIME) {
+        gst_segment_set_newsegment_full(&decode->segment, update, rate, applied_rate,
+                                        format, start, stop, time);
+        GST_DEBUG("configured new segment, update %d, rate %lf, applied rate %lf, "
+                  "format GST_FORMAT_TIME, "
+                  "start %" GST_TIME_FORMAT ", stop %" GST_TIME_FORMAT ", "
+                  "time %" GST_TIME_FORMAT,
+                  update, rate, applied_rate,
+                  GST_TIME_ARGS(start), GST_TIME_ARGS(stop),
+                  GST_TIME_ARGS(time));
+    }
+}
+
+/* GstImplementsInterface interface */
+
+static gboolean
+gst_vaapidecode_implements_interface_supported(
+    GstImplementsInterface *iface,
+    GType                   type
+)
+{
+    return (type == GST_TYPE_VIDEO_CONTEXT);
+}
+
+static void
+gst_vaapidecode_implements_iface_init(GstImplementsInterfaceClass *iface)
+{
+    iface->supported = gst_vaapidecode_implements_interface_supported;
+}
+
+/* GstVideoContext interface */
+
+static void
+gst_vaapidecode_set_video_context(GstVideoContext *context, const gchar *type,
+    const GValue *value)
+{
+    GstVaapiDecode *decode = GST_VAAPIDECODE (context);
+    gst_vaapi_set_display (type, value, &decode->display);
+}
+
+static void
+gst_video_context_interface_init(GstVideoContextInterface *iface)
+{
+    iface->set_context = gst_vaapidecode_set_video_context;
+}
+
+static void
+gst_vaapidecode_finalize(GObject *object)
+{
+    GstVaapiDecode * const decode = GST_VAAPIDECODE(object);
+
+    gst_vaapidecode_destroy(decode);
+
+    if (decode->sinkpad_caps) {
+        gst_caps_unref(decode->sinkpad_caps);
+        decode->sinkpad_caps = NULL;
+    }
+
+    if (decode->srcpad_caps) {
+        gst_caps_unref(decode->srcpad_caps);
+        decode->srcpad_caps = NULL;
+    }
+
+    g_clear_object(&decode->display);
+
+    if (decode->allowed_caps) {
+        gst_caps_unref(decode->allowed_caps);
+        decode->allowed_caps = NULL;
+    }
+
+    if (decode->delayed_new_seg) {
+        gst_event_unref(decode->delayed_new_seg);
+        decode->delayed_new_seg = NULL;
+    }
+
+    G_OBJECT_CLASS(gst_vaapidecode_parent_class)->finalize(object);
+}
+
+static GstStateChangeReturn
+gst_vaapidecode_change_state(GstElement *element, GstStateChange transition)
+{
+    GstVaapiDecode * const decode = GST_VAAPIDECODE(element);
+    GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+
+    switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:
+        decode->is_ready = TRUE;
+        break;
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+        break;
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+        break;
+    default:
+        break;
+    }
+
+    ret = GST_ELEMENT_CLASS(gst_vaapidecode_parent_class)->change_state(element, transition);
+    if (ret != GST_STATE_CHANGE_SUCCESS)
+        return ret;
+
+    switch (transition) {
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+        break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+        break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+        gst_vaapidecode_destroy(decode);
+        g_clear_object(&decode->display);
+        decode->is_ready = FALSE;
+        break;
+    default:
+        break;
+    }
+    return GST_STATE_CHANGE_SUCCESS;
+}
+
+static void
+gst_vaapidecode_class_init(GstVaapiDecodeClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
+    GstPadTemplate *pad_template;
+
+    GST_DEBUG_CATEGORY_INIT(gst_debug_vaapidecode,
+                            GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
+
+    object_class->finalize      = gst_vaapidecode_finalize;
+
+    element_class->change_state = gst_vaapidecode_change_state;
+
+    gst_element_class_set_details_simple(
+        element_class,
+        gst_vaapidecode_details.longname,
+        gst_vaapidecode_details.klass,
+        gst_vaapidecode_details.description,
+        gst_vaapidecode_details.author
+    );
+
+    /* sink pad */
+    pad_template = gst_static_pad_template_get(&gst_vaapidecode_sink_factory);
+    gst_element_class_add_pad_template(element_class, pad_template);
+    gst_object_unref(pad_template);
+
+    /* src pad */
+    pad_template = gst_static_pad_template_get(&gst_vaapidecode_src_factory);
+    gst_element_class_add_pad_template(element_class, pad_template);
+    gst_object_unref(pad_template);
+}
+
+static gboolean
+gst_vaapidecode_ensure_allowed_caps(GstVaapiDecode *decode)
+{
+    GstCaps *decode_caps;
+    guint i, n_decode_caps;
+
+    if (decode->allowed_caps)
+        return TRUE;
+
+    if (!gst_vaapidecode_ensure_display(decode))
+        goto error_no_display;
+
+    decode_caps = gst_vaapi_display_get_decode_caps(decode->display);
+    if (!decode_caps)
+        goto error_no_decode_caps;
+    n_decode_caps = gst_caps_get_size(decode_caps);
+
+    decode->allowed_caps = gst_caps_new_empty();
+    if (!decode->allowed_caps)
+        goto error_no_memory;
+
+    for (i = 0; i < n_decode_caps; i++) {
+        GstStructure *structure;
+        structure = gst_caps_get_structure(decode_caps, i);
+        if (!structure)
+            continue;
+        structure = gst_structure_copy(structure);
+        if (!structure)
+            continue;
+        gst_structure_remove_field(structure, "profile");
+        gst_structure_set(
+            structure,
+            "width",  GST_TYPE_INT_RANGE, 1, G_MAXINT,
+            "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
+            NULL
+        );
+        gst_caps_merge_structure(decode->allowed_caps, structure);
+    }
+
+    gst_caps_unref(decode_caps);
+    return TRUE;
+
+    /* ERRORS */
+error_no_display:
+    {
+        GST_DEBUG("failed to retrieve VA display");
+        return FALSE;
+    }
+error_no_decode_caps:
+    {
+        GST_DEBUG("failed to retrieve VA decode caps");
+        return FALSE;
+    }
+error_no_memory:
+    {
+        GST_DEBUG("failed to allocate allowed-caps set");
+        gst_caps_unref(decode_caps);
+        return FALSE;
+    }
+}
+
+static GstCaps *
+gst_vaapidecode_get_caps(GstPad *pad)
+{
+    GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
+
+    if (!decode->is_ready)
+        return gst_static_pad_template_get_caps(&gst_vaapidecode_sink_factory);
+
+    if (!gst_vaapidecode_ensure_allowed_caps(decode))
+        return gst_caps_new_empty();
+
+    return gst_caps_ref(decode->allowed_caps);
+}
+
+static gboolean
+gst_vaapidecode_set_caps(GstPad *pad, GstCaps *caps)
+{
+    GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
+
+    g_return_val_if_fail(pad == decode->sinkpad, FALSE);
+
+    if (!gst_vaapidecode_update_sink_caps(decode, caps))
+        return FALSE;
+    if (!gst_vaapidecode_update_src_caps(decode, caps))
+        return FALSE;
+    if (!gst_vaapidecode_reset(decode, decode->sinkpad_caps))
+        return FALSE;
+
+    /* Propagate NEWSEGMENT event downstream, now that pads are linked */
+    if (decode->delayed_new_seg) {
+        if (gst_pad_push_event(decode->srcpad, decode->delayed_new_seg))
+            gst_event_unref(decode->delayed_new_seg);
+        decode->delayed_new_seg = NULL;
+    }
+    return TRUE;
+}
+
+static GstFlowReturn
+gst_vaapidecode_chain(GstPad *pad, GstBuffer *buf)
+{
+    GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
+
+    if (!gst_vaapi_decoder_put_buffer(decode->decoder, buf))
+        goto error_push_buffer;
+
+    gst_buffer_unref(buf);
+    return gst_vaapidecode_step(decode);
+
+    /* ERRORS */
+error_push_buffer:
+    {
+        GST_DEBUG("failed to push input buffer to decoder");
+        gst_buffer_unref(buf);
+        return GST_FLOW_UNEXPECTED;
+    }
+}
+
+static gboolean
+gst_vaapidecode_sink_event(GstPad *pad, GstEvent *event)
+{
+    GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
+
+    GST_DEBUG("handle sink event '%s'", GST_EVENT_TYPE_NAME(event));
+
+    /* Propagate event downstream */
+    switch (GST_EVENT_TYPE(event)) {
+    case GST_EVENT_FLUSH_STOP:
+        gst_segment_init(&decode->segment, GST_FORMAT_UNDEFINED);
+        if (decode->decoder)
+            gst_vaapi_decoder_clear_buffer(decode->decoder);
+        break;
+    case GST_EVENT_NEWSEGMENT:
+        if (decode->delayed_new_seg) {
+            gst_event_unref(decode->delayed_new_seg);
+            decode->delayed_new_seg = NULL;
+        }
+        if (!GST_PAD_PEER(decode->srcpad)) {
+            decode->delayed_new_seg = gst_event_ref(event);
+            return TRUE;
+        }
+        gst_vaapidecode_configure_segment(decode, event);
+        break;
+    default:
+        break;
+    }
+    return gst_pad_push_event(decode->srcpad, event);
+}
+
+static gboolean
+gst_vaapidecode_src_event(GstPad *pad, GstEvent *event)
+{
+    GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
+
+    GST_DEBUG("handle src event '%s'", GST_EVENT_TYPE_NAME(event));
+
+    /* Propagate event upstream */
+    return gst_pad_push_event(decode->sinkpad, event);
+}
+
+static gboolean
+gst_vaapidecode_query (GstPad *pad, GstQuery *query) {
+    GstVaapiDecode *decode = GST_VAAPIDECODE (gst_pad_get_parent_element (pad));
+    gboolean res;
+
+    GST_DEBUG ("sharing display %p", decode->display);
+
+    if (gst_vaapi_reply_to_query (query, decode->display))
+      res = TRUE;
+    else
+      res = gst_pad_query_default (pad, query);
+
+    g_object_unref (decode);
+    return res;
+}
+
+static void
+gst_vaapidecode_init(GstVaapiDecode *decode)
+{
+    GstVaapiDecodeClass *klass = GST_VAAPIDECODE_GET_CLASS(decode);
+    GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
+
+    decode->display             = NULL;
+    decode->decoder             = NULL;
+    decode->decoder_mutex       = NULL;
+    decode->decoder_ready       = NULL;
+    decode->decoder_caps        = NULL;
+    decode->allowed_caps        = NULL;
+    decode->delayed_new_seg     = NULL;
+    decode->is_ready            = FALSE;
+    gst_segment_init(&decode->segment, GST_FORMAT_UNDEFINED);
+
+    /* Pad through which data comes in to the element */
+    decode->sinkpad = gst_pad_new_from_template(
+        gst_element_class_get_pad_template(element_class, "sink"),
+        "sink"
+    );
+    decode->sinkpad_caps = NULL;
+
+    gst_pad_set_getcaps_function(decode->sinkpad, gst_vaapidecode_get_caps);
+    gst_pad_set_setcaps_function(decode->sinkpad, gst_vaapidecode_set_caps);
+    gst_pad_set_chain_function(decode->sinkpad, gst_vaapidecode_chain);
+    gst_pad_set_event_function(decode->sinkpad, gst_vaapidecode_sink_event);
+    gst_pad_set_query_function(decode->sinkpad, gst_vaapidecode_query);
+    gst_element_add_pad(GST_ELEMENT(decode), decode->sinkpad);
+
+    /* Pad through which data goes out of the element */
+    decode->srcpad = gst_pad_new_from_template(
+        gst_element_class_get_pad_template(element_class, "src"),
+        "src"
+    );
+    decode->srcpad_caps = NULL;
+
+    gst_pad_use_fixed_caps(decode->srcpad);
+    gst_pad_set_event_function(decode->srcpad, gst_vaapidecode_src_event);
+    gst_pad_set_query_function(decode->srcpad, gst_vaapidecode_query);
+    gst_element_add_pad(GST_ELEMENT(decode), decode->srcpad);
+}
diff --git a/gst/vaapi/gstvaapidecode.h b/gst/vaapi/gstvaapidecode.h
new file mode 100644 (file)
index 0000000..6d22507
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ *  gstvaapidecode.h - VA-API video decoder
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPIDECODE_H
+#define GST_VAAPIDECODE_H
+
+#include <gst/gst.h>
+#include <gst/gsttask.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapidecoder.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_VAAPIDECODE \
+    (gst_vaapidecode_get_type())
+
+#define GST_VAAPIDECODE(obj)                            \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                  \
+                                GST_TYPE_VAAPIDECODE,   \
+                                GstVaapiDecode))
+
+#define GST_VAAPIDECODE_CLASS(klass)                    \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                   \
+                             GST_TYPE_VAAPIDECODE,      \
+                             GstVaapiDecodeClass))
+
+#define GST_IS_VAAPIDECODE(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_VAAPIDECODE))
+
+#define GST_IS_VAAPIDECODE_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_VAAPIDECODE))
+
+#define GST_VAAPIDECODE_GET_CLASS(obj)                  \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                   \
+                               GST_TYPE_VAAPIDECODE,    \
+                               GstVaapiDecodeClass))
+
+typedef struct _GstVaapiDecode                  GstVaapiDecode;
+typedef struct _GstVaapiDecodeClass             GstVaapiDecodeClass;
+
+struct _GstVaapiDecode {
+    /*< private >*/
+    GstElement          parent_instance;
+
+    GstPad             *sinkpad;
+    GstCaps            *sinkpad_caps;
+    GstPad             *srcpad;
+    GstCaps            *srcpad_caps;
+    GstVaapiDisplay    *display;
+    GstVaapiDecoder    *decoder;
+    GMutex             *decoder_mutex;
+    GCond              *decoder_ready;
+    GstCaps            *decoder_caps;
+    GstCaps            *allowed_caps;
+    GstEvent           *delayed_new_seg;
+    GstSegment          segment;
+    unsigned int        is_ready        : 1;
+};
+
+struct _GstVaapiDecodeClass {
+    /*< private >*/
+    GstElementClass     parent_class;
+};
+
+GType
+gst_vaapidecode_get_type(void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* GST_VAAPIDECODE_H */
diff --git a/gst/vaapi/gstvaapidownload.c b/gst/vaapi/gstvaapidownload.c
new file mode 100644 (file)
index 0000000..56ae902
--- /dev/null
@@ -0,0 +1,620 @@
+/*
+ *  gstvaapidownload.c - VA-API video downloader
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapidownload
+ * @short_description: A VA to video flow filter
+ *
+ * vaapidownload converts from VA surfaces to raw YUV pixels.
+ */
+
+#include "config.h"
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/video/videocontext.h>
+#include <gst/vaapi/gstvaapivideobuffer.h>
+
+#include "gstvaapidownload.h"
+#include "gstvaapipluginutil.h"
+#include "gstvaapipluginbuffer.h"
+
+#define GST_PLUGIN_NAME "vaapidownload"
+#define GST_PLUGIN_DESC "A VA to video flow filter"
+
+GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapidownload);
+#define GST_CAT_DEFAULT gst_debug_vaapidownload
+
+/* ElementFactory information */
+static const GstElementDetails gst_vaapidownload_details =
+    GST_ELEMENT_DETAILS(
+        "VA-API colorspace converter",
+        "Filter/Converter/Video",
+        GST_PLUGIN_DESC,
+        "Gwenole Beauchesne <gwenole.beauchesne@intel.com>");
+
+/* Default templates */
+static const char gst_vaapidownload_yuv_caps_str[] =
+    "video/x-raw-yuv, "
+    "width  = (int) [ 1, MAX ], "
+    "height = (int) [ 1, MAX ]; ";
+
+static const char gst_vaapidownload_vaapi_caps_str[] =
+    GST_VAAPI_SURFACE_CAPS;
+
+static GstStaticPadTemplate gst_vaapidownload_sink_factory =
+    GST_STATIC_PAD_TEMPLATE(
+        "sink",
+        GST_PAD_SINK,
+        GST_PAD_ALWAYS,
+        GST_STATIC_CAPS(gst_vaapidownload_vaapi_caps_str));
+
+static GstStaticPadTemplate gst_vaapidownload_src_factory =
+    GST_STATIC_PAD_TEMPLATE(
+        "src",
+        GST_PAD_SRC,
+        GST_PAD_ALWAYS,
+        GST_STATIC_CAPS(gst_vaapidownload_yuv_caps_str));
+
+typedef struct _TransformSizeCache TransformSizeCache;
+struct _TransformSizeCache {
+    GstCaps            *caps;
+    guint               size;
+};
+
+struct _GstVaapiDownload {
+    /*< private >*/
+    GstBaseTransform    parent_instance;
+
+    GstVaapiDisplay    *display;
+    GstCaps            *allowed_caps;
+    TransformSizeCache  transform_size_cache[2];
+    GstVaapiVideoPool  *images;
+    GstVaapiImageFormat image_format;
+    guint               image_width;
+    guint               image_height;
+    unsigned int        images_reset    : 1;
+};
+
+struct _GstVaapiDownloadClass {
+    /*< private >*/
+    GstBaseTransformClass parent_class;
+};
+
+static void
+gst_vaapidownload_implements_iface_init(GstImplementsInterfaceClass *iface);
+
+static void
+gst_video_context_interface_init(GstVideoContextInterface *iface);
+
+#define GstVideoContextClass GstVideoContextInterface
+G_DEFINE_TYPE_WITH_CODE(
+    GstVaapiDownload,
+    gst_vaapidownload,
+    GST_TYPE_BASE_TRANSFORM,
+    G_IMPLEMENT_INTERFACE(GST_TYPE_IMPLEMENTS_INTERFACE,
+                          gst_vaapidownload_implements_iface_init);
+    G_IMPLEMENT_INTERFACE(GST_TYPE_VIDEO_CONTEXT,
+                          gst_video_context_interface_init));
+
+static gboolean
+gst_vaapidownload_start(GstBaseTransform *trans);
+
+static gboolean
+gst_vaapidownload_stop(GstBaseTransform *trans);
+
+static void
+gst_vaapidownload_before_transform(GstBaseTransform *trans, GstBuffer *buffer);
+
+static GstFlowReturn
+gst_vaapidownload_transform(
+    GstBaseTransform *trans,
+    GstBuffer        *inbuf,
+    GstBuffer        *outbuf
+);
+
+static GstCaps *
+gst_vaapidownload_transform_caps(
+    GstBaseTransform *trans,
+    GstPadDirection   direction,
+    GstCaps          *caps
+);
+
+static gboolean
+gst_vaapidownload_transform_size(
+    GstBaseTransform *trans,
+    GstPadDirection   direction,
+    GstCaps          *caps,
+    guint             size,
+    GstCaps          *othercaps,
+    guint            *othersize
+);
+
+static gboolean
+gst_vaapidownload_set_caps(
+    GstBaseTransform *trans,
+    GstCaps          *incaps,
+    GstCaps          *outcaps
+);
+
+static gboolean
+gst_vaapidownload_query(
+    GstPad   *pad,
+    GstQuery *query
+);
+
+/* GstImplementsInterface interface */
+
+static gboolean
+gst_vaapidownload_implements_interface_supported(
+    GstImplementsInterface *iface,
+    GType                   type
+)
+{
+    return (type == GST_TYPE_VIDEO_CONTEXT);
+}
+
+static void
+gst_vaapidownload_implements_iface_init(GstImplementsInterfaceClass *iface)
+{
+    iface->supported = gst_vaapidownload_implements_interface_supported;
+}
+
+/* GstVideoContext interface */
+
+static void
+gst_vaapidownload_set_video_context(GstVideoContext *context, const gchar *type,
+    const GValue *value)
+{
+  GstVaapiDownload *download = GST_VAAPIDOWNLOAD (context);
+  gst_vaapi_set_display (type, value, &download->display);
+}
+
+static void
+gst_video_context_interface_init(GstVideoContextInterface *iface)
+{
+    iface->set_context = gst_vaapidownload_set_video_context;
+}
+
+static void
+gst_vaapidownload_destroy(GstVaapiDownload *download)
+{
+    guint i;
+
+    for (i = 0; i < G_N_ELEMENTS(download->transform_size_cache); i++) {
+        TransformSizeCache * const tsc = &download->transform_size_cache[i];
+        if (tsc->caps) {
+            gst_caps_unref(tsc->caps);
+            tsc->caps = NULL;
+            tsc->size = 0;
+        }
+    }
+
+    if (download->allowed_caps) {
+        gst_caps_unref(download->allowed_caps);
+        download->allowed_caps = NULL;
+    }
+
+    g_clear_object(&download->images);
+    g_clear_object(&download->display);
+}
+
+static void
+gst_vaapidownload_finalize(GObject *object)
+{
+    gst_vaapidownload_destroy(GST_VAAPIDOWNLOAD(object));
+
+    G_OBJECT_CLASS(gst_vaapidownload_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapidownload_class_init(GstVaapiDownloadClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstBaseTransformClass * const trans_class = GST_BASE_TRANSFORM_CLASS(klass);
+    GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
+    GstPadTemplate *pad_template;
+
+    GST_DEBUG_CATEGORY_INIT(gst_debug_vaapidownload,
+                            GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
+
+    object_class->finalize        = gst_vaapidownload_finalize;
+    trans_class->start            = gst_vaapidownload_start;
+    trans_class->stop             = gst_vaapidownload_stop;
+    trans_class->before_transform = gst_vaapidownload_before_transform;
+    trans_class->transform        = gst_vaapidownload_transform;
+    trans_class->transform_caps   = gst_vaapidownload_transform_caps;
+    trans_class->transform_size   = gst_vaapidownload_transform_size;
+    trans_class->set_caps         = gst_vaapidownload_set_caps;
+
+    gst_element_class_set_details_simple(
+        element_class,
+        gst_vaapidownload_details.longname,
+        gst_vaapidownload_details.klass,
+        gst_vaapidownload_details.description,
+        gst_vaapidownload_details.author
+    );
+
+    /* sink pad */
+    pad_template = gst_static_pad_template_get(&gst_vaapidownload_sink_factory);
+    gst_element_class_add_pad_template(element_class, pad_template);
+    gst_object_unref(pad_template);
+
+    /* src pad */
+    pad_template = gst_static_pad_template_get(&gst_vaapidownload_src_factory);
+    gst_element_class_add_pad_template(element_class, pad_template);
+    gst_object_unref(pad_template);
+}
+
+static void
+gst_vaapidownload_init(GstVaapiDownload *download)
+{
+    GstPad *sinkpad, *srcpad;
+
+    download->display           = NULL;
+    download->allowed_caps      = NULL;
+    download->images            = NULL;
+    download->images_reset      = FALSE;
+    download->image_format      = (GstVaapiImageFormat)0;
+    download->image_width       = 0;
+    download->image_height      = 0;
+
+    /* Override buffer allocator on sink pad */
+    sinkpad = gst_element_get_static_pad(GST_ELEMENT(download), "sink");
+    gst_pad_set_query_function(sinkpad, gst_vaapidownload_query);
+    gst_object_unref(sinkpad);
+
+    /* Override query on src pad */
+    srcpad = gst_element_get_static_pad(GST_ELEMENT(download), "src");
+    gst_pad_set_query_function(srcpad, gst_vaapidownload_query);
+    gst_object_unref(srcpad);
+}
+
+static inline gboolean
+gst_vaapidownload_ensure_display(GstVaapiDownload *download)
+{
+    return gst_vaapi_ensure_display(download, GST_VAAPI_DISPLAY_TYPE_ANY,
+        &download->display);
+}
+
+static gboolean
+gst_vaapidownload_start(GstBaseTransform *trans)
+{
+    GstVaapiDownload * const download = GST_VAAPIDOWNLOAD(trans);
+
+    if (!gst_vaapidownload_ensure_display(download))
+        return FALSE;
+    return TRUE;
+}
+
+static gboolean
+gst_vaapidownload_stop(GstBaseTransform *trans)
+{
+    GstVaapiDownload * const download = GST_VAAPIDOWNLOAD(trans);
+
+    g_clear_object(&download->display);
+
+    return TRUE;
+}
+
+static GstVaapiImageFormat
+get_surface_format(GstVaapiSurface *surface)
+{
+    GstVaapiImage *image;
+    GstVaapiImageFormat format = GST_VAAPI_IMAGE_NV12;
+
+    /* XXX: NV12 is assumed by default */
+    image = gst_vaapi_surface_derive_image(surface);
+    if (image) {
+        format = gst_vaapi_image_get_format(image);
+        g_object_unref(image);
+    }
+    return format;
+}
+
+static gboolean
+gst_vaapidownload_update_src_caps(GstVaapiDownload *download, GstBuffer *buffer)
+{
+    GstVaapiVideoBuffer *vbuffer;
+    GstVaapiSurface *surface;
+    GstVaapiImageFormat format;
+    GstPad *srcpad;
+    GstCaps *in_caps, *out_caps;
+
+    vbuffer = GST_VAAPI_VIDEO_BUFFER(buffer);
+    surface = gst_vaapi_video_buffer_get_surface(vbuffer);
+    if (!surface) {
+        GST_WARNING("failed to retrieve VA surface from buffer");
+        return FALSE;
+    }
+
+    format = get_surface_format(surface);
+    if (format == download->image_format)
+        return TRUE;
+
+    in_caps = GST_BUFFER_CAPS(buffer);
+    if (!in_caps) {
+        GST_WARNING("failed to retrieve caps from buffer");
+        return FALSE;
+    }
+
+    out_caps = gst_vaapi_image_format_get_caps(format);
+    if (!out_caps) {
+        GST_WARNING("failed to create caps from format %" GST_FOURCC_FORMAT,
+                    GST_FOURCC_ARGS(format));
+        return FALSE;
+    }
+
+    if (!gst_vaapi_append_surface_caps(out_caps, in_caps)) {
+        gst_caps_unref(out_caps);
+        return FALSE;
+    }
+
+    /* Try to renegotiate downstream caps */
+    srcpad = gst_element_get_static_pad(GST_ELEMENT(download), "src");
+    gst_pad_set_caps(srcpad, out_caps);
+    gst_object_unref(srcpad);
+
+    gst_vaapidownload_set_caps(GST_BASE_TRANSFORM(download), in_caps, out_caps);
+    gst_caps_replace(&download->allowed_caps, out_caps);
+    gst_caps_unref(out_caps);
+    return TRUE;
+}
+
+static void
+gst_vaapidownload_before_transform(GstBaseTransform *trans, GstBuffer *buffer)
+{
+    GstVaapiDownload * const download = GST_VAAPIDOWNLOAD(trans);
+
+    gst_vaapidownload_update_src_caps(download, buffer);
+}
+
+static GstFlowReturn
+gst_vaapidownload_transform(
+    GstBaseTransform *trans,
+    GstBuffer        *inbuf,
+    GstBuffer        *outbuf
+)
+{
+    GstVaapiDownload * const download = GST_VAAPIDOWNLOAD(trans);
+    GstVaapiVideoBuffer *vbuffer;
+    GstVaapiSurface *surface;
+    GstVaapiImage *image = NULL;
+    gboolean success;
+
+    vbuffer = GST_VAAPI_VIDEO_BUFFER(inbuf);
+    surface = gst_vaapi_video_buffer_get_surface(vbuffer);
+    if (!surface)
+        return GST_FLOW_UNEXPECTED;
+
+    image = gst_vaapi_video_pool_get_object(download->images);
+    if (!image)
+        return GST_FLOW_UNEXPECTED;
+    if (!gst_vaapi_surface_get_image(surface, image))
+        goto error_get_image;
+
+    success = gst_vaapi_image_get_buffer(image, outbuf, NULL);
+    gst_vaapi_video_pool_put_object(download->images, image);
+    if (!success)
+        goto error_get_buffer;
+    return GST_FLOW_OK;
+
+error_get_image:
+    {
+        GST_WARNING("failed to download %" GST_FOURCC_FORMAT " image "
+                    "from surface 0x%08x",
+                    GST_FOURCC_ARGS(gst_vaapi_image_get_format(image)),
+                    gst_vaapi_surface_get_id(surface));
+        gst_vaapi_video_pool_put_object(download->images, image);
+        return GST_FLOW_UNEXPECTED;
+    }
+
+error_get_buffer:
+    {
+        GST_WARNING("failed to transfer image to output video buffer");
+        return GST_FLOW_UNEXPECTED;
+    }
+}
+
+static GstCaps *
+gst_vaapidownload_transform_caps(
+    GstBaseTransform *trans,
+    GstPadDirection   direction,
+    GstCaps          *caps
+)
+{
+    GstVaapiDownload * const download = GST_VAAPIDOWNLOAD(trans);
+    GstPad *srcpad;
+    GstCaps *allowed_caps, *inter_caps, *out_caps = NULL;
+    GstStructure *structure;
+
+    g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
+
+    structure = gst_caps_get_structure(caps, 0);
+
+    if (direction == GST_PAD_SINK) {
+        if (!gst_structure_has_name(structure, GST_VAAPI_SURFACE_CAPS_NAME))
+            return NULL;
+        if (!gst_vaapidownload_ensure_display(download))
+            return NULL;
+        out_caps = gst_caps_from_string(gst_vaapidownload_yuv_caps_str);
+
+        /* Build up allowed caps */
+        /* XXX: we don't know the decoded surface format yet so we
+           expose whatever VA images we support */
+        if (download->allowed_caps)
+            allowed_caps = gst_caps_ref(download->allowed_caps);
+        else {
+            allowed_caps = gst_vaapi_display_get_image_caps(download->display);
+            if (!allowed_caps)
+                return NULL;
+        }
+        inter_caps = gst_caps_intersect(out_caps, allowed_caps);
+        gst_caps_unref(allowed_caps);
+        gst_caps_unref(out_caps);
+        out_caps = inter_caps;
+
+        /* Intersect with allowed caps from the peer, if any */
+        srcpad = gst_element_get_static_pad(GST_ELEMENT(download), "src");
+        allowed_caps = gst_pad_peer_get_caps(srcpad);
+        if (allowed_caps) {
+            inter_caps = gst_caps_intersect(out_caps, allowed_caps);
+            gst_caps_unref(allowed_caps);
+            gst_caps_unref(out_caps);
+            out_caps = inter_caps;
+        }
+    }
+    else {
+        if (!gst_structure_has_name(structure, "video/x-raw-yuv"))
+            return NULL;
+        out_caps = gst_caps_from_string(gst_vaapidownload_vaapi_caps_str);
+
+        structure = gst_caps_get_structure(out_caps, 0);
+        gst_structure_set(
+            structure,
+            "type", G_TYPE_STRING, "vaapi",
+            "opengl", G_TYPE_BOOLEAN, USE_GLX,
+            NULL
+        );
+    }
+
+    if (!gst_vaapi_append_surface_caps(out_caps, caps)) {
+        gst_caps_unref(out_caps);
+        return NULL;
+    }
+    return out_caps;
+}
+
+static gboolean
+gst_vaapidownload_ensure_image_pool(GstVaapiDownload *download, GstCaps *caps)
+{
+    GstStructure * const structure = gst_caps_get_structure(caps, 0);
+    GstVaapiImageFormat format;
+    gint width, height;
+
+    format = gst_vaapi_image_format_from_caps(caps);
+    gst_structure_get_int(structure, "width",  &width);
+    gst_structure_get_int(structure, "height", &height);
+
+    if (format != download->image_format ||
+        width  != download->image_width  ||
+        height != download->image_height) {
+        download->image_format = format;
+        download->image_width  = width;
+        download->image_height = height;
+        g_clear_object(&download->images);
+        download->images = gst_vaapi_image_pool_new(download->display, caps);
+        if (!download->images)
+            return FALSE;
+        download->images_reset = TRUE;
+    }
+    return TRUE;
+}
+
+static inline gboolean
+gst_vaapidownload_negotiate_buffers(
+    GstVaapiDownload  *download,
+    GstCaps          *incaps,
+    GstCaps          *outcaps
+)
+{
+    if (!gst_vaapidownload_ensure_image_pool(download, outcaps))
+        return FALSE;
+    return TRUE;
+}
+
+static gboolean
+gst_vaapidownload_set_caps(
+    GstBaseTransform *trans,
+    GstCaps          *incaps,
+    GstCaps          *outcaps
+)
+{
+    GstVaapiDownload * const download = GST_VAAPIDOWNLOAD(trans);
+
+    if (!gst_vaapidownload_negotiate_buffers(download, incaps, outcaps))
+        return FALSE;
+    return TRUE;
+}
+
+static gboolean
+gst_vaapidownload_transform_size(
+    GstBaseTransform *trans,
+    GstPadDirection   direction,
+    GstCaps          *caps,
+    guint             size,
+    GstCaps          *othercaps,
+    guint            *othersize
+)
+{
+    GstVaapiDownload * const download = GST_VAAPIDOWNLOAD(trans);
+    GstStructure * const structure = gst_caps_get_structure(othercaps, 0);
+    GstVideoFormat format;
+    gint width, height;
+    guint i;
+
+    /* Lookup in cache */
+    for (i = 0; i < G_N_ELEMENTS(download->transform_size_cache); i++) {
+        TransformSizeCache * const tsc = &download->transform_size_cache[i];
+        if (tsc->caps && tsc->caps == othercaps) {
+            *othersize = tsc->size;
+            return TRUE;
+        }
+    }
+
+    /* Compute requested buffer size */
+    if (gst_structure_has_name(structure, GST_VAAPI_SURFACE_CAPS_NAME))
+        *othersize = 0;
+    else {
+        if (!gst_video_format_parse_caps(othercaps, &format, &width, &height))
+            return FALSE;
+        *othersize = gst_video_format_get_size(format, width, height);
+    }
+
+    /* Update cache */
+    for (i = 0; i < G_N_ELEMENTS(download->transform_size_cache); i++) {
+        TransformSizeCache * const tsc = &download->transform_size_cache[i];
+        if (!tsc->caps) {
+            gst_caps_replace(&tsc->caps, othercaps);
+            tsc->size = *othersize;
+        }
+    }
+    return TRUE;
+}
+
+static gboolean
+gst_vaapidownload_query(GstPad *pad, GstQuery *query)
+{
+    GstVaapiDownload * const download = GST_VAAPIDOWNLOAD(gst_pad_get_parent_element(pad));
+    gboolean res;
+
+    GST_DEBUG("sharing display %p", download->display);
+
+    if (gst_vaapi_reply_to_query(query, download->display))
+        res = TRUE;
+    else
+        res = gst_pad_query_default(pad, query);
+
+    g_object_unref(download);
+    return res;
+
+}
diff --git a/gst/vaapi/gstvaapidownload.h b/gst/vaapi/gstvaapidownload.h
new file mode 100644 (file)
index 0000000..7a594c4
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  gstvaapidownload.h - VA-API video downloader
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This program 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 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser 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
+*/
+
+#ifndef GST_VAAPIDOWNLOAD_H
+#define GST_VAAPIDOWNLOAD_H
+
+#include <gst/base/gstbasetransform.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapisurface.h>
+#include <gst/vaapi/gstvaapiimagepool.h>
+#include <gst/vaapi/gstvaapisurfacepool.h>
+#include <gst/vaapi/gstvaapivideobuffer.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_VAAPIDOWNLOAD \
+    (gst_vaapidownload_get_type())
+
+#define GST_VAAPIDOWNLOAD(obj)                          \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                  \
+                                GST_TYPE_VAAPIDOWNLOAD, \
+                                GstVaapiDownload))
+
+#define GST_VAAPIDOWNLOAD_CLASS(klass)                  \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                   \
+                             GST_TYPE_VAAPIDOWNLOAD,    \
+                             GstVaapiDownloadClass))
+
+#define GST_IS_VAAPIDOWNLOAD(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_VAAPIDOWNLOAD))
+
+#define GST_IS_VAAPIDOWNLOAD_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_VAAPIDOWNLOAD))
+
+#define GST_VAAPIDOWNLOAD_GET_CLASS(obj)                \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                   \
+                               GST_TYPE_VAAPIDOWNLOAD,  \
+                               GstVaapiDownloadClass))
+
+typedef struct _GstVaapiDownload                GstVaapiDownload;
+typedef struct _GstVaapiDownloadClass           GstVaapiDownloadClass;
+
+GType
+gst_vaapidownload_get_type(void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* GST_VAAPIDOWNLOAD_H */
diff --git a/gst/vaapi/gstvaapiencode.c b/gst/vaapi/gstvaapiencode.c
new file mode 100644 (file)
index 0000000..a524dc9
--- /dev/null
@@ -0,0 +1,728 @@
+/*
+ *  gstvaapiencode.c - VA-API video encoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "gstvaapiencode.h"
+
+#include <string.h>
+#include <X11/Xlib.h>
+#include <gst/video/videocontext.h>
+#include "gst/vaapi/gstvaapibaseencoder.h"
+
+#include "gstvaapiencode_h264.h"
+#include "gstvaapiencode_h263.h"
+#include "gstvaapiencode_mpeg4.h"
+#include "gstvaapipluginutil.h"
+#include "gstvaapipluginbuffer.h"
+
+/* gst_debug
+     GST_DEBUG_CATEGORY_STATIC (gst_vaapi_encode_debug)
+     #define GST_CAT_DEFAULT gst_vaapi_encode_debug
+         //class_init
+         GST_DEBUG_CATEGORY_INIT (gst_vaapi_encode_debug, "vaapiencode", 0,
+          "vaapiencode element");
+*/
+GST_DEBUG_CATEGORY_STATIC (gst_vaapi_encode_debug);
+#define GST_CAT_DEFAULT gst_vaapi_encode_debug
+
+#define GST_VAAPI_ENCODE_GET_PRIVATE(obj)                 \
+    (G_TYPE_INSTANCE_GET_PRIVATE ((obj),                  \
+                                  GST_TYPE_VAAPI_ENCODE,  \
+                                  GstVaapiEncodePrivate))
+
+typedef struct _GstVaapiEncodePrivate GstVaapiEncodePrivate;
+
+#define GstVideoContextClass GstVideoContextInterface
+
+#define GST_VAAPI_ENCODE_MUTEX_LOCK(encode)  \
+    G_STMT_START{ g_mutex_lock((encode)->mutex); }G_STMT_END
+
+#define GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode) \
+    G_STMT_START{ g_mutex_unlock((encode)->mutex); }G_STMT_END
+
+#define GST_VAAPI_ENCODE_IDLE_BUF_WAIT(encode)                       \
+        G_STMT_START {                                               \
+            g_cond_wait((encode)->idle_buf_added, (encode)->mutex);  \
+        } G_STMT_END
+
+#define GST_VAAPI_ENCODE_IDLE_BUF_SIGNAL(encode)                     \
+        G_STMT_START {                                               \
+            g_cond_signal((encode)->idle_buf_added);                 \
+        } G_STMT_END
+
+#define GST_VAAPI_ENCODE_BUSY_BUF_WAIT(encode)                       \
+        G_STMT_START {                                               \
+            g_cond_wait((encode)->busy_buf_added, (encode)->mutex);  \
+        } G_STMT_END
+
+#define GST_VAAPI_ENCODE_BUSY_BUF_SIGNAL(encode)                     \
+        G_STMT_START {                                               \
+            g_cond_signal((encode)->busy_buf_added);                 \
+        } G_STMT_END
+
+GST_BOILERPLATE_WITH_INTERFACE(
+    GstVaapiEncode,
+    gst_vaapi_encode,
+    GstElement,
+    GST_TYPE_ELEMENT,
+    GstVideoContext,
+    GST_TYPE_VIDEO_CONTEXT,
+    gst_video_context)
+
+
+enum {
+    PROP_0,
+};
+
+static char*
+_encode_dump_caps(GstCaps *cpas)
+{
+  guint i = 0, j = 0;
+  GstStructure const *structure;
+  GValue const *value;
+  static char caps_string[4096*5];
+  char *tmp;
+
+  char *cur = caps_string;
+  memset(caps_string, 0, sizeof(caps_string));
+  for (i = 0; i < gst_caps_get_size(cpas); i++) {
+    structure = gst_caps_get_structure(cpas, i);
+    const char* caps_name = gst_structure_get_name (structure);
+    sprintf(cur, "cap_%02d:%s\n", i, caps_name);
+    cur += strlen(cur);
+
+    for (j = 0; j < gst_structure_n_fields(structure); j++) {
+      const char* name = gst_structure_nth_field_name(structure, j);
+      value = gst_structure_get_value(structure, name);
+      tmp = gst_value_serialize(value);
+      sprintf(cur, "\t%s:%s(%s)\n", name, tmp, G_VALUE_TYPE_NAME(value));
+      cur += strlen(cur);
+      g_free(tmp);
+    }
+  }
+
+  return caps_string;
+}
+
+/* context(display) interface */
+static void
+gst_vaapi_encode_set_video_context(
+    GstVideoContext *context,
+    const gchar *type,
+    const GValue *value
+)
+{
+    GstVaapiEncode *encode = GST_VAAPI_ENCODE (context);
+    GstVaapiDisplay *display = NULL;
+
+    gst_vaapi_set_display (type, value, &display);
+    gst_vaapi_encoder_set_display(encode->encoder, display);
+}
+
+static gboolean
+gst_video_context_supported (GstVaapiEncode *decode, GType iface_type)
+{
+  return (iface_type == GST_TYPE_VIDEO_CONTEXT);
+}
+
+static void
+gst_video_context_interface_init(GstVideoContextInterface *iface)
+{
+    iface->set_context = gst_vaapi_encode_set_video_context;
+}
+
+static gboolean
+gst_vaapi_encode_query (GstPad *pad, GstQuery *query)
+{
+    GstVaapiEncode *encode = GST_VAAPI_ENCODE (gst_pad_get_parent_element (pad));
+    gboolean res;
+
+    if (encode->encoder &&
+        gst_vaapi_reply_to_query(query, ENCODER_DISPLAY(encode->encoder)))
+      res = TRUE;
+    else
+      res = gst_pad_query_default (pad, query);
+
+    g_object_unref (encode);
+    return res;
+}
+
+static inline gboolean
+gst_vaapi_encode_ensure_display(GstVaapiEncode *encode)
+{
+    return gst_vaapi_ensure_display(encode,
+                                    GST_VAAPI_DISPLAY_TYPE_ANY,
+                                    &ENCODER_DISPLAY(encode->encoder));
+}
+
+static void
+gst_vaapi_encode_buffer_loop(GstVaapiEncode *encode)
+{
+  GstBuffer *buf = NULL;
+  EncoderStatus encoder_ret = ENCODER_NO_ERROR;
+  gboolean is_running;
+
+  GST_VAAPI_ENCODE_MUTEX_LOCK(encode);
+  is_running = encode->is_running;
+  GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode);
+  if (!is_running)
+    return;
+
+  encoder_ret =
+      gst_vaapi_encoder_get_encoded_buffer(
+          encode->encoder,
+          &buf);
+  if (encoder_ret < ENCODER_NO_ERROR) {
+    ENCODER_LOG_ERROR("get encoded buffer failed");
+    return;
+  }
+  GST_VAAPI_ENCODE_IDLE_BUF_SIGNAL(encode);
+
+  if (!buf)
+    return;
+
+  GST_VAAPI_ENCODE_MUTEX_LOCK(encode);
+  if (encode->first_src_frame) { /* Set src pad caps and codec data */
+    GstBuffer *codec_data = NULL;
+    if ((ENCODER_NO_ERROR ==
+         gst_vaapi_encoder_get_codec_data(encode->encoder, &codec_data)) &&
+        codec_data) {
+      gst_caps_set_simple(encode->srcpad_caps,
+                          "codec_data",GST_TYPE_BUFFER, codec_data,
+                          NULL);
+    }
+    gst_pad_set_caps (encode->srcpad, encode->srcpad_caps);
+    GST_BUFFER_CAPS(buf) = gst_caps_ref(encode->srcpad_caps);
+    ENCODER_LOG_INFO("gst_vaapi_encode_chain 1st push-buffer caps,\n%s",
+                     _encode_dump_caps(encode->srcpad_caps));
+    encode->first_src_frame = FALSE;
+  }
+  GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode);
+  ENCODER_LOG_DEBUG(
+      "output:%" GST_TIME_FORMAT ", 0x%s",
+      GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buf)),
+      vaapi_encoder_dump_bytes(GST_BUFFER_DATA(buf),
+                               (GST_BUFFER_SIZE(buf) > 16 ?
+                                16: GST_BUFFER_SIZE(buf)))
+                   );
+  gst_pad_push(encode->srcpad, buf);
+}
+
+static gboolean
+_encoder_status_callback(
+    GstVaapiBaseEncoder* encoder,
+    EncoderStatus status,
+    void* user_data
+)
+{
+  GstVaapiEncode *encode = (GstVaapiEncode *)user_data;
+  gboolean ret = FALSE;
+
+  GST_VAAPI_ENCODE_MUTEX_LOCK(encode);
+
+  if (!encode->is_running) {
+    ret = FALSE;
+    goto end;
+  }
+
+  switch (status) {
+  case ENCODER_NO_IDLE_BUF:
+    GST_VAAPI_ENCODE_IDLE_BUF_WAIT(encode);
+    ret = TRUE;
+    break;
+
+  case ENCODER_NO_BUSY_BUF:
+    GST_VAAPI_ENCODE_BUSY_BUF_WAIT(encode);
+    ret = TRUE;
+    break;
+
+  default:
+    ret = FALSE;
+    goto end;
+  }
+
+  if (!encode->is_running)
+    ret = FALSE;
+
+end:
+  GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode);
+
+  return ret;
+}
+
+static gboolean
+gst_vaapi_encode_set_caps(GstPad *sink_pad, GstCaps *caps)
+{
+  GstVaapiEncode *encode = GST_VAAPI_ENCODE(GST_OBJECT_PARENT(sink_pad));
+  GstVaapiEncodeClass *encode_class = GST_VAAPI_ENCODE_GET_CLASS(encode);
+  GstStructure *structure = NULL, *src_struct = NULL;
+  gint width = 0, height = 0;
+  gint fps_n = 0, fps_d = 0;
+  const GValue *fps_value = NULL, *format_value;
+  guint32 format = 0;
+  gboolean ret = TRUE;
+  EncoderStatus encoder_ret = ENCODER_NO_ERROR;
+
+  GST_VAAPI_ENCODE_MUTEX_LOCK(encode);
+
+  encode->sinkpad_caps = caps;
+  gst_caps_ref(caps);
+  ENCODER_LOG_INFO("gst_vaapi_encode_set_caps,\n%s",
+                   _encode_dump_caps(caps));
+
+  structure = gst_caps_get_structure (caps, 0);
+
+  if (gst_structure_has_name(structure, GST_VAAPI_BUFFER_SHARING_CAPS_NAME))
+    encode->is_buffer_sharing = TRUE;
+  else
+    encode->is_buffer_sharing = FALSE;
+
+  if (gst_structure_get_int (structure, "width", &width)) {
+    encode->encoder->width = width;
+  }
+  if (gst_structure_get_int (structure, "height", &height)) {
+    encode->encoder->height = height;
+  }
+  fps_value = gst_structure_get_value (structure, "framerate");
+  if (fps_value) {
+    fps_n = gst_value_get_fraction_numerator (fps_value);
+    fps_d = gst_value_get_fraction_denominator (fps_value);
+    encode->encoder->frame_rate = fps_n/fps_d;
+  }
+  format_value = gst_structure_get_value (structure, "format");
+  if (format_value && GST_IS_VAAPI_ENCODE_H264(encode)) {
+    ENCODER_CHECK_STATUS((format_value &&
+                          GST_TYPE_FOURCC == G_VALUE_TYPE(format_value)),
+                         FALSE,
+                         "1st buffer caps' format type is not fourcc.");
+    format = gst_value_get_fourcc (format_value);
+    if (format) {
+      gst_vaapi_base_encoder_set_input_format(
+          GST_VAAPI_BASE_ENCODER(encode->encoder),
+          format);
+    }
+  }
+
+  /*set src pad caps*/
+  if (encode->srcpad_caps) {
+    gst_caps_unref(encode->srcpad_caps);
+  }
+  encode->srcpad_caps =
+      gst_caps_copy(gst_pad_get_pad_template_caps(encode->srcpad));
+  src_struct = gst_caps_get_structure(encode->srcpad_caps, 0);
+  gst_structure_set(src_struct,
+                    "width", G_TYPE_INT, width,
+                    "height", G_TYPE_INT, height,
+                    "framerate", GST_TYPE_FRACTION, fps_n, fps_d,
+                    NULL);
+  if (encode_class->set_encoder_src_caps) {
+    encode_class->set_encoder_src_caps(encode, encode->srcpad_caps);
+  }
+
+  /*set display and initialize encoder*/
+  ENCODER_CHECK_STATUS(gst_vaapi_encode_ensure_display(encode),
+                       FALSE,
+                       "encoder ensure display failed on setting caps.");
+
+  gst_vaapi_base_encoder_set_notify_status(
+      GST_VAAPI_BASE_ENCODER(encode->encoder),
+      _encoder_status_callback,
+      encode);
+  gst_vaapi_base_encoder_set_buffer_sharing(
+      GST_VAAPI_BASE_ENCODER(encode->encoder),
+      encode->is_buffer_sharing);
+
+  encoder_ret = gst_vaapi_encoder_initialize(encode->encoder);
+  ENCODER_CHECK_STATUS (ENCODER_NO_ERROR == encoder_ret,
+                        FALSE,
+                        "gst_vaapi_encoder_initialize failed.");
+
+  encoder_ret = gst_vaapi_encoder_open(encode->encoder);
+  ENCODER_CHECK_STATUS (ENCODER_NO_ERROR == encoder_ret,
+                        FALSE,
+                        "gst_vaapi_encoder_open failed.");
+
+  encode->is_running = TRUE;
+
+end:
+  GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode);
+  if (ret) {
+    ret = gst_pad_start_task(encode->srcpad,
+                             (GstTaskFunction)gst_vaapi_encode_buffer_loop,
+                             encode);
+       if (!ret)
+          ENCODER_LOG_INFO("gstvaapiencode start task failed.");
+  }
+  return ret;
+}
+
+static GstCaps *
+gst_vaapi_encode_get_caps(GstPad *sink_pad)
+{
+  GstCaps *caps = NULL;
+  GstVaapiEncode * const encode =
+      GST_VAAPI_ENCODE(GST_OBJECT_PARENT(sink_pad));
+
+  GST_VAAPI_ENCODE_MUTEX_LOCK(encode);
+
+  if (encode->sinkpad_caps) {
+    gst_caps_ref(encode->sinkpad_caps);
+    ENCODER_LOG_INFO("get caps,\n%s",
+                     _encode_dump_caps(encode->sinkpad_caps));
+    caps = encode->sinkpad_caps;
+  } else
+    caps = gst_caps_copy(gst_pad_get_pad_template_caps(sink_pad));
+
+  GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode);
+  return caps;
+}
+
+static GstStateChangeReturn
+gst_vaapi_encode_change_state(
+    GstElement *element,
+    GstStateChange transition
+)
+{
+  GstVaapiEncode * const encode = GST_VAAPI_ENCODE(element);
+  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+
+  switch (transition) {
+  case GST_STATE_CHANGE_READY_TO_PAUSED:
+    break;
+  case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+    break;
+  case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+    break;
+  case GST_STATE_CHANGE_PAUSED_TO_READY: {
+    GST_VAAPI_ENCODE_MUTEX_LOCK (encode);
+    encode->is_running = FALSE;
+    encode->is_buffer_sharing = FALSE;
+    GST_VAAPI_ENCODE_BUSY_BUF_SIGNAL(encode);
+    GST_VAAPI_ENCODE_IDLE_BUF_SIGNAL(encode);
+    GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode);
+    gst_pad_stop_task(encode->srcpad);
+    break;
+  }
+  default:
+    break;
+  }
+
+  ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
+  if (ret != GST_STATE_CHANGE_SUCCESS)
+    return ret;
+
+  switch (transition) {
+  case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+    break;
+  case GST_STATE_CHANGE_PAUSED_TO_READY:
+    gst_vaapi_encoder_close(encode->encoder);
+    GST_VAAPI_ENCODE_MUTEX_LOCK(encode);
+    if (encode->video_pool) {
+      g_object_unref(encode->video_pool);
+      encode->video_pool = NULL;
+    }
+    GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode);
+    break;
+  default:
+    break;
+  }
+
+  return GST_STATE_CHANGE_SUCCESS;
+}
+
+static GstFlowReturn
+gst_vaapi_encode_chain(GstPad *sink_pad, GstBuffer *buf)
+{
+  GstFlowReturn ret = GST_FLOW_OK;
+  GstVaapiEncode *encode = GST_VAAPI_ENCODE(GST_OBJECT_PARENT(sink_pad));
+  EncoderStatus encoder_ret = ENCODER_NO_ERROR;
+  gboolean is_buffer_sharing;
+
+  ENCODER_ASSERT(encode && encode->encoder);
+
+  GST_VAAPI_ENCODE_MUTEX_LOCK(encode);
+  is_buffer_sharing = encode->is_buffer_sharing;
+  GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode);
+  
+  if (!is_buffer_sharing && !GST_VAAPI_IS_VIDEO_BUFFER(buf)) {
+    ENCODER_LOG_ERROR("gst_vaapi_encode_chain parameter doesn't have video buffer.");
+    ret = ENCODER_NO_ERROR;
+    goto end;
+  }
+
+  /*encoding frames*/
+  encoder_ret = gst_vaapi_encoder_encode(encode->encoder, buf);
+  GST_VAAPI_ENCODE_BUSY_BUF_SIGNAL(encode);
+  ENCODER_CHECK_STATUS (ENCODER_NO_ERROR <= encoder_ret,
+                        GST_FLOW_ERROR,
+                        "gst_vaapi_encoder_encode failed.");
+
+end:
+  gst_buffer_unref(buf);
+  return ret;
+}
+
+static gboolean
+gst_vaapi_encode_ensure_video_pool(
+    GstVaapiEncode *encode,
+    GstCaps *caps)
+{
+  GstStructure *structure;
+  gint width = 0, height = 0;
+
+  g_return_val_if_fail(caps, FALSE);
+
+  structure = gst_caps_get_structure(caps, 0);
+  g_return_val_if_fail(structure, FALSE);
+
+  if (encode->video_pool)
+    return TRUE;
+
+  if (!gst_structure_get_int(structure, "width",  &width) ||
+      !gst_structure_get_int(structure, "height", &height))
+    return FALSE;
+
+  encode->video_pool =
+      gst_vaapi_surface_pool_new(ENCODER_DISPLAY(encode->encoder), caps);
+  if (!encode->video_pool)
+    return FALSE;
+
+  return TRUE;
+}
+
+static GstFlowReturn
+gst_vaapi_encode_buffer_alloc(
+    GstPad * pad,
+    guint64 offset,
+    guint size,
+    GstCaps * caps,
+    GstBuffer ** buf
+)
+{
+  GstVaapiEncode * const encode = GST_VAAPI_ENCODE(GST_OBJECT_PARENT(pad));
+  GstStructure *structure = NULL;
+  GstBuffer *video_buffer = NULL;
+  GstFlowReturn ret = GST_FLOW_ERROR;
+
+  if (!caps)
+    return GST_FLOW_ERROR;
+
+  structure = gst_caps_get_structure(caps, 0);
+  if (!structure ||
+      (!gst_structure_has_name(structure, GST_VAAPI_SURFACE_CAPS_NAME) &&
+       !gst_structure_has_name(structure, GST_VAAPI_BUFFER_SHARING_CAPS_NAME)))
+    return GST_FLOW_ERROR;
+
+  ENCODER_CHECK_STATUS(
+      gst_vaapi_encode_ensure_display(encode),
+      GST_FLOW_ERROR,
+      "gst_vaapi_encode_buffer_alloc can't ensure display");
+
+  GST_VAAPI_ENCODE_MUTEX_LOCK(encode);
+  if (!gst_vaapi_encode_ensure_video_pool(encode, caps))
+    goto unlock;
+
+  video_buffer = gst_vaapi_video_buffer_new_from_pool(encode->video_pool);
+
+unlock:
+  GST_VAAPI_ENCODE_MUTEX_UNLOCK(encode);
+
+  ENCODER_CHECK_STATUS(video_buffer,
+                       GST_FLOW_ERROR,
+                       "gst_vaapi_encode_buffer_alloc failed.");
+
+  if (gst_structure_has_name(structure, GST_VAAPI_BUFFER_SHARING_CAPS_NAME)) {
+    ENCODER_CHECK_STATUS(
+        gst_vaapi_video_buffer_ensure_pointer(GST_VAAPI_VIDEO_BUFFER(video_buffer)),
+        GST_FLOW_ERROR,
+        "gst_vaapi_video_buffer_ensure_pointer failed.");
+  }
+
+  if (caps) {
+    gst_buffer_set_caps(video_buffer, caps);
+  }
+  *buf = video_buffer;
+  ret = GST_FLOW_OK;
+
+end:
+  return ret;
+}
+
+static void
+gst_vaapi_encode_finalize(GObject *object)
+{
+  GstVaapiEncode * const encode = GST_VAAPI_ENCODE(object);
+
+  if (encode->sinkpad_caps) {
+    gst_caps_unref(encode->sinkpad_caps);
+    encode->sinkpad_caps = NULL;
+  }
+  encode->sinkpad = NULL;
+
+  if (encode->srcpad_caps) {
+    gst_caps_unref(encode->srcpad_caps);
+    encode->srcpad_caps = NULL;
+  }
+  encode->srcpad = NULL;
+
+  if (encode->video_pool)
+    g_object_unref(encode->video_pool);
+
+  if (encode->encoder) {
+      gst_vaapi_encoder_close(encode->encoder);
+      gst_vaapi_encoder_uninitialize(encode->encoder);
+      gst_vaapi_encoder_unref(encode->encoder);
+      encode->encoder = NULL;
+  }
+
+  g_mutex_free(encode->mutex);
+  g_cond_free(encode->idle_buf_added);
+  g_cond_free(encode->busy_buf_added);
+
+  G_OBJECT_CLASS(parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_encode_init(
+    GstVaapiEncode *encode,
+    GstVaapiEncodeClass *klass
+)
+{
+  GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
+
+  encode->sinkpad_caps       = NULL;
+  encode->srcpad_caps        = NULL;
+  encode->first_src_frame    = TRUE;
+  encode->is_running         = FALSE;
+  encode->is_buffer_sharing  = FALSE;
+
+  encode->encoder = NULL;
+  encode->video_pool = NULL;
+
+  encode->mutex = g_mutex_new();
+  encode->idle_buf_added = g_cond_new();
+  encode->busy_buf_added = g_cond_new();
+
+  /*sink pad */
+  encode->sinkpad = gst_pad_new_from_template(
+      gst_element_class_get_pad_template(element_class, "sink"),
+      "sink"
+  );
+  gst_pad_set_getcaps_function(encode->sinkpad, gst_vaapi_encode_get_caps);
+  gst_pad_set_setcaps_function(encode->sinkpad, gst_vaapi_encode_set_caps);
+  gst_pad_set_chain_function(encode->sinkpad, gst_vaapi_encode_chain);
+  gst_pad_set_bufferalloc_function(encode->sinkpad,
+                                   gst_vaapi_encode_buffer_alloc);
+  /*gst_pad_set_event_function(encode->sinkpad, gst_vaapi_encode_sink_event); */
+  /*gst_pad_use_fixed_caps(encode->sinkpad);*/
+  gst_pad_set_query_function(encode->sinkpad, gst_vaapi_encode_query);
+  gst_element_add_pad(GST_ELEMENT(encode), encode->sinkpad);
+
+  /* src pad */
+  encode->srcpad = gst_pad_new_from_template(
+      gst_element_class_get_pad_template(element_class, "src"),
+      "src"
+  );
+  encode->srcpad_caps = NULL;
+
+  gst_pad_use_fixed_caps(encode->srcpad);
+  /*gst_pad_set_event_function(encode->srcpad, gst_vaapi_encode_src_event);*/
+  gst_pad_set_query_function(encode->srcpad, gst_vaapi_encode_query);
+  gst_element_add_pad(GST_ELEMENT(encode), encode->srcpad);
+}
+
+static void
+gst_vaapi_encode_set_property(
+    GObject *object,
+    guint prop_id,
+    const GValue *value,
+    GParamSpec *pspec)
+{
+  GstVaapiEncode *encode = GST_VAAPI_ENCODE(object);
+  ENCODER_ASSERT(encode->encoder);
+
+  switch (prop_id) {
+  }
+}
+
+static void
+gst_vaapi_encode_get_property (
+    GObject * object,
+    guint prop_id,
+    GValue * value,
+    GParamSpec * pspec
+)
+{
+  GstVaapiEncode *encode = GST_VAAPI_ENCODE(object);
+  ENCODER_ASSERT(encode->encoder);
+
+  switch (prop_id) {
+  }
+}
+
+static void
+gst_vaapi_encode_base_init(gpointer klass)
+{
+  #if 0
+  GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
+
+  gst_element_class_set_details(element_class, &gst_vaapi_encode_details);
+
+  /* sink pad */
+  gst_element_class_add_pad_template(
+      element_class,
+      gst_static_pad_template_get(&gst_vaapi_encode_sink_factory)
+  );
+
+  /* src pad */
+  gst_element_class_add_pad_template(
+      element_class,
+      gst_static_pad_template_get(&gst_vaapi_encode_src_factory)
+  );
+  #endif
+}
+
+static void
+gst_vaapi_encode_class_init(GstVaapiEncodeClass *klass)
+{
+  GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+  GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
+
+  object_class->finalize      = gst_vaapi_encode_finalize;
+  object_class->set_property  = gst_vaapi_encode_set_property;
+  object_class->get_property  = gst_vaapi_encode_get_property;
+
+  GST_DEBUG_CATEGORY_INIT (gst_vaapi_encode_debug,
+                           "vaapiencode",
+                           0,
+                           "vaapiencode element");
+
+  element_class->change_state = gst_vaapi_encode_change_state;
+
+  klass->set_encoder_src_caps = NULL;
+
+  /* Registering debug symbols for function pointers */
+  GST_DEBUG_REGISTER_FUNCPTR (gst_vaapi_encode_change_state);
+  GST_DEBUG_REGISTER_FUNCPTR (gst_vaapi_encode_get_caps);
+  GST_DEBUG_REGISTER_FUNCPTR (gst_vaapi_encode_set_caps);
+  GST_DEBUG_REGISTER_FUNCPTR (gst_vaapi_encode_chain);
+  GST_DEBUG_REGISTER_FUNCPTR (gst_vaapi_encode_buffer_alloc);
+}
diff --git a/gst/vaapi/gstvaapiencode.h b/gst/vaapi/gstvaapiencode.h
new file mode 100644 (file)
index 0000000..7127ad3
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *  gstvaapiencode.h - VA-API video encoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_ENCODE_H
+#define GST_VAAPI_ENCODE_H
+
+#include <gst/gst.h>
+#include "gst/vaapi/gstvaapiencoder.h"
+
+G_BEGIN_DECLS
+
+/* Default templates */
+#define GST_CAPS_CODEC(CODEC)          \
+    CODEC ", "                         \
+    "width  = (int) [ 1, MAX ], "      \
+    "height = (int) [ 1, MAX ]; "
+
+#define GST_TYPE_VAAPI_ENCODE \
+    (gst_vaapi_encode_get_type())
+
+#define GST_IS_VAAPI_ENCODE(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_ENCODE))
+
+#define GST_IS_VAAPI_ENCODE_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VAAPI_ENCODE))
+
+#define GST_VAAPI_ENCODE_GET_CLASS(obj)                 \
+    (G_TYPE_INSTANCE_GET_CLASS ((obj),                  \
+                                GST_TYPE_VAAPI_ENCODE,  \
+                                GstVaapiEncodeClass))
+
+#define GST_VAAPI_ENCODE(obj)                           \
+    (G_TYPE_CHECK_INSTANCE_CAST ((obj),                 \
+                                 GST_TYPE_VAAPI_ENCODE, \
+                                 GstVaapiEncode))
+
+#define GST_VAAPI_ENCODE_CLASS(klass)                   \
+    (G_TYPE_CHECK_CLASS_CAST ((klass),                  \
+                               GST_TYPE_VAAPI_ENCODE,   \
+                               GstVaapiEncodeClass))
+
+typedef struct _GstVaapiEncode        GstVaapiEncode;
+typedef struct _GstVaapiEncodeClass   GstVaapiEncodeClass;
+
+struct _GstVaapiEncode {
+    GstElement          parent_instance;
+
+    GstPad             *sinkpad;
+    GstCaps            *sinkpad_caps;
+
+    GstPad             *srcpad;
+    GstCaps            *srcpad_caps;
+
+    GstVaapiEncoder    *encoder;
+    gboolean            first_src_frame;
+
+    GstVaapiVideoPool  *video_pool;
+
+    /*encode chain lock*/
+    GMutex             *mutex;
+    GCond              *idle_buf_added;
+    GCond              *busy_buf_added;
+    gboolean            is_running;
+    gboolean            is_buffer_sharing;
+};
+
+struct _GstVaapiEncodeClass {
+    GstElementClass     parent_class;
+    gboolean          (*set_encoder_src_caps)(GstVaapiEncode* encode, GstCaps *caps);
+};
+
+GType gst_vaapi_encode_get_type(void);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_ENCODE_H */
+
diff --git a/gst/vaapi/gstvaapiencode_h263.c b/gst/vaapi/gstvaapiencode_h263.c
new file mode 100644 (file)
index 0000000..eeb5a00
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ *  gstvaapiencode_h263.c - VA-API H.263 encoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "gstvaapiencode_h263.h"
+#include "gst/vaapi/gstvaapiencoder_h263.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_vaapi_h263_encode_debug);
+#define GST_CAT_DEFAULT gst_vaapi_h263_encode_debug
+
+#define GST_VAAPI_ENCODE_GET_PRIVATE(obj)                  \
+    (G_TYPE_INSTANCE_GET_PRIVATE ((obj),                   \
+                                  GST_TYPE_VAAPI_ENCODE,   \
+                                  GstVaapiEncodePrivate))
+
+static const char gst_vaapi_encode_h263_sink_caps_str[] =
+    GST_VAAPI_SURFACE_CAPS "; "
+    GST_VAAPI_BUFFER_SHARING_CAPS;
+
+static const GstElementDetails gst_vaapi_encode_h263_details =
+    GST_ELEMENT_DETAILS(
+      "VA-API h263 encoder",
+      "Codec/Encoder/Video",
+      "A VA-API based h263 encoder",
+      "Feng Yuan <feng.yuan@intel.com>");
+
+
+static const char gst_vaapi_encode_h263_src_caps_str[] =
+    GST_CAPS_CODEC("video/x-h263");
+
+static GstStaticPadTemplate gst_vaapi_encode_h263_sink_factory =
+    GST_STATIC_PAD_TEMPLATE(
+        "sink",
+        GST_PAD_SINK,
+        GST_PAD_ALWAYS,
+        GST_STATIC_CAPS(gst_vaapi_encode_h263_sink_caps_str));
+
+static GstStaticPadTemplate gst_vaapi_encode_h263_src_factory =
+    GST_STATIC_PAD_TEMPLATE(
+        "src",
+        GST_PAD_SRC,
+        GST_PAD_ALWAYS,
+        GST_STATIC_CAPS(gst_vaapi_encode_h263_src_caps_str));
+
+/* h263 encode */
+GST_BOILERPLATE(
+    GstVaapiEncodeH263,
+    gst_vaapi_encode_h263,
+    GstVaapiEncode,
+    GST_TYPE_VAAPI_ENCODE)
+
+enum {
+    H263_PROP_0,
+    H263_PROP_BITRATE,
+    H263_PROP_INTRA_PERIOD,
+    H263_PROP_INIT_QP,
+    H263_PROP_MIN_QP,
+};
+
+static void
+gst_vaapi_encode_h263_init(
+    GstVaapiEncodeH263 *h263_encode,
+    GstVaapiEncodeH263Class *klass
+)
+{
+  GstVaapiEncode *encode = GST_VAAPI_ENCODE(h263_encode);
+  encode->encoder = GST_VAAPI_ENCODER(gst_vaapi_encoder_h263_new());
+  ENCODER_ASSERT(encode->encoder);
+}
+
+static void
+gst_vaapi_encode_h263_set_property(
+    GObject *object,
+    guint prop_id,
+    const GValue *value,
+    GParamSpec *pspec
+)
+{
+  GstVaapiEncode *base = GST_VAAPI_ENCODE(object);
+  GstVaapiEncoderH263 *encoder = GST_VAAPI_ENCODER_H263(base->encoder);
+
+  ENCODER_ASSERT(encoder);
+
+  switch (prop_id) {
+    case H263_PROP_BITRATE: {
+      encoder->bitrate = g_value_get_uint(value);
+    }
+      break;
+
+    case H263_PROP_INTRA_PERIOD: {
+      encoder->intra_period = g_value_get_uint(value);
+    }
+      break;
+
+    case H263_PROP_INIT_QP: {
+      encoder->init_qp = g_value_get_uint(value);
+    }
+      break;
+
+    case H263_PROP_MIN_QP: {
+      encoder->min_qp = g_value_get_uint(value);
+    }
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_vaapi_encode_h263_get_property (
+    GObject * object,
+    guint prop_id,
+    GValue * value,
+    GParamSpec * pspec
+)
+{
+  GstVaapiEncode *base = GST_VAAPI_ENCODE(object);
+  GstVaapiEncoderH263 *encoder = GST_VAAPI_ENCODER_H263(base->encoder);
+  ENCODER_ASSERT(encoder);
+
+  switch (prop_id) {
+    case H263_PROP_BITRATE:
+      g_value_set_uint (value, encoder->bitrate);
+      break;
+
+    case H263_PROP_INTRA_PERIOD:
+      g_value_set_uint (value, encoder->intra_period);
+      break;
+
+    case H263_PROP_INIT_QP:
+      g_value_set_uint (value, encoder->init_qp);
+      break;
+
+    case H263_PROP_MIN_QP:
+      g_value_set_uint (value, encoder->min_qp);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_vaapi_encode_h263_base_init(gpointer klass)
+{
+  GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
+
+  gst_element_class_set_details(element_class, &gst_vaapi_encode_h263_details);
+
+  /* sink pad */
+  gst_element_class_add_pad_template(
+      element_class,
+      gst_static_pad_template_get(&gst_vaapi_encode_h263_sink_factory)
+  );
+
+  /* src pad */
+  gst_element_class_add_pad_template(
+      element_class,
+      gst_static_pad_template_get(&gst_vaapi_encode_h263_src_factory)
+  );
+}
+
+static void
+gst_vaapi_encode_h263_class_init(GstVaapiEncodeH263Class *klass)
+{
+  GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+
+  GST_DEBUG_CATEGORY_INIT (gst_vaapi_h263_encode_debug,
+                           "vaapih263encode",
+                           0,
+                           "vaapih263encode element");
+
+  /* object_class->finalize      = gst_vaapi_encode_h263_finalize; */
+  object_class->set_property  = gst_vaapi_encode_h263_set_property;
+  object_class->get_property  = gst_vaapi_encode_h263_get_property;
+
+  g_object_class_install_property (
+      object_class,
+      H263_PROP_BITRATE,
+      g_param_spec_uint (
+          "bitrate",
+          "H263 encoding bitrate(kpbs)",
+          "H263 encoding bitrate(kbps), (0, auto-calculate)",
+          0,
+          100*1024,
+          0,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (
+      object_class,
+      H263_PROP_INTRA_PERIOD,
+      g_param_spec_uint (
+          "intra-period",
+          "H263 encoding intra-period",
+          "H263 encoding intra-period",
+          1,
+          300,
+          H263_DEFAULT_INTRA_PERIOD,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (
+      object_class,
+      H263_PROP_INIT_QP,
+      g_param_spec_uint (
+          "init-qp",
+          "H263 init-qp",
+          "H263 init-qp",
+          1,
+          51,
+          H263_DEFAULT_INIT_QP,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (
+      object_class,
+      H263_PROP_MIN_QP,
+      g_param_spec_uint (
+          "min-qp",
+          "H263 min-qp",
+          "H263 min-qp",
+          1,
+          51,
+          H263_DEFAULT_MIN_QP,
+          G_PARAM_READWRITE));
+
+}
diff --git a/gst/vaapi/gstvaapiencode_h263.h b/gst/vaapi/gstvaapiencode_h263.h
new file mode 100644 (file)
index 0000000..5d4657f
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ *  gstvaapiencode_h263.h - VA-API H.263 encoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_ENCODE_H263_H
+#define GST_VAAPI_ENCODE_H263_H
+
+#include <gst/gst.h>
+#include "gstvaapiencode.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_VAAPI_ENCODE_H263 \
+    (gst_vaapi_encode_h263_get_type())
+
+#define GST_IS_VAAPI_ENCODE_H263(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_ENCODE_H263))
+
+#define GST_IS_VAAPI_ENCODE_H263_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VAAPI_ENCODE_H263))
+
+#define GST_VAAPI_ENCODE_H263_GET_CLASS(obj)                   \
+    (G_TYPE_INSTANCE_GET_CLASS ((obj),                         \
+                                GST_TYPE_VAAPI_ENCODE_H263,    \
+                                GstVaapiEncodeH263Class))
+
+#define GST_VAAPI_ENCODE_H263(obj)                             \
+    (G_TYPE_CHECK_INSTANCE_CAST ((obj),                        \
+                                 GST_TYPE_VAAPI_ENCODE_H263,   \
+                                 GstVaapiEncodeH263))
+
+#define GST_VAAPI_ENCODE_H263_CLASS(klass)                     \
+    (G_TYPE_CHECK_CLASS_CAST ((klass),                         \
+                              GST_TYPE_VAAPI_ENCODE_H263,      \
+                              GstVaapiEncodeH263Class))
+
+typedef struct _GstVaapiEncodeH263        GstVaapiEncodeH263;
+typedef struct _GstVaapiEncodeH263Class   GstVaapiEncodeH263Class;
+
+struct _GstVaapiEncodeH263 {
+  GstVaapiEncode parent;
+};
+
+struct _GstVaapiEncodeH263Class {
+    GstVaapiEncodeClass     parent_class;
+};
+
+GType gst_vaapi_encode_h263_get_type(void);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_ENCODE_H263_H */
diff --git a/gst/vaapi/gstvaapiencode_h264.c b/gst/vaapi/gstvaapiencode_h264.c
new file mode 100644 (file)
index 0000000..0bb7475
--- /dev/null
@@ -0,0 +1,457 @@
+/*
+ *  gstvaapiencode_h264.c - VA-API H.264 encoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "gstvaapiencode_h264.h"
+#include "gst/vaapi/gstvaapiencoder_h264.h"
+#include "gst/vaapi/gstvaapivalue.h"
+
+#include <string.h>
+
+GST_DEBUG_CATEGORY_STATIC (gst_vaapi_h264_encode_debug);
+#define GST_CAT_DEFAULT gst_vaapi_h264_encode_debug
+
+static const char gst_vaapi_encode_h264_sink_caps_str[] =
+    GST_VAAPI_SURFACE_CAPS "; "
+    GST_VAAPI_BUFFER_SHARING_CAPS;
+
+static const GstElementDetails gst_vaapi_encode_h264_details =
+    GST_ELEMENT_DETAILS(
+        "VA-API h264 encoder",
+        "Codec/Encoder/Video",
+        "A VA-API based h264 encoder",
+        "Feng Yuan<feng.yuan@intel.com>");
+
+
+static const char gst_vaapi_encode_h264_src_caps_str[] =
+    GST_CAPS_CODEC("video/x-h264");
+
+static GstStaticPadTemplate gst_vaapi_encode_h264_sink_factory =
+    GST_STATIC_PAD_TEMPLATE(
+        "sink",
+        GST_PAD_SINK,
+        GST_PAD_ALWAYS,
+        GST_STATIC_CAPS(gst_vaapi_encode_h264_sink_caps_str));
+
+static GstStaticPadTemplate gst_vaapi_encode_h264_src_factory =
+    GST_STATIC_PAD_TEMPLATE(
+        "src",
+        GST_PAD_SRC,
+        GST_PAD_ALWAYS,
+        GST_STATIC_CAPS(gst_vaapi_encode_h264_src_caps_str));
+
+/* h264 encode */
+GST_BOILERPLATE(
+    GstVaapiEncodeH264,
+    gst_vaapi_encode_h264,
+    GstVaapiEncode,
+    GST_TYPE_VAAPI_ENCODE)
+
+enum {
+    H264_PROP_0,
+    H264_PROP_PROFILE,
+    H264_PROP_LEVEL,
+    H264_PROP_RATE_CONTROL,
+    H264_PROP_BITRATE,
+    H264_PROP_INTRA_PERIOD,
+    H264_PROP_INIT_QP,
+    H264_PROP_MIN_QP,
+    H264_PROP_SLICE_NUM,
+    H264_PROP_B_FRAME_NUM,
+};
+
+static void
+gst_vaapi_encode_h264_init(
+    GstVaapiEncodeH264 *h264_encode,
+    GstVaapiEncodeH264Class *klass
+)
+{
+  GstVaapiEncode *encode = GST_VAAPI_ENCODE(h264_encode);
+  encode->encoder = GST_VAAPI_ENCODER(gst_vaapi_encoder_h264_new());
+  ENCODER_ASSERT(encode->encoder);
+}
+
+static void
+gst_vaapi_encode_h264_finalize(GObject *object)
+{
+  //GstVaapiEncodeH264 * const h264_encode = GST_VAAPI_ENCODE_H264(object);
+  G_OBJECT_CLASS(parent_class)->finalize(object);
+}
+
+
+static inline gboolean
+h264_check_valid_profile(guint profile)
+{
+   static const guint limit_profiles[] = {
+         H264_PROFILE_BASELINE,
+         H264_PROFILE_MAIN,
+         H264_PROFILE_HIGH
+        };
+   guint n_profiles = sizeof(limit_profiles)/sizeof(limit_profiles[0]);
+   guint i;
+   for (i = 0; i < n_profiles; ++i) {
+     if (limit_profiles[i] == profile)
+       return TRUE;
+   }
+   return FALSE;
+}
+
+static inline gboolean
+h264_check_valid_level(guint level)
+{
+  static const guint limit_levels[] = {
+        H264_LEVEL_10,
+        H264_LEVEL_11,
+        H264_LEVEL_12,
+        H264_LEVEL_13,
+        H264_LEVEL_20,
+        H264_LEVEL_21,
+        H264_LEVEL_22,
+        H264_LEVEL_30,
+        H264_LEVEL_31,
+        H264_LEVEL_32,
+        H264_LEVEL_40,
+        H264_LEVEL_41,
+        H264_LEVEL_42,
+        H264_LEVEL_50,
+        H264_LEVEL_51
+       };
+  guint n_levels = sizeof(limit_levels)/sizeof(limit_levels[0]);
+  guint i;
+  for (i = 0; i < n_levels; ++i) {
+    if (limit_levels[i] == level)
+      return TRUE;
+  }
+  return FALSE;
+
+}
+
+
+static void
+gst_vaapi_encode_h264_set_property(
+    GObject *object,
+    guint prop_id,
+    const GValue *value,
+    GParamSpec *pspec
+)
+{
+  GstVaapiEncode *encode = GST_VAAPI_ENCODE(object);
+  GstVaapiEncoderH264 *h264encoder = GST_VAAPI_ENCODER_H264(encode->encoder);
+
+  ENCODER_ASSERT(h264encoder);
+
+  switch (prop_id) {
+    case H264_PROP_PROFILE: {
+      guint profile = g_value_get_uint(value);
+      if (h264_check_valid_profile(profile)) {
+        h264encoder->profile = profile;
+      } else {
+        ENCODER_LOG_ERROR("h264encode set property <profile> failed.");
+      }
+    }
+      break;
+
+    case H264_PROP_LEVEL: {
+      guint level = g_value_get_uint(value);
+      if (h264_check_valid_level(level)) {
+        h264encoder->level= level;
+      } else {
+        ENCODER_LOG_ERROR("h264encode set property <level> failed.");
+      }
+    }
+      break;
+
+    case H264_PROP_RATE_CONTROL: {
+      ENCODER_RATE_CONTROL(h264encoder) = g_value_get_enum(value);
+    }
+      break;
+
+    case H264_PROP_BITRATE: {
+      h264encoder->bitrate = g_value_get_uint(value);
+    }
+      break;
+
+    case H264_PROP_INTRA_PERIOD: {
+      h264encoder->intra_period = g_value_get_uint(value);
+    }
+      break;
+
+    case H264_PROP_INIT_QP: {
+      h264encoder->init_qp = g_value_get_uint(value);
+    }
+      break;
+
+    case H264_PROP_MIN_QP: {
+      h264encoder->min_qp = g_value_get_uint(value);
+    }
+      break;
+
+    case H264_PROP_SLICE_NUM: {
+      h264encoder->slice_num= g_value_get_uint(value);
+    }
+      break;
+
+    case H264_PROP_B_FRAME_NUM: {
+      h264encoder->b_frame_num= g_value_get_uint(value);
+    }
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_vaapi_encode_h264_get_property (
+    GObject * object,
+    guint prop_id,
+    GValue * value,
+    GParamSpec * pspec
+)
+{
+  GstVaapiEncode *encode = GST_VAAPI_ENCODE(object);
+  GstVaapiEncoderH264 *h264encoder = GST_VAAPI_ENCODER_H264(encode->encoder);
+  ENCODER_ASSERT(h264encoder);
+
+  switch (prop_id) {
+    case H264_PROP_PROFILE:
+      g_value_set_uint (value, h264encoder->profile);
+      break;
+
+    case H264_PROP_LEVEL:
+      g_value_set_uint (value, h264encoder->level);
+      break;
+
+    case H264_PROP_RATE_CONTROL:
+      g_value_set_enum(value, ENCODER_RATE_CONTROL(h264encoder));
+      break;
+
+    case H264_PROP_BITRATE:
+      g_value_set_uint (value, h264encoder->bitrate);
+      break;
+
+    case H264_PROP_INTRA_PERIOD:
+      g_value_set_uint (value, h264encoder->intra_period);
+      break;
+
+    case H264_PROP_INIT_QP:
+      g_value_set_uint (value, h264encoder->init_qp);
+      break;
+
+    case H264_PROP_MIN_QP:
+      g_value_set_uint (value, h264encoder->min_qp);
+      break;
+
+    case H264_PROP_SLICE_NUM:
+      g_value_set_uint (value, h264encoder->slice_num);
+      break;
+
+    case H264_PROP_B_FRAME_NUM:
+      g_value_set_uint (value, h264encoder->b_frame_num);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static gboolean
+gst_vaapi_encode_h264_set_src_caps(
+    GstVaapiEncode* encode,
+    GstCaps *caps
+)
+{
+  GstVaapiEncoderH264 *h264encoder = GST_VAAPI_ENCODER_H264(encode->encoder);
+  GstCaps *peer_caps, *allowed_caps;
+  GstStructure *s;
+  const gchar *stream_format;
+
+  g_return_val_if_fail(caps,FALSE);
+  peer_caps = gst_pad_peer_get_caps_reffed(encode->srcpad);
+  if (peer_caps) {
+    allowed_caps = gst_caps_intersect(peer_caps, caps);
+    if (allowed_caps) {
+      allowed_caps = gst_caps_make_writable(allowed_caps);
+      gst_pad_fixate_caps(encode->srcpad, caps);
+      s = gst_caps_get_structure (allowed_caps, 0);
+      stream_format = gst_structure_get_string (s, "stream-format");
+      if (stream_format) {
+        if (!strcmp (stream_format, "avc")) {
+            gst_vaapi_encoder_h264_set_avc_flag(h264encoder, TRUE);
+        } else if (!strcmp (stream_format, "byte-stream")) {
+            gst_vaapi_encoder_h264_set_avc_flag(h264encoder, FALSE);
+        }
+      }
+      gst_caps_unref(allowed_caps);
+    }
+    gst_caps_unref(peer_caps);
+  }
+  gst_caps_set_simple(caps, "stream-format",
+                            G_TYPE_STRING,
+                            (gst_vaapi_encoder_h264_get_avc_flag(h264encoder) ? "avc" : "byte-stream"),
+                            "alignment", G_TYPE_STRING, "au",
+                            NULL);
+  return TRUE;
+}
+
+static void
+gst_vaapi_encode_h264_base_init(gpointer klass)
+{
+  GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
+
+  gst_element_class_set_details(element_class, &gst_vaapi_encode_h264_details);
+
+  /* sink pad */
+  gst_element_class_add_pad_template(
+      element_class,
+      gst_static_pad_template_get(&gst_vaapi_encode_h264_sink_factory)
+  );
+
+  /* src pad */
+  gst_element_class_add_pad_template(
+      element_class,
+      gst_static_pad_template_get(&gst_vaapi_encode_h264_src_factory)
+  );
+}
+
+static void
+gst_vaapi_encode_h264_class_init(GstVaapiEncodeH264Class *klass)
+{
+  GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+  GstVaapiEncodeClass *const encode_class = GST_VAAPI_ENCODE_CLASS(klass);
+  GST_DEBUG_CATEGORY_INIT (gst_vaapi_h264_encode_debug,
+                           "vaapih264encode",
+                           0,
+                           "vaapih264encode element");
+
+  object_class->finalize      = gst_vaapi_encode_h264_finalize;
+  object_class->set_property  = gst_vaapi_encode_h264_set_property;
+  object_class->get_property  = gst_vaapi_encode_h264_get_property;
+
+  encode_class->set_encoder_src_caps = gst_vaapi_encode_h264_set_src_caps;
+
+  g_object_class_install_property (
+      object_class,
+      H264_PROP_PROFILE,
+      g_param_spec_uint (
+          "profile",
+          "H264 Profile",
+          "Profile supports: 66(Baseline), 77(Main), 100(High)",
+          H264_PROFILE_BASELINE,
+          H264_PROFILE_HIGH10,
+          H264_DEFAULT_PROFILE,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (
+      object_class,
+      H264_PROP_LEVEL,
+      g_param_spec_uint (
+          "level",
+          "H264 level idc",
+          "Level idc supports: 10, 11, 12, 13, 20, 21, 22, 30, 31, 32, 40, 41",
+          H264_LEVEL_10,
+          H264_LEVEL_41,
+          H264_DEFAULT_LEVEL,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (
+      object_class,
+      H264_PROP_RATE_CONTROL,
+      g_param_spec_enum ("rate-control",
+          "rate-control",
+          "Rate control mode",
+          GST_VAAPI_TYPE_RATE_CONTROL,
+          GST_VAAPI_RATECONTROL_NONE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (
+      object_class,
+      H264_PROP_BITRATE,
+      g_param_spec_uint (
+          "bitrate",
+          "H264 encoding bitrate(kbps)",
+          "H264 encoding bitrate(kbps), (0, auto-calculate)",
+          0,
+          100*1024,
+          0,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (
+      object_class,
+      H264_PROP_INTRA_PERIOD,
+      g_param_spec_uint (
+          "intra-period",
+          "H264 encoding intra-period",
+          "H264 encoding intra-period",
+          1,
+          300,
+          H264_DEFAULT_INTRA_PERIOD,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (
+      object_class,
+      H264_PROP_INIT_QP,
+      g_param_spec_uint (
+          "init-qp",
+          "H264 init-qp",
+          "H264 init-qp",
+          1,
+          51,
+          H264_DEFAULT_INIT_QP,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (
+      object_class,
+      H264_PROP_MIN_QP,
+      g_param_spec_uint (
+          "min-qp",
+          "H264 min-qp",
+          "H264 min-qp",
+          1,
+          51,
+          H264_DEFAULT_MIN_QP,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (
+      object_class,
+      H264_PROP_SLICE_NUM,
+      g_param_spec_uint (
+          "slice-num",
+          "H264 slice num",
+          "H264 slice num",
+          1,
+          200,
+          1,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (
+      object_class,
+      H264_PROP_B_FRAME_NUM,
+      g_param_spec_uint (
+          "b-frame-num",
+          "B frams num",
+          "B frams num",
+          0,
+          10,
+          0,
+          G_PARAM_READWRITE));
+}
diff --git a/gst/vaapi/gstvaapiencode_h264.h b/gst/vaapi/gstvaapiencode_h264.h
new file mode 100644 (file)
index 0000000..ba4b383
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *  gstvaapiencode_h264.h - VA-API H.264 encoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_ENCODE_H264_H
+#define GST_VAAPI_ENCODE_H264_H
+
+#include <gst/gst.h>
+#include "gstvaapiencode.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_VAAPI_ENCODE_H264 \
+    (gst_vaapi_encode_h264_get_type())
+
+#define GST_IS_VAAPI_ENCODE_H264(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_ENCODE_H264))
+
+#define GST_IS_VAAPI_ENCODE_H264_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VAAPI_ENCODE_H264))
+
+#define GST_VAAPI_ENCODE_H264_GET_CLASS(obj)                   \
+    (G_TYPE_INSTANCE_GET_CLASS ((obj),                         \
+                                GST_TYPE_VAAPI_ENCODE_H264,    \
+                                GstVaapiEncodeH264Class))
+
+#define GST_VAAPI_ENCODE_H264(obj)                             \
+    (G_TYPE_CHECK_INSTANCE_CAST ((obj),                        \
+                                 GST_TYPE_VAAPI_ENCODE_H264,   \
+                                 GstVaapiEncodeH264))
+
+#define GST_VAAPI_ENCODE_H264_CLASS(klass)                     \
+    (G_TYPE_CHECK_CLASS_CAST ((klass),                         \
+                              GST_TYPE_VAAPI_ENCODE_H264,      \
+                              GstVaapiEncodeH264Class))
+
+
+typedef struct _GstVaapiEncodeH264        GstVaapiEncodeH264;
+typedef struct _GstVaapiEncodeH264Class   GstVaapiEncodeH264Class;
+
+struct _GstVaapiEncodeH264 {
+  GstVaapiEncode parent;
+};
+
+struct _GstVaapiEncodeH264Class {
+    GstVaapiEncodeClass     parent_class;
+};
+
+GType gst_vaapi_encode_h264_get_type(void);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_ENCODE_H264_H */
diff --git a/gst/vaapi/gstvaapiencode_mpeg4.c b/gst/vaapi/gstvaapiencode_mpeg4.c
new file mode 100644 (file)
index 0000000..74cb7f7
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ *  gstvaapiencode_mpeg4.c - VA-API MPEG-4 encoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "gstvaapiencode_mpeg4.h"
+#include "gst/vaapi/gstvaapiencoder_mpeg4.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_vaapi_encode_mpeg4_debug);
+#define GST_CAT_DEFAULT gst_vaapi_encode_mpeg4_debug
+
+
+static const char gst_vaapi_encode_mpeg4_sink_caps_str[] =
+    GST_VAAPI_SURFACE_CAPS "; "
+    GST_VAAPI_BUFFER_SHARING_CAPS;
+
+static const GstElementDetails gst_vaapi_encode_mpeg4_details =
+    GST_ELEMENT_DETAILS(
+        "VA-API mpeg4 encoder",
+        "Codec/Encoder/Video",
+        "A VA-API based mpeg4 encoder",
+        "Feng Yuan<feng.yuan@intel.com>");
+
+
+static const char gst_vaapi_encode_mpeg4_src_caps_str[] =
+    GST_CAPS_CODEC("video/mpeg, mpegversion=4");
+
+static GstStaticPadTemplate gst_vaapi_encode_mpeg4_sink_factory =
+    GST_STATIC_PAD_TEMPLATE(
+        "sink",
+        GST_PAD_SINK,
+        GST_PAD_ALWAYS,
+        GST_STATIC_CAPS(gst_vaapi_encode_mpeg4_sink_caps_str));
+
+static GstStaticPadTemplate gst_vaapi_encode_mpeg4_src_factory =
+    GST_STATIC_PAD_TEMPLATE(
+        "src",
+        GST_PAD_SRC,
+        GST_PAD_ALWAYS,
+        GST_STATIC_CAPS(gst_vaapi_encode_mpeg4_src_caps_str));
+
+
+/* mpeg4 encode */
+GST_BOILERPLATE(
+    GstVaapiEncodeMpeg4,
+    gst_vaapi_encode_mpeg4,
+    GstVaapiEncode,
+    GST_TYPE_VAAPI_ENCODE)
+
+enum {
+    MPEG4_PROP_0,
+    MPEG4_PROP_PROFILE,
+    MPEG4_PROP_BITRATE,
+    MPEG4_PROP_INTRA_PERIOD,
+    MPEG4_PROP_INIT_QP,
+    MPEG4_PROP_MIN_QP,
+};
+
+static void
+gst_vaapi_encode_mpeg4_init(
+    GstVaapiEncodeMpeg4 *mpeg4_encode,
+    GstVaapiEncodeMpeg4Class *klass)
+{
+  GstVaapiEncode *encode = GST_VAAPI_ENCODE(mpeg4_encode);
+  encode->encoder = GST_VAAPI_ENCODER(gst_vaapi_encoder_mpeg4_new());
+  ENCODER_ASSERT(encode->encoder);
+}
+
+static void
+gst_vaapi_encode_mpeg4_finalize(GObject *object)
+{
+  //GstVaapiEncodeMpeg4 * const mpeg4_encode = GST_VAAPI_ENCODE_MPEG4(object);
+  G_OBJECT_CLASS(parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_encode_mpeg4_set_property(
+    GObject *object,
+    guint prop_id,
+    const GValue *value,
+    GParamSpec *pspec
+)
+{
+  GstVaapiEncode *encode = GST_VAAPI_ENCODE(object);
+  GstVaapiEncoderMpeg4 *mpeg4encoder = GST_VAAPI_ENCODER_MPEG4(encode->encoder);
+
+  ENCODER_ASSERT(mpeg4encoder);
+
+  switch (prop_id) {
+    case MPEG4_PROP_PROFILE: {
+      mpeg4encoder->profile = g_value_get_uint(value);
+    }
+      break;
+
+    case MPEG4_PROP_BITRATE: {
+      mpeg4encoder->bitrate = g_value_get_uint(value);
+    }
+      break;
+
+    case MPEG4_PROP_INTRA_PERIOD: {
+      mpeg4encoder->intra_period = g_value_get_uint(value);
+    }
+      break;
+
+    case MPEG4_PROP_INIT_QP: {
+      mpeg4encoder->init_qp = g_value_get_uint(value);
+    }
+      break;
+
+    case MPEG4_PROP_MIN_QP: {
+      mpeg4encoder->min_qp = g_value_get_uint(value);
+    }
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_vaapi_encode_mpeg4_get_property(
+    GObject * object,
+    guint prop_id,
+    GValue * value,
+    GParamSpec * pspec
+)
+{
+  GstVaapiEncode *encode = GST_VAAPI_ENCODE(object);
+  GstVaapiEncoderMpeg4 *mpeg4encoder = GST_VAAPI_ENCODER_MPEG4(encode->encoder);
+  ENCODER_ASSERT(mpeg4encoder);
+
+  switch (prop_id) {
+    case MPEG4_PROP_PROFILE:
+      g_value_set_uint (value, mpeg4encoder->profile);
+      break;
+
+    case MPEG4_PROP_BITRATE:
+      g_value_set_uint (value, mpeg4encoder->bitrate);
+      break;
+
+    case MPEG4_PROP_INTRA_PERIOD:
+      g_value_set_uint (value, mpeg4encoder->intra_period);
+      break;
+
+    case MPEG4_PROP_INIT_QP:
+      g_value_set_uint (value, mpeg4encoder->init_qp);
+      break;
+
+    case MPEG4_PROP_MIN_QP:
+      g_value_set_uint (value, mpeg4encoder->min_qp);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_vaapi_encode_mpeg4_base_init(gpointer klass)
+{
+  GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
+
+  gst_element_class_set_details(element_class, &gst_vaapi_encode_mpeg4_details);
+
+  /* sink pad */
+  gst_element_class_add_pad_template(
+      element_class,
+      gst_static_pad_template_get(&gst_vaapi_encode_mpeg4_sink_factory)
+  );
+
+  /* src pad */
+  gst_element_class_add_pad_template(
+      element_class,
+      gst_static_pad_template_get(&gst_vaapi_encode_mpeg4_src_factory)
+  );
+}
+
+static void
+gst_vaapi_encode_mpeg4_class_init(GstVaapiEncodeMpeg4Class *klass)
+{
+  GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+
+  GST_DEBUG_CATEGORY_INIT (gst_vaapi_encode_mpeg4_debug,
+                           "vaapimpeg4encode",
+                           0,
+                           "vaapimpeg4encode element");
+
+  object_class->finalize      = gst_vaapi_encode_mpeg4_finalize;
+  object_class->set_property  = gst_vaapi_encode_mpeg4_set_property;
+  object_class->get_property  = gst_vaapi_encode_mpeg4_get_property;
+
+
+  g_object_class_install_property (
+      object_class,
+      MPEG4_PROP_PROFILE,
+      g_param_spec_uint (
+          "profile",
+          "MPEG4 Profile",
+          "Profile supports: 2(Baseline), 3(ASP)",
+          2,
+          3,
+          2,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (
+      object_class,
+      MPEG4_PROP_BITRATE,
+      g_param_spec_uint (
+          "bitrate",
+          "MPEG4 encoding bitrate(kpbs)",
+          "MPEG4 encoding bitrate(kpbs), (0, auto-calculate)",
+          0,
+          100*1024,
+          0,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (
+      object_class,
+      MPEG4_PROP_INTRA_PERIOD,
+      g_param_spec_uint (
+          "intra-period",
+          "MPEG4 encoding intra-period",
+          "MPEG4 encoding intra-period",
+          1,
+          300,
+          MPEG4_DEFAULT_INTRA_PERIOD,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (
+      object_class,
+      MPEG4_PROP_INIT_QP,
+      g_param_spec_uint (
+          "init-qp",
+          "MPEG4 init-qp",
+          "MPEG4 init-qp",
+          1,
+          51,
+          MPEG4_DEFAULT_INIT_QP,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (
+      object_class,
+      MPEG4_PROP_MIN_QP,
+      g_param_spec_uint (
+          "min-qp",
+          "MPEG4 min-qp",
+          "MPEG4 min-qp",
+          1,
+          51,
+          MPEG4_DEFAULT_MIN_QP,
+          G_PARAM_READWRITE));
+}
diff --git a/gst/vaapi/gstvaapiencode_mpeg4.h b/gst/vaapi/gstvaapiencode_mpeg4.h
new file mode 100644 (file)
index 0000000..e13a406
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *  gstvaapiencode_mpeg4.h - VA-API MPEG-4 encoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_ENCODE_MPEG4_H
+#define GST_VAAPI_ENCODE_MPEG4_H
+
+#include <gst/gst.h>
+#include "gstvaapiencode.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_VAAPI_ENCODE_MPEG4 \
+    (gst_vaapi_encode_mpeg4_get_type())
+
+#define GST_IS_VAAPI_ENCODE_MPEG4(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_ENCODE_MPEG4))
+
+#define GST_IS_VAAPI_ENCODE_MPEG4_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VAAPI_ENCODE_MPEG4))
+
+#define GST_VAAPI_ENCODE_MPEG4_GET_CLASS(obj)                  \
+    (G_TYPE_INSTANCE_GET_CLASS ((obj),                         \
+                                GST_TYPE_VAAPI_ENCODE_MPEG4,   \
+                                GstVaapiEncodeMpeg4Class))
+
+#define GST_VAAPI_ENCODE_MPEG4(obj)                            \
+    (G_TYPE_CHECK_INSTANCE_CAST ((obj),                        \
+                                 GST_TYPE_VAAPI_ENCODE_MPEG4,  \
+                                 GstVaapiEncodeMpeg4))
+
+#define GST_VAAPI_ENCODE_MPEG4_CLASS(klass)                    \
+    (G_TYPE_CHECK_CLASS_CAST ((klass),                         \
+                              GST_TYPE_VAAPI_ENCODE_MPEG4,     \
+                              GstVaapiEncodeMpeg4Class))
+
+
+typedef struct _GstVaapiEncodeMpeg4        GstVaapiEncodeMpeg4;
+typedef struct _GstVaapiEncodeMpeg4Class   GstVaapiEncodeMpeg4Class;
+
+struct _GstVaapiEncodeMpeg4 {
+  GstVaapiEncode parent;
+};
+
+struct _GstVaapiEncodeMpeg4Class {
+    GstVaapiEncodeClass     parent_class;
+};
+
+GType gst_vaapi_encode_mpeg4_get_type(void);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_ENCODE_MPEG4_H */
diff --git a/gst/vaapi/gstvaapipluginbuffer.c b/gst/vaapi/gstvaapipluginbuffer.c
new file mode 100644 (file)
index 0000000..33cb917
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ *  gstvaapipluginbuffer.c - Private GStreamer/VA video buffers
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gst/vaapi/gstvaapivideobuffer.h>
+#include <gst/vaapi/gstvaapivideobuffer_priv.h>
+#if USE_GLX
+# include <gst/vaapi/gstvaapivideobuffer_glx.h>
+#endif
+#include "gstvaapipluginbuffer.h"
+
+static GType
+get_type(GstVaapiDisplay *display)
+{
+    GType type;
+
+    switch (gst_vaapi_display_get_display_type(display)) {
+#if USE_GLX
+    case GST_VAAPI_DISPLAY_TYPE_GLX:
+        type = GST_VAAPI_TYPE_VIDEO_BUFFER_GLX;
+        break;
+#endif
+    default:
+        type = GST_VAAPI_TYPE_VIDEO_BUFFER;
+        break;
+    }
+    return type;
+}
+
+GstBuffer *
+gst_vaapi_video_buffer_new(GstVaapiDisplay *display)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+
+    return gst_vaapi_video_buffer_typed_new(get_type(display), display);
+}
+
+GstBuffer *
+gst_vaapi_video_buffer_new_from_pool(GstVaapiVideoPool *pool)
+{
+    GstVaapiDisplay *display;
+
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool), NULL);
+
+    display = gst_vaapi_video_pool_get_display(pool);
+    if (!display)
+        return NULL;
+    return gst_vaapi_video_buffer_typed_new_from_pool(get_type(display), pool);
+}
+
+GstBuffer *
+gst_vaapi_video_buffer_new_from_buffer(GstBuffer *buffer)
+{
+    GstVaapiVideoBuffer *vbuffer;
+    GstVaapiDisplay *display;
+
+    g_return_val_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer), NULL);
+
+    vbuffer = GST_VAAPI_VIDEO_BUFFER(buffer);
+    display = gst_vaapi_video_buffer_get_display(vbuffer);
+    if (!display)
+        return NULL;
+
+    return gst_vaapi_video_buffer_typed_new_from_buffer(
+        get_type(display), buffer);
+}
+
+GstBuffer *
+gst_vaapi_video_buffer_new_with_image(GstVaapiImage *image)
+{
+    GstVaapiDisplay *display;
+
+    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL);
+
+    display = gst_vaapi_object_get_display(GST_VAAPI_OBJECT(image));
+    if (!display)
+        return NULL;
+
+    return gst_vaapi_video_buffer_typed_new_with_image(
+        get_type(display), image);
+}
+
+GstBuffer *
+gst_vaapi_video_buffer_new_with_surface(GstVaapiSurface *surface)
+{
+    GstVaapiDisplay *display;
+
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), NULL);
+
+    display = gst_vaapi_object_get_display(GST_VAAPI_OBJECT(surface));
+    if (!display)
+        return NULL;
+
+    return gst_vaapi_video_buffer_typed_new_with_surface(
+        get_type(display), surface);
+}
+
+GstBuffer *
+gst_vaapi_video_buffer_new_with_surface_proxy(GstVaapiSurfaceProxy *proxy)
+{
+    GstVaapiDisplay *display;
+    GstVaapiSurface *surface;
+
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy), NULL);
+
+    surface = gst_vaapi_surface_proxy_get_surface(proxy);
+    if (!surface)
+        return NULL;
+
+    display = gst_vaapi_object_get_display(GST_VAAPI_OBJECT(surface));
+    if (!display)
+        return NULL;
+
+    return gst_vaapi_video_buffer_typed_new_with_surface_proxy(
+        get_type(display), proxy);
+}
diff --git a/gst/vaapi/gstvaapipluginbuffer.h b/gst/vaapi/gstvaapipluginbuffer.h
new file mode 100644 (file)
index 0000000..d6798d5
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ *  gstvaapipluginbuffer.h - Private GStreamer/VA video buffers
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_PLUGIN_BUFFER_H
+#define GST_VAAPI_PLUGIN_BUFFER_H
+
+G_GNUC_INTERNAL
+GstBuffer *
+gst_vaapi_video_buffer_new(GstVaapiDisplay *display);
+
+G_GNUC_INTERNAL
+GstBuffer *
+gst_vaapi_video_buffer_new_from_pool(GstVaapiVideoPool *pool);
+
+G_GNUC_INTERNAL
+GstBuffer *
+gst_vaapi_video_buffer_new_from_buffer(GstBuffer *buffer);
+
+G_GNUC_INTERNAL
+GstBuffer *
+gst_vaapi_video_buffer_new_with_image(GstVaapiImage *image);
+
+G_GNUC_INTERNAL
+GstBuffer *
+gst_vaapi_video_buffer_new_with_surface(GstVaapiSurface *surface);
+
+G_GNUC_INTERNAL
+GstBuffer *
+gst_vaapi_video_buffer_new_with_surface_proxy(GstVaapiSurfaceProxy *proxy);
+
+#endif /* GST_VAAPI_PLUGIN_BUFFER_H */
diff --git a/gst/vaapi/gstvaapipluginutil.c b/gst/vaapi/gstvaapipluginutil.c
new file mode 100644 (file)
index 0000000..0a56893
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ *  gstvaapipluginutil.h - VA-API plugin helpers
+ *
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *  Copyright (C) 2011 Collabora
+ *    Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; 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
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <string.h>
+#include <gst/video/videocontext.h>
+#if USE_DRM
+# include <gst/vaapi/gstvaapidisplay_drm.h>
+#endif
+#if USE_X11
+# include <gst/vaapi/gstvaapidisplay_x11.h>
+#endif
+#if USE_GLX
+# include <gst/vaapi/gstvaapidisplay_glx.h>
+#endif
+#if USE_WAYLAND
+# include <gst/vaapi/gstvaapidisplay_wayland.h>
+#endif
+#include "gstvaapipluginutil.h"
+
+/* Preferred first */
+static const char *display_types[] = {
+    "gst-vaapi-display",
+    "vaapi-display",
+#if USE_WAYLAND
+    "wl-display",
+    "wl-display-name",
+#endif
+#if USE_X11
+    "x11-display",
+    "x11-display-name",
+#endif
+#if USE_DRM
+    "drm-device",
+    "drm-device-path",
+#endif
+    NULL
+};
+
+typedef struct {
+    const gchar        *type_str;
+    GstVaapiDisplayType type;
+    GstVaapiDisplay * (*create_display)(const gchar *);
+} DisplayMap;
+
+static const DisplayMap g_display_map[] = {
+#if USE_WAYLAND
+    { "wayland",
+      GST_VAAPI_DISPLAY_TYPE_WAYLAND,
+      gst_vaapi_display_wayland_new },
+#endif
+#if USE_X11
+    { "x11",
+      GST_VAAPI_DISPLAY_TYPE_X11,
+      gst_vaapi_display_x11_new },
+#endif
+#if USE_GLX
+    { "glx",
+      GST_VAAPI_DISPLAY_TYPE_GLX,
+      gst_vaapi_display_glx_new },
+#endif
+#if USE_DRM
+    { "drm",
+      GST_VAAPI_DISPLAY_TYPE_DRM,
+      gst_vaapi_display_drm_new },
+#endif
+    { NULL, }
+};
+
+gboolean
+gst_vaapi_ensure_display(
+    gpointer             element,
+    GstVaapiDisplayType  display_type,
+    GstVaapiDisplay    **display_ptr
+)
+{
+    GstVaapiDisplay *display;
+    GstVideoContext *context;
+    const DisplayMap *m;
+
+    g_return_val_if_fail(GST_IS_VIDEO_CONTEXT(element), FALSE);
+    g_return_val_if_fail(display_ptr != NULL, FALSE);
+
+    /* Already exist ? */
+    display = *display_ptr;
+    if (display)
+        return TRUE;
+
+    context = GST_VIDEO_CONTEXT(element);
+    g_return_val_if_fail(context != NULL, FALSE);
+
+    gst_video_context_prepare(context, display_types);
+
+    /* Neighbour found and it updated the display */
+    if (*display_ptr)
+        return TRUE;
+
+    /* If no neighboor, or application not interested, use system default */
+    for (m = g_display_map; m->type_str != NULL; m++) {
+        if (display_type != GST_VAAPI_DISPLAY_TYPE_ANY &&
+            display_type != m->type)
+            continue;
+
+        display = m->create_display(NULL);
+        if (display) {
+            /* FIXME: allocator should return NULL if an error occurred */
+            if (gst_vaapi_display_get_display(display)) {
+                display_type = m->type;
+                break;
+            }
+            g_object_unref(display);
+            display = NULL;
+        }
+
+        if (display_type != GST_VAAPI_DISPLAY_TYPE_ANY)
+            break;
+    }
+
+    if (display_ptr)
+        *display_ptr = display;
+    return display != NULL;
+}
+
+void
+gst_vaapi_set_display(
+    const gchar      *type,
+    const GValue     *value,
+    GstVaapiDisplay **display
+)
+{
+    GstVaapiDisplay *dpy = NULL;
+
+    if (!strcmp(type, "vaapi-display")) {
+        g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
+        dpy = gst_vaapi_display_new_with_display(g_value_get_pointer(value));
+    }
+    else if (!strcmp(type, "gst-vaapi-display")) {
+        g_return_if_fail(G_VALUE_HOLDS_OBJECT(value));
+        dpy = g_value_dup_object(value);
+    }
+#if USE_DRM
+    else if (!strcmp(type, "drm-device")) {
+        gint device;
+        g_return_if_fail(G_VALUE_HOLDS_INT(value));
+        device = g_value_get_int(value);
+        dpy = gst_vaapi_display_drm_new_with_device(device);
+    }
+    else if (!strcmp(type, "drm-device-path")) {
+        const gchar *device_path;
+        g_return_if_fail(G_VALUE_HOLDS_STRING(value));
+        device_path = g_value_get_string(value);
+        dpy = gst_vaapi_display_drm_new(device_path);
+    }
+#endif
+#if USE_X11
+    else if (!strcmp(type, "x11-display-name")) {
+        g_return_if_fail(G_VALUE_HOLDS_STRING(value));
+#if USE_GLX
+        dpy = gst_vaapi_display_glx_new(g_value_get_string(value));
+#endif
+        if (!dpy)
+            dpy = gst_vaapi_display_x11_new(g_value_get_string(value));
+    }
+    else if (!strcmp(type, "x11-display")) {
+        g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
+#if USE_GLX
+        dpy = gst_vaapi_display_glx_new_with_display(g_value_get_pointer(value));
+#endif
+        if (!dpy)
+            dpy = gst_vaapi_display_x11_new_with_display(g_value_get_pointer(value));
+    }
+#endif
+#if USE_WAYLAND
+    else if (!strcmp(type, "wl-display")) {
+        struct wl_display *wl_display;
+        g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
+        wl_display = g_value_get_pointer(value);
+        dpy = gst_vaapi_display_wayland_new_with_display(wl_display);
+    }
+    else if (!strcmp(type, "wl-display-name")) {
+        const gchar *display_name;
+        g_return_if_fail(G_VALUE_HOLDS_STRING(value));
+        display_name = g_value_get_string(value);
+        dpy = gst_vaapi_display_wayland_new(display_name);
+    }
+#endif
+
+    if (dpy) {
+        if (*display)
+            g_object_unref(*display);
+        *display = dpy;
+    }
+}
+
+gboolean
+gst_vaapi_reply_to_query(GstQuery *query, GstVaapiDisplay *display)
+{
+    GstVaapiDisplayType display_type;
+    const gchar **types;
+    const gchar *type;
+    gint i;
+    gboolean res = FALSE;
+
+    if (!display)
+        return FALSE;
+
+    types = gst_video_context_query_get_supported_types(query);
+
+    if (!types)
+        return FALSE;
+
+    display_type = gst_vaapi_display_get_display_type(display);
+    for (i = 0; types[i] && !res; i++) {
+        type = types[i];
+
+        res = TRUE;
+        if (!strcmp(type, "gst-vaapi-display")) {
+            gst_video_context_query_set_object(query, type, G_OBJECT(display));
+        }
+        else if (!strcmp(type, "vaapi-display")) {
+            VADisplay vadpy = gst_vaapi_display_get_display(display);
+            gst_video_context_query_set_pointer(query, type, vadpy);
+        }
+        else {
+            switch (display_type) {
+#if USE_DRM
+            case GST_VAAPI_DISPLAY_TYPE_DRM: {
+                GstVaapiDisplayDRM * const drm_dpy =
+                    GST_VAAPI_DISPLAY_DRM(display);
+                if (!strcmp(type, "drm-device-path"))
+                    gst_video_context_query_set_string(query, type,
+                        gst_vaapi_display_drm_get_device_path(drm_dpy));
+#if 0
+                /* XXX: gst_video_context_query_set_int() does not exist yet */
+                else if (!strcmp(type, "drm-device"))
+                    gst_video_context_query_set_int(query, type,
+                        gst_vaapi_display_drm_get_device(drm_dpy));
+#endif
+                else
+                    res = FALSE;
+                break;
+            }
+#endif
+#if USE_X11
+#if USE_GLX
+            case GST_VAAPI_DISPLAY_TYPE_GLX:
+#endif
+            case GST_VAAPI_DISPLAY_TYPE_X11: {
+                GstVaapiDisplayX11 * const xvadpy =
+                    GST_VAAPI_DISPLAY_X11(display);
+                Display * const x11dpy =
+                    gst_vaapi_display_x11_get_display(xvadpy);
+                if (!strcmp(type, "x11-display"))
+                    gst_video_context_query_set_pointer(query, type, x11dpy);
+                else if (!strcmp(type, "x11-display-name"))
+                    gst_video_context_query_set_string(query, type,
+                        DisplayString(x11dpy));
+                else
+                    res = FALSE;
+                break;
+            }
+#endif
+#if USE_WAYLAND
+            case GST_VAAPI_DISPLAY_TYPE_WAYLAND: {
+                GstVaapiDisplayWayland * const wlvadpy =
+                    GST_VAAPI_DISPLAY_WAYLAND(display);
+                struct wl_display * const wldpy =
+                    gst_vaapi_display_wayland_get_display(wlvadpy);
+                if (!strcmp(type, "wl-display"))
+                    gst_video_context_query_set_pointer(query, type, wldpy);
+                else
+                    res = FALSE;
+                break;
+            }
+#endif
+            default:
+                res = FALSE;
+                break;
+            }
+        }
+    }
+    return res;
+}
+
+gboolean
+gst_vaapi_append_surface_caps(GstCaps *out_caps, GstCaps *in_caps)
+{
+    GstStructure *structure;
+    const GValue *v_width, *v_height, *v_framerate, *v_par;
+    guint i, n_structures;
+
+    structure   = gst_caps_get_structure(in_caps, 0);
+    v_width     = gst_structure_get_value(structure, "width");
+    v_height    = gst_structure_get_value(structure, "height");
+    v_framerate = gst_structure_get_value(structure, "framerate");
+    v_par       = gst_structure_get_value(structure, "pixel-aspect-ratio");
+    if (!v_width || !v_height)
+        return FALSE;
+
+    n_structures = gst_caps_get_size(out_caps);
+    for (i = 0; i < n_structures; i++) {
+        structure = gst_caps_get_structure(out_caps, i);
+        gst_structure_set_value(structure, "width", v_width);
+        gst_structure_set_value(structure, "height", v_height);
+        if (v_framerate)
+            gst_structure_set_value(structure, "framerate", v_framerate);
+        if (v_par)
+            gst_structure_set_value(structure, "pixel-aspect-ratio", v_par);
+    }
+    return TRUE;
+}
diff --git a/gst/vaapi/gstvaapipluginutil.h b/gst/vaapi/gstvaapipluginutil.h
new file mode 100644 (file)
index 0000000..78f274f
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *  gstvaapipluginutil.h - VA-API plugins private helper
+ *
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *  Copyright (C) 2011 Collabora
+ *    Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_PLUGIN_UTIL_H
+#define GST_VAAPI_PLUGIN_UTIL_H
+
+#include <gst/vaapi/gstvaapidisplay.h>
+
+G_GNUC_INTERNAL
+gboolean
+gst_vaapi_ensure_display(
+    gpointer             element,
+    GstVaapiDisplayType  display_type,
+    GstVaapiDisplay    **display
+);
+
+G_GNUC_INTERNAL
+void
+gst_vaapi_set_display(
+    const gchar      *type,
+    const GValue     *value,
+    GstVaapiDisplay **display
+);
+
+G_GNUC_INTERNAL
+gboolean
+gst_vaapi_reply_to_query(GstQuery *query, GstVaapiDisplay *display);
+
+G_GNUC_INTERNAL
+gboolean
+gst_vaapi_append_surface_caps (GstCaps *out_caps, GstCaps *in_caps);
+
+#ifndef G_PRIMITIVE_SWAP
+#define G_PRIMITIVE_SWAP(type, a, b) do {       \
+        const type t = a; a = b; b = t;         \
+    } while (0)
+#endif
+
+#endif /* GST_VAAPI_PLUGIN_UTIL_H */
diff --git a/gst/vaapi/gstvaapipostproc.c b/gst/vaapi/gstvaapipostproc.c
new file mode 100644 (file)
index 0000000..6f6a818
--- /dev/null
@@ -0,0 +1,746 @@
+/*
+ *  gstvaapipostproc.c - VA-API video postprocessing
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapipostproc
+ * @short_description: A video postprocessing filter
+ *
+ * vaapipostproc consists in various postprocessing algorithms to be
+ * applied to VA surfaces. So far, only basic bob deinterlacing is
+ * implemented.
+ */
+
+#include "config.h"
+#include <gst/video/video.h>
+#include <gst/video/videocontext.h>
+#include <gst/vaapi/gstvaapivideobuffer.h>
+
+#include "gstvaapipostproc.h"
+#include "gstvaapipluginutil.h"
+#include "gstvaapipluginbuffer.h"
+
+#define GST_PLUGIN_NAME "vaapipostproc"
+#define GST_PLUGIN_DESC "A video postprocessing filter"
+
+GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapipostproc);
+#define GST_CAT_DEFAULT gst_debug_vaapipostproc
+
+/* ElementFactory information */
+static const GstElementDetails gst_vaapipostproc_details =
+    GST_ELEMENT_DETAILS(
+        "VA-API video postprocessing",
+        "Filter/Converter/Video",
+        GST_PLUGIN_DESC,
+        "Gwenole Beauchesne <gwenole.beauchesne@intel.com>");
+
+/* Default templates */
+static const char gst_vaapipostproc_sink_caps_str[] =
+    GST_VAAPI_SURFACE_CAPS ", "
+    "interlaced = (boolean) { true, false }";
+
+static const char gst_vaapipostproc_src_caps_str[] =
+    GST_VAAPI_SURFACE_CAPS ", "
+    "interlaced = (boolean) false";
+
+static GstStaticPadTemplate gst_vaapipostproc_sink_factory =
+    GST_STATIC_PAD_TEMPLATE(
+        "sink",
+        GST_PAD_SINK,
+        GST_PAD_ALWAYS,
+        GST_STATIC_CAPS(gst_vaapipostproc_sink_caps_str));
+
+static GstStaticPadTemplate gst_vaapipostproc_src_factory =
+    GST_STATIC_PAD_TEMPLATE(
+        "src",
+        GST_PAD_SRC,
+        GST_PAD_ALWAYS,
+        GST_STATIC_CAPS(gst_vaapipostproc_src_caps_str));
+
+static void
+gst_vaapipostproc_implements_iface_init(GstImplementsInterfaceClass *iface);
+
+static void
+gst_video_context_interface_init(GstVideoContextInterface *iface);
+
+#define GstVideoContextClass GstVideoContextInterface
+G_DEFINE_TYPE_WITH_CODE(
+    GstVaapiPostproc,
+    gst_vaapipostproc,
+    GST_TYPE_ELEMENT,
+    G_IMPLEMENT_INTERFACE(GST_TYPE_IMPLEMENTS_INTERFACE,
+                          gst_vaapipostproc_implements_iface_init);
+    G_IMPLEMENT_INTERFACE(GST_TYPE_VIDEO_CONTEXT,
+                          gst_video_context_interface_init));
+
+enum {
+    PROP_0,
+
+    PROP_DEINTERLACE_MODE,
+    PROP_DEINTERLACE_METHOD,
+};
+
+#define DEFAULT_DEINTERLACE_MODE        GST_VAAPI_DEINTERLACE_MODE_AUTO
+#define DEFAULT_DEINTERLACE_METHOD      GST_VAAPI_DEINTERLACE_METHOD_BOB
+
+#define GST_TYPE_VAAPI_DEINTERLACE_MODES \
+    gst_vaapi_deinterlace_modes_get_type()
+
+static GType
+gst_vaapi_deinterlace_modes_get_type(void)
+{
+    static GType deinterlace_modes_type = 0;
+
+    static const GEnumValue modes_types[] = {
+        { GST_VAAPI_DEINTERLACE_MODE_AUTO,
+          "Auto detection", "auto" },
+        { GST_VAAPI_DEINTERLACE_MODE_INTERLACED,
+          "Force deinterlacing", "interlaced" },
+        { GST_VAAPI_DEINTERLACE_MODE_DISABLED,
+          "Never deinterlace", "disabled" },
+        { 0, NULL, NULL },
+    };
+
+    if (!deinterlace_modes_type) {
+        deinterlace_modes_type =
+            g_enum_register_static("GstVaapiDeinterlaceModes", modes_types);
+    }
+    return deinterlace_modes_type;
+}
+
+#define GST_TYPE_VAAPI_DEINTERLACE_METHODS \
+    gst_vaapi_deinterlace_methods_get_type()
+
+static GType
+gst_vaapi_deinterlace_methods_get_type(void)
+{
+    static GType deinterlace_methods_type = 0;
+
+    static const GEnumValue methods_types[] = {
+        { GST_VAAPI_DEINTERLACE_METHOD_BOB,
+          "Bob deinterlacing", "bob" },
+#if 0
+        /* VA/VPP */
+        { GST_VAAPI_DEINTERLACE_METHOD_WEAVE,
+          "Weave deinterlacing", "weave" },
+        { GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE,
+          "Motion adaptive deinterlacing", "motion-adaptive" },
+        { GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED,
+          "Motion compensated deinterlacing", "motion-compensated" },
+#endif
+        { 0, NULL, NULL },
+    };
+
+    if (!deinterlace_methods_type) {
+        deinterlace_methods_type =
+            g_enum_register_static("GstVaapiDeinterlaceMethods", methods_types);
+    }
+    return deinterlace_methods_type;
+}
+
+static inline GstVaapiPostproc *
+get_vaapipostproc_from_pad(GstPad *pad)
+{
+    return GST_VAAPIPOSTPROC(gst_pad_get_parent_element(pad));
+}
+
+/* GstImplementsInterface interface */
+
+static gboolean
+gst_vaapipostproc_implements_interface_supported(
+    GstImplementsInterface *iface,
+    GType                   type
+)
+{
+    return (type == GST_TYPE_VIDEO_CONTEXT);
+}
+
+static void
+gst_vaapipostproc_implements_iface_init(GstImplementsInterfaceClass *iface)
+{
+    iface->supported = gst_vaapipostproc_implements_interface_supported;
+}
+
+/* GstVideoContext interface */
+
+static void
+gst_vaapipostproc_set_video_context(
+    GstVideoContext *context,
+    const gchar     *type,
+    const GValue    *value
+)
+{
+    GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(context);
+
+    gst_vaapi_set_display(type, value, &postproc->display);
+}
+
+static void
+gst_video_context_interface_init(GstVideoContextInterface *iface)
+{
+    iface->set_context = gst_vaapipostproc_set_video_context;
+}
+
+static inline gboolean
+gst_vaapipostproc_ensure_display(GstVaapiPostproc *postproc)
+{
+    return gst_vaapi_ensure_display(postproc, GST_VAAPI_DISPLAY_TYPE_ANY,
+        &postproc->display);
+}
+
+static gboolean
+gst_vaapipostproc_create(GstVaapiPostproc *postproc, GstCaps *caps)
+{
+    if (!gst_vaapipostproc_ensure_display(postproc))
+        return FALSE;
+
+    gst_caps_replace(&postproc->postproc_caps, caps);
+    return TRUE;
+}
+
+static void
+gst_vaapipostproc_destroy(GstVaapiPostproc *postproc)
+{
+    gst_caps_replace(&postproc->postproc_caps, NULL);
+
+    g_clear_object(&postproc->display);
+}
+
+static gboolean
+gst_vaapipostproc_reset(GstVaapiPostproc *postproc, GstCaps *caps)
+{
+    if (postproc->postproc_caps &&
+        gst_caps_is_always_compatible(caps, postproc->postproc_caps))
+        return TRUE;
+
+    gst_vaapipostproc_destroy(postproc);
+    return gst_vaapipostproc_create(postproc, caps);
+}
+
+static gboolean
+gst_vaapipostproc_start(GstVaapiPostproc *postproc)
+{
+    if (!gst_vaapipostproc_ensure_display(postproc))
+        return FALSE;
+    return TRUE;
+}
+
+static gboolean
+gst_vaapipostproc_stop(GstVaapiPostproc *postproc)
+{
+    if (postproc->display) {
+        g_object_unref(postproc->display);
+        postproc->display = NULL;
+    }
+    return TRUE;
+}
+
+static GstFlowReturn
+gst_vaapipostproc_process(GstVaapiPostproc *postproc, GstBuffer *buf)
+{
+    GstVaapiVideoBuffer *vbuf = GST_VAAPI_VIDEO_BUFFER(buf);
+    GstVaapiSurfaceProxy *proxy;
+    GstClockTime timestamp;
+    GstFlowReturn ret;
+    GstBuffer *outbuf = NULL;
+    guint outbuf_flags, flags;
+    gboolean interlaced, tff;
+
+    flags = gst_vaapi_video_buffer_get_render_flags(vbuf);
+
+    /* Deinterlacing disabled, push frame */
+    if (!postproc->deinterlace) {
+        gst_vaapi_video_buffer_set_render_flags(vbuf, flags);
+        ret = gst_pad_push(postproc->srcpad, buf);
+        if (ret != GST_FLOW_OK)
+            goto error_push_buffer;
+        return GST_FLOW_OK;
+    }
+
+    timestamp  = GST_BUFFER_TIMESTAMP(buf);
+    proxy      = gst_vaapi_video_buffer_get_surface_proxy(vbuf);
+    interlaced = gst_vaapi_surface_proxy_get_interlaced(proxy);
+    tff        = gst_vaapi_surface_proxy_get_tff(proxy);
+
+    flags &= ~(GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD|
+               GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD);
+
+    /* First field */
+    outbuf = gst_vaapi_video_buffer_new_with_surface_proxy(proxy);
+    if (!outbuf)
+        goto error_create_buffer;
+
+    vbuf = GST_VAAPI_VIDEO_BUFFER(outbuf);
+    outbuf_flags = flags;
+    outbuf_flags |= interlaced ? (
+        tff ?
+        GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD :
+        GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD) :
+        GST_VAAPI_PICTURE_STRUCTURE_FRAME;
+    gst_vaapi_video_buffer_set_render_flags(vbuf, outbuf_flags);
+
+    GST_BUFFER_TIMESTAMP(outbuf) = timestamp;
+    GST_BUFFER_DURATION(outbuf)  = postproc->field_duration;
+    gst_buffer_set_caps(outbuf, postproc->srcpad_caps);
+    ret = gst_pad_push(postproc->srcpad, outbuf);
+    if (ret != GST_FLOW_OK)
+        goto error_push_buffer;
+
+    /* Second field */
+    outbuf = gst_vaapi_video_buffer_new_with_surface_proxy(proxy);
+    if (!outbuf)
+        goto error_create_buffer;
+
+    vbuf = GST_VAAPI_VIDEO_BUFFER(outbuf);
+    outbuf_flags = flags;
+    outbuf_flags |= interlaced ? (
+        tff ?
+        GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD :
+        GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD) :
+        GST_VAAPI_PICTURE_STRUCTURE_FRAME;
+    gst_vaapi_video_buffer_set_render_flags(vbuf, outbuf_flags);
+
+    GST_BUFFER_TIMESTAMP(outbuf) = timestamp + postproc->field_duration;
+    GST_BUFFER_DURATION(outbuf)  = postproc->field_duration;
+    gst_buffer_set_caps(outbuf, postproc->srcpad_caps);
+    ret = gst_pad_push(postproc->srcpad, outbuf);
+    if (ret != GST_FLOW_OK)
+        goto error_push_buffer;
+
+    gst_buffer_unref(buf);
+    return GST_FLOW_OK;
+
+    /* ERRORS */
+error_create_buffer:
+    {
+        GST_ERROR("failed to create output buffer");
+        gst_buffer_unref(buf);
+        return GST_FLOW_UNEXPECTED;
+    }
+error_push_buffer:
+    {
+        if (ret != GST_FLOW_WRONG_STATE)
+            GST_ERROR("failed to push output buffer to video sink");
+        gst_buffer_unref(buf);
+        return GST_FLOW_UNEXPECTED;
+    }
+}
+
+static gboolean
+gst_vaapipostproc_update_sink_caps(GstVaapiPostproc *postproc, GstCaps *caps)
+{
+    gint fps_n, fps_d;
+    gboolean interlaced;
+
+    if (!gst_video_parse_caps_framerate(caps, &fps_n, &fps_d))
+        return FALSE;
+    postproc->fps_n = fps_n;
+    postproc->fps_d = fps_d;
+
+    switch (postproc->deinterlace_mode) {
+    case GST_VAAPI_DEINTERLACE_MODE_AUTO:
+        if (!gst_video_format_parse_caps_interlaced(caps, &interlaced))
+            return FALSE;
+        postproc->deinterlace = interlaced;
+        break;
+    case GST_VAAPI_DEINTERLACE_MODE_INTERLACED:
+        postproc->deinterlace = TRUE;
+        break;
+    case GST_VAAPI_DEINTERLACE_MODE_DISABLED:
+        postproc->deinterlace = FALSE;
+        break;
+    }
+
+    postproc->field_duration = gst_util_uint64_scale(
+        GST_SECOND,
+        postproc->fps_d,
+        (1 + postproc->deinterlace) * postproc->fps_n
+    );
+
+    gst_caps_replace(&postproc->sinkpad_caps, caps);
+    return TRUE;
+}
+
+static gboolean
+gst_vaapipostproc_update_src_caps(GstVaapiPostproc *postproc, GstCaps *caps)
+{
+    GstCaps *src_caps;
+    GstStructure *structure;
+    const GValue *v_width, *v_height, *v_par;
+    gint fps_n, fps_d;
+
+    if (postproc->srcpad_caps)
+        src_caps = gst_caps_make_writable(postproc->srcpad_caps);
+    else
+        src_caps = gst_caps_from_string(GST_VAAPI_SURFACE_CAPS_NAME);
+    if (!src_caps)
+        return FALSE;
+    postproc->srcpad_caps = src_caps;
+
+    structure    = gst_caps_get_structure(caps, 0);
+    v_width      = gst_structure_get_value(structure, "width");
+    v_height     = gst_structure_get_value(structure, "height");
+    v_par        = gst_structure_get_value(structure, "pixel-aspect-ratio");
+
+    structure = gst_caps_get_structure(src_caps, 0);
+    if (v_width && v_height) {
+        gst_structure_set_value(structure, "width", v_width);
+        gst_structure_set_value(structure, "height", v_height);
+    }
+    if (v_par)
+        gst_structure_set_value(structure, "pixel-aspect-ratio", v_par);
+
+    gst_structure_set(structure, "type", G_TYPE_STRING, "vaapi", NULL);
+    gst_structure_set(structure, "opengl", G_TYPE_BOOLEAN, USE_GLX, NULL);
+
+    if (!postproc->deinterlace)
+        gst_structure_remove_field(structure, "interlaced");
+    else {
+        /* Set double framerate in interlaced mode */
+        if (!gst_util_fraction_multiply(postproc->fps_n, postproc->fps_d,
+                                        2, 1,
+                                        &fps_n, &fps_d))
+            return FALSE;
+
+        gst_structure_set(
+            structure,
+            "interlaced", G_TYPE_BOOLEAN, FALSE,
+            "framerate", GST_TYPE_FRACTION, fps_n, fps_d,
+            NULL
+        );
+    }
+    return gst_pad_set_caps(postproc->srcpad, src_caps);
+}
+
+static gboolean
+gst_vaapipostproc_ensure_allowed_caps(GstVaapiPostproc *postproc)
+{
+    if (postproc->allowed_caps)
+        return TRUE;
+
+    postproc->allowed_caps =
+        gst_caps_from_string(gst_vaapipostproc_sink_caps_str);
+    if (!postproc->allowed_caps)
+        return FALSE;
+
+    /* XXX: append VA/VPP filters */
+    return TRUE;
+}
+
+static GstCaps *
+gst_vaapipostproc_get_caps(GstPad *pad)
+{
+    GstVaapiPostproc * const postproc = get_vaapipostproc_from_pad(pad);
+    GstCaps *out_caps;
+
+    if (gst_vaapipostproc_ensure_allowed_caps(postproc))
+        out_caps = gst_caps_ref(postproc->allowed_caps);
+    else
+        out_caps = gst_caps_new_empty();
+
+    gst_object_unref(postproc);
+    return out_caps;
+}
+
+static gboolean
+gst_vaapipostproc_set_caps(GstPad *pad, GstCaps *caps)
+{
+    GstVaapiPostproc * const postproc = get_vaapipostproc_from_pad(pad);
+    gboolean success = FALSE;
+
+    g_return_val_if_fail(pad == postproc->sinkpad, FALSE);
+
+    do {
+        if (!gst_vaapipostproc_update_sink_caps(postproc, caps))
+            break;
+        if (!gst_vaapipostproc_update_src_caps(postproc, caps))
+            break;
+        if (!gst_vaapipostproc_reset(postproc, postproc->sinkpad_caps))
+            break;
+        success = TRUE;
+    } while (0);
+    gst_object_unref(postproc);
+    return success;
+}
+
+static GstFlowReturn
+gst_vaapipostproc_chain(GstPad *pad, GstBuffer *buf)
+{
+    GstVaapiPostproc * const postproc = get_vaapipostproc_from_pad(pad);
+    GstFlowReturn ret;
+
+    ret = gst_vaapipostproc_process(postproc, buf);
+    gst_object_unref(postproc);
+    return ret;
+}
+
+static gboolean
+gst_vaapipostproc_sink_event(GstPad *pad, GstEvent *event)
+{
+    GstVaapiPostproc * const postproc = get_vaapipostproc_from_pad(pad);
+    gboolean success;
+
+    GST_DEBUG("handle sink event '%s'", GST_EVENT_TYPE_NAME(event));
+
+    /* Propagate event downstream */
+    success = gst_pad_push_event(postproc->srcpad, event);
+    gst_object_unref(postproc);
+    return success;
+}
+
+static gboolean
+gst_vaapipostproc_src_event(GstPad *pad, GstEvent *event)
+{
+    GstVaapiPostproc * const postproc = get_vaapipostproc_from_pad(pad);
+    gboolean success;
+
+    GST_DEBUG("handle src event '%s'", GST_EVENT_TYPE_NAME(event));
+
+    /* Propagate event upstream */
+    success = gst_pad_push_event(postproc->sinkpad, event);
+    gst_object_unref(postproc);
+    return success;
+}
+
+static gboolean
+gst_vaapipostproc_query(GstPad *pad, GstQuery *query)
+{
+    GstVaapiPostproc * const postproc = get_vaapipostproc_from_pad(pad);
+    gboolean success;
+
+    GST_DEBUG("sharing display %p", postproc->display);
+
+    if (gst_vaapi_reply_to_query(query, postproc->display))
+        success = TRUE;
+    else
+        success = gst_pad_query_default(pad, query);
+
+    gst_object_unref(postproc);
+    return success;
+}
+
+static void
+gst_vaapipostproc_finalize(GObject *object)
+{
+    GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(object);
+
+    gst_vaapipostproc_destroy(postproc);
+
+    gst_caps_replace(&postproc->sinkpad_caps, NULL);
+    gst_caps_replace(&postproc->srcpad_caps,  NULL);
+    gst_caps_replace(&postproc->allowed_caps, NULL);
+
+    G_OBJECT_CLASS(gst_vaapipostproc_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapipostproc_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(object);
+
+    switch (prop_id) {
+    case PROP_DEINTERLACE_MODE:
+        postproc->deinterlace_mode = g_value_get_enum(value);
+        break;
+    case PROP_DEINTERLACE_METHOD:
+        postproc->deinterlace_method = g_value_get_enum(value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapipostproc_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(object);
+
+    switch (prop_id) {
+    case PROP_DEINTERLACE_MODE:
+        g_value_set_enum(value, postproc->deinterlace_mode);
+        break;
+    case PROP_DEINTERLACE_METHOD:
+        g_value_set_enum(value, postproc->deinterlace_method);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static GstStateChangeReturn
+gst_vaapipostproc_change_state(GstElement *element, GstStateChange transition)
+{
+    GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(element);
+    GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+
+    switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:
+        if (!gst_vaapipostproc_start(postproc))
+            return GST_STATE_CHANGE_FAILURE;
+        break;
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+        break;
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+        break;
+    default:
+        break;
+    }
+
+    ret = GST_ELEMENT_CLASS(gst_vaapipostproc_parent_class)->change_state(element, transition);
+    if (ret != GST_STATE_CHANGE_SUCCESS)
+        return ret;
+
+    switch (transition) {
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+        break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+        break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+        if (!gst_vaapipostproc_stop(postproc))
+            return GST_STATE_CHANGE_FAILURE;
+        break;
+    default:
+        break;
+    }
+    return GST_STATE_CHANGE_SUCCESS;
+}
+
+static void
+gst_vaapipostproc_class_init(GstVaapiPostprocClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
+    GstPadTemplate *pad_template;
+
+    GST_DEBUG_CATEGORY_INIT(gst_debug_vaapipostproc,
+                            GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
+
+    object_class->finalize      = gst_vaapipostproc_finalize;
+    object_class->set_property  = gst_vaapipostproc_set_property;
+    object_class->get_property  = gst_vaapipostproc_get_property;
+
+    element_class->change_state = gst_vaapipostproc_change_state;
+
+    gst_element_class_set_details_simple(
+        element_class,
+        gst_vaapipostproc_details.longname,
+        gst_vaapipostproc_details.klass,
+        gst_vaapipostproc_details.description,
+        gst_vaapipostproc_details.author
+    );
+
+    /* sink pad */
+    pad_template = gst_static_pad_template_get(&gst_vaapipostproc_sink_factory);
+    gst_element_class_add_pad_template(element_class, pad_template);
+    gst_object_unref(pad_template);
+
+    /* src pad */
+    pad_template = gst_static_pad_template_get(&gst_vaapipostproc_src_factory);
+    gst_element_class_add_pad_template(element_class, pad_template);
+    gst_object_unref(pad_template);
+
+    /**
+     * GstVaapiPostproc:deinterlace-mode:
+     *
+     * This selects whether the deinterlacing should always be applied or if
+     * they should only be applied on content that has the "interlaced" flag
+     * on the caps.
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_DEINTERLACE_MODE,
+         g_param_spec_enum("deinterlace",
+                           "Deinterlace",
+                           "Deinterlace mode to use",
+                           GST_TYPE_VAAPI_DEINTERLACE_MODES,
+                           DEFAULT_DEINTERLACE_MODE,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+    /**
+     * GstVaapiPostproc:deinterlace-method:
+     *
+     * This selects the deinterlacing method to apply.
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_DEINTERLACE_METHOD,
+         g_param_spec_enum("deinterlace-method",
+                           "Deinterlace method",
+                           "Deinterlace method to use",
+                           GST_TYPE_VAAPI_DEINTERLACE_METHODS,
+                           DEFAULT_DEINTERLACE_METHOD,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+gst_vaapipostproc_init(GstVaapiPostproc *postproc)
+{
+    GstVaapiPostprocClass *klass = GST_VAAPIPOSTPROC_GET_CLASS(postproc);
+    GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
+
+    postproc->allowed_caps              = NULL;
+    postproc->postproc_caps             = NULL;
+    postproc->display                   = NULL;
+    postproc->surface_width             = 0;
+    postproc->surface_height            = 0;
+    postproc->deinterlace               = FALSE;
+    postproc->deinterlace_mode          = DEFAULT_DEINTERLACE_MODE;
+    postproc->deinterlace_method        = DEFAULT_DEINTERLACE_METHOD;
+    postproc->field_duration            = GST_CLOCK_TIME_NONE;
+    postproc->fps_n                     = 0;
+    postproc->fps_d                     = 0;
+
+    /* Pad through which data comes in to the element */
+    postproc->sinkpad = gst_pad_new_from_template(
+        gst_element_class_get_pad_template(element_class, "sink"),
+        "sink"
+    );
+    postproc->sinkpad_caps = NULL;
+
+    gst_pad_set_getcaps_function(postproc->sinkpad, gst_vaapipostproc_get_caps);
+    gst_pad_set_setcaps_function(postproc->sinkpad, gst_vaapipostproc_set_caps);
+    gst_pad_set_chain_function(postproc->sinkpad, gst_vaapipostproc_chain);
+    gst_pad_set_event_function(postproc->sinkpad, gst_vaapipostproc_sink_event);
+    gst_pad_set_query_function(postproc->sinkpad, gst_vaapipostproc_query);
+    gst_element_add_pad(GST_ELEMENT(postproc), postproc->sinkpad);
+
+    /* Pad through which data goes out of the element */
+    postproc->srcpad = gst_pad_new_from_template(
+        gst_element_class_get_pad_template(element_class, "src"),
+        "src"
+    );
+    postproc->srcpad_caps = NULL;
+
+    gst_pad_set_event_function(postproc->srcpad, gst_vaapipostproc_src_event);
+    gst_pad_set_query_function(postproc->srcpad, gst_vaapipostproc_query);
+    gst_element_add_pad(GST_ELEMENT(postproc), postproc->srcpad);
+}
diff --git a/gst/vaapi/gstvaapipostproc.h b/gst/vaapi/gstvaapipostproc.h
new file mode 100644 (file)
index 0000000..6ec56d1
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ *  gstvaapipostproc.h - VA-API video post processing
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This program 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 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser 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
+*/
+
+#ifndef GST_VAAPIPOSTPROC_H
+#define GST_VAAPIPOSTPROC_H
+
+#include <gst/gst.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapisurface.h>
+#include <gst/vaapi/gstvaapisurfacepool.h>
+#include <gst/vaapi/gstvaapivideobuffer.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_VAAPIPOSTPROC \
+    (gst_vaapipostproc_get_type())
+
+#define GST_VAAPIPOSTPROC(obj)                          \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                  \
+                                GST_TYPE_VAAPIPOSTPROC, \
+                                GstVaapiPostproc))
+
+#define GST_VAAPIPOSTPROC_CLASS(klass)                  \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                   \
+                             GST_TYPE_VAAPIPOSTPROC,    \
+                             GstVaapiPostprocClass))
+
+#define GST_IS_VAAPIPOSTPROC(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_VAAPIPOSTPROC))
+
+#define GST_IS_VAAPIPOSTPROC_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_VAAPIPOSTPROC))
+
+#define GST_VAAPIPOSTPROC_GET_CLASS(obj)                \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                   \
+                               GST_TYPE_VAAPIPOSTPROC,  \
+                               GstVaapiPostprocClass))
+
+typedef struct _GstVaapiPostproc                GstVaapiPostproc;
+typedef struct _GstVaapiPostprocClass           GstVaapiPostprocClass;
+
+typedef enum _GstVaapiDeinterlaceMode           GstVaapiDeinterlaceMode;
+typedef enum _GstVaapiDeinterlaceMethod         GstVaapiDeinterlaceMethod;
+
+/**
+ * GstVaapiDeinterlaceMode:
+ * @GST_VAAPI_DEINTERLACE_MODE_AUTO: Auto detect needs for deinterlacing.
+ * @GST_VAAPI_DEINTERLACE_MODE_INTERLACED: Force deinterlacing.
+ * @GST_VAAPI_DEINTERLACE_MODE_DISABLED: Never perform deinterlacing.
+ */
+enum _GstVaapiDeinterlaceMode {
+    GST_VAAPI_DEINTERLACE_MODE_AUTO = 0,
+    GST_VAAPI_DEINTERLACE_MODE_INTERLACED,
+    GST_VAAPI_DEINTERLACE_MODE_DISABLED,
+};
+
+/**
+ * GstVaapiDeinterlaceMethod:
+ * @GST_VAAPI_DEINTERLACE_METHOD_BOB: Basic bob deinterlacing algorithm.
+ * @GST_VAAPI_DEINTERLACE_METHOD_WEAVE: Weave deinterlacing algorithm.
+ * @GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE: Motion adaptive deinterlacing algorithm.
+ * @GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED: Motion compensated deinterlacing algorithm.
+ */
+enum _GstVaapiDeinterlaceMethod {
+    GST_VAAPI_DEINTERLACE_METHOD_BOB = 1,
+    GST_VAAPI_DEINTERLACE_METHOD_WEAVE,
+    GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE,
+    GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED,
+};
+
+struct _GstVaapiPostproc {
+    /*< private >*/
+    GstElement                  parent_instance;
+
+    GstPad                     *sinkpad;
+    GstCaps                    *sinkpad_caps;
+    GstPad                     *srcpad;
+    GstCaps                    *srcpad_caps;
+    GstCaps                    *allowed_caps;
+    GstCaps                    *postproc_caps;
+
+    GstVaapiDisplay            *display;
+    guint                       surface_width;
+    guint                       surface_height;
+
+    /* Deinterlacing */
+    gboolean                    deinterlace;
+    GstVaapiDeinterlaceMode     deinterlace_mode;
+    GstVaapiDeinterlaceMethod   deinterlace_method;
+    GstClockTime                field_duration;
+    gint                        fps_n;
+    gint                        fps_d;
+};
+
+struct _GstVaapiPostprocClass {
+    /*< private >*/
+    GstElementClass             parent_class;
+};
+
+GType
+gst_vaapipostproc_get_type(void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* GST_VAAPIPOSTPROC_H */
diff --git a/gst/vaapi/gstvaapisink.c b/gst/vaapi/gstvaapisink.c
new file mode 100644 (file)
index 0000000..c3c55a4
--- /dev/null
@@ -0,0 +1,1310 @@
+/*
+ *  gstvaapisink.c - VA-API video sink
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapisink
+ * @short_description: A VA-API based videosink
+ *
+ * vaapisink renders video frames to a drawable (X #Window) on a local
+ * display using the Video Acceleration (VA) API. The element will
+ * create its own internal window and render into it.
+ */
+
+#include "config.h"
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/video/videocontext.h>
+#include <gst/vaapi/gstvaapivalue.h>
+#include <gst/vaapi/gstvaapivideobuffer.h>
+#include <gst/vaapi/gstvaapipluginbuffer.h>
+#include <gst/vaapi/gstvaapidebug.h>
+
+#if USE_DRM
+# include <gst/vaapi/gstvaapidisplay_drm.h>
+#endif
+#if USE_X11
+# include <gst/vaapi/gstvaapidisplay_x11.h>
+# include <gst/vaapi/gstvaapiwindow_x11.h>
+#endif
+#if USE_GLX
+# include <gst/vaapi/gstvaapidisplay_glx.h>
+# include <gst/vaapi/gstvaapiwindow_glx.h>
+#endif
+#if USE_WAYLAND
+# include <gst/vaapi/gstvaapidisplay_wayland.h>
+# include <gst/vaapi/gstvaapiwindow_wayland.h>
+#endif
+
+/* Supported interfaces */
+#include <gst/interfaces/xoverlay.h>
+
+#include "gstvaapisink.h"
+#include "gstvaapipluginutil.h"
+
+#define GST_PLUGIN_NAME "vaapisink"
+#define GST_PLUGIN_DESC "A VA-API based videosink"
+
+GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapisink);
+#define GST_CAT_DEFAULT gst_debug_vaapisink
+
+/* ElementFactory information */
+static const GstElementDetails gst_vaapisink_details =
+    GST_ELEMENT_DETAILS(
+        "VA-API sink",
+        "Sink/Video",
+        GST_PLUGIN_DESC,
+        "Gwenole Beauchesne <gwenole.beauchesne@intel.com>");
+
+static const char gst_vaapisink_sink_caps_str[] =
+    GST_VAAPI_SURFACE_CAPS "; "
+    GST_VAAPI_BUFFER_SHARING_CAPS;
+
+/* Default template */
+static GstStaticPadTemplate gst_vaapisink_sink_factory =
+    GST_STATIC_PAD_TEMPLATE(
+        "sink",
+        GST_PAD_SINK,
+        GST_PAD_ALWAYS,
+        GST_STATIC_CAPS(gst_vaapisink_sink_caps_str));
+
+static void
+gst_vaapisink_implements_iface_init(GstImplementsInterfaceClass *iface);
+
+static void
+gst_vaapisink_video_context_iface_init(GstVideoContextInterface *iface);
+
+static void
+gst_vaapisink_xoverlay_iface_init(GstXOverlayClass *iface);
+
+G_DEFINE_TYPE_WITH_CODE(
+    GstVaapiSink,
+    gst_vaapisink,
+    GST_TYPE_VIDEO_SINK,
+    G_IMPLEMENT_INTERFACE(GST_TYPE_IMPLEMENTS_INTERFACE,
+                          gst_vaapisink_implements_iface_init);
+    G_IMPLEMENT_INTERFACE(GST_TYPE_VIDEO_CONTEXT,
+                          gst_vaapisink_video_context_iface_init);
+    G_IMPLEMENT_INTERFACE(GST_TYPE_X_OVERLAY,
+                          gst_vaapisink_xoverlay_iface_init));
+
+enum {
+    PROP_0,
+
+    PROP_DISPLAY_TYPE,
+    PROP_FULLSCREEN,
+    PROP_SYNCHRONOUS,
+    PROP_USE_REFLECTION,
+    PROP_ROTATION,
+    PROP_IS_PIXMAP,
+};
+
+#define DEFAULT_DISPLAY_TYPE            GST_VAAPI_DISPLAY_TYPE_ANY
+#define DEFAULT_ROTATION                GST_VAAPI_ROTATION_0
+
+/* GstImplementsInterface interface */
+/**
+ * gst_vaapisink_prepare_xid:
+ * @overlay: a #GstXOverlay which does not yet have an XWindow or XPixmap.
+ *
+ * This will post a "prepare-xid" element message with video size and display size on the bus
+ * to give applications an opportunity to call
+ * gst_x_overlay_set_xwindow_id() before a plugin creates its own
+ * window or pixmap.
+ *
+ * This function should only be used by video overlay plugin developers.
+ */
+static void
+gst_vaapisink_prepare_xid (GstXOverlay * overlay)
+{
+  GstStructure *s;
+  GstMessage *msg;
+
+  g_return_if_fail (overlay != NULL);
+  g_return_if_fail (GST_IS_X_OVERLAY (overlay));
+
+  GstVaapiSink *sink;
+  sink = GST_VAAPISINK (GST_OBJECT (overlay));
+
+  GST_DEBUG ("post \"prepare-xid\" element message with video-width(%d), video-height(%d), display-width(%d), display-height(%d)",
+       sink->video_width, sink->video_height, sink->window_width, sink->window_height);
+
+  GST_LOG_OBJECT (GST_OBJECT (overlay), "prepare xid");
+  s = gst_structure_new ("prepare-xid",
+        "video-width", G_TYPE_INT, sink->video_width,
+        "video-height", G_TYPE_INT, sink->video_height,
+        "display-width", G_TYPE_INT, sink->window_width,
+        "display-height", G_TYPE_INT, sink->window_height,
+        NULL);
+  msg = gst_message_new_element (GST_OBJECT (overlay), s);
+  gst_element_post_message (GST_ELEMENT (overlay), msg);
+}
+
+static gboolean
+gst_vaapisink_implements_interface_supported(
+    GstImplementsInterface *iface,
+    GType                   type
+)
+{
+    return (type == GST_TYPE_VIDEO_CONTEXT ||
+            type == GST_TYPE_X_OVERLAY);
+}
+
+static void
+gst_vaapisink_implements_iface_init(GstImplementsInterfaceClass *iface)
+{
+    iface->supported = gst_vaapisink_implements_interface_supported;
+}
+
+/* GstVideoContext interface */
+
+static void
+gst_vaapisink_set_video_context(GstVideoContext *context, const gchar *type,
+    const GValue *value)
+{
+  GstVaapiSink *sink = GST_VAAPISINK (context);
+  gst_vaapi_set_display (type, value, &sink->display);
+}
+
+static void
+gst_vaapisink_video_context_iface_init(GstVideoContextInterface *iface)
+{
+    iface->set_context = gst_vaapisink_set_video_context;
+}
+
+/* GstXOverlay interface */
+
+#if USE_X11
+static gboolean
+gst_vaapisink_ensure_window_xid(GstVaapiSink *sink, guintptr window_id);
+#endif
+
+static gboolean
+gst_vaapisink_ensure_display_rect(GstVaapiSink *sink, guint width, guint height);
+
+static GstFlowReturn
+gst_vaapisink_show_frame(GstBaseSink *base_sink, GstBuffer *buffer);
+
+static void
+gst_vaapisink_xoverlay_set_window_handle(GstXOverlay *overlay, guintptr window)
+{
+    GstVaapiSink * const sink = GST_VAAPISINK(overlay);
+
+    /* Disable GLX rendering when vaapisink is using a foreign X
+       window. It's pretty much useless */
+    if (sink->display_type == GST_VAAPI_DISPLAY_TYPE_GLX)
+        sink->display_type = GST_VAAPI_DISPLAY_TYPE_X11;
+
+    sink->foreign_window = TRUE;
+
+    switch (sink->display_type) {
+#if USE_X11
+    case GST_VAAPI_DISPLAY_TYPE_X11:
+        gst_vaapisink_ensure_window_xid(sink, window);
+        break;
+#endif
+    default:
+        break;
+    }
+}
+
+static void
+gst_vaapisink_xoverlay_set_render_rectangle(
+    GstXOverlay *overlay,
+    gint         x,
+    gint         y,
+    gint         width,
+    gint         height
+)
+{
+    GstVaapiSink * const sink = GST_VAAPISINK(overlay);
+    GstVaapiRectangle * const render_rect = &sink->render_rect;
+
+    render_rect->x      = x;
+    render_rect->y      = y;
+    render_rect->width  = width;
+    render_rect->height = height;
+    
+    GST_DEBUG("render rect (%d,%d):%ux%u",
+              render_rect->x, render_rect->y,
+              render_rect->width, render_rect->height);
+
+    gst_vaapisink_ensure_display_rect(
+        sink,
+        sink->render_rect.width,
+        sink->render_rect.height);
+}
+
+static void
+gst_vaapisink_xoverlay_expose(GstXOverlay *overlay)
+{
+    GstBaseSink * const base_sink = GST_BASE_SINK(overlay);
+    GstBuffer *buffer;
+
+    buffer = gst_base_sink_get_last_buffer(base_sink);
+    if (buffer) {
+        gst_vaapisink_show_frame(base_sink, buffer);
+        gst_buffer_unref(buffer);
+    }
+}
+
+static void
+gst_vaapisink_xoverlay_iface_init(GstXOverlayClass *iface)
+{
+    iface->set_window_handle    = gst_vaapisink_xoverlay_set_window_handle;
+    iface->set_render_rectangle = gst_vaapisink_xoverlay_set_render_rectangle;
+    iface->expose               = gst_vaapisink_xoverlay_expose;
+}
+
+static void
+gst_vaapisink_destroy(GstVaapiSink *sink)
+{
+    gst_buffer_replace(&sink->video_buffer, NULL);
+    g_clear_object(&sink->texture);
+    g_clear_object(&sink->display);
+
+    gst_caps_replace(&sink->caps, NULL);
+
+    if (sink->video_pool) {
+        g_object_unref(sink->video_pool);
+        sink->video_pool = NULL;
+    }
+}
+
+#if USE_X11
+/* Checks whether a ConfigureNotify event is in the queue */
+typedef struct _ConfigureNotifyEventPendingArgs ConfigureNotifyEventPendingArgs;
+struct _ConfigureNotifyEventPendingArgs {
+    Window      window;
+    guint       width;
+    guint       height;
+    gboolean    match;
+};
+
+static Bool
+configure_notify_event_pending_cb(Display *dpy, XEvent *xev, XPointer arg)
+{
+    ConfigureNotifyEventPendingArgs * const args =
+        (ConfigureNotifyEventPendingArgs *)arg;
+
+    if (xev->type == ConfigureNotify &&
+        xev->xconfigure.window == args->window &&
+        xev->xconfigure.width  == args->width  &&
+        xev->xconfigure.height == args->height)
+        args->match = TRUE;
+
+    /* XXX: this is a hack to traverse the whole queue because we
+       can't use XPeekIfEvent() since it could block */
+    return False;
+}
+
+static gboolean
+configure_notify_event_pending(
+    GstVaapiSink *sink,
+    Window        window,
+    guint         width,
+    guint         height
+)
+{
+    ConfigureNotifyEventPendingArgs args;
+    XEvent xev;
+
+    args.window = window;
+    args.width  = width;
+    args.height = height;
+    args.match  = FALSE;
+
+    /* XXX: don't use XPeekIfEvent() because it might block */
+    XCheckIfEvent(
+        gst_vaapi_display_x11_get_display(GST_VAAPI_DISPLAY_X11(sink->display)),
+        &xev,
+        configure_notify_event_pending_cb, (XPointer)&args
+    );
+    return args.match;
+}
+#endif
+
+static const gchar *
+get_display_type_name(GstVaapiDisplayType display_type)
+{
+    gpointer const klass = g_type_class_peek(GST_VAAPI_TYPE_DISPLAY_TYPE);
+    GEnumValue * const e = g_enum_get_value(klass, display_type);
+
+    if (e)
+        return e->value_name;
+    return "<unknown-type>";
+}
+
+static inline gboolean
+gst_vaapisink_ensure_display(GstVaapiSink *sink)
+{
+    GstVaapiDisplayType display_type;
+    GstVaapiRenderMode render_mode;
+    GstVaapiDisplay *old_display = sink->display;
+
+    if (!gst_vaapi_ensure_display(sink, sink->display_type, &sink->display))
+        return FALSE;
+
+    display_type = gst_vaapi_display_get_display_type(sink->display);
+    if (display_type != sink->display_type || old_display != sink->display) {
+        GST_INFO("created %s %p", get_display_type_name(display_type),
+            sink->display);
+        sink->display_type = display_type;
+
+        sink->use_overlay =
+            gst_vaapi_display_get_render_mode(sink->display, &render_mode) &&
+            render_mode == GST_VAAPI_RENDER_MODE_OVERLAY;
+        GST_DEBUG("use %s rendering mode", sink->use_overlay ? "overlay" : "texture");
+
+        sink->use_rotation = gst_vaapi_display_has_property(
+            sink->display, GST_VAAPI_DISPLAY_PROP_ROTATION);
+    }
+    return TRUE;
+}
+
+static gboolean
+gst_vaapisink_ensure_display_rect(GstVaapiSink *sink, guint width, guint height)
+{
+    GstVaapiRectangle * const display_rect = &sink->display_rect;
+    guint num, den, display_par_n, display_par_d;
+    gboolean success;
+
+    /* Return success if caps are not set yet */
+    if (!sink->caps)
+        return TRUE;
+
+    GST_DEBUG("ensure render rect within %ux%u bounds", width, height);
+
+    gst_vaapi_display_get_pixel_aspect_ratio(
+        sink->display,
+        &display_par_n, &display_par_d
+    );
+    GST_DEBUG("display pixel-aspect-ratio %d/%d",
+              display_par_n, display_par_d);
+
+    success = gst_video_calculate_display_ratio(
+        &num, &den,
+        sink->video_width, sink->video_height,
+        sink->video_par_n, sink->video_par_d,
+        display_par_n, display_par_d
+    );
+    if (!success)
+        return FALSE;
+    GST_DEBUG("video size %dx%d, calculated ratio %d/%d",
+              sink->video_width, sink->video_height, num, den);
+
+    display_rect->width = gst_util_uint64_scale_int(height, num, den);
+    if (display_rect->width <= width) {
+        GST_DEBUG("keeping window height");
+        display_rect->height = height;
+    }
+    else {
+        GST_DEBUG("keeping window width");
+        display_rect->width  = width;
+        display_rect->height =
+            gst_util_uint64_scale_int(width, den, num);
+    }
+    GST_DEBUG("scaling video to %ux%u", display_rect->width, display_rect->height);
+
+    g_assert(display_rect->width  <= width);
+    g_assert(display_rect->height <= height);
+
+    display_rect->x = (width  - display_rect->width)  / 2;
+    display_rect->y = (height - display_rect->height) / 2;
+
+    display_rect->x += sink->render_rect.x;
+    display_rect->y += sink->render_rect.y;
+
+    GST_DEBUG("render rect (%d,%d):%ux%u",
+              display_rect->x, display_rect->y,
+              display_rect->width, display_rect->height);
+    return TRUE;
+}
+
+static void
+gst_vaapisink_ensure_window_size(GstVaapiSink *sink, guint *pwidth, guint *pheight)
+{
+    GstVideoRectangle src_rect, dst_rect, out_rect;
+    guint num, den, display_width, display_height, display_par_n, display_par_d;
+    gboolean success, scale;
+
+    if (sink->foreign_window) {
+        *pwidth  = sink->window_width;
+        *pheight = sink->window_height;
+        return;
+    }
+
+    gst_vaapi_display_get_size(sink->display, &display_width, &display_height);
+    if (sink->fullscreen) {
+        *pwidth  = display_width;
+        *pheight = display_height;
+        return;
+    }
+
+    gst_vaapi_display_get_pixel_aspect_ratio(
+        sink->display,
+        &display_par_n, &display_par_d
+    );
+
+    success = gst_video_calculate_display_ratio(
+        &num, &den,
+        sink->video_width, sink->video_height,
+        sink->video_par_n, sink->video_par_d,
+        display_par_n, display_par_d
+    );
+    if (!success) {
+        num = sink->video_par_n;
+        den = sink->video_par_d;
+    }
+
+    src_rect.x = 0;
+    src_rect.y = 0;
+    src_rect.w = gst_util_uint64_scale_int(sink->video_height, num, den);
+    src_rect.h = sink->video_height;
+    dst_rect.x = 0;
+    dst_rect.y = 0;
+    dst_rect.w = display_width;
+    dst_rect.h = display_height;
+    scale      = (src_rect.w > dst_rect.w || src_rect.h > dst_rect.h);
+    gst_video_sink_center_rect(src_rect, dst_rect, &out_rect, scale);
+    *pwidth    = out_rect.w;
+    *pheight   = out_rect.h;
+}
+
+static inline gboolean
+gst_vaapisink_ensure_window(GstVaapiSink *sink, guint width, guint height)
+{
+    GstVaapiDisplay * const display = sink->display;
+
+    if (!sink->window) {
+        sink->render_rect.x = 0;
+        sink->render_rect.y = 0;
+        sink->render_rect.width = width;
+        sink->render_rect.height = height;
+
+        switch (sink->display_type) {
+#if USE_GLX
+        case GST_VAAPI_DISPLAY_TYPE_GLX:
+            sink->window = gst_vaapi_window_glx_new(display, width, height);
+            goto notify_xoverlay_interface;
+#endif
+#if USE_X11
+        case GST_VAAPI_DISPLAY_TYPE_X11:
+            sink->window = gst_vaapi_window_x11_new(display, width, height);
+        notify_xoverlay_interface:
+            if (!sink->window)
+                break;
+            gst_x_overlay_got_window_handle(
+                GST_X_OVERLAY(sink),
+                gst_vaapi_window_x11_get_xid(GST_VAAPI_WINDOW_X11(sink->window))
+            );
+            break;
+#endif
+#if USE_WAYLAND
+        case GST_VAAPI_DISPLAY_TYPE_WAYLAND:
+            sink->window = gst_vaapi_window_wayland_new(display, width, height);
+            break;
+#endif
+        default:
+            GST_ERROR("unsupported display type %d", sink->display_type);
+            return FALSE;
+        }
+    }
+    return sink->window != NULL;
+}
+
+#if USE_X11
+static gboolean
+gst_vaapisink_ensure_window_xid(GstVaapiSink *sink, guintptr window_id)
+{
+    Window rootwin;
+    unsigned int width, height, border_width, depth;
+    int x, y, i;
+    XID xid = window_id;
+
+    if (!gst_vaapisink_ensure_display(sink))
+        return FALSE;
+
+    gst_vaapi_display_lock(sink->display);
+    XGetGeometry(
+        gst_vaapi_display_x11_get_display(GST_VAAPI_DISPLAY_X11(sink->display)),
+        xid,
+        &rootwin,
+        &x, &y, &width, &height, &border_width, &depth
+    );
+    gst_vaapi_display_unlock(sink->display);
+
+    sink->render_rect.x = 0;
+    sink->render_rect.y = 0;
+    sink->render_rect.width = width;
+    sink->render_rect.height = height;
+
+    if ((width != sink->window_width || height != sink->window_height) &&
+        !configure_notify_event_pending(sink, xid, width, height)) {
+        if (!gst_vaapisink_ensure_display_rect(sink, width, height))
+            return FALSE;
+        sink->window_width  = width;
+        sink->window_height = height;
+    }
+
+    if (sink->is_pixmap) {
+        for (i = 0; i < MAX_PIXMAP_COUNT; i++) {
+            if (sink->pixmap_pool[i])
+            if (sink->pixmap_pool[i] &&
+                gst_vaapi_window_x11_get_xid(GST_VAAPI_WINDOW_X11(sink->pixmap_pool[i])) == xid) {
+                sink->window = sink->pixmap_pool[i];
+                return TRUE;
+            }
+        }
+    }
+    else {
+        if (sink->window &&
+            gst_vaapi_window_x11_get_xid(GST_VAAPI_WINDOW_X11(sink->window)) == xid)
+            return TRUE;
+        g_clear_object(&sink->window);
+    }
+
+    switch (sink->display_type) {
+#if USE_GLX
+    case GST_VAAPI_DISPLAY_TYPE_GLX:
+        sink->window = gst_vaapi_window_glx_new_with_xid(sink->display, xid);
+        break;
+#endif
+    case GST_VAAPI_DISPLAY_TYPE_X11:
+        sink->window = gst_vaapi_window_x11_new_with_xid(sink->display, xid, sink->is_pixmap);
+        break;
+    default:
+        GST_ERROR("unsupported display type %d", sink->display_type);
+        return FALSE;
+    }
+
+    gboolean save_pixmap_to_pool = FALSE;
+    for (i = 0; i < MAX_PIXMAP_COUNT; i++) {
+      if (!sink->pixmap_pool[i]) {
+        sink->pixmap_pool[i] = sink->window;
+        save_pixmap_to_pool = TRUE;
+        break;
+      }
+    }
+
+    if (!save_pixmap_to_pool) {
+        g_clear_object(&sink->pixmap_pool[MAX_PIXMAP_COUNT-1]);
+        sink->pixmap_pool[MAX_PIXMAP_COUNT-1] = sink->window;
+        GST_WARNING("exceed MAX_PIXMAP_COUNT: %d", MAX_PIXMAP_COUNT);
+    }
+
+    return sink->window != NULL;
+}
+#endif
+
+static gboolean
+gst_vaapisink_ensure_rotation(GstVaapiSink *sink, gboolean recalc_display_rect)
+{
+    gboolean success = FALSE;
+
+    g_return_val_if_fail(sink->display, FALSE);
+
+    if (sink->rotation == sink->rotation_req)
+        return TRUE;
+
+    if (!sink->use_rotation) {
+        GST_WARNING("VA display does not support rotation");
+        goto end;
+    }
+
+    gst_vaapi_display_lock(sink->display);
+    success = gst_vaapi_display_set_rotation(sink->display, sink->rotation_req);
+    gst_vaapi_display_unlock(sink->display);
+    if (!success) {
+        GST_ERROR("failed to change VA display rotation mode");
+        goto end;
+    }
+
+    if (((sink->rotation + sink->rotation_req) % 180) == 90) {
+        /* Orientation changed */
+        G_PRIMITIVE_SWAP(guint, sink->video_width, sink->video_height);
+        G_PRIMITIVE_SWAP(gint, sink->video_par_n, sink->video_par_d);
+    }
+
+    if (recalc_display_rect )
+        gst_vaapisink_ensure_display_rect(sink, sink->render_rect.width,
+            sink->render_rect.height);
+    success = TRUE;
+
+end:
+    sink->rotation = sink->rotation_req;
+    return success;
+}
+
+static gboolean
+gst_vaapisink_start(GstBaseSink *base_sink)
+{
+    GstVaapiSink * const sink = GST_VAAPISINK(base_sink);
+
+    return gst_vaapisink_ensure_display(sink);
+}
+
+static gboolean
+gst_vaapisink_stop(GstBaseSink *base_sink)
+{
+    int i = 0;
+    GstVaapiSink * const sink = GST_VAAPISINK(base_sink);
+
+    gst_buffer_replace(&sink->video_buffer, NULL);
+    if (sink->is_pixmap) {
+        for (i=0; i<MAX_PIXMAP_COUNT; i++) {
+            if (sink->pixmap_pool[i])  {
+                g_clear_object(&sink->pixmap_pool[i]);
+            }
+        }
+    }
+    else
+        g_clear_object(&sink->window);
+    sink->window = NULL;
+
+    g_clear_object(&sink->display);
+
+    if (sink->video_pool) {
+        g_object_unref(sink->video_pool);
+        sink->video_pool = NULL;
+    }
+    sink->buffer_sharing = FALSE;
+
+    return TRUE;
+}
+
+static gboolean
+gst_vaapisink_set_caps(GstBaseSink *base_sink, GstCaps *caps)
+{
+    GstVaapiSink * const sink = GST_VAAPISINK(base_sink);
+    GstStructure * const structure = gst_caps_get_structure(caps, 0);
+    guint win_width, win_height;
+    gint video_width, video_height, video_par_n = 1, video_par_d = 1;
+
+#if USE_DRM
+    if (sink->display_type == GST_VAAPI_DISPLAY_TYPE_DRM)
+        return TRUE;
+#endif
+
+    if (!structure)
+        return FALSE;
+    if (gst_structure_has_name(structure, GST_VAAPI_BUFFER_SHARING_CAPS_NAME))
+        sink->buffer_sharing = TRUE;
+    else
+        sink->buffer_sharing = FALSE;
+    if (!gst_structure_get_int(structure, "width",  &video_width))
+        return FALSE;
+    if (!gst_structure_get_int(structure, "height", &video_height))
+        return FALSE;
+    sink->video_width  = video_width;
+    sink->video_height = video_height;
+
+    gst_video_parse_caps_pixel_aspect_ratio(caps, &video_par_n, &video_par_d);
+    sink->video_par_n  = video_par_n;
+    sink->video_par_d  = video_par_d;
+    GST_DEBUG("video pixel-aspect-ratio %d/%d", video_par_n, video_par_d);
+
+    gst_caps_replace(&sink->caps, caps);
+
+    if (!gst_vaapisink_ensure_display(sink))
+        return FALSE;
+
+    gst_vaapisink_ensure_rotation(sink, FALSE);
+
+    gst_vaapisink_ensure_window_size(sink, &win_width, &win_height);
+    if (sink->window) {
+        if (!sink->foreign_window || sink->fullscreen)
+            gst_vaapi_window_set_size(sink->window, win_width, win_height);
+    }
+    else {
+        gst_vaapi_display_lock(sink->display);
+        gst_x_overlay_prepare_xwindow_id(GST_X_OVERLAY(sink));
+        if (!sink->window)
+            gst_vaapisink_prepare_xid(GST_X_OVERLAY(sink)); // tizen customized interface/message for webkit-efl
+        gst_vaapi_display_unlock(sink->display);
+        if (sink->window)
+            return TRUE;
+        if (!gst_vaapisink_ensure_window(sink, win_width, win_height))
+            return FALSE;
+        gst_vaapi_window_set_fullscreen(sink->window, sink->fullscreen);
+        gst_vaapi_window_show(sink->window);
+        gst_vaapi_window_get_size(sink->window, &win_width, &win_height);
+    }
+    sink->window_width  = win_width;
+    sink->window_height = win_height;
+    if (!sink->render_rect.width || !sink->render_rect.height) {
+        sink->render_rect.width = win_width;
+        sink->render_rect.height = win_height;
+    }
+    GST_DEBUG("window size %ux%u", win_width, win_height);
+
+    return gst_vaapisink_ensure_display_rect(sink,
+                                             sink->render_rect.width,
+                                             sink->render_rect.height);
+}
+
+#if USE_GLX
+static void
+render_background(GstVaapiSink *sink)
+{
+    /* Original code from Mirco Muller (MacSlow):
+       <http://cgit.freedesktop.org/~macslow/gl-gst-player/> */
+    GLfloat fStartX = 0.0f;
+    GLfloat fStartY = 0.0f;
+    GLfloat fWidth  = (GLfloat)sink->window_width;
+    GLfloat fHeight = (GLfloat)sink->window_height;
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    glBegin(GL_QUADS);
+    {
+        /* top third, darker grey to white */
+        glColor3f(0.85f, 0.85f, 0.85f);
+        glVertex3f(fStartX, fStartY, 0.0f);
+        glColor3f(0.85f, 0.85f, 0.85f);
+        glVertex3f(fStartX + fWidth, fStartY, 0.0f);
+        glColor3f(1.0f, 1.0f, 1.0f);
+        glVertex3f(fStartX + fWidth, fStartY + fHeight / 3.0f, 0.0f);
+        glColor3f(1.0f, 1.0f, 1.0f);
+        glVertex3f(fStartX, fStartY + fHeight / 3.0f, 0.0f);
+
+        /* middle third, just plain white */
+        glColor3f(1.0f, 1.0f, 1.0f);
+        glVertex3f(fStartX, fStartY + fHeight / 3.0f, 0.0f);
+        glVertex3f(fStartX + fWidth, fStartY + fHeight / 3.0f, 0.0f);
+        glVertex3f(fStartX + fWidth, fStartY + 2.0f * fHeight / 3.0f, 0.0f);
+        glVertex3f(fStartX, fStartY + 2.0f * fHeight / 3.0f, 0.0f);
+
+        /* bottom third, white to lighter grey */
+        glColor3f(1.0f, 1.0f, 1.0f);
+        glVertex3f(fStartX, fStartY + 2.0f * fHeight / 3.0f, 0.0f);
+        glColor3f(1.0f, 1.0f, 1.0f);
+        glVertex3f(fStartX + fWidth, fStartY + 2.0f * fHeight / 3.0f, 0.0f);
+        glColor3f(0.62f, 0.66f, 0.69f);
+        glVertex3f(fStartX + fWidth, fStartY + fHeight, 0.0f);
+        glColor3f(0.62f, 0.66f, 0.69f);
+        glVertex3f(fStartX, fStartY + fHeight, 0.0f);
+    }
+    glEnd();
+}
+
+static void
+render_frame(GstVaapiSink *sink)
+{
+    const guint x1 = sink->display_rect.x;
+    const guint x2 = sink->display_rect.x + sink->display_rect.width;
+    const guint y1 = sink->display_rect.y;
+    const guint y2 = sink->display_rect.y + sink->display_rect.height;
+
+    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+    glBegin(GL_QUADS);
+    {
+        glTexCoord2f(0.0f, 0.0f); glVertex2i(x1, y1);
+        glTexCoord2f(0.0f, 1.0f); glVertex2i(x1, y2);
+        glTexCoord2f(1.0f, 1.0f); glVertex2i(x2, y2);
+        glTexCoord2f(1.0f, 0.0f); glVertex2i(x2, y1);
+    }
+    glEnd();
+}
+
+static void
+render_reflection(GstVaapiSink *sink)
+{
+    const guint x1 = sink->display_rect.x;
+    const guint x2 = sink->display_rect.x + sink->display_rect.width;
+    const guint y1 = sink->display_rect.y;
+    const guint rh = sink->display_rect.height / 5;
+    GLfloat     ry = 1.0f - (GLfloat)rh / (GLfloat)sink->display_rect.height;
+
+    glBegin(GL_QUADS);
+    {
+        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+        glTexCoord2f(0.0f, 1.0f); glVertex2i(x1, y1);
+        glTexCoord2f(1.0f, 1.0f); glVertex2i(x2, y1);
+
+        glColor4f(1.0f, 1.0f, 1.0f, 0.0f);
+        glTexCoord2f(1.0f, ry); glVertex2i(x2, y1 + rh);
+        glTexCoord2f(0.0f, ry); glVertex2i(x1, y1 + rh);
+    }
+    glEnd();
+}
+
+static gboolean
+gst_vaapisink_show_frame_glx(
+    GstVaapiSink    *sink,
+    GstVaapiSurface *surface,
+    guint            flags
+)
+{
+    GstVaapiWindowGLX * const window = GST_VAAPI_WINDOW_GLX(sink->window);
+    GLenum target;
+    GLuint texture;
+
+    gst_vaapi_window_glx_make_current(window);
+    if (!sink->texture) {
+        sink->texture = gst_vaapi_texture_new(
+            sink->display,
+            GL_TEXTURE_2D,
+            GL_BGRA,
+            sink->video_width,
+            sink->video_height
+        );
+        if (!sink->texture)
+            goto error_create_texture;
+    }
+    if (!gst_vaapi_texture_put_surface(sink->texture, surface, flags))
+        goto error_transfer_surface;
+
+    target  = gst_vaapi_texture_get_target(sink->texture);
+    texture = gst_vaapi_texture_get_id(sink->texture);
+    if (target != GL_TEXTURE_2D || !texture)
+        return FALSE;
+
+    if (sink->use_reflection)
+        render_background(sink);
+
+    glEnable(target);
+    glBindTexture(target, texture);
+    {
+        if (sink->use_reflection) {
+            glPushMatrix();
+            glRotatef(20.0f, 0.0f, 1.0f, 0.0f);
+            glTranslatef(50.0f, 0.0f, 0.0f);
+        }
+        render_frame(sink);
+        if (sink->use_reflection) {
+            glPushMatrix();
+            glTranslatef(0.0, (GLfloat)sink->display_rect.height + 5.0f, 0.0f);
+            render_reflection(sink);
+            glPopMatrix();
+            glPopMatrix();
+        }
+    }
+    glBindTexture(target, 0);
+    glDisable(target);
+    gst_vaapi_window_glx_swap_buffers(window);
+    return TRUE;
+
+    /* ERRORS */
+error_create_texture:
+    {
+        GST_DEBUG("could not create VA/GLX texture");
+        return FALSE;
+    }
+error_transfer_surface:
+    {
+        GST_DEBUG("could not transfer VA surface to texture");
+        return FALSE;
+    }
+}
+#endif
+
+static inline gboolean
+gst_vaapisink_put_surface(
+    GstVaapiSink    *sink,
+    GstVaapiSurface *surface,
+    guint            flags
+)
+{
+    if (!gst_vaapi_window_put_surface(sink->window, surface,
+                NULL, &sink->display_rect, flags)) {
+        GST_DEBUG("could not render VA surface");
+        return FALSE;
+    }
+    return TRUE;
+}
+
+static GstFlowReturn
+gst_vaapisink_show_frame(GstBaseSink *base_sink, GstBuffer *buffer)
+{
+    GstVaapiSink * const sink = GST_VAAPISINK(base_sink);
+    GstVaapiVideoBuffer * vbuffer;
+    GstVaapiSurface *surface;
+    guint flags;
+    gboolean success;
+    GstVideoOverlayComposition * const composition =
+        gst_video_buffer_get_overlay_composition(buffer);
+
+    if (sink->buffer_sharing)
+        vbuffer = GST_VAAPI_VIDEO_BUFFER(buffer->data);
+    else
+        vbuffer = GST_VAAPI_VIDEO_BUFFER(buffer);
+
+    if (sink->display != gst_vaapi_video_buffer_get_display (vbuffer)) {
+      g_clear_object(&sink->display);
+      sink->display = g_object_ref (gst_vaapi_video_buffer_get_display (vbuffer));
+    }
+
+    if (!sink->window)
+        return GST_FLOW_UNEXPECTED;
+
+    gst_vaapisink_ensure_rotation(sink, TRUE);
+
+    surface = gst_vaapi_video_buffer_get_surface(vbuffer);
+    if (!surface)
+        return GST_FLOW_UNEXPECTED;
+
+    GST_DEBUG("render surface %" GST_VAAPI_ID_FORMAT,
+              GST_VAAPI_ID_ARGS(gst_vaapi_surface_get_id(surface)));
+
+    flags = gst_vaapi_video_buffer_get_render_flags(vbuffer);
+
+    if (!gst_vaapi_surface_set_subpictures_from_composition(surface,
+             composition, TRUE))
+        GST_WARNING("could not update subtitles");
+
+    switch (sink->display_type) {
+#if USE_GLX
+    case GST_VAAPI_DISPLAY_TYPE_GLX:
+        success = gst_vaapisink_show_frame_glx(sink, surface, flags);
+        break;
+#endif
+#if USE_DRM
+    case GST_VAAPI_DISPLAY_TYPE_DRM:
+        success = TRUE;
+        break;
+#endif
+#if USE_X11
+    case GST_VAAPI_DISPLAY_TYPE_X11:
+        success = gst_vaapisink_put_surface(sink, surface, flags);
+        break;
+#endif
+#if USE_WAYLAND
+    case GST_VAAPI_DISPLAY_TYPE_WAYLAND:
+        success = gst_vaapisink_put_surface(sink, surface, flags);
+        break;
+#endif
+    default:
+        GST_ERROR("unsupported display type %d", sink->display_type);
+        success = FALSE;
+        break;
+    }
+    if (!success)
+        return GST_FLOW_UNEXPECTED;
+
+    /* Retain VA surface until the next one is displayed */
+    if (sink->use_overlay)
+        gst_buffer_replace(&sink->video_buffer, buffer);
+
+    FPS_CALCULATION(vaapisink);
+    return GST_FLOW_OK;
+}
+
+static gboolean
+gst_vaapisink_query(GstBaseSink *base_sink, GstQuery *query)
+{
+    GstVaapiSink *sink = GST_VAAPISINK(base_sink);
+    GST_DEBUG ("sharing display %p", sink->display);
+    return gst_vaapi_reply_to_query (query, sink->display);
+}
+
+static gboolean
+gst_vaapisink_ensure_video_pool(
+    GstVaapiSink *sink,
+    GstCaps *caps)
+{
+    GstStructure *structure;
+    gint width = 0, height = 0;
+
+    g_return_val_if_fail(caps, FALSE);
+
+    structure = gst_caps_get_structure(caps, 0);
+    g_return_val_if_fail(structure, FALSE);
+
+    if (sink->video_pool)
+        return TRUE;
+
+    if (!gst_structure_get_int(structure, "width",  &width) ||
+        !gst_structure_get_int(structure, "height", &height))
+        return FALSE;
+
+    sink->video_pool = gst_vaapi_surface_pool_new(sink->display, caps);
+    if (!sink->video_pool) {
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+static GstFlowReturn
+gst_vaapisink_pad_buffer_alloc(
+    GstPad * pad,
+    guint64 offset,
+    guint size,
+    GstCaps * caps,
+    GstBuffer ** buf)
+{
+    GstVaapiSink * const sink = GST_VAAPISINK(GST_OBJECT_PARENT(pad));
+    GstStructure *structure = NULL;
+    GstBuffer *video_buffer = NULL;
+
+    if (!caps)
+        goto error;
+
+    structure = gst_caps_get_structure(caps, 0);
+    if (!structure ||
+        (!gst_structure_has_name(structure, GST_VAAPI_SURFACE_CAPS_NAME) &&
+         !gst_structure_has_name(structure, GST_VAAPI_BUFFER_SHARING_CAPS_NAME)))
+        goto error;
+
+    if (!gst_vaapisink_ensure_display(sink))
+        goto error;
+
+    if (!gst_vaapisink_ensure_video_pool(sink, caps))
+        goto error;
+
+    video_buffer = gst_vaapi_video_buffer_new_from_pool(sink->video_pool);
+
+    if (gst_structure_has_name(structure, GST_VAAPI_BUFFER_SHARING_CAPS_NAME) &&
+        !gst_vaapi_video_buffer_ensure_pointer(GST_VAAPI_VIDEO_BUFFER(video_buffer)))
+        goto error;
+
+    *buf = video_buffer;
+    return GST_FLOW_OK;
+
+error:
+    GST_ERROR("vaapisink allocate buffer failed.");
+    return GST_FLOW_ERROR;
+}
+
+static void
+gst_vaapisink_finalize(GObject *object)
+{
+    gst_vaapisink_destroy(GST_VAAPISINK(object));
+
+    G_OBJECT_CLASS(gst_vaapisink_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapisink_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiSink * const sink = GST_VAAPISINK(object);
+
+    switch (prop_id) {
+    case PROP_DISPLAY_TYPE:
+        sink->display_type = g_value_get_enum(value);
+        break;
+    case PROP_FULLSCREEN:
+        sink->fullscreen = g_value_get_boolean(value);
+        break;
+    case PROP_SYNCHRONOUS:
+        sink->synchronous = g_value_get_boolean(value);
+        break;
+    case PROP_USE_REFLECTION:
+        sink->use_reflection = g_value_get_boolean(value);
+        break;
+    case PROP_ROTATION:
+        sink->rotation_req = g_value_get_enum(value);
+        break;
+    case PROP_IS_PIXMAP:
+        sink->is_pixmap = g_value_get_boolean(value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapisink_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiSink * const sink = GST_VAAPISINK(object);
+
+    switch (prop_id) {
+    case PROP_DISPLAY_TYPE:
+        g_value_set_enum(value, sink->display_type);
+        break;
+    case PROP_FULLSCREEN:
+        g_value_set_boolean(value, sink->fullscreen);
+        break;
+    case PROP_SYNCHRONOUS:
+        g_value_set_boolean(value, sink->synchronous);
+        break;
+    case PROP_USE_REFLECTION:
+        g_value_set_boolean(value, sink->use_reflection);
+        break;
+    case PROP_ROTATION:
+        g_value_set_enum(value, sink->rotation);
+        break;
+    case PROP_IS_PIXMAP:
+        g_value_set_boolean(value, sink->is_pixmap);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapisink_class_init(GstVaapiSinkClass *klass)
+{
+    GObjectClass * const     object_class   = G_OBJECT_CLASS(klass);
+    GstElementClass * const  element_class  = GST_ELEMENT_CLASS(klass);
+    GstBaseSinkClass * const basesink_class = GST_BASE_SINK_CLASS(klass);
+    GstPadTemplate *pad_template;
+
+    GST_DEBUG_CATEGORY_INIT(gst_debug_vaapisink,
+                            GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
+
+    object_class->finalize       = gst_vaapisink_finalize;
+    object_class->set_property   = gst_vaapisink_set_property;
+    object_class->get_property   = gst_vaapisink_get_property;
+
+    basesink_class->start        = gst_vaapisink_start;
+    basesink_class->stop         = gst_vaapisink_stop;
+    basesink_class->set_caps     = gst_vaapisink_set_caps;
+    basesink_class->preroll      = gst_vaapisink_show_frame;
+    basesink_class->render       = gst_vaapisink_show_frame;
+    basesink_class->query        = gst_vaapisink_query;
+
+    gst_element_class_set_details_simple(
+        element_class,
+        gst_vaapisink_details.longname,
+        gst_vaapisink_details.klass,
+        gst_vaapisink_details.description,
+        gst_vaapisink_details.author
+    );
+
+    pad_template = gst_static_pad_template_get(&gst_vaapisink_sink_factory);
+    gst_element_class_add_pad_template(element_class, pad_template);
+    gst_object_unref(pad_template);
+
+    g_object_class_install_property
+        (object_class,
+         PROP_DISPLAY_TYPE,
+         g_param_spec_enum("display",
+                           "display type",
+                           "display type to use",
+                           GST_VAAPI_TYPE_DISPLAY_TYPE,
+                           GST_VAAPI_DISPLAY_TYPE_ANY,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+#if USE_GLX
+    g_object_class_install_property
+        (object_class,
+         PROP_USE_REFLECTION,
+         g_param_spec_boolean("use-reflection",
+                              "Reflection effect",
+                              "Enables OpenGL reflection effect",
+                              FALSE,
+                              G_PARAM_READWRITE));
+#endif
+
+    g_object_class_install_property
+        (object_class,
+         PROP_FULLSCREEN,
+         g_param_spec_boolean("fullscreen",
+                              "Fullscreen",
+                              "Requests window in fullscreen state",
+                              FALSE,
+                              G_PARAM_READWRITE));
+
+    /**
+     * GstVaapiSink:synchronous:
+     *
+     * When enabled, runs the X display in synchronous mode. Note that
+     * this is used only for debugging.
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_SYNCHRONOUS,
+         g_param_spec_boolean("synchronous",
+                              "Synchronous mode",
+                              "Toggles X display synchronous mode",
+                              FALSE,
+                              G_PARAM_READWRITE));
+
+    /**
+     * GstVaapiSink:rotation:
+     *
+     * The VA display rotation mode, expressed as a #GstVaapiRotation.
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_ROTATION,
+         g_param_spec_enum(GST_VAAPI_DISPLAY_PROP_ROTATION,
+                           "rotation",
+                           "The display rotation mode",
+                           GST_VAAPI_TYPE_ROTATION,
+                           DEFAULT_ROTATION,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_IS_PIXMAP,
+         g_param_spec_boolean("is-pixmap",
+                              "IsPixmap",
+                              "the X drawable is Pixmap or not",
+                              FALSE,
+                              G_PARAM_READWRITE));
+
+}
+
+static void
+gst_vaapisink_init(GstVaapiSink *sink)
+{
+    int i = 0;
+    GstPad *sinkpad = GST_BASE_SINK_PAD(sink);
+
+    gst_pad_set_bufferalloc_function(sinkpad,
+      gst_vaapisink_pad_buffer_alloc);
+
+    sink->caps           = NULL;
+    sink->display        = NULL;
+    sink->window         = NULL;
+    sink->window_width   = 0;
+    sink->window_height  = 0;
+    sink->texture        = NULL;
+    sink->video_buffer   = NULL;
+    sink->video_width    = 0;
+    sink->video_height   = 0;
+    sink->video_par_n    = 1;
+    sink->video_par_d    = 1;
+    sink->foreign_window = FALSE;
+    sink->fullscreen     = FALSE;
+    sink->synchronous    = FALSE;
+    sink->display_type   = DEFAULT_DISPLAY_TYPE;
+    sink->rotation       = DEFAULT_ROTATION;
+    sink->rotation_req   = DEFAULT_ROTATION;
+    sink->use_reflection = FALSE;
+    sink->use_overlay    = FALSE;
+    sink->use_rotation   = FALSE;
+    sink->render_rect.x  = 0;
+    sink->render_rect.y  = 0;
+    sink->render_rect.width  = 0;
+    sink->render_rect.height = 0;
+    sink->video_pool     = NULL;
+    sink->buffer_sharing = FALSE;
+    sink->is_pixmap      = FALSE;
+
+    for (i=0; i<MAX_PIXMAP_COUNT; i++) {
+        sink->pixmap_pool[i] = NULL;
+    }
+}
diff --git a/gst/vaapi/gstvaapisink.h b/gst/vaapi/gstvaapisink.h
new file mode 100644 (file)
index 0000000..acf6dd6
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ *  gstvaapisink.h - VA-API video sink
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+*/
+
+#ifndef GST_VAAPISINK_H
+#define GST_VAAPISINK_H
+
+#include <gst/video/gstvideosink.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapiwindow.h>
+#if USE_GLX
+#include <gst/vaapi/gstvaapitexture.h>
+#endif
+#include "gstvaapipluginutil.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_VAAPISINK \
+    (gst_vaapisink_get_type())
+
+#define GST_VAAPISINK(obj)                              \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                  \
+                                GST_TYPE_VAAPISINK,     \
+                                GstVaapiSink))
+
+#define GST_VAAPISINK_CLASS(klass)                      \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                   \
+                             GST_TYPE_VAAPISINK,        \
+                             GstVaapiSinkClass))
+
+#define GST_IS_VAAPISINK(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_VAAPISINK))
+
+#define GST_IS_VAAPISINK_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_VAAPISINK))
+
+#define GST_VAAPISINK_GET_CLASS(obj)                    \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                   \
+                               GST_TYPE_VAAPISINK,      \
+                               GstVaapiSinkClass))
+
+typedef struct _GstVaapiSink                    GstVaapiSink;
+typedef struct _GstVaapiSinkClass               GstVaapiSinkClass;
+#if !USE_GLX
+typedef struct _GstVaapiTexture                 GstVaapiTexture;
+#endif
+
+#define MAX_PIXMAP_COUNT  20
+
+struct _GstVaapiSink {
+    /*< private >*/
+    GstVideoSink parent_instance;
+
+    GstCaps            *caps;
+    GstVaapiDisplay    *display;
+    GstVaapiDisplayType display_type;
+    GstVaapiWindow     *window;
+    guint               window_width;
+    guint               window_height;
+    GstVaapiTexture    *texture;
+    GstBuffer          *video_buffer;
+    guint               video_width;
+    guint               video_height;
+    gint                video_par_n;
+    gint                video_par_d;
+    GstVaapiRectangle   display_rect; /* centralized video display position */
+    GstVaapiRectangle   render_rect;  /* user defined rendering position */
+    GstVaapiRotation    rotation;
+    GstVaapiRotation    rotation_req;
+    GstVaapiVideoPool  *video_pool;
+    guint               foreign_window  : 1;
+    guint               fullscreen      : 1;
+    guint               synchronous     : 1;
+    guint               use_reflection  : 1;
+    guint               use_overlay     : 1;
+    guint               use_rotation    : 1;
+    guint               buffer_sharing  : 1;
+    guint               is_pixmap       : 1;
+    GstVaapiWindow     *pixmap_pool[MAX_PIXMAP_COUNT];
+};
+
+struct _GstVaapiSinkClass {
+    /*< private >*/
+    GstVideoSinkClass parent_class;
+};
+
+GType
+gst_vaapisink_get_type(void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* GST_VAAPISINK_H */
diff --git a/gst/vaapi/gstvaapiupload.c b/gst/vaapi/gstvaapiupload.c
new file mode 100644 (file)
index 0000000..ce31088
--- /dev/null
@@ -0,0 +1,945 @@
+/*
+ *  gstvaapiupload.c - VA-API video uploader
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:gstvaapiupload
+ * @short_description: A video to VA flow filter
+ *
+ * vaapiupload uploads from raw YUV pixels to VA surfaces suitable
+ * for the vaapisink element, for example.
+ */
+
+#include "config.h"
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/video/videocontext.h>
+#include <gst/vaapi/gstvaapivideobuffer.h>
+#include <gst/vaapi/gstvaapidebug.h>
+
+#include "gstvaapiupload.h"
+#include "gstvaapipluginutil.h"
+#include "gstvaapipluginbuffer.h"
+
+#define GST_PLUGIN_NAME "vaapiupload"
+#define GST_PLUGIN_DESC "A video to VA flow filter"
+
+GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapiupload);
+#define GST_CAT_DEFAULT gst_debug_vaapiupload
+
+/* ElementFactory information */
+static const GstElementDetails gst_vaapiupload_details =
+    GST_ELEMENT_DETAILS(
+        "VA-API colorspace uploader",
+        "Filter/Converter/Video",
+        GST_PLUGIN_DESC,
+        "Gwenole Beauchesne <gwenole.beauchesne@intel.com>");
+
+/* Default templates */
+static const char gst_vaapiupload_yuv_caps_str[] =
+    "video/x-raw-yuv, "
+    "width  = (int) [ 1, MAX ], "
+    "height = (int) [ 1, MAX ]; ";
+
+static const char gst_vaapiupload_vaapi_caps_str[] =
+    GST_VAAPI_SURFACE_CAPS;
+
+static GstStaticPadTemplate gst_vaapiupload_sink_factory =
+    GST_STATIC_PAD_TEMPLATE(
+        "sink",
+        GST_PAD_SINK,
+        GST_PAD_ALWAYS,
+        GST_STATIC_CAPS(gst_vaapiupload_yuv_caps_str));
+
+static GstStaticPadTemplate gst_vaapiupload_src_factory =
+    GST_STATIC_PAD_TEMPLATE(
+        "src",
+        GST_PAD_SRC,
+        GST_PAD_ALWAYS,
+        GST_STATIC_CAPS(gst_vaapiupload_vaapi_caps_str));
+
+static void
+gst_vaapiupload_implements_iface_init(GstImplementsInterfaceClass *iface);
+
+static void
+gst_video_context_interface_init(GstVideoContextInterface *iface);
+
+#define GstVideoContextClass GstVideoContextInterface
+G_DEFINE_TYPE_WITH_CODE(
+    GstVaapiUpload,
+    gst_vaapiupload,
+    GST_TYPE_BASE_TRANSFORM,
+    G_IMPLEMENT_INTERFACE(GST_TYPE_IMPLEMENTS_INTERFACE,
+                          gst_vaapiupload_implements_iface_init);
+    G_IMPLEMENT_INTERFACE(GST_TYPE_VIDEO_CONTEXT,
+                          gst_video_context_interface_init));
+
+/*
+ * Direct rendering levels (direct-rendering)
+ * 0: upstream allocated YUV pixels
+ * 1: vaapiupload allocated YUV pixels (mapped from VA image)
+ * 2: vaapiupload allocated YUV pixels (mapped from VA surface)
+ */
+#define DIRECT_RENDERING_DEFAULT 2
+
+enum {
+    PROP_0,
+
+    PROP_DIRECT_RENDERING,
+};
+
+static gboolean
+gst_vaapiupload_start(GstBaseTransform *trans);
+
+static gboolean
+gst_vaapiupload_stop(GstBaseTransform *trans);
+
+static GstFlowReturn
+gst_vaapiupload_transform(
+    GstBaseTransform *trans,
+    GstBuffer        *inbuf,
+    GstBuffer        *outbuf
+);
+
+static GstCaps *
+gst_vaapiupload_transform_caps(
+    GstBaseTransform *trans,
+    GstPadDirection   direction,
+    GstCaps          *caps
+);
+
+static gboolean
+gst_vaapiupload_set_caps(
+    GstBaseTransform *trans,
+    GstCaps          *incaps,
+    GstCaps          *outcaps
+);
+
+static gboolean
+gst_vaapiupload_get_unit_size(
+    GstBaseTransform *trans,
+    GstCaps          *caps,
+    guint            *size
+);
+
+static GstFlowReturn
+gst_vaapiupload_sinkpad_buffer_alloc(
+    GstPad           *pad,
+    guint64           offset,
+    guint             size,
+    GstCaps          *caps,
+    GstBuffer       **pbuf
+);
+
+static GstFlowReturn
+gst_vaapiupload_prepare_output_buffer(
+    GstBaseTransform *trans,
+    GstBuffer        *inbuf,
+    gint              size,
+    GstCaps          *caps,
+    GstBuffer       **poutbuf
+);
+
+static gboolean
+gst_vaapiupload_query(
+    GstPad   *pad,
+    GstQuery *query
+);
+
+/* GstImplementsInterface interface */
+
+static gboolean
+gst_vaapiupload_implements_interface_supported(
+    GstImplementsInterface *iface,
+    GType                   type
+)
+{
+    return (type == GST_TYPE_VIDEO_CONTEXT);
+}
+
+static void
+gst_vaapiupload_implements_iface_init(GstImplementsInterfaceClass *iface)
+{
+    iface->supported = gst_vaapiupload_implements_interface_supported;
+}
+
+/* GstVideoContext interface */
+
+static void
+gst_vaapiupload_set_video_context(GstVideoContext *context, const gchar *type,
+    const GValue *value)
+{
+  GstVaapiUpload *upload = GST_VAAPIUPLOAD (context);
+  gst_vaapi_set_display (type, value, &upload->display);
+}
+
+static void
+gst_video_context_interface_init(GstVideoContextInterface *iface)
+{
+    iface->set_context = gst_vaapiupload_set_video_context;
+}
+
+static void
+gst_vaapiupload_destroy(GstVaapiUpload *upload)
+{
+    g_clear_object(&upload->images);
+    g_clear_object(&upload->surfaces);
+    g_clear_object(&upload->display);
+}
+
+static void
+gst_vaapiupload_finalize(GObject *object)
+{
+    gst_vaapiupload_destroy(GST_VAAPIUPLOAD(object));
+
+    G_OBJECT_CLASS(gst_vaapiupload_parent_class)->finalize(object);
+}
+
+
+static void
+gst_vaapiupload_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiUpload * const upload = GST_VAAPIUPLOAD(object);
+
+    switch (prop_id) {
+    case PROP_DIRECT_RENDERING:
+        GST_OBJECT_LOCK(upload);
+        upload->direct_rendering = g_value_get_uint(value);
+        GST_OBJECT_UNLOCK(upload);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapiupload_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiUpload * const upload = GST_VAAPIUPLOAD(object);
+
+    switch (prop_id) {
+    case PROP_DIRECT_RENDERING:
+        g_value_set_uint(value, upload->direct_rendering);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapiupload_class_init(GstVaapiUploadClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+    GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
+    GstBaseTransformClass * const trans_class = GST_BASE_TRANSFORM_CLASS(klass);
+    GstPadTemplate *pad_template;
+
+    GST_DEBUG_CATEGORY_INIT(gst_debug_vaapiupload,
+                            GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
+
+    object_class->finalize      = gst_vaapiupload_finalize;
+    object_class->set_property  = gst_vaapiupload_set_property;
+    object_class->get_property  = gst_vaapiupload_get_property;
+
+    trans_class->start          = gst_vaapiupload_start;
+    trans_class->stop           = gst_vaapiupload_stop;
+    trans_class->transform      = gst_vaapiupload_transform;
+    trans_class->transform_caps = gst_vaapiupload_transform_caps;
+    trans_class->set_caps       = gst_vaapiupload_set_caps;
+    trans_class->get_unit_size  = gst_vaapiupload_get_unit_size;
+    trans_class->prepare_output_buffer = gst_vaapiupload_prepare_output_buffer;
+
+    gst_element_class_set_details_simple(
+        element_class,
+        gst_vaapiupload_details.longname,
+        gst_vaapiupload_details.klass,
+        gst_vaapiupload_details.description,
+        gst_vaapiupload_details.author
+    );
+
+    /* sink pad */
+    pad_template = gst_static_pad_template_get(&gst_vaapiupload_sink_factory);
+    gst_element_class_add_pad_template(element_class, pad_template);
+    gst_object_unref(pad_template);
+
+    /* src pad */
+    pad_template = gst_static_pad_template_get(&gst_vaapiupload_src_factory);
+    gst_element_class_add_pad_template(element_class, pad_template);
+    gst_object_unref(pad_template);
+
+    /**
+     * GstVaapiUpload:direct-rendering:
+     *
+     * Selects the direct rendering level.
+     * <orderedlist>
+     * <listitem override="0">
+     *   Disables direct rendering.
+     * </listitem>
+     * <listitem>
+     *   Enables direct rendering to the output buffer. i.e. this
+     *   tries to use a single buffer for both sink and src pads.
+     * </listitem>
+     * <listitem>
+     *   Enables direct rendering to the underlying surface. i.e. with
+     *   drivers supporting vaDeriveImage(), the output surface pixels
+     *   will be modified directly.
+     * </listitem>
+     * </orderedlist>
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_DIRECT_RENDERING,
+         g_param_spec_uint("direct-rendering",
+                           "Direct rendering",
+                           "Direct rendering level",
+                           0, 2,
+                           DIRECT_RENDERING_DEFAULT,
+                           G_PARAM_READWRITE));
+}
+
+static void
+gst_vaapiupload_init(GstVaapiUpload *upload)
+{
+    GstPad *sinkpad, *srcpad;
+
+    upload->display                    = NULL;
+    upload->images                     = NULL;
+    upload->images_reset               = FALSE;
+    upload->image_width                = 0;
+    upload->image_height               = 0;
+    upload->surfaces                   = NULL;
+    upload->surfaces_reset             = FALSE;
+    upload->surface_width              = 0;
+    upload->surface_height             = 0;
+    upload->direct_rendering_caps      = 0;
+    upload->direct_rendering           = G_MAXUINT32;
+    upload->need_manual_upload        = FALSE;
+
+    /* Override buffer allocator on sink pad */
+    sinkpad = gst_element_get_static_pad(GST_ELEMENT(upload), "sink");
+    gst_pad_set_bufferalloc_function(
+        sinkpad,
+        gst_vaapiupload_sinkpad_buffer_alloc
+    );
+    gst_pad_set_query_function(sinkpad, gst_vaapiupload_query);
+    g_object_unref(sinkpad);
+
+    /* Override query on src pad */
+    srcpad = gst_element_get_static_pad(GST_ELEMENT(upload), "src");
+    gst_pad_set_query_function(srcpad, gst_vaapiupload_query);
+    g_object_unref(srcpad);
+}
+
+static inline gboolean
+gst_vaapiupload_ensure_display(GstVaapiUpload *upload)
+{
+    return gst_vaapi_ensure_display(upload, GST_VAAPI_DISPLAY_TYPE_ANY,
+        &upload->display);
+}
+
+static gboolean
+gst_vaapiupload_start(GstBaseTransform *trans)
+{
+    GstVaapiUpload * const upload = GST_VAAPIUPLOAD(trans);
+
+    if (!gst_vaapiupload_ensure_display(upload))
+        return FALSE;
+    return TRUE;
+}
+
+static gboolean
+gst_vaapiupload_stop(GstBaseTransform *trans)
+{
+    GstVaapiUpload * const upload = GST_VAAPIUPLOAD(trans);
+
+    g_clear_object(&upload->display);
+
+    return TRUE;
+}
+
+static GstFlowReturn
+gst_vaapiupload_transform(
+    GstBaseTransform *trans,
+    GstBuffer        *inbuf,
+    GstBuffer        *outbuf
+)
+{
+    GstVaapiUpload * const upload = GST_VAAPIUPLOAD(trans);
+    GstVaapiVideoBuffer *vbuffer;
+    GstVaapiSurface *surface;
+    GstVaapiImage *image;
+    gboolean success;
+
+    vbuffer = GST_VAAPI_VIDEO_BUFFER(outbuf);
+    surface = gst_vaapi_video_buffer_get_surface(vbuffer);
+    if (!surface)
+        return GST_FLOW_UNEXPECTED;
+
+    if (upload->direct_rendering) {
+        if (!GST_VAAPI_IS_VIDEO_BUFFER(inbuf)) {
+            GST_DEBUG("GstVaapiVideoBuffer was expected");
+            return GST_FLOW_UNEXPECTED;
+        }
+
+        vbuffer = GST_VAAPI_VIDEO_BUFFER(inbuf);
+        image   = gst_vaapi_video_buffer_get_image(vbuffer);
+        if (!image)
+            return GST_FLOW_UNEXPECTED;
+        if (!gst_vaapi_image_unmap(image))
+            return GST_FLOW_UNEXPECTED;
+
+        if (upload->direct_rendering < 2) {
+            if (!gst_vaapi_surface_put_image(surface, image))
+                goto error_put_image;
+        }
+        goto flow_ok;
+    }
+
+    /* PVR need directly copy image to surface */
+    image = gst_vaapi_surface_derive_image(surface);
+    //image = gst_vaapi_video_pool_get_object(upload->images);
+    if (!image)
+        goto error_put_image;
+
+    if (!upload->need_manual_upload) {
+        success = gst_vaapi_image_update_from_buffer(image, inbuf, NULL);
+    } else { /* manually copy data to image*/
+        success = gst_vaapi_convert_buffer_to_image(image, inbuf);
+    }
+    if (!success)
+            goto error_put_image;
+
+    //success = gst_vaapi_surface_put_image(surface, image);
+    //gst_vaapi_video_pool_put_object(upload->images, image);
+    //if (!success)
+    //    goto error_put_image;
+    g_object_unref(image);
+
+flow_ok:
+    FPS_CALCULATION(vaapiupload);
+    return GST_FLOW_OK;
+
+error_put_image:
+    {
+        GST_WARNING("failed to upload %" GST_FOURCC_FORMAT " image "
+                    "to surface 0x%08x",
+                    GST_FOURCC_ARGS(gst_vaapi_image_get_format(image)),
+                    gst_vaapi_surface_get_id(surface));
+        if (!upload->direct_rendering && image)
+            g_object_unref(image);
+        return GST_FLOW_OK;
+    }
+}
+
+static GstCaps *
+gst_vaapi_get_other_support_caps(GstVaapiUpload *upload)
+{
+  GstCaps *caps;
+  caps = gst_caps_from_string(GST_VIDEO_CAPS_YUV("YUY2"));
+  return caps;
+}
+
+static GstCaps *
+gst_vaapiupload_transform_caps(
+    GstBaseTransform *trans,
+    GstPadDirection   direction,
+    GstCaps          *caps
+)
+{
+    GstVaapiUpload * const upload = GST_VAAPIUPLOAD(trans);
+    GstCaps *out_caps = NULL;
+    GstStructure *structure;
+
+    g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
+
+    structure = gst_caps_get_structure(caps, 0);
+
+    if (direction == GST_PAD_SINK) {
+        if (!gst_structure_has_name(structure, "video/x-raw-yuv"))
+            return NULL;
+        out_caps = gst_caps_from_string(gst_vaapiupload_vaapi_caps_str);
+
+        structure = gst_caps_get_structure(out_caps, 0);
+        gst_structure_set(
+            structure,
+            "type", G_TYPE_STRING, "vaapi",
+            "opengl", G_TYPE_BOOLEAN, USE_GLX,
+            NULL
+        );
+    }
+    else {
+        if (!gst_structure_has_name(structure, GST_VAAPI_SURFACE_CAPS_NAME))
+            return NULL;
+        out_caps = gst_caps_from_string(gst_vaapiupload_yuv_caps_str);
+        if (upload->display) {
+            GstCaps *allowed_caps, *inter_caps, *other_caps;
+            allowed_caps = gst_vaapi_display_get_image_caps(upload->display);
+            if (!allowed_caps)
+                return NULL;
+            /* can direct copy other YUV to va surface */
+            other_caps = gst_vaapi_get_other_support_caps(upload);
+            gst_caps_merge(allowed_caps, other_caps);
+
+            inter_caps = gst_caps_intersect(out_caps, allowed_caps);
+            gst_caps_unref(allowed_caps);
+            gst_caps_unref(out_caps);
+            out_caps = inter_caps;
+        }
+    }
+
+    if (!gst_vaapi_append_surface_caps(out_caps, caps)) {
+        gst_caps_unref(out_caps);
+        return NULL;
+    }
+    return out_caps;
+}
+
+static gboolean
+gst_vaapiupload_ensure_image_pool(GstVaapiUpload *upload, GstCaps *caps)
+{
+    GstStructure * const structure = gst_caps_get_structure(caps, 0);
+    gint width, height;
+
+    gst_structure_get_int(structure, "width",  &width);
+    gst_structure_get_int(structure, "height", &height);
+
+    if (width != upload->image_width || height != upload->image_height) {
+        upload->image_width  = width;
+        upload->image_height = height;
+        g_clear_object(&upload->images);
+        upload->images = gst_vaapi_image_pool_new(upload->display, caps);
+        if (!upload->images)
+            return FALSE;
+        upload->images_reset = TRUE;
+    }
+    return TRUE;
+}
+
+static gboolean
+gst_vaapiupload_ensure_surface_pool(GstVaapiUpload *upload, GstCaps *caps)
+{
+    GstStructure * const structure = gst_caps_get_structure(caps, 0);
+    gint width, height;
+
+    gst_structure_get_int(structure, "width",  &width);
+    gst_structure_get_int(structure, "height", &height);
+
+    if (width != upload->surface_width || height != upload->surface_height) {
+        upload->surface_width  = width;
+        upload->surface_height = height;
+        g_clear_object(&upload->surfaces);
+        upload->surfaces = gst_vaapi_surface_pool_new(upload->display, caps);
+        if (!upload->surfaces)
+            return FALSE;
+        upload->surfaces_reset = TRUE;
+    }
+    return TRUE;
+}
+
+static void
+gst_vaapiupload_ensure_direct_rendering_caps(
+    GstVaapiUpload *upload,
+    GstCaps         *caps
+)
+{
+    GstVaapiSurface *surface;
+    GstVaapiImage *image;
+    GstVaapiImageFormat vaformat;
+    GstVideoFormat vformat;
+    GstStructure *structure;
+    gint width, height;
+
+    if (!upload->images_reset && !upload->surfaces_reset)
+        return;
+
+    upload->images_reset          = FALSE;
+    upload->surfaces_reset        = FALSE;
+    upload->direct_rendering_caps = 0;
+
+    structure = gst_caps_get_structure(caps, 0);
+    if (!structure)
+        return;
+    gst_structure_get_int(structure, "width",  &width);
+    gst_structure_get_int(structure, "height", &height);
+
+    /* Translate from Gst video format to VA image format */
+    if (!gst_video_format_parse_caps(caps, &vformat, NULL, NULL))
+        return;
+    if (!gst_video_format_is_yuv(vformat))
+        return;
+    vaformat = gst_vaapi_image_format_from_video(vformat);
+    if (!vaformat)
+        return;
+
+    /* Check if we can alias sink & output buffers (same data_size) */
+    image = gst_vaapi_video_pool_get_object(upload->images);
+    if (image) {
+        if (upload->direct_rendering_caps == 0 &&
+            (gst_vaapi_image_get_format(image) == vaformat &&
+             gst_vaapi_image_is_linear(image) &&
+             (gst_vaapi_image_get_data_size(image) ==
+              gst_video_format_get_size(vformat, width, height))))
+            upload->direct_rendering_caps = 1;
+        gst_vaapi_video_pool_put_object(upload->images, image);
+    }
+
+    /* Check if we can access to the surface pixels directly */
+    surface = gst_vaapi_video_pool_get_object(upload->surfaces);
+    if (surface) {
+        image = gst_vaapi_surface_derive_image(surface);
+        if (image) {
+            if (gst_vaapi_image_map(image)) {
+                if (upload->direct_rendering_caps == 1 &&
+                    (gst_vaapi_image_get_format(image) == vaformat &&
+                     gst_vaapi_image_is_linear(image) &&
+                     (gst_vaapi_image_get_data_size(image) ==
+                      gst_video_format_get_size(vformat, width, height))))
+                    upload->direct_rendering_caps = 2;
+                gst_vaapi_image_unmap(image);
+            }
+            g_object_unref(image);
+        }
+        gst_vaapi_video_pool_put_object(upload->surfaces, surface);
+    }
+}
+
+typedef enum YUV_TYPE {
+  YUV_UNKOWN = 0,
+  YUV_411    = 1,
+  YUV_422    = 2,
+  YUV_444    = 4
+} YUV_TYPE;
+
+static YUV_TYPE
+_image_format_to_yuv_type(guint32 fourcc)
+{
+    switch (fourcc) {
+        case GST_MAKE_FOURCC('N','V','1','2'):
+        case GST_MAKE_FOURCC('Y','V','1','2'):
+        case GST_MAKE_FOURCC('I','4','2','0'):
+        case GST_MAKE_FOURCC('N','V','2','1'):
+        return YUV_411;
+
+        case GST_MAKE_FOURCC('Y','U','Y','2'):
+        case GST_MAKE_FOURCC('Y','V','Y','U'):
+        return YUV_422;
+
+        case GST_MAKE_FOURCC('A','Y','U','V'):
+        return YUV_UNKOWN;
+
+        default:
+        return YUV_UNKOWN;
+    }
+}
+
+static GstCaps *
+_get_nearest_caps(GstCaps *caps_list, GstCaps *src_caps)
+{
+    GstCaps *ret = NULL;
+    GstStructure *cur_struct, *tmp_struct;
+    guint32 cur_format, dest_format, tmp_format;
+    YUV_TYPE cur_type, tmp_type;
+    const GValue*tmp_val;
+    guint  n_caps;
+    guint  i;
+    guint min_diff, tmp_diff;
+
+    cur_struct = gst_caps_get_structure(src_caps, 0);
+    tmp_val = gst_structure_get_value (cur_struct, "format");
+    if (!tmp_val)
+        return NULL;
+
+    cur_format = gst_value_get_fourcc(tmp_val);
+    if((cur_type = _image_format_to_yuv_type(cur_format)) == YUV_UNKOWN)
+        return NULL;
+
+    n_caps = gst_caps_get_size(caps_list);
+    min_diff = 100;
+    dest_format = 0;
+    for (i = 0; i < n_caps; ++i) {
+      tmp_struct = gst_caps_get_structure(caps_list, i);
+      tmp_val = gst_structure_get_value (tmp_struct, "format");
+      if (!tmp_val)
+          continue;
+      tmp_format = gst_value_get_fourcc(tmp_val);
+      if ((tmp_type = _image_format_to_yuv_type(tmp_format)) == YUV_UNKOWN)
+          continue;
+      tmp_diff = abs(tmp_type - cur_type);
+      if (tmp_diff < min_diff) {
+          min_diff = tmp_diff;
+          dest_format = tmp_format;
+      }
+    }
+
+    if (dest_format == 0)
+      return NULL;
+
+    ret = gst_caps_copy(src_caps);
+    tmp_struct = gst_caps_get_structure(ret, 0);
+    gst_structure_set(tmp_struct, "format", GST_TYPE_FOURCC, dest_format, NULL);
+    return ret;
+}
+
+static gboolean
+gst_vaapiupload_negotiate_buffers(
+    GstVaapiUpload  *upload,
+    GstCaps          *incaps,
+    GstCaps          *outcaps
+)
+{
+    guint dr;
+    gboolean ret = TRUE;
+    GstCaps *image_allowed_caps = NULL;
+    GstCaps *image_caps = NULL;
+
+    image_allowed_caps = gst_vaapi_display_get_image_caps(upload->display);
+    if (gst_caps_can_intersect(incaps, image_allowed_caps)) {
+        image_caps = gst_caps_ref(incaps);
+        upload->need_manual_upload = FALSE;
+    } else {
+        image_caps = _get_nearest_caps(image_allowed_caps, incaps);
+        upload->need_manual_upload = TRUE;
+    }
+
+    if (!gst_vaapiupload_ensure_image_pool(upload, image_caps))
+        goto failed;
+
+    if (!gst_vaapiupload_ensure_surface_pool(upload, outcaps))
+        goto failed;
+
+    gst_vaapi_video_pool_set_capacity(upload->surfaces, 6);
+    gst_vaapi_video_pool_reserve(upload->surfaces, 4);
+
+    if (upload->direct_rendering && !upload->need_manual_upload)
+      gst_vaapiupload_ensure_direct_rendering_caps(upload, incaps);
+    dr = MIN(upload->direct_rendering, upload->direct_rendering_caps);
+    if (upload->direct_rendering != dr) {
+        upload->direct_rendering = dr;
+        GST_DEBUG("direct-rendering level: %d", dr);
+    }
+    ret = TRUE;
+    goto end;
+
+  failed:
+    ret = FALSE;
+
+  end:
+    gst_caps_unref(image_caps);
+    gst_caps_unref(image_allowed_caps);
+    return ret;
+}
+
+static gboolean
+gst_vaapiupload_set_caps(
+    GstBaseTransform *trans,
+    GstCaps          *incaps,
+    GstCaps          *outcaps
+)
+{
+    GstVaapiUpload * const upload = GST_VAAPIUPLOAD(trans);
+
+    if (!gst_vaapiupload_negotiate_buffers(upload, incaps, outcaps))
+        return FALSE;
+
+    GST_INFO("set caps\nIN caps:\n%" GST_PTR_FORMAT "\nOUT caps:\n%" GST_PTR_FORMAT,
+             incaps, outcaps);
+    return TRUE;
+}
+
+static gboolean
+gst_vaapiupload_get_unit_size(
+    GstBaseTransform *trans,
+    GstCaps          *caps,
+    guint            *size
+)
+{
+    GstStructure * const structure = gst_caps_get_structure(caps, 0);
+    GstVideoFormat format;
+    gint width, height;
+
+    if (gst_structure_has_name(structure, GST_VAAPI_SURFACE_CAPS_NAME))
+        *size = 0;
+    else {
+        if (!gst_video_format_parse_caps(caps, &format, &width, &height))
+            return FALSE;
+        *size = gst_video_format_get_size(format, width, height);
+    }
+    return TRUE;
+}
+
+static GstFlowReturn
+gst_vaapiupload_buffer_alloc(
+    GstBaseTransform *trans,
+    guint             size,
+    GstCaps          *caps,
+    GstBuffer       **pbuf
+)
+{
+    GstVaapiUpload * const upload = GST_VAAPIUPLOAD(trans);
+    GstBuffer *buffer = NULL;
+    GstVaapiImage *image = NULL;
+    GstVaapiSurface *surface = NULL;
+    GstVaapiVideoBuffer *vbuffer;
+
+    /* already checked */
+    if (!upload->direct_rendering)
+        return GST_FLOW_OK;
+
+    /* Check if we can use direct-rendering */
+    if (!gst_vaapiupload_negotiate_buffers(upload, caps, caps))
+        goto error;
+    if (!upload->direct_rendering)
+        return GST_FLOW_OK;
+
+    switch (upload->direct_rendering) {
+    case 2:
+        buffer  = gst_vaapi_video_buffer_new_from_pool(upload->surfaces);
+        if (!buffer)
+            goto error;
+        vbuffer = GST_VAAPI_VIDEO_BUFFER(buffer);
+
+        surface = gst_vaapi_video_buffer_get_surface(vbuffer);
+        image   = gst_vaapi_surface_derive_image(surface);
+        if (image && gst_vaapi_image_get_data_size(image) == size) {
+            gst_vaapi_video_buffer_set_image(vbuffer, image);
+            g_object_unref(image); /* video buffer owns an extra reference */
+            break;
+        }
+
+        /* We can't use the derive-image optimization. Disable it. */
+        upload->direct_rendering = 1;
+        gst_buffer_unref(buffer);
+        buffer = NULL;
+
+    case 1:
+        buffer  = gst_vaapi_video_buffer_new_from_pool(upload->images);
+        if (!buffer)
+            goto error;
+        vbuffer = GST_VAAPI_VIDEO_BUFFER(buffer);
+
+        image   = gst_vaapi_video_buffer_get_image(vbuffer);
+        break;
+    }
+    g_assert(image);
+
+    if (!gst_vaapi_image_map(image))
+        goto error;
+
+    GST_BUFFER_DATA(buffer) = gst_vaapi_image_get_plane(image, 0);
+    GST_BUFFER_SIZE(buffer) = gst_vaapi_image_get_data_size(image);
+
+    gst_buffer_set_caps(buffer, caps);
+    *pbuf = buffer;
+    return GST_FLOW_OK;
+
+error:
+    /* We can't use the inout-buffers optimization. Disable it. */
+    GST_DEBUG("disable in/out buffer optimization");
+    if (buffer)
+        gst_buffer_unref(buffer);
+    upload->direct_rendering = 0;
+    return GST_FLOW_OK;
+}
+
+static GstFlowReturn
+gst_vaapiupload_sinkpad_buffer_alloc(
+    GstPad           *pad,
+    guint64           offset,
+    guint             size,
+    GstCaps          *caps,
+    GstBuffer       **pbuf
+)
+{
+    GstBaseTransform *trans;
+    GstFlowReturn ret;
+
+    trans = GST_BASE_TRANSFORM(gst_pad_get_parent_element(pad));
+    if (!trans)
+        return GST_FLOW_UNEXPECTED;
+
+    ret = gst_vaapiupload_buffer_alloc(trans, size, caps, pbuf);
+    g_object_unref(trans);
+    return ret;
+}
+
+static GstFlowReturn
+gst_vaapiupload_prepare_output_buffer(
+    GstBaseTransform *trans,
+    GstBuffer        *inbuf,
+    gint              size,
+    GstCaps          *caps,
+    GstBuffer       **poutbuf
+)
+{
+    GstVaapiUpload * const upload = GST_VAAPIUPLOAD(trans);
+    GstBuffer *buffer = NULL;
+
+    if (upload->direct_rendering == 2) {
+        if (GST_VAAPI_IS_VIDEO_BUFFER(inbuf)) {
+            buffer = gst_vaapi_video_buffer_new_from_buffer(inbuf);
+            GST_BUFFER_SIZE(buffer) = size;
+        }
+        else {
+            GST_DEBUG("upstream element destroyed our in/out buffer");
+            upload->direct_rendering = 1;
+        }
+    }
+
+    if (!buffer) {
+        buffer = gst_vaapi_video_buffer_new_from_pool(upload->surfaces);
+        if (!buffer)
+            return GST_FLOW_UNEXPECTED;
+        gst_buffer_set_caps(buffer, caps);
+    }
+
+    *poutbuf = buffer;
+    return GST_FLOW_OK;
+}
+
+static gboolean
+gst_vaapiupload_query(GstPad *pad, GstQuery *query)
+{
+  GstVaapiUpload *upload = GST_VAAPIUPLOAD (gst_pad_get_parent_element (pad));
+  gboolean res;
+
+  GST_DEBUG ("sharing display %p", upload->display);
+
+  if (gst_vaapi_reply_to_query (query, upload->display))
+    res = TRUE;
+  else
+    res = gst_pad_query_default (pad, query);
+
+  g_object_unref (upload);
+  return res;
+}
diff --git a/gst/vaapi/gstvaapiupload.h b/gst/vaapi/gstvaapiupload.h
new file mode 100644 (file)
index 0000000..c9627d2
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ *  gstvaapiupload.h - VA-API video uploader
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This program 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 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser 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
+*/
+
+#ifndef GST_VAAPIUPLOAD_H
+#define GST_VAAPIUPLOAD_H
+
+#include <gst/base/gstbasetransform.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapisurface.h>
+#include <gst/vaapi/gstvaapiimagepool.h>
+#include <gst/vaapi/gstvaapisurfacepool.h>
+#include <gst/vaapi/gstvaapivideobuffer.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_VAAPIUPLOAD \
+    (gst_vaapiupload_get_type())
+
+#define GST_VAAPIUPLOAD(obj)                            \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                  \
+                                GST_TYPE_VAAPIUPLOAD,   \
+                                GstVaapiUpload))
+
+#define GST_VAAPIUPLOAD_CLASS(klass)                    \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                   \
+                             GST_TYPE_VAAPIUPLOAD,      \
+                             GstVaapiUploadClass))
+
+#define GST_IS_VAAPIUPLOAD(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_VAAPIUPLOAD))
+
+#define GST_IS_VAAPIUPLOAD_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_VAAPIUPLOAD))
+
+#define GST_VAAPIUPLOAD_GET_CLASS(obj)                  \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                   \
+                               GST_TYPE_VAAPIUPLOAD,    \
+                               GstVaapiUploadClass))
+
+typedef struct _GstVaapiUpload                  GstVaapiUpload;
+typedef struct _GstVaapiUploadClass             GstVaapiUploadClass;
+
+/* Max output surfaces */
+#define GST_VAAPIUPLOAD_MAX_SURFACES 2
+
+struct _GstVaapiUpload {
+    /*< private >*/
+    GstBaseTransform    parent_instance;
+
+    GstVaapiDisplay    *display;
+    GstVaapiVideoPool  *images;
+    guint               image_width;
+    guint               image_height;
+    GstVaapiVideoPool  *surfaces;
+    guint               surface_width;
+    guint               surface_height;
+    guint               direct_rendering_caps;
+    guint               direct_rendering;
+    unsigned int        images_reset    : 1;
+    unsigned int        surfaces_reset  : 1;
+    unsigned int        need_manual_upload : 1;
+};
+
+struct _GstVaapiUploadClass {
+    /*< private >*/
+    GstBaseTransformClass parent_class;
+};
+
+GType
+gst_vaapiupload_get_type(void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* GST_VAAPIUPLOAD_H */
diff --git a/packaging/gstreamer-vaapi.changes b/packaging/gstreamer-vaapi.changes
new file mode 100644 (file)
index 0000000..107bc3a
--- /dev/null
@@ -0,0 +1,32 @@
+* Mon Sep 24 2012 Yan Yin <yan.yin@intel.com> accepted/2.0_beta/20120917.204432@eadd4f0
+- decoder_h264: reduce max_dec_frame_buffering from 16 to 8
+- vaapidecode: dynamically add surface to vaapicontext.
+
+* Mon Sep 17 2012 Yan Yin <yan.yin@intel.com> accepted/2.0_beta/20120912.025253@838e26e
+- vaapisink: ensure render rect for foreign window
+- vaapisink: centralizing display_rect even in user defined render_rect
+- vaapsink: fix display properties check after display_type set
+
+* Tue Sep 11 2012 Yan Yin <yan.yin@intel.com> submit/2.0_beta/20120907.063807@d0aadd7
+- fix summary for devel pacakge
+
+* Wed Sep 05 2012 Yan Yin <yan.yin@intel.com> submit/2.0_beta/20120831.083100@c9d3506
+- fix build failure of libdrm.
+
+* Tue Aug 07 2012 Yan Yin <yan.yin@intel.com> build/2012-08-01.041209@c9c8547
+- fix wrong version number to 0.4.0.pre1
+
+* Wed Aug 01 2012 Yan Yin <yan.yin@intel.com> build/2012-08-01.041020@bc1613b
+- rebase to 0.3.8pre
+
+* Thu Jun 28 2012 Yan Yin <yan.yin@intel.com> 0.2.6@0372cfd
+- add manifest file
+
+* Tue Jun 26 2012 Yan Yin <yan.yin@intel.com> 0.2.6@f766365
+- add packaging files
+
+* Mon Jun 25 2012 Yan Yin <yan.yin@intel.com> 0.2.6@3706b26
+- fix build failure when compiling without GLX
+
+* Fri May 04 2012 Markus Lehtonen <markus.lehtonen@linux.intel.com> 0.2.6@1860d12
+- tizen build: disable docs
diff --git a/packaging/gstreamer-vaapi.manifest b/packaging/gstreamer-vaapi.manifest
new file mode 100644 (file)
index 0000000..017d22d
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+ <request>
+    <domain name="_"/>
+ </request>
+</manifest>
diff --git a/packaging/gstreamer-vaapi.spec b/packaging/gstreamer-vaapi.spec
new file mode 100644 (file)
index 0000000..2c6acd5
--- /dev/null
@@ -0,0 +1,70 @@
+Name:       gstreamer-vaapi
+Version:    0.4.0.pre1
+Release:    0
+Summary:    VA-API based plugins for GStreamer and helper libraries
+Group:      Multimedia/Gstreamer
+License:    LGPLv2+ and GPLv2+
+URL:        http://gitorious.org/vaapi/gstreamer-vaapi
+Source0:    %{name}-%{version}.tar.bz2
+Source1001: packaging/gstreamer-vaapi.manifest
+BuildRequires:  pkgconfig(x11)
+BuildRequires:  pkgconfig(libva)
+BuildRequires:  pkgconfig(gstreamer-0.10)
+BuildRequires:  pkgconfig(gstreamer-basevideo-0.10)
+BuildRequires:  pkgconfig(gstreamer-plugins-base-0.10)
+BuildRequires:  pvr-bin-mdfld-devel
+BuildRequires:  pkgconfig(libdrm)
+BuildRequires:  which
+ExclusiveArch:  %{ix86}
+
+%description
+Gstreamer-vaapi is a collection of VA-API based plugins for GStreamer
+and helper libraries. vaapidecode is used to decode MPEG-2, MPEG-4,
+H.264, VC-1, WMV3 videos to video/x-vaapi-surface surfaces, depending
+on the underlying HW capabilities. vaapiconvert is used to convert from
+video/x-raw-yuv pixels to video/x-vaapi-surface surfaces. vaapisink is
+used to display video/x-vaapi-surface surfaces to the screen.
+
+%package devel
+Summary:    Development files for gstreamer-vaapi
+Group:      Development/Libraries
+Requires:   %{name} = %{version}-%{release}
+Requires:   pkgconfig
+
+%description devel
+The %{name}-devel package contains libraries and header files for
+developing applications that use %{name}.
+
+%prep
+%setup -q -n %{name}-%{version}
+
+%build
+cp %{SOURCE1001} .
+
+./autogen.sh --prefix=/usr --enable-encoders
+make %{?_smp_mflags}
+
+%install
+rm -rf %{buildroot}
+make install DESTDIR=%{buildroot}
+find %{buildroot} -regex ".*\.la$" | xargs rm -f --
+find %{buildroot} -regex ".*\.a$" | xargs rm -f --
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+%files
+%manifest gstreamer-vaapi.manifest
+%defattr(-,root,root,-)
+%doc AUTHORS COPYING.LIB NEWS README
+%{_libdir}/*.so.*
+%{_libdir}/gstreamer-0.10/*.so
+
+%files devel
+%manifest gstreamer-vaapi.manifest
+%defattr(-,root,root,-)
+%doc README COPYING.LIB
+%{_includedir}/gstreamer-0.10/gst/vaapi
+%{_libdir}/*.so
+%{_libdir}/pkgconfig/%{name}*.pc
diff --git a/pkgconfig/Makefile.am b/pkgconfig/Makefile.am
new file mode 100644 (file)
index 0000000..04537d1
--- /dev/null
@@ -0,0 +1,33 @@
+pcfiles_in  = gstreamer-vaapi.pc.in
+if USE_DRM
+pcfiles_in += gstreamer-vaapi-drm.pc.in
+endif
+if USE_X11
+pcfiles_in += gstreamer-vaapi-x11.pc.in
+endif
+if USE_GLX
+pcfiles_in += gstreamer-vaapi-glx.pc.in
+endif
+if USE_WAYLAND
+pcfiles_in += gstreamer-vaapi-wayland.pc.in
+endif
+
+pcfiles = $(pcfiles_in:%.pc.in=%-@GST_MAJORMINOR@.pc)
+
+all_pcfiles_in  = gstreamer-vaapi.pc.in
+all_pcfiles_in += gstreamer-vaapi-drm.pc.in
+all_pcfiles_in += gstreamer-vaapi-x11.pc.in
+all_pcfiles_in += gstreamer-vaapi-glx.pc.in
+all_pcfiles_in += gstreamer-vaapi-wayland.pc.in
+
+all_pcfiles = $(all_pcfiles_in:%.pc.in=%-@GST_MAJORMINOR@.pc)
+
+pkgconfigdir = @pkgconfigdir@
+pkgconfig_DATA = $(pcfiles)
+
+EXTRA_DIST = $(all_pcfiles_in)
+
+DISTCLEANFILES = $(all_pcfiles)
+
+# Extra clean files so that maintainer-clean removes *everything*
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/pkgconfig/gstreamer-vaapi-drm.pc.in b/pkgconfig/gstreamer-vaapi-drm.pc.in
new file mode 100644 (file)
index 0000000..3ebfadf
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/gstreamer-@GST_MAJORMINOR@
+pluginsdir=@libdir@/gstreamer-@GST_MAJORMINOR@
+
+Name: GStreamer VA-API (DRM) Plugins Libraries
+Description: Streaming media framework, VA-API (DRM) plugins libraries
+Requires: gstreamer-vaapi-@GST_MAJORMINOR@ libva-drm
+Version: @VERSION@
+Libs: -L${libdir} -lgstvaapi-drm-@GST_MAJORMINOR@
+Cflags: -I${includedir}
diff --git a/pkgconfig/gstreamer-vaapi-glx.pc.in b/pkgconfig/gstreamer-vaapi-glx.pc.in
new file mode 100644 (file)
index 0000000..73b4c1b
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/gstreamer-@GST_MAJORMINOR@
+pluginsdir=@libdir@/gstreamer-@GST_MAJORMINOR@
+
+Name: GStreamer VA-API (glx) Plugins Libraries
+Description: Streaming media framework, VA-API (glx) plugins libraries
+Requires: gstreamer-vaapi-@GST_MAJORMINOR@ @LIBVA_GLX_PKGNAME@
+Version: @VERSION@
+Libs: -L${libdir} -lgstvaapi-glx-@GST_MAJORMINOR@ @LIBVA_EXTRA_LIBS@
+Cflags: -I${includedir} @LIBVA_EXTRA_CFLAGS@
diff --git a/pkgconfig/gstreamer-vaapi-wayland.pc.in b/pkgconfig/gstreamer-vaapi-wayland.pc.in
new file mode 100644 (file)
index 0000000..07f1da0
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/gstreamer-@GST_MAJORMINOR@
+pluginsdir=@libdir@/gstreamer-@GST_MAJORMINOR@
+
+Name: GStreamer VA-API (Wayland) Plugins Libraries
+Description: Streaming media framework, VA-API (Wayland) plugins libraries
+Requires: gstreamer-vaapi-@GST_MAJORMINOR@ libva-wayland
+Version: @VERSION@
+Libs: -L${libdir} -lgstvaapi-wayland-@GST_MAJORMINOR@
+Cflags: -I${includedir}
diff --git a/pkgconfig/gstreamer-vaapi-x11.pc.in b/pkgconfig/gstreamer-vaapi-x11.pc.in
new file mode 100644 (file)
index 0000000..1f258de
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/gstreamer-@GST_MAJORMINOR@
+pluginsdir=@libdir@/gstreamer-@GST_MAJORMINOR@
+
+Name: GStreamer VA-API (x11) Plugins Libraries
+Description: Streaming media framework, VA-API (x11) plugins libraries
+Requires: gstreamer-vaapi-@GST_MAJORMINOR@ @LIBVA_X11_PKGNAME@
+Version: @VERSION@
+Libs: -L${libdir} -lgstvaapi-x11-@GST_MAJORMINOR@ @LIBVA_EXTRA_LIBS@
+Cflags: -I${includedir} @LIBVA_EXTRA_CFLAGS@
diff --git a/pkgconfig/gstreamer-vaapi.pc.in b/pkgconfig/gstreamer-vaapi.pc.in
new file mode 100644 (file)
index 0000000..281dee0
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/gstreamer-@GST_MAJORMINOR@
+pluginsdir=@libdir@/gstreamer-@GST_MAJORMINOR@
+
+Name: GStreamer VA-API Plugins Libraries
+Description: Streaming media framework, VA-API plugins libraries
+Requires: gstreamer-@GST_MAJORMINOR@ gstreamer-base-@GST_MAJORMINOR@ @LIBVA_PKGNAME@
+Version: @VERSION@
+Libs: -L${libdir} -lgstvaapi-@GST_MAJORMINOR@ @LIBVA_EXTRA_LIBS@
+Cflags: -I${includedir} @LIBVA_EXTRA_CFLAGS@
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644 (file)
index 0000000..4c8edbb
--- /dev/null
@@ -0,0 +1,99 @@
+noinst_PROGRAMS = \
+       test-decode                     \
+       test-display                    \
+       test-surfaces                   \
+       test-windows                    \
+       test-subpicture                 \
+       $(NULL)
+
+if USE_GLX
+noinst_PROGRAMS += \
+       test-textures                   \
+       $(NULL)
+endif
+
+TEST_CFLAGS = \
+       -DGST_USE_UNSTABLE_API          \
+       -I$(top_srcdir)/gst-libs        \
+       $(LIBVA_CFLAGS)                 \
+       $(GST_CFLAGS)                   \
+       $(NULL)
+
+TEST_LIBS = \
+       $(LIBVA_LIBS)                   \
+       $(GST_LIBS)                     \
+       $(top_builddir)/gst-libs/gst/vaapi/libgstvaapi-@GST_MAJORMINOR@.la
+
+if USE_DRM
+TEST_CFLAGS    += $(LIBVA_DRM_CFLAGS)
+TEST_LIBS      += \
+       $(LIBVA_DRM_LIBS)               \
+       $(top_builddir)/gst-libs/gst/vaapi/libgstvaapi-drm-@GST_MAJORMINOR@.la
+endif
+
+if USE_X11
+TEST_CFLAGS    += $(X11_CFLAGS)
+TEST_LIBS      += \
+       $(LIBVA_X11_LIBS)               \
+       $(X11_LIBS)                     \
+       $(top_builddir)/gst-libs/gst/vaapi/libgstvaapi-x11-@GST_MAJORMINOR@.la
+endif
+
+if USE_GLX
+TEST_CFLAGS    += $(X11_CFLAGS) $(GL_CFLAGS)
+TEST_LIBS      += \
+       $(LIBVA_GLX_LIBS)               \
+       $(X11_LIBS)                     \
+       $(GL_LIBS)                      \
+       $(top_builddir)/gst-libs/gst/vaapi/libgstvaapi-glx-@GST_MAJORMINOR@.la
+endif
+
+if USE_WAYLAND
+TEST_CFLAGS    += $(WAYLAND_CFLAGS)
+TEST_LIBS      += \
+       $(LIBVA_WAYLAND_LIBS)           \
+       $(WAYLAND_LIBS)                 \
+       $(top_builddir)/gst-libs/gst/vaapi/libgstvaapi-wayland-@GST_MAJORMINOR@.la
+endif
+
+test_codecs_source_c   = test-mpeg2.c test-h264.c test-vc1.c test-jpeg.c
+test_codecs_source_h   = $(test_codecs_source_c:%.c=%.h) test-decode.h
+
+test_utils_source_c    = image.c output.c $(test_codecs_source_c)
+test_utils_source_h    = image.h output.h $(test_codecs_source_h)
+
+noinst_LTLIBRARIES     = libutils.la
+libutils_la_SOURCES    = $(test_utils_source_c)
+libutils_la_CFLAGS     = $(TEST_CFLAGS)
+
+test_decode_SOURCES    = test-decode.c $(test_codecs_source_c)
+test_decode_CFLAGS     = $(TEST_CFLAGS)
+test_decode_LDADD      = libutils.la $(TEST_LIBS)
+
+test_display_SOURCES   = test-display.c
+test_display_CFLAGS    = $(TEST_CFLAGS)
+test_display_LDADD     = libutils.la $(TEST_LIBS)
+
+test_surfaces_SOURCES  = test-surfaces.c
+test_surfaces_CFLAGS   = $(TEST_CFLAGS)
+test_surfaces_LDADD    = libutils.la $(TEST_LIBS)
+
+test_subpicture_SOURCES = test-subpicture.c test-subpicture-data.c
+test_subpicture_CFLAGS  = $(TEST_CFLAGS)
+test_subpicture_LDADD   = libutils.la $(TEST_LIBS)
+
+test_windows_SOURCES   = test-windows.c
+test_windows_CFLAGS    = $(TEST_CFLAGS)
+test_windows_LDADD     = libutils.la $(TEST_LIBS)
+
+test_textures_SOURCES  = test-textures.c
+test_textures_CFLAGS   = $(TEST_CFLAGS)
+test_textures_LDADD    = libutils.la $(TEST_LIBS)
+
+EXTRA_DIST = \
+       test-subpicture-data.h  \
+       $(test_utils_source_h)  \
+       $(NULL)
+
+# Extra clean files so that maintainer-clean removes *everything*
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/tests/image.c b/tests/image.c
new file mode 100644 (file)
index 0000000..39a8ac5
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+ *  image.c - Image utilities for the tests
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+*/
+
+#include "image.h"
+
+GstVaapiImage *
+image_generate(
+    GstVaapiDisplay    *display,
+    GstVaapiImageFormat format,
+    guint               width,
+    guint               height
+)
+{
+    const guint w = width;
+    const guint h = height;
+    GstVaapiImage *image;
+
+    image = gst_vaapi_image_new(display, format, w, h);
+    if (!image)
+        return NULL;
+
+    if (image_draw_rectangle(image, 0,   0,   w/2, h/2, 0xffff0000) &&
+        image_draw_rectangle(image, w/2, 0,   w/2, h/2, 0xff00ff00) &&
+        image_draw_rectangle(image, 0,   h/2, w/2, h/2, 0xff0000ff) &&
+        image_draw_rectangle(image, w/2, h/2, w/2, h/2, 0xff000000))
+        return image;
+
+    g_object_unref(image);
+    return NULL;
+}
+
+typedef void (*DrawRectFunc)(
+    guchar *pixels[3],
+    guint   stride[3],
+    gint    x,
+    gint    y,
+    guint   width,
+    guint   height,
+    guint32 color
+);
+
+static void draw_rect_ARGB(
+    guchar *pixels[3],
+    guint   stride[3],
+    gint    x,
+    gint    y,
+    guint   width,
+    guint   height,
+    guint32 color
+)
+{
+    guint i, j;
+
+    color = GUINT32_TO_BE(color);
+
+    for (j = 0; j < height; j++) {
+        guint32 *p = (guint32 *)(pixels[0] + (y + j) * stride[0] + x * 4);
+        for (i = 0; i < width; i++)
+            p[i] = color;
+    }
+}
+
+static void draw_rect_BGRA(
+    guchar *pixels[3],
+    guint   stride[3],
+    gint    x,
+    gint    y,
+    guint   width,
+    guint   height,
+    guint32 color
+)
+{
+    // Converts ARGB color to BGRA
+    color = GUINT32_SWAP_LE_BE(color);
+
+    draw_rect_ARGB(pixels, stride, x, y, width, height, color);
+}
+
+static void draw_rect_RGBA(
+    guchar *pixels[3],
+    guint   stride[3],
+    gint    x,
+    gint    y,
+    guint   width,
+    guint   height,
+    guint32 color
+)
+{
+    // Converts ARGB color to RGBA
+    color = ((color >> 24) & 0xff) | ((color & 0xffffff) << 8);
+
+    draw_rect_ARGB(pixels, stride, x, y, width, height, color);
+}
+
+static void draw_rect_ABGR(
+    guchar *pixels[3],
+    guint   stride[3],
+    gint    x,
+    gint    y,
+    guint   width,
+    guint   height,
+    guint32 color
+)
+{
+    // Converts ARGB color to ABGR
+    color = ((color & 0xff00ff00)   |
+             ((color >> 16) & 0xff) |
+             ((color & 0xff) << 16));
+
+    draw_rect_ARGB(pixels, stride, x, y, width, height, color);
+}
+
+static void draw_rect_NV12( // Y, UV planes
+    guchar *pixels[3],
+    guint   stride[3],
+    gint    x,
+    gint    y,
+    guint   width,
+    guint   height,
+    guint32 color
+)
+{
+    const guchar Y  = color >> 16;
+    const guchar Cb = color >> 8;
+    const guchar Cr = color;
+    guchar *dst;
+    guint i, j;
+
+    dst = pixels[0] + y * stride[0] + x;
+    for (j = 0; j < height; j++, dst += stride[0])
+        for (i = 0; i < width; i++)
+            dst[i] = Y;
+
+    x      /= 2;
+    y      /= 2;
+    width  /= 2;
+    height /= 2;
+
+    dst = pixels[1] + y * stride[1] + x * 2;
+    for (j = 0; j < height; j++, dst += stride[1])
+        for (i = 0; i < width; i++) {
+            dst[2*i + 0] = Cb;
+            dst[2*i + 1] = Cr;
+        }
+}
+
+static void draw_rect_YV12( // Y, V, U planes
+    guchar *pixels[3],
+    guint   stride[3],
+    gint    x,
+    gint    y,
+    guint   width,
+    guint   height,
+    guint32 color
+)
+{
+    const guchar Y  = color >> 16;
+    const guchar Cb = color >> 8;
+    const guchar Cr = color;
+    guchar *pY, *pU, *pV;
+    guint i, j;
+
+    pY = pixels[0] + y * stride[0] + x;
+    for (j = 0; j < height; j++, pY += stride[0])
+        for (i = 0; i < width; i++)
+            pY[i] = Y;
+
+    x      /= 2;
+    y      /= 2;
+    width  /= 2;
+    height /= 2;
+
+    pU = pixels[1] + y * stride[1] + x;
+    pV = pixels[2] + y * stride[2] + x;
+    for (j = 0; j < height; j++, pU += stride[1], pV += stride[2])
+        for (i = 0; i < width; i++) {
+            pU[i] = Cb;
+            pV[i] = Cr;
+        }
+}
+
+static void draw_rect_I420( // Y, U, V planes
+    guchar *pixels[3],
+    guint   stride[3],
+    gint    x,
+    gint    y,
+    guint   width,
+    guint   height,
+    guint32 color
+)
+{
+    guchar *new_pixels[3] = { pixels[0], pixels[2], pixels[1] };
+    guint   new_stride[3] = { stride[0], stride[2], stride[1] };
+
+    draw_rect_YV12(new_pixels, new_stride, x, y, width, height, color);
+}
+
+static void draw_rect_AYUV(
+    guchar *pixels[3],
+    guint   stride[3],
+    gint    x,
+    gint    y,
+    guint   width,
+    guint   height,
+    guint32 color
+)
+{
+    guint i, j;
+
+    color = color | 0xff000000;
+
+    for (j = 0; j < height; j++) {
+        guint32 *p = (guint32 *)(pixels[0] + (y + j) * stride[0] + x * 4);
+        for (i = 0; i < width; i++)
+            p[i] = color;
+    }
+}
+
+static inline guint32 argb2yuv(guint32 color)
+{
+    const gint32 r = (color >> 16) & 0xff;
+    const gint32 g = (color >>  8) & 0xff;
+    const gint32 b = (color      ) & 0xff;
+
+    const guint32 y = (( 263 * r + 516 * g + 100 * b) >> 10) +  16;
+    const guint32 u = ((-152 * r - 298 * g + 450 * b) >> 10) + 128;
+    const guint32 v = (( 450 * r - 376 * g -  73 * b) >> 10) + 128;
+
+    return (y << 16) | (u << 8) | v;
+}
+
+gboolean
+image_draw_rectangle(
+    GstVaapiImage *image,
+    gint           x,
+    gint           y,
+    guint          width,
+    guint          height,
+    guint32        color
+)
+{
+    const GstVaapiImageFormat image_format = gst_vaapi_image_get_format(image);
+    const guint               image_width  = gst_vaapi_image_get_width(image);
+    const guint               image_height = gst_vaapi_image_get_height(image);
+    GstVaapiDisplay          *display;
+    guchar                   *pixels[3];
+    guint                     stride[3];
+    DrawRectFunc              draw_rect = NULL;
+    guint                     i;
+
+    static const struct {
+        GstVaapiImageFormat   format;
+        DrawRectFunc          draw_rect;
+    }
+    map[] = {
+#define _(FORMAT) { GST_VAAPI_IMAGE_##FORMAT, draw_rect_##FORMAT }
+        _(ARGB),
+        _(BGRA),
+        _(RGBA),
+        _(ABGR),
+        _(NV12),
+        _(YV12),
+        _(I420),
+        _(AYUV),
+#undef  _
+        { 0, }
+    };
+
+    for (i = 0; !draw_rect && map[i].format; i++)
+        if (map[i].format == image_format)
+            draw_rect = map[i].draw_rect;
+    if (!draw_rect)
+        return FALSE;
+
+    display = gst_vaapi_object_get_display(GST_VAAPI_OBJECT(image));
+    if (!display)
+        return FALSE;
+
+    if (!gst_vaapi_image_map(image))
+        return FALSE;
+
+    for (i = 0; i < gst_vaapi_image_get_plane_count(image); i++) {
+        pixels[i] = gst_vaapi_image_get_plane(image, i);
+        stride[i] = gst_vaapi_image_get_pitch(image, i);
+    }
+
+    if (gst_vaapi_image_format_is_yuv(image_format))
+        color = argb2yuv(color);
+
+    if (x < 0)
+        x = 0;
+    if (y < 0)
+        y = 0;
+    if (width > image_width - x)
+        width = image_width - x;
+    if (height > image_height - y)
+        height = image_height - y;
+
+    gst_vaapi_display_lock(display);
+    draw_rect(pixels, stride, x, y, width, height, color);
+    gst_vaapi_display_unlock(display);
+    return gst_vaapi_image_unmap(image);
+}
+
+gboolean
+image_upload(GstVaapiImage *image, GstVaapiSurface *surface)
+{
+    GstVaapiDisplay    *display;
+    GstVaapiImageFormat format;
+    GstVaapiSubpicture *subpicture;
+
+    display = gst_vaapi_object_get_display(GST_VAAPI_OBJECT(surface));
+    if (!display)
+        return FALSE;
+
+    format = gst_vaapi_image_get_format(image);
+    if (!format)
+        return FALSE;
+
+    if (gst_vaapi_surface_put_image(surface, image))
+        return TRUE;
+
+    g_print("could not upload %" GST_FOURCC_FORMAT" image to surface\n",
+            GST_FOURCC_ARGS(format));
+
+    if (!gst_vaapi_display_has_subpicture_format(display, format))
+        return FALSE;
+
+    g_print("trying as a subpicture\n");
+
+    subpicture = gst_vaapi_subpicture_new(image);
+    if (!subpicture)
+        g_error("could not create VA subpicture");
+
+    if (!gst_vaapi_surface_associate_subpicture(surface, subpicture,
+                                                NULL, NULL))
+        g_error("could not associate subpicture to surface");
+
+    /* The surface holds a reference to the subpicture. This is safe */
+    g_object_unref(subpicture);
+    return TRUE;
+}
diff --git a/tests/image.h b/tests/image.h
new file mode 100644 (file)
index 0000000..f958065
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ *  image.h - Image utilities for the tests
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+*/
+
+#ifndef IMAGE_H
+#define IMAGE_H
+
+#include <gst/vaapi/gstvaapiimage.h>
+#include <gst/vaapi/gstvaapisurface.h>
+
+GstVaapiImage *
+image_generate(
+    GstVaapiDisplay    *display,
+    GstVaapiImageFormat format,
+    guint               width,
+    guint               height
+);
+
+gboolean
+image_draw_rectangle(
+    GstVaapiImage *image,
+    gint           x,
+    gint           y,
+    guint          width,
+    guint          height,
+    guint32        color
+);
+
+gboolean
+image_upload(GstVaapiImage *image, GstVaapiSurface *surface);
+
+#endif /* IMAGE_H */
diff --git a/tests/output.c b/tests/output.c
new file mode 100644 (file)
index 0000000..438c04c
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ *  output.c - Video output helpers
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include <string.h>
+#include <gst/gst.h>
+#if USE_DRM
+# include <gst/vaapi/gstvaapidisplay_drm.h>
+# include <gst/vaapi/gstvaapiwindow_drm.h>
+#endif
+#if USE_X11
+# include <gst/vaapi/gstvaapidisplay_x11.h>
+# include <gst/vaapi/gstvaapiwindow_x11.h>
+#endif
+#if USE_GLX
+# include <gst/vaapi/gstvaapidisplay_glx.h>
+# include <gst/vaapi/gstvaapiwindow_glx.h>
+#endif
+#if USE_WAYLAND
+# include <gst/vaapi/gstvaapidisplay_wayland.h>
+# include <gst/vaapi/gstvaapiwindow_wayland.h>
+#endif
+#include "output.h"
+
+static const VideoOutputInfo *g_video_output;
+static const VideoOutputInfo g_video_outputs[] = {
+    /* Video outputs are sorted in test order for automatic characterisation */
+#if USE_WAYLAND
+    { "wayland",
+      gst_vaapi_display_wayland_new,
+      gst_vaapi_window_wayland_new
+    },
+#endif
+#if USE_X11
+    { "x11",
+      gst_vaapi_display_x11_new,
+      gst_vaapi_window_x11_new
+    },
+#endif
+#if USE_GLX
+    { "glx",
+      gst_vaapi_display_glx_new,
+      gst_vaapi_window_glx_new
+    },
+#endif
+#if USE_DRM
+    { "drm",
+      gst_vaapi_display_drm_new,
+      gst_vaapi_window_drm_new
+    },
+#endif
+    { NULL, }
+};
+
+static gchar *g_output_name;
+static gboolean g_list_outputs = FALSE;
+
+static GOptionEntry g_options[] = {
+    { "list-outputs", 0,
+      0,
+      G_OPTION_ARG_NONE, &g_list_outputs,
+      "list video outputs", NULL },
+    { "output", 'o',
+      0,
+      G_OPTION_ARG_STRING, &g_output_name,
+      "video output name", NULL },
+    { NULL, }
+};
+
+static void
+list_outputs(void)
+{
+    const VideoOutputInfo *o;
+
+    g_print("Video outputs:");
+    for (o = g_video_outputs; o->name != NULL; o++)
+        g_print(" %s", o->name);
+    g_print("\n");
+}
+
+gboolean
+video_output_init(int *argc, char *argv[], GOptionEntry *options)
+{
+    GOptionContext *ctx;
+    gboolean success;
+
+#if !GLIB_CHECK_VERSION(2,31,0)
+    if (!g_thread_supported())
+        g_thread_init(NULL);
+#endif
+
+    ctx = g_option_context_new("- test options");
+    if (!ctx)
+        return FALSE;
+
+    g_option_context_add_group(ctx, gst_init_get_option_group());
+    g_option_context_add_main_entries(ctx, g_options, NULL);
+    if (options)
+        g_option_context_add_main_entries(ctx, options, NULL);
+    success = g_option_context_parse(ctx, argc, &argv, NULL);
+    g_option_context_free(ctx);
+
+    if (g_list_outputs) {
+        list_outputs();
+        exit(0);
+    }
+    return success;
+}
+
+void
+video_output_exit(void)
+{
+    g_free(g_output_name);
+    gst_deinit();
+}
+
+const VideoOutputInfo *
+video_output_lookup(const gchar *output_name)
+{
+    const VideoOutputInfo *o;
+
+    if (!output_name)
+        return NULL;
+
+    for (o = g_video_outputs; o->name != NULL; o++) {
+        if (g_ascii_strcasecmp(o->name, output_name) == 0)
+            return o;
+    }
+    return NULL;
+}
+
+GstVaapiDisplay *
+video_output_create_display(const gchar *display_name)
+{
+    const VideoOutputInfo *o = g_video_output;
+    GstVaapiDisplay *display = NULL;
+
+    if (!o) {
+        if (g_output_name)
+            o = video_output_lookup(g_output_name);
+        else {
+            for (o = g_video_outputs; o->name != NULL; o++) {
+                display = o->create_display(display_name);
+                if (display) {
+                    if (gst_vaapi_display_get_display(display))
+                        break;
+                    g_object_unref(display);
+                    display = NULL;
+                }
+            }
+        }
+        if (!o || !o->name)
+            return NULL;
+        g_print("Using %s video output\n", o->name);
+        g_video_output = o;
+    }
+
+    if (!display)
+        display = o->create_display(display_name);
+    return display;
+}
+
+GstVaapiWindow *
+video_output_create_window(GstVaapiDisplay *display, guint width, guint height)
+{
+    if (!g_video_output)
+        return NULL;
+    return g_video_output->create_window(display, width, height);
+}
diff --git a/tests/output.h b/tests/output.h
new file mode 100644 (file)
index 0000000..3377915
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *  output.h - Video output helpers
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef OUTPUT_H
+#define OUTPUT_H
+
+#include <glib.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapiwindow.h>
+
+typedef GstVaapiDisplay *(*CreateDisplayFunc)(const gchar *display_name);
+typedef GstVaapiWindow *(*CreateWindowFunc)(GstVaapiDisplay *display,
+                                            guint width, guint height);
+
+typedef struct _VideoOutputInfo VideoOutputInfo;
+struct _VideoOutputInfo {
+    const gchar        *name;
+    CreateDisplayFunc   create_display;
+    CreateWindowFunc    create_window;
+};
+
+gboolean
+video_output_init(int *argc, char *argv[], GOptionEntry *options);
+
+void
+video_output_exit(void);
+
+const VideoOutputInfo *
+video_output_lookup(const gchar *output_name);
+
+GstVaapiDisplay *
+video_output_create_display(const gchar *display_name);
+
+GstVaapiWindow *
+video_output_create_window(GstVaapiDisplay *display, guint width, guint height);
+
+#endif /* OUTPUT_H */
diff --git a/tests/test-decode.c b/tests/test-decode.c
new file mode 100644 (file)
index 0000000..a425f82
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ *  test-decode.c - Test GstVaapiDecoder
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+*/
+
+#include "config.h"
+#include <string.h>
+#include <gst/vaapi/gstvaapidecoder.h>
+#include <gst/vaapi/gstvaapisurface.h>
+#include <gst/vaapi/gstvaapidecoder_h264.h>
+#include <gst/vaapi/gstvaapidecoder_jpeg.h>
+#include <gst/vaapi/gstvaapidecoder_mpeg2.h>
+#include <gst/vaapi/gstvaapidecoder_vc1.h>
+#include "test-jpeg.h"
+#include "test-mpeg2.h"
+#include "test-h264.h"
+#include "test-vc1.h"
+#include "output.h"
+
+/* Set to 1 to check display cache works (shared VA display) */
+#define CHECK_DISPLAY_CACHE 1
+
+typedef void (*GetVideoInfoFunc)(VideoDecodeInfo *info);
+
+typedef struct _CodecDefs CodecDefs;
+struct _CodecDefs {
+    const gchar        *codec_str;
+    GetVideoInfoFunc    get_video_info;
+};
+
+static const CodecDefs g_codec_defs[] = {
+#define INIT_FUNCS(CODEC) { #CODEC, CODEC##_get_video_info }
+    INIT_FUNCS(jpeg),
+    INIT_FUNCS(mpeg2),
+    INIT_FUNCS(h264),
+    INIT_FUNCS(vc1),
+#undef INIT_FUNCS
+    { NULL, }
+};
+
+static const CodecDefs *
+get_codec_defs(const gchar *codec_str)
+{
+    const CodecDefs *c;
+    for (c = g_codec_defs; c->codec_str; c++)
+        if (strcmp(codec_str, c->codec_str) == 0)
+            return c;
+    return NULL;
+}
+
+static inline void pause(void)
+{
+    g_print("Press any key to continue...\n");
+    getchar();
+}
+
+static gchar *g_codec_str;
+
+static GOptionEntry g_options[] = {
+    { "codec", 'c',
+      0,
+      G_OPTION_ARG_STRING, &g_codec_str,
+      "codec to test", NULL },
+    { NULL, }
+};
+
+int
+main(int argc, char *argv[])
+{
+    GstVaapiDisplay      *display, *display2;
+    GstVaapiWindow       *window;
+    GstVaapiDecoder      *decoder;
+    GstCaps              *decoder_caps;
+    GstStructure         *structure;
+    GstVaapiDecoderStatus status;
+    const CodecDefs      *codec;
+    GstBuffer            *buffer;
+    GstVaapiSurfaceProxy *proxy;
+    VideoDecodeInfo       info;
+
+    static const guint win_width  = 640;
+    static const guint win_height = 480;
+
+    if (!video_output_init(&argc, argv, g_options))
+        g_error("failed to initialize video output subsystem");
+
+    if (!g_codec_str)
+        g_codec_str = g_strdup("h264");
+
+    g_print("Test %s decode\n", g_codec_str);
+    codec = get_codec_defs(g_codec_str);
+    if (!codec)
+        g_error("no %s codec data found", g_codec_str);
+
+    display = video_output_create_display(NULL);
+    if (!display)
+        g_error("could not create VA display");
+
+    if (CHECK_DISPLAY_CACHE)
+        display2 = video_output_create_display(NULL);
+    else
+        display2 = g_object_ref(display);
+    if (!display2)
+        g_error("could not create second VA display");
+
+    window = video_output_create_window(display, win_width, win_height);
+    if (!window)
+        g_error("could not create window");
+
+    codec->get_video_info(&info);
+    decoder_caps = gst_vaapi_profile_get_caps(info.profile);
+    if (!decoder_caps)
+        g_error("could not create decoder caps");
+
+    structure = gst_caps_get_structure(decoder_caps, 0);
+    if (info.width > 0 && info.height > 0)
+        gst_structure_set(
+            structure,
+            "width",  G_TYPE_INT, info.width,
+            "height", G_TYPE_INT, info.height,
+            NULL
+        );
+
+    switch (gst_vaapi_profile_get_codec(info.profile)) {
+    case GST_VAAPI_CODEC_H264:
+        decoder = gst_vaapi_decoder_h264_new(display, decoder_caps);
+        break;
+#if USE_JPEG_DECODER
+    case GST_VAAPI_CODEC_JPEG:
+        decoder = gst_vaapi_decoder_jpeg_new(display, decoder_caps);
+        break;
+#endif
+    case GST_VAAPI_CODEC_MPEG2:
+        decoder = gst_vaapi_decoder_mpeg2_new(display, decoder_caps);
+        break;
+    case GST_VAAPI_CODEC_VC1:
+        decoder = gst_vaapi_decoder_vc1_new(display, decoder_caps);
+        break;
+    default:
+        decoder = NULL;
+        break;
+    }
+    if (!decoder)
+        g_error("could not create decoder");
+    gst_caps_unref(decoder_caps);
+
+    buffer = gst_buffer_new();
+    if (!buffer)
+        g_error("could not create encoded data buffer");
+    gst_buffer_set_data(buffer, (guchar *)info.data, info.data_size);
+
+    if (!gst_vaapi_decoder_put_buffer(decoder, buffer))
+        g_error("could not send video data to the decoder");
+    gst_buffer_unref(buffer);
+
+    if (!gst_vaapi_decoder_put_buffer(decoder, NULL))
+        g_error("could not send EOS to the decoder");
+
+    proxy = gst_vaapi_decoder_get_surface(decoder, &status);
+    if (!proxy)
+        g_error("could not get decoded surface (decoder status %d)", status);
+
+    gst_vaapi_window_show(window);
+
+    if (!gst_vaapi_window_put_surface(window,
+                                      GST_VAAPI_SURFACE_PROXY_SURFACE(proxy),
+                                      NULL,
+                                      NULL,
+                                      GST_VAAPI_PICTURE_STRUCTURE_FRAME))
+        g_error("could not render surface");
+
+    pause();
+
+    g_object_unref(proxy);
+    g_object_unref(decoder);
+    g_object_unref(window);
+    g_object_unref(display);
+    g_object_unref(display2);
+    g_free(g_codec_str);
+    video_output_exit();
+    return 0;
+}
diff --git a/tests/test-decode.h b/tests/test-decode.h
new file mode 100644 (file)
index 0000000..147f51c
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ *  test-decode.h - Test GstVaapiDecoder
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef TEST_DECODE_H
+#define TEST_DECODE_H
+
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapiprofile.h>
+
+typedef struct _VideoDecodeInfo VideoDecodeInfo;
+struct _VideoDecodeInfo {
+    GstVaapiProfile     profile;
+    guint               width;
+    guint               height;
+    const guchar       *data;
+    guint               data_size;
+};
+
+#endif /* TEST_DECODE_H */
diff --git a/tests/test-display.c b/tests/test-display.c
new file mode 100644 (file)
index 0000000..fa381cd
--- /dev/null
@@ -0,0 +1,499 @@
+/*
+ *  test-display.c - Test GstVaapiDisplayX11
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+*/
+
+#include "config.h"
+#include <gst/video/video.h>
+#if USE_DRM
+# include <gst/vaapi/gstvaapidisplay_drm.h>
+# include <va/va_drm.h>
+# include <fcntl.h>
+# include <unistd.h>
+# ifndef DRM_DEVICE_PATH
+# define DRM_DEVICE_PATH "/dev/dri/card0"
+# endif
+#endif
+#if USE_X11
+# include <gst/vaapi/gstvaapidisplay_x11.h>
+#endif
+#if USE_GLX
+# include <gst/vaapi/gstvaapidisplay_glx.h>
+#endif
+#if USE_WAYLAND
+# include <gst/vaapi/gstvaapidisplay_wayland.h>
+#endif
+
+#ifdef HAVE_VA_VA_GLX_H
+# include <va/va_glx.h>
+#endif
+
+static void
+print_value(const GValue *value, const gchar *name)
+{
+    gchar *value_string;
+
+    value_string = g_strdup_value_contents(value);
+    if (!value_string)
+        return;
+    g_print("  %s: %s\n", name, value_string);
+    g_free(value_string);
+}
+
+static void
+print_profile_caps(GstCaps *caps, const gchar *name)
+{
+    guint i, n_caps = gst_caps_get_size(caps);
+    gint version;
+    const gchar *profile;
+    gboolean has_version;
+
+    g_print("%u %s caps\n", n_caps, name);
+
+    for (i = 0; i < gst_caps_get_size(caps); i++) {
+        GstStructure * const structure = gst_caps_get_structure(caps, i);
+        if (!structure)
+            g_error("could not get caps structure %d", i);
+
+        has_version = (
+            gst_structure_get_int(structure, "version", &version) ||
+            gst_structure_get_int(structure, "mpegversion", &version)
+        );
+
+        g_print("  %s", gst_structure_get_name(structure));
+        if (has_version)
+            g_print("%d", version);
+
+        profile = gst_structure_get_string(structure, "profile");
+        if (!profile)
+            g_error("could not get structure profile");
+        g_print(": %s profile\n", profile);
+    }
+}
+
+static void
+print_format_caps(GstCaps *caps, const gchar *name)
+{
+    guint i, n_caps = gst_caps_get_size(caps);
+
+    g_print("%u %s caps\n", n_caps, name);
+
+    for (i = 0; i < gst_caps_get_size(caps); i++) {
+        GstStructure * const structure = gst_caps_get_structure(caps, i);
+        if (!structure)
+            g_error("could not get caps structure %d", i);
+
+        g_print("  %s:", gst_structure_get_name(structure));
+
+        if (gst_structure_has_name(structure, "video/x-raw-yuv")) {
+            guint32 fourcc;
+
+            gst_structure_get_fourcc(structure, "format", &fourcc);
+
+            g_print(" fourcc '%c%c%c%c'",
+                    fourcc & 0xff,
+                    (fourcc >> 8) & 0xff,
+                    (fourcc >> 16) & 0xff,
+                    (fourcc >> 24) & 0xff);
+        }
+        else {
+            gint bpp, endian, rmask, gmask, bmask, amask;
+            gboolean has_alpha;
+
+            gst_structure_get_int(structure, "bpp",         &bpp);
+            gst_structure_get_int(structure, "endianness",  &endian);
+            gst_structure_get_int(structure, "red_mask",    &rmask);
+            gst_structure_get_int(structure, "blue_mask",   &bmask);
+            gst_structure_get_int(structure, "green_mask",  &gmask);
+            has_alpha = gst_structure_get_int(structure, "alpha_mask", &amask);
+
+            g_print(" %d bits per pixel, %s endian,",
+                    bpp, endian == G_BIG_ENDIAN ? "big" : "little");
+            g_print(" %s masks", has_alpha ? "rgba" : "rgb");
+            g_print(" 0x%08x 0x%08x 0x%08x", rmask, gmask, bmask);
+            if (has_alpha)
+                g_print(" 0x%08x", amask);
+        }
+        g_print("\n");
+    }
+}
+
+typedef struct _GstVaapiDisplayProperty GstVaapiDisplayProperty;
+struct _GstVaapiDisplayProperty {
+    const gchar *name;
+    GValue       value;
+};
+
+static void
+gst_vaapi_display_property_free(GstVaapiDisplayProperty *prop)
+{
+    if (!prop)
+        return;
+    g_value_unset(&prop->value);
+    g_slice_free(GstVaapiDisplayProperty, prop);
+}
+
+static GstVaapiDisplayProperty *
+gst_vaapi_display_property_new(const gchar *name)
+{
+    GstVaapiDisplayProperty *prop;
+
+    prop = g_slice_new0(GstVaapiDisplayProperty);
+    if (!prop)
+        return NULL;
+    prop->name = name;
+    return prop;
+}
+
+static void
+free_property_cb(gpointer data, gpointer user_data)
+{
+    gst_vaapi_display_property_free(data);
+}
+
+static inline GParamSpec *
+get_display_property(GstVaapiDisplay *display, const gchar *name)
+{
+    GObjectClass *klass;
+
+    klass = G_OBJECT_CLASS(GST_VAAPI_DISPLAY_GET_CLASS(display));
+    if (!klass)
+        return NULL;
+    return g_object_class_find_property(klass, name);
+}
+
+static void
+dump_properties(GstVaapiDisplay *display)
+{
+    GstVaapiDisplayProperty *prop;
+    GPtrArray *properties;
+    guint i;
+
+    static const gchar *g_properties[] = {
+        GST_VAAPI_DISPLAY_PROP_RENDER_MODE,
+        GST_VAAPI_DISPLAY_PROP_ROTATION,
+        GST_VAAPI_DISPLAY_PROP_HUE,
+        GST_VAAPI_DISPLAY_PROP_SATURATION,
+        GST_VAAPI_DISPLAY_PROP_BRIGHTNESS,
+        GST_VAAPI_DISPLAY_PROP_CONTRAST,
+        NULL
+    };
+
+    properties = g_ptr_array_new();
+    if (!properties)
+        return;
+
+    for (i = 0; g_properties[i] != NULL; i++) {
+        GParamSpec *pspec = get_display_property(display, g_properties[i]);
+
+        if (!pspec) {
+            GST_ERROR("failed to find GstVaapiDisplay property '%s'",
+                      g_properties[i]);
+            goto end;
+        }
+
+        if (!gst_vaapi_display_has_property(display, pspec->name))
+            continue;
+            
+        prop = gst_vaapi_display_property_new(pspec->name);
+        if (!prop) {
+            GST_ERROR("failed to allocate GstVaapiDisplayProperty");
+            goto end;
+        }
+
+        g_value_init(&prop->value, pspec->value_type);
+        g_object_get_property(G_OBJECT(display), pspec->name, &prop->value);
+        g_ptr_array_add(properties, prop);
+    }
+
+    g_print("%u properties\n", properties->len);
+    for (i = 0; i < properties->len; i++) {
+        prop = g_ptr_array_index(properties, i);
+        print_value(&prop->value, prop->name);
+    }
+
+end:
+    if (properties) {
+        g_ptr_array_foreach(properties, free_property_cb, NULL);
+        g_ptr_array_free(properties, TRUE);
+    }
+}
+
+static void
+dump_info(GstVaapiDisplay *display)
+{
+    GstCaps *caps;
+
+    caps = gst_vaapi_display_get_decode_caps(display);
+    if (!caps)
+        g_error("could not get VA decode caps");
+
+    print_profile_caps(caps, "decoders");
+    gst_caps_unref(caps);
+
+    caps = gst_vaapi_display_get_encode_caps(display);
+    if (!caps)
+        g_error("could not get VA encode caps");
+
+    print_profile_caps(caps, "encoders");
+    gst_caps_unref(caps);
+
+    caps = gst_vaapi_display_get_image_caps(display);
+    if (!caps)
+        g_error("could not get VA image caps");
+
+    print_format_caps(caps, "image");
+    gst_caps_unref(caps);
+
+    caps = gst_vaapi_display_get_subpicture_caps(display);
+    if (!caps)
+        g_error("could not get VA subpicture caps");
+
+    print_format_caps(caps, "subpicture");
+    gst_caps_unref(caps);
+
+    dump_properties(display);
+}
+
+int
+main(int argc, char *argv[])
+{
+    GstVaapiDisplay *display;
+    guint width, height, par_n, par_d;
+
+    gst_init(&argc, &argv);
+
+#if USE_DRM
+    g_print("#\n");
+    g_print("# Create display with gst_vaapi_display_drm_new()\n");
+    g_print("#\n");
+    {
+        display = gst_vaapi_display_drm_new(NULL);
+        if (!display)
+            g_error("could not create Gst/VA display");
+
+        dump_info(display);
+        g_object_unref(display);
+    }
+    g_print("\n");
+
+    g_print("#\n");
+    g_print("# Create display with gst_vaapi_display_drm_new_with_device()\n");
+    g_print("#\n");
+    {
+        int drm_device;
+
+        drm_device = open(DRM_DEVICE_PATH, O_RDWR|O_CLOEXEC);
+        if (drm_device < 0)
+            g_error("could not open DRM device");
+
+        display = gst_vaapi_display_drm_new_with_device(drm_device);
+        if (!display)
+            g_error("could not create Gst/VA display");
+
+        dump_info(display);
+        g_object_unref(display);
+        close(drm_device);
+    }
+    g_print("\n");
+
+    g_print("#\n");
+    g_print("# Create display with gst_vaapi_display_new_with_display() [vaGetDisplayDRM()]\n");
+    g_print("#\n");
+    {
+        int drm_device;
+        VADisplay va_display;
+
+        drm_device = open(DRM_DEVICE_PATH, O_RDWR|O_CLOEXEC);
+        if (drm_device < 0)
+            g_error("could not open DRM device");
+
+        va_display = vaGetDisplayDRM(drm_device);
+        if (!va_display)
+            g_error("could not create VA display");
+
+        display = gst_vaapi_display_new_with_display(va_display);
+        if (!display)
+            g_error("could not create Gst/VA display");
+
+        dump_info(display);
+        g_object_unref(display);
+        close(drm_device);
+    }
+    g_print("\n");
+#endif
+
+#if USE_X11
+    g_print("#\n");
+    g_print("# Create display with gst_vaapi_display_x11_new()\n");
+    g_print("#\n");
+    {
+        display = gst_vaapi_display_x11_new(NULL);
+        if (!display)
+            g_error("could not create Gst/VA display");
+
+        gst_vaapi_display_get_size(display, &width, &height);
+        g_print("Display size: %ux%u\n", width, height);
+
+        gst_vaapi_display_get_pixel_aspect_ratio(display, &par_n, &par_d);
+        g_print("Pixel aspect ratio: %u/%u\n", par_n, par_d);
+
+        dump_info(display);
+        g_object_unref(display);
+    }
+    g_print("\n");
+
+    g_print("#\n");
+    g_print("# Create display with gst_vaapi_display_x11_new_with_display()\n");
+    g_print("#\n");
+    {
+        Display *x11_display;
+
+        x11_display = XOpenDisplay(NULL);
+        if (!x11_display)
+            g_error("could not create X11 display");
+
+        display = gst_vaapi_display_x11_new_with_display(x11_display);
+        if (!display)
+            g_error("could not create Gst/VA display");
+
+        dump_info(display);
+        g_object_unref(display);
+        XCloseDisplay(x11_display);
+    }
+    g_print("\n");
+
+    g_print("#\n");
+    g_print("# Create display with gst_vaapi_display_new_with_display() [vaGetDisplay()]\n");
+    g_print("#\n");
+    {
+        Display *x11_display;
+        VADisplay va_display;
+
+        x11_display = XOpenDisplay(NULL);
+        if (!x11_display)
+            g_error("could not create X11 display");
+
+        va_display = vaGetDisplay(x11_display);
+        if (!va_display)
+            g_error("could not create VA display");
+
+        display = gst_vaapi_display_new_with_display(va_display);
+        if (!display)
+            g_error("could not create Gst/VA display");
+
+        dump_info(display);
+        g_object_unref(display);
+        XCloseDisplay(x11_display);
+    }
+    g_print("\n");
+#endif
+
+#if USE_GLX
+    g_print("#\n");
+    g_print("# Create display with gst_vaapi_display_glx_new()\n");
+    g_print("#\n");
+    {
+        display = gst_vaapi_display_glx_new(NULL);
+        if (!display)
+            g_error("could not create Gst/VA display");
+
+        gst_vaapi_display_get_size(display, &width, &height);
+        g_print("Display size: %ux%u\n", width, height);
+
+        gst_vaapi_display_get_pixel_aspect_ratio(display, &par_n, &par_d);
+        g_print("Pixel aspect ratio: %u/%u\n", par_n, par_d);
+
+        dump_info(display);
+        g_object_unref(display);
+    }
+    g_print("\n");
+
+    g_print("#\n");
+    g_print("# Create display with gst_vaapi_display_glx_new_with_display()\n");
+    g_print("#\n");
+    {
+        Display *x11_display;
+
+        x11_display = XOpenDisplay(NULL);
+        if (!x11_display)
+            g_error("could not create X11 display");
+
+        display = gst_vaapi_display_glx_new_with_display(x11_display);
+        if (!display)
+            g_error("could not create Gst/VA display");
+
+        dump_info(display);
+        g_object_unref(display);
+        XCloseDisplay(x11_display);
+    }
+    g_print("\n");
+
+#ifdef HAVE_VA_VA_GLX_H
+    g_print("#\n");
+    g_print("# Create display with gst_vaapi_display_new_with_display() [vaGetDisplayGLX()]\n");
+    g_print("#\n");
+    {
+        Display *x11_display;
+        VADisplay va_display;
+
+        x11_display = XOpenDisplay(NULL);
+        if (!x11_display)
+            g_error("could not create X11 display");
+
+        va_display = vaGetDisplayGLX(x11_display);
+        if (!va_display)
+            g_error("could not create VA display");
+
+        display = gst_vaapi_display_new_with_display(va_display);
+        if (!display)
+            g_error("could not create Gst/VA display");
+
+        dump_info(display);
+        g_object_unref(display);
+        XCloseDisplay(x11_display);
+    }
+    g_print("\n");
+#endif
+#endif
+
+#if USE_WAYLAND
+    g_print("#\n");
+    g_print("# Create display with gst_vaapi_display_wayland_new()\n");
+    g_print("#\n");
+    {
+        display = gst_vaapi_display_wayland_new(NULL);
+        if (!display)
+            g_error("could not create Gst/VA display");
+
+        gst_vaapi_display_get_size(display, &width, &height);
+        g_print("Display size: %ux%u\n", width, height);
+
+        gst_vaapi_display_get_pixel_aspect_ratio(display, &par_n, &par_d);
+        g_print("Pixel aspect ratio: %u/%u\n", par_n, par_d);
+
+        dump_info(display);
+        g_object_unref(display);
+    }
+    g_print("\n");
+#endif
+
+    gst_deinit();
+    return 0;
+}
diff --git a/tests/test-h264.c b/tests/test-h264.c
new file mode 100644 (file)
index 0000000..e25c392
--- /dev/null
@@ -0,0 +1,1049 @@
+/*
+ *  test-h264.c - H.264 test data
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+*/
+
+#include "test-h264.h"
+
+#define H264_CLIP_WIDTH           320
+#define H264_CLIP_HEIGHT          240
+#define H264_CLIP_DATA_SIZE     12111
+
+/* Data dump of a 320x240 H.264 video clip (h264.mp4), it has a single frame */
+static const guchar h264_clip[H264_CLIP_DATA_SIZE] = {
+    0x00, 0x00, 0x01, 0x67, 0x4d, 0x40, 0x0d, 0xab, 0x40, 0xa0, 0xfd, 0x80,
+    0x88, 0x00, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0xc4, 0x78,
+    0xa1, 0x55, 0x00, 0x00, 0x01, 0x68, 0xee, 0x32, 0xc8, 0x00, 0x00, 0x01,
+    0x65, 0x88, 0x82, 0x00, 0x45, 0xbb, 0x9d, 0x38, 0x9b, 0xe8, 0x48, 0xef,
+    0xed, 0xa7, 0xd7, 0x9c, 0x19, 0x9b, 0x5a, 0xca, 0x00, 0x0d, 0x54, 0x0c,
+    0xe3, 0xd5, 0xad, 0xa9, 0x5d, 0x71, 0x24, 0x83, 0xbb, 0x36, 0x4d, 0xb1,
+    0xf5, 0x0f, 0xc6, 0x66, 0xb6, 0x6d, 0x1d, 0xa5, 0x45, 0xfc, 0xa0, 0x4c,
+    0xbf, 0xfb, 0x2f, 0x5c, 0x1a, 0x5a, 0x3b, 0x29, 0xe0, 0x35, 0x95, 0x44,
+    0x8e, 0x2f, 0x22, 0xd3, 0x3a, 0x48, 0x88, 0x7d, 0x32, 0x97, 0xff, 0xd8,
+    0x54, 0x7f, 0x7f, 0x65, 0x57, 0x71, 0xaf, 0xba, 0x17, 0xe0, 0x12, 0x24,
+    0xc9, 0x5b, 0xaa, 0xc7, 0xd5, 0x27, 0xc9, 0x64, 0x5d, 0x5e, 0xa0, 0xea,
+    0x57, 0xd2, 0x7d, 0x55, 0x6c, 0xf2, 0x44, 0x2f, 0x4b, 0x5d, 0xbd, 0x62,
+    0xb9, 0xc2, 0xfa, 0x1e, 0x8f, 0xbc, 0x57, 0x5f, 0xc1, 0x2d, 0xb3, 0x9a,
+    0x0e, 0x58, 0x75, 0xf7, 0x08, 0xdf, 0x2d, 0xda, 0xc1, 0xa5, 0x55, 0x76,
+    0x06, 0xaf, 0x92, 0x28, 0x43, 0xc5, 0x20, 0x16, 0x96, 0xf5, 0x79, 0x1e,
+    0x88, 0x77, 0xb3, 0x4e, 0xb8, 0x4f, 0x3e, 0x51, 0x3c, 0xcf, 0xc0, 0x28,
+    0xda, 0xb8, 0xa3, 0x1d, 0xed, 0x8e, 0x04, 0x74, 0x82, 0xc1, 0x5d, 0xa8,
+    0x3c, 0x25, 0xd2, 0x84, 0x0b, 0x34, 0x40, 0x8b, 0x7f, 0xee, 0xae, 0xf8,
+    0xde, 0x6e, 0x28, 0xf6, 0xfc, 0xfc, 0x14, 0x7e, 0x95, 0xd9, 0xd8, 0x2c,
+    0x09, 0x49, 0x27, 0x64, 0x13, 0x83, 0x5c, 0x6f, 0xd4, 0x09, 0x48, 0xa8,
+    0xd4, 0x1b, 0x6e, 0x4d, 0x05, 0x0a, 0xbe, 0x27, 0xff, 0xf4, 0x27, 0x04,
+    0x41, 0xa0, 0x23, 0x61, 0xe6, 0x26, 0x32, 0xf4, 0xa3, 0xca, 0x97, 0xfc,
+    0xeb, 0x6b, 0x45, 0x35, 0x13, 0x69, 0xd9, 0x41, 0x0f, 0xa6, 0xc0, 0xbe,
+    0xd5, 0xfa, 0x28, 0xa6, 0x4f, 0x62, 0x3e, 0x1f, 0xcb, 0x98, 0x0a, 0x70,
+    0x09, 0xc1, 0xe3, 0x69, 0x30, 0x20, 0xe7, 0xd5, 0x1c, 0xf0, 0x7e, 0x52,
+    0x1d, 0x6a, 0xdd, 0x14, 0x58, 0x5e, 0x7a, 0x35, 0x57, 0xa1, 0xe6, 0x83,
+    0x46, 0x57, 0x6e, 0x57, 0x7f, 0x72, 0x5d, 0x0c, 0x0c, 0xf4, 0x40, 0x11,
+    0x8c, 0xbb, 0xdf, 0xd1, 0x54, 0xfb, 0x7d, 0xf7, 0x03, 0xb9, 0x4e, 0xa3,
+    0x76, 0x4c, 0xce, 0xfb, 0x9e, 0x39, 0x02, 0xf0, 0x48, 0xb5, 0x8c, 0x36,
+    0x6e, 0x93, 0x79, 0x48, 0xcc, 0x28, 0xec, 0xd7, 0xb8, 0x02, 0xe5, 0xa3,
+    0x37, 0x01, 0xe1, 0x3c, 0x40, 0x8f, 0x68, 0x27, 0xbc, 0xec, 0x6b, 0x59,
+    0xb9, 0xfe, 0xb8, 0x67, 0x68, 0x83, 0x99, 0x97, 0x1e, 0xcc, 0x4e, 0x23,
+    0x82, 0x26, 0x93, 0x7b, 0x7a, 0x9e, 0xdc, 0x42, 0xca, 0x1b, 0x3e, 0x13,
+    0x19, 0x45, 0x03, 0x40, 0xab, 0xd2, 0xda, 0x6b, 0x6c, 0x26, 0xdb, 0xe3,
+    0x72, 0x06, 0x89, 0xea, 0x03, 0x95, 0xe3, 0x14, 0xe1, 0x4a, 0x16, 0x58,
+    0x2d, 0x67, 0xaa, 0xbf, 0xbe, 0x37, 0x54, 0x19, 0xb1, 0x57, 0x61, 0x85,
+    0x82, 0x5f, 0x63, 0x33, 0xe2, 0xf8, 0x7f, 0x4f, 0x21, 0x44, 0x8a, 0x0e,
+    0x21, 0x2b, 0x12, 0x99, 0x4d, 0xd9, 0x2e, 0xea, 0x36, 0x2d, 0x45, 0xcb,
+    0xe2, 0xfe, 0xdd, 0x03, 0x3b, 0x08, 0x58, 0x60, 0x1e, 0xb2, 0xfa, 0x3b,
+    0x89, 0xa5, 0x03, 0xde, 0xab, 0x71, 0x32, 0x48, 0x46, 0x2c, 0xfb, 0x2b,
+    0x84, 0x83, 0xc9, 0xff, 0xf6, 0xf5, 0x2f, 0xe7, 0x2f, 0x6a, 0x5d, 0x86,
+    0xe2, 0x48, 0x23, 0x6d, 0x84, 0x60, 0x9b, 0xc0, 0x25, 0x1e, 0xff, 0x94,
+    0xe8, 0xf4, 0xd0, 0x4e, 0x11, 0x60, 0xda, 0x20, 0xa8, 0xfd, 0xf3, 0x00,
+    0x4f, 0x0e, 0x4f, 0xa2, 0xeb, 0xe1, 0xa8, 0xb3, 0x47, 0x35, 0x62, 0x83,
+    0x6f, 0x08, 0x6b, 0xb8, 0x82, 0x04, 0xcc, 0x63, 0x69, 0xd7, 0xba, 0x10,
+    0xd4, 0x51, 0xe6, 0xb5, 0x34, 0xe8, 0x7d, 0xaf, 0x87, 0xcf, 0x1d, 0xeb,
+    0x46, 0xc1, 0xcd, 0xcb, 0xf2, 0x3b, 0x3e, 0xa0, 0x61, 0xc7, 0x68, 0x86,
+    0x0b, 0x9f, 0x0b, 0x59, 0xc0, 0x79, 0x4e, 0xcc, 0x79, 0x91, 0xa0, 0xe8,
+    0x80, 0x6c, 0xbd, 0x35, 0x12, 0x71, 0x2f, 0x5e, 0xa4, 0xfc, 0xe6, 0x51,
+    0xe0, 0xbe, 0x41, 0x1a, 0x19, 0x60, 0xd8, 0xac, 0xcd, 0x93, 0x05, 0x70,
+    0xa0, 0xda, 0x53, 0x4e, 0x5a, 0x6d, 0x9b, 0x3f, 0x28, 0x73, 0x87, 0x6f,
+    0x6d, 0x41, 0x5a, 0x13, 0xd0, 0xea, 0x19, 0xb3, 0xb7, 0xf1, 0x75, 0x92,
+    0xae, 0x43, 0x9d, 0xe3, 0xa7, 0x4d, 0x5a, 0x52, 0x36, 0xce, 0x6b, 0x1e,
+    0x2b, 0x2e, 0xab, 0x0c, 0xd7, 0xe4, 0x1c, 0x44, 0x72, 0x9d, 0x86, 0xb6,
+    0xeb, 0xe5, 0x80, 0xc4, 0x45, 0x21, 0x8b, 0xe0, 0xe0, 0x9d, 0x09, 0xfa,
+    0x0b, 0x59, 0x0c, 0x2c, 0x9d, 0x97, 0x15, 0x56, 0xd0, 0x21, 0xd8, 0x90,
+    0xb4, 0x89, 0xc4, 0x96, 0x76, 0xf1, 0x64, 0xa5, 0x85, 0x2a, 0x13, 0xfb,
+    0xfa, 0x11, 0x1e, 0x2d, 0x63, 0xc2, 0x9a, 0x87, 0x99, 0x2c, 0x18, 0xb8,
+    0xeb, 0x6a, 0x5c, 0x68, 0x26, 0x63, 0xcc, 0x1b, 0x1a, 0x5c, 0x7f, 0x0d,
+    0x45, 0xcc, 0x56, 0x46, 0x92, 0xbb, 0x76, 0xf2, 0x2e, 0x52, 0x05, 0x3c,
+    0xe3, 0xbb, 0x59, 0x9b, 0x89, 0x03, 0x0d, 0x48, 0xb1, 0xdc, 0x78, 0x04,
+    0x03, 0x24, 0xf4, 0x62, 0xcf, 0xb1, 0xc6, 0x64, 0x05, 0xbd, 0x89, 0x94,
+    0x1a, 0x8d, 0xc1, 0xbe, 0xac, 0xe0, 0xed, 0x89, 0xf3, 0x47, 0x81, 0x82,
+    0xb9, 0x64, 0xcc, 0x8e, 0xc4, 0x1e, 0xa9, 0xf6, 0xde, 0x8d, 0xb7, 0x33,
+    0xba, 0x5b, 0x49, 0x0d, 0x0a, 0x16, 0x96, 0x7d, 0x89, 0x82, 0xe0, 0x5a,
+    0x08, 0x55, 0xbd, 0xce, 0xca, 0xc0, 0x46, 0x1a, 0x6b, 0xf9, 0x7d, 0x03,
+    0xe8, 0x35, 0x69, 0x7d, 0x87, 0xc9, 0x71, 0x01, 0x7e, 0xa8, 0x3a, 0x9c,
+    0xd5, 0xe2, 0x71, 0xa6, 0xc7, 0xe2, 0x2d, 0xf3, 0x6f, 0x74, 0x0f, 0x3e,
+    0x03, 0x70, 0x5e, 0xec, 0x8c, 0x66, 0xf9, 0x71, 0x9a, 0xd2, 0x56, 0x57,
+    0x37, 0xcd, 0x50, 0x55, 0x97, 0xea, 0x67, 0x20, 0x59, 0x06, 0x4d, 0x22,
+    0xa0, 0x85, 0x90, 0xb3, 0x59, 0x15, 0x75, 0x0d, 0x70, 0xbd, 0xb5, 0x7d,
+    0x72, 0xaa, 0xea, 0xfc, 0x9d, 0x08, 0x8d, 0xdf, 0x31, 0x21, 0x2d, 0xef,
+    0x00, 0x24, 0x6c, 0xae, 0x82, 0x6e, 0x1a, 0x4b, 0x28, 0xa5, 0x6d, 0x98,
+    0xeb, 0x50, 0x87, 0x6f, 0x1b, 0xa5, 0xba, 0x1c, 0xda, 0x59, 0xb8, 0x4c,
+    0x17, 0xe3, 0xd5, 0x10, 0x46, 0x94, 0x91, 0xed, 0x0b, 0xd3, 0xfc, 0x06,
+    0x81, 0x60, 0x88, 0x5f, 0x58, 0x81, 0x26, 0x54, 0xdc, 0xd5, 0x7c, 0xbe,
+    0x30, 0x04, 0x17, 0x84, 0x76, 0xe8, 0xb6, 0x8a, 0xec, 0x84, 0x02, 0xcf,
+    0xc7, 0xda, 0x2d, 0x2e, 0x31, 0xc2, 0x77, 0x31, 0x54, 0x32, 0xbd, 0x77,
+    0xa2, 0xa5, 0x5d, 0xec, 0x1c, 0x27, 0xf6, 0xec, 0xc8, 0x3f, 0xeb, 0x1a,
+    0x24, 0xcb, 0x74, 0xd0, 0xb3, 0x52, 0xa8, 0x8f, 0x4c, 0x26, 0xbf, 0x68,
+    0xb2, 0x87, 0xf3, 0xa8, 0xa9, 0x4f, 0x71, 0x57, 0xc7, 0xa8, 0x34, 0x5a,
+    0x01, 0x68, 0xae, 0x5c, 0xb3, 0xd8, 0x23, 0x6b, 0xea, 0x18, 0xdf, 0xa9,
+    0xe5, 0xc4, 0x11, 0x49, 0x2b, 0xfa, 0xa8, 0xf3, 0x8f, 0x80, 0x47, 0xa0,
+    0x19, 0xc7, 0x20, 0xef, 0xbf, 0xed, 0xe1, 0x38, 0x8b, 0x16, 0x54, 0x36,
+    0x60, 0x8b, 0x04, 0x26, 0x9c, 0x6b, 0x1a, 0x95, 0x4c, 0x94, 0x6a, 0x53,
+    0xcf, 0xb4, 0x4b, 0x38, 0x3a, 0x15, 0x26, 0x94, 0x10, 0x1c, 0x35, 0xe4,
+    0x57, 0x80, 0x19, 0xad, 0x1f, 0x82, 0xe8, 0x47, 0xe4, 0x90, 0xa2, 0x42,
+    0x30, 0x43, 0x15, 0x92, 0x2b, 0x39, 0xfb, 0x7b, 0xb3, 0xdb, 0xc7, 0x5b,
+    0x79, 0x5e, 0x91, 0xba, 0x38, 0x74, 0xd6, 0x00, 0x26, 0xa5, 0x8f, 0xa4,
+    0x31, 0xe6, 0x7b, 0xeb, 0x52, 0xc2, 0xe2, 0xa1, 0x6b, 0x5f, 0x17, 0xf1,
+    0x15, 0xc9, 0x4b, 0x44, 0x93, 0x77, 0x28, 0xdf, 0x2a, 0xc0, 0xb5, 0x97,
+    0xfc, 0xbe, 0x2e, 0x72, 0x53, 0x58, 0xf9, 0x33, 0x3a, 0xb0, 0x6e, 0xaf,
+    0x0c, 0x1b, 0xcf, 0x71, 0x37, 0x6b, 0x4a, 0x9a, 0x66, 0x16, 0x90, 0x43,
+    0x9b, 0x70, 0x0d, 0x8f, 0xd3, 0x04, 0x4b, 0x14, 0xf2, 0x58, 0x9f, 0x64,
+    0x33, 0x21, 0xdc, 0x02, 0x8a, 0x5b, 0xd6, 0x80, 0x9c, 0x22, 0xc8, 0x39,
+    0x7d, 0x2d, 0x7c, 0x09, 0x4e, 0x6a, 0x8c, 0x8d, 0x0c, 0xc4, 0xfe, 0x6f,
+    0x8c, 0x50, 0xf2, 0x75, 0xc0, 0x12, 0x6f, 0xd3, 0x9d, 0x07, 0xc0, 0xe9,
+    0xdf, 0x36, 0xa2, 0x6f, 0xca, 0x14, 0x5b, 0x0f, 0x5a, 0xd8, 0x35, 0x72,
+    0x07, 0x08, 0x80, 0xba, 0x2f, 0x61, 0x7f, 0xb0, 0x5e, 0xbb, 0xb1, 0x47,
+    0x6a, 0xbd, 0x6a, 0xe4, 0xb6, 0xa2, 0xec, 0x2e, 0x27, 0x43, 0xbc, 0xd7,
+    0x2c, 0x2c, 0xf3, 0x6c, 0x12, 0x4c, 0x86, 0x5a, 0x38, 0xa4, 0x87, 0xa8,
+    0xe1, 0x70, 0x17, 0x15, 0xd0, 0x2b, 0x87, 0xdb, 0x87, 0xc0, 0x85, 0x57,
+    0x30, 0x31, 0x16, 0x07, 0x9b, 0x72, 0x07, 0xf5, 0x18, 0x6d, 0xd1, 0x8d,
+    0x31, 0xa1, 0x25, 0x6a, 0xb4, 0xf3, 0x07, 0x5f, 0x0c, 0x99, 0x33, 0x68,
+    0xbf, 0x2c, 0xa1, 0xfd, 0xde, 0x16, 0x2d, 0x4a, 0x5a, 0xa0, 0x7e, 0xe5,
+    0x9b, 0x89, 0x4a, 0x8d, 0xe7, 0x18, 0x21, 0x32, 0x47, 0x3c, 0x9d, 0x48,
+    0xab, 0x7d, 0xca, 0xb4, 0x63, 0xd9, 0xfd, 0x29, 0x2d, 0x4c, 0xf1, 0xf2,
+    0x20, 0x0a, 0x91, 0x2e, 0x2c, 0xa1, 0x49, 0x83, 0x73, 0x15, 0xa0, 0x7d,
+    0x6e, 0xae, 0x51, 0x45, 0x0d, 0x09, 0x1f, 0x8f, 0x61, 0x42, 0xbd, 0x24,
+    0xcd, 0x3e, 0xe8, 0x66, 0x84, 0xc6, 0x97, 0x08, 0x7b, 0x72, 0x73, 0x7e,
+    0xe7, 0x99, 0x05, 0xab, 0x63, 0xff, 0x3c, 0x44, 0xa1, 0xc0, 0x1b, 0xfc,
+    0xff, 0x27, 0xe9, 0x45, 0x82, 0x75, 0x82, 0x6f, 0x9c, 0x65, 0xef, 0x67,
+    0xd6, 0x00, 0xd1, 0x9f, 0x61, 0x9f, 0x38, 0xdd, 0x7f, 0x5f, 0x4d, 0x67,
+    0x5b, 0x5d, 0xff, 0x98, 0x6b, 0x13, 0xe0, 0xe7, 0x69, 0xcb, 0x7f, 0x7c,
+    0x11, 0x91, 0xe0, 0x05, 0xb9, 0x64, 0xd0, 0xb7, 0x91, 0xe5, 0xd4, 0x3a,
+    0x47, 0x05, 0x25, 0x4f, 0x15, 0x46, 0xaf, 0x41, 0x9e, 0xc7, 0x49, 0x15,
+    0x17, 0xd1, 0x9c, 0x28, 0xef, 0x80, 0xa3, 0x8b, 0x60, 0xcc, 0x60, 0xeb,
+    0x96, 0x36, 0x3a, 0x23, 0x94, 0xf3, 0x6c, 0xe5, 0x3f, 0xe8, 0x8b, 0x5c,
+    0x8c, 0xfe, 0x6f, 0x91, 0x65, 0x19, 0xa1, 0x4d, 0x45, 0x7b, 0x06, 0x0f,
+    0x71, 0xb7, 0x9a, 0x8d, 0x8e, 0x82, 0x7b, 0x68, 0x44, 0xa4, 0xa6, 0xc3,
+    0xe5, 0x67, 0x9f, 0x6c, 0xd0, 0xe4, 0xe8, 0x37, 0x08, 0x6b, 0xbb, 0xa0,
+    0x3a, 0xd0, 0xa9, 0xd9, 0x04, 0xaa, 0x91, 0xac, 0x71, 0xff, 0xec, 0x7e,
+    0xaf, 0xa9, 0x99, 0xa2, 0x8d, 0x91, 0x95, 0xb3, 0xd8, 0xe4, 0xf3, 0x3f,
+    0xa6, 0x4b, 0x0c, 0x19, 0x23, 0xf7, 0xa7, 0xcd, 0x4c, 0x41, 0x28, 0x63,
+    0x9f, 0x0b, 0x8f, 0x70, 0x70, 0xbd, 0x25, 0x16, 0x8e, 0x86, 0x8a, 0x69,
+    0xe3, 0x6a, 0xd4, 0x98, 0x42, 0x56, 0x15, 0x2d, 0x3d, 0xdb, 0x17, 0x1b,
+    0x23, 0x58, 0x82, 0x56, 0x11, 0x97, 0x85, 0xf2, 0x68, 0x95, 0x92, 0xd5,
+    0x9e, 0x91, 0x05, 0x70, 0xc8, 0x96, 0xb2, 0x73, 0x6d, 0x1e, 0x12, 0x8c,
+    0xa0, 0xe4, 0x1a, 0x84, 0x5b, 0xb4, 0x32, 0xf7, 0x9e, 0x08, 0xd0, 0x6c,
+    0x42, 0xf0, 0x0b, 0xc4, 0x1f, 0xe0, 0xbb, 0x71, 0xe1, 0x2d, 0x86, 0xd7,
+    0x77, 0x24, 0x43, 0x53, 0x0c, 0x88, 0x21, 0x75, 0x95, 0xd0, 0xfe, 0x10,
+    0x23, 0xcd, 0xba, 0x77, 0x3d, 0x9b, 0x0f, 0xb2, 0xe2, 0xcc, 0x0f, 0x94,
+    0xe0, 0x66, 0x90, 0x0e, 0xf7, 0x6a, 0x3c, 0x9f, 0xc0, 0xf6, 0x98, 0x1c,
+    0x4c, 0x9f, 0x25, 0xc4, 0xeb, 0x1d, 0x91, 0x32, 0x29, 0x34, 0x2a, 0xb0,
+    0x7e, 0x1c, 0x09, 0x77, 0x13, 0x83, 0xfa, 0xcf, 0x24, 0xa2, 0x5f, 0x79,
+    0x78, 0x64, 0xf7, 0x45, 0x81, 0xbe, 0x6a, 0x82, 0x26, 0xfd, 0xe7, 0xc3,
+    0x61, 0x41, 0x27, 0xcc, 0x99, 0x69, 0x77, 0xc8, 0xa7, 0xf3, 0x52, 0x01,
+    0xa7, 0x8c, 0x0b, 0x7d, 0x86, 0x8d, 0xbb, 0x31, 0xd6, 0x67, 0xf9, 0xa7,
+    0x8f, 0x76, 0xb6, 0x74, 0x26, 0x43, 0x35, 0xb8, 0x83, 0x7c, 0x16, 0x34,
+    0x88, 0x0c, 0xb6, 0xec, 0xf0, 0x01, 0x8c, 0x1c, 0xe5, 0x52, 0xd4, 0xca,
+    0x01, 0x2e, 0xb5, 0x87, 0xc1, 0xc1, 0x1b, 0xa3, 0x02, 0x17, 0x13, 0xd3,
+    0x35, 0xe8, 0x80, 0xe1, 0xd1, 0x01, 0x9c, 0x0a, 0x62, 0x7d, 0x98, 0x7c,
+    0x68, 0xa4, 0x8e, 0x3a, 0x50, 0x4b, 0x95, 0x59, 0xa3, 0x11, 0xf6, 0xa3,
+    0xde, 0x92, 0x65, 0x00, 0xa0, 0xe8, 0x32, 0xf0, 0xc3, 0x77, 0x68, 0x0b,
+    0xed, 0xc1, 0x69, 0xd2, 0x6e, 0xce, 0x80, 0xe4, 0x56, 0x9b, 0x15, 0xbf,
+    0x3c, 0x4a, 0x38, 0x26, 0xf6, 0x6a, 0xdb, 0x62, 0x7a, 0xab, 0xb1, 0x77,
+    0x75, 0x0d, 0xa7, 0xa4, 0xcf, 0x5e, 0x2d, 0xea, 0x24, 0x84, 0xbd, 0x83,
+    0x8e, 0xaa, 0x91, 0xe1, 0x72, 0x5f, 0x7f, 0x26, 0x54, 0x4f, 0xab, 0xa6,
+    0x50, 0x22, 0x68, 0x8c, 0xa6, 0x06, 0x67, 0x3c, 0x3e, 0x93, 0x9a, 0xc2,
+    0x53, 0x15, 0x08, 0x1a, 0x3c, 0xb3, 0x3f, 0xf0, 0x83, 0xf5, 0x0d, 0x9c,
+    0xe3, 0x76, 0x11, 0x45, 0x21, 0x6b, 0x65, 0x97, 0xea, 0x3c, 0xdb, 0x0d,
+    0xcd, 0x6e, 0xb7, 0x26, 0x7b, 0x82, 0x63, 0x35, 0x7e, 0x76, 0xf4, 0xb8,
+    0x0e, 0xe5, 0x1d, 0x95, 0x94, 0x1c, 0x60, 0xc7, 0xea, 0x9c, 0x1c, 0x73,
+    0x75, 0x0e, 0x9b, 0x5f, 0x78, 0x09, 0x4f, 0x90, 0x31, 0x5c, 0xc8, 0x5b,
+    0x78, 0xce, 0xb3, 0x3e, 0x31, 0x61, 0x90, 0xba, 0xe0, 0xe1, 0x57, 0x1d,
+    0x71, 0x80, 0x92, 0x6b, 0x75, 0xe1, 0x34, 0x95, 0xeb, 0x88, 0xe4, 0x0b,
+    0x72, 0xdc, 0x34, 0x24, 0x3b, 0x6d, 0x94, 0xc9, 0xe9, 0x8d, 0x38, 0x72,
+    0x9c, 0x61, 0x6e, 0x07, 0xd7, 0x35, 0xa1, 0x74, 0xc2, 0x0c, 0x36, 0xc3,
+    0x54, 0xd3, 0xe5, 0xd1, 0x08, 0x8e, 0x24, 0x77, 0xf5, 0x61, 0xcf, 0x69,
+    0x9b, 0x27, 0x70, 0xe7, 0x52, 0xf6, 0xef, 0x66, 0x8f, 0x0e, 0x8b, 0xc0,
+    0xf3, 0x64, 0x2a, 0xa8, 0xff, 0xcc, 0xd9, 0x61, 0x53, 0xac, 0x36, 0x23,
+    0x4f, 0x3c, 0x0f, 0xe0, 0xec, 0xad, 0xc5, 0x35, 0x3f, 0x3b, 0x74, 0x26,
+    0x84, 0x48, 0xd1, 0xfe, 0x72, 0x01, 0xea, 0x4d, 0x03, 0x46, 0x66, 0x5a,
+    0xc4, 0x0a, 0x55, 0x43, 0x61, 0x36, 0x6a, 0xc1, 0xd2, 0x74, 0x0a, 0x8f,
+    0x01, 0xb2, 0xc2, 0xaa, 0xd7, 0x2d, 0x0a, 0x0f, 0x67, 0xa1, 0x25, 0x7d,
+    0x45, 0x60, 0x0f, 0x06, 0xfb, 0x8f, 0x8b, 0xe0, 0x4a, 0x8c, 0xd7, 0x19,
+    0xac, 0xcc, 0x47, 0xa2, 0x7c, 0x30, 0x90, 0x94, 0x81, 0xab, 0xde, 0x38,
+    0xb8, 0xc9, 0xdb, 0x63, 0x9c, 0xcb, 0xdd, 0x71, 0xde, 0x4f, 0x1e, 0x43,
+    0x08, 0xe4, 0xe3, 0x83, 0x86, 0x0f, 0x34, 0xb7, 0x1e, 0x53, 0xc1, 0xde,
+    0x46, 0xf1, 0x70, 0xf5, 0xd8, 0x47, 0xd2, 0x9b, 0x44, 0x88, 0x85, 0x8e,
+    0x32, 0xa9, 0x0c, 0x09, 0x2f, 0xd0, 0xe4, 0x4b, 0x30, 0x3a, 0x2e, 0x65,
+    0x0c, 0xff, 0xb4, 0x0d, 0xa8, 0x8f, 0x61, 0x3e, 0x7e, 0x90, 0x66, 0xbb,
+    0xf6, 0xbe, 0xfd, 0x7d, 0xe4, 0xdc, 0x2c, 0x59, 0x87, 0x81, 0x60, 0x96,
+    0xd7, 0x1d, 0x10, 0x02, 0x35, 0xdd, 0x16, 0x4c, 0xe9, 0x2d, 0x52, 0x45,
+    0xdd, 0x3f, 0xc9, 0xff, 0x8d, 0x19, 0xad, 0x02, 0x74, 0xf1, 0x09, 0x99,
+    0x94, 0x66, 0x2e, 0x8b, 0xa3, 0xdc, 0x3d, 0xf3, 0xf5, 0x85, 0xf2, 0x60,
+    0x7d, 0x9d, 0xe0, 0xd3, 0x0f, 0xa4, 0x92, 0xf3, 0x55, 0xbc, 0x7b, 0x20,
+    0x6b, 0xf6, 0xc4, 0xc4, 0x0f, 0x8a, 0xd7, 0x5a, 0x02, 0xb0, 0xb7, 0x78,
+    0xb4, 0x9e, 0xb6, 0x93, 0x95, 0x2e, 0x76, 0x06, 0x1e, 0x34, 0x5d, 0x34,
+    0x77, 0x77, 0x6d, 0x32, 0xbb, 0x46, 0xad, 0x43, 0xd7, 0x72, 0x61, 0x33,
+    0x4f, 0x98, 0xe9, 0x56, 0x3a, 0x96, 0x89, 0x6e, 0x1f, 0xaf, 0x6b, 0xa0,
+    0x9a, 0xe4, 0x42, 0x5a, 0xb3, 0xb8, 0x2a, 0xe1, 0x2d, 0xa6, 0x32, 0xa2,
+    0x01, 0xf5, 0x3a, 0x9a, 0xbb, 0x06, 0x76, 0x0b, 0xa8, 0xac, 0x02, 0x96,
+    0x0c, 0x58, 0xd3, 0x64, 0xc8, 0xe2, 0xae, 0x6c, 0xf7, 0xa7, 0x32, 0x4b,
+    0x51, 0x50, 0x11, 0x90, 0xcf, 0x37, 0xed, 0xd2, 0xa0, 0xa4, 0x97, 0xb3,
+    0x45, 0x1d, 0x7d, 0xf3, 0xff, 0xde, 0x9f, 0x80, 0xa9, 0x61, 0xac, 0x37,
+    0x7f, 0x5d, 0xc9, 0xf6, 0xdc, 0x26, 0xd0, 0x65, 0xf2, 0xdc, 0x0c, 0x1a,
+    0xcb, 0xde, 0x6b, 0x77, 0xf3, 0x08, 0xa4, 0x93, 0xab, 0x2a, 0xdf, 0x18,
+    0x1a, 0xc7, 0xa6, 0xa1, 0x7e, 0x43, 0x75, 0xca, 0x88, 0xcc, 0x6f, 0xa2,
+    0x85, 0x0e, 0xb0, 0xd5, 0xcd, 0x8a, 0xff, 0xc1, 0x57, 0x20, 0x66, 0xf7,
+    0x19, 0x7a, 0x52, 0x5b, 0x46, 0x87, 0x5f, 0xf7, 0x77, 0xe2, 0xab, 0x4e,
+    0x4a, 0xce, 0x8f, 0x3f, 0xe6, 0x9f, 0x88, 0x3a, 0x33, 0x65, 0x3c, 0x3a,
+    0x41, 0xc3, 0x8e, 0xee, 0x79, 0xe7, 0x2c, 0xb0, 0x3b, 0x93, 0x82, 0xa0,
+    0x1a, 0x71, 0x0e, 0xf6, 0x31, 0xc5, 0x6f, 0xc1, 0xa8, 0x32, 0x89, 0x3b,
+    0x33, 0x68, 0x53, 0x81, 0x15, 0x70, 0x5e, 0x22, 0xdc, 0x99, 0xc6, 0x88,
+    0xf8, 0x11, 0x06, 0x56, 0x1f, 0x80, 0x7e, 0x0b, 0x27, 0x90, 0xfc, 0x97,
+    0x76, 0x61, 0xdc, 0x30, 0x5d, 0x34, 0x4e, 0x83, 0x85, 0xce, 0xe2, 0x91,
+    0x4d, 0x8d, 0x92, 0x88, 0x26, 0xa0, 0xde, 0x47, 0x82, 0xd2, 0xa8, 0xa5,
+    0xe7, 0x27, 0x0c, 0x45, 0x41, 0x85, 0xa1, 0x12, 0xcb, 0x3a, 0x74, 0x53,
+    0x93, 0x77, 0xd0, 0x8b, 0x42, 0x8d, 0x00, 0xca, 0x44, 0x67, 0xa0, 0x6a,
+    0xbd, 0xcd, 0x4a, 0x3c, 0xfe, 0x6c, 0xa1, 0x48, 0x26, 0x0d, 0x51, 0x54,
+    0x59, 0xc9, 0xf9, 0x51, 0x5c, 0xd3, 0x55, 0xf0, 0x72, 0x77, 0xdb, 0x52,
+    0xee, 0x0a, 0x5e, 0x8a, 0xf0, 0xbe, 0x9a, 0x37, 0xa0, 0x1b, 0x94, 0xe3,
+    0x2d, 0x17, 0xc4, 0xbe, 0x9c, 0xad, 0x9c, 0xd1, 0xc6, 0xbc, 0x36, 0x5c,
+    0x3b, 0xe3, 0x2e, 0x66, 0x29, 0x0c, 0x3a, 0x3d, 0xe7, 0xe3, 0xf3, 0x58,
+    0x70, 0x3e, 0x59, 0xb2, 0x6c, 0x91, 0x14, 0xfe, 0x9e, 0x5e, 0x5d, 0xb2,
+    0x7b, 0x46, 0x66, 0x46, 0x55, 0xe2, 0x78, 0x47, 0xeb, 0xdf, 0x2b, 0xb4,
+    0xf2, 0xb2, 0x14, 0xbe, 0x64, 0x9e, 0x17, 0x16, 0x9f, 0xf5, 0x6a, 0xdd,
+    0x25, 0xa1, 0x55, 0x6e, 0xb1, 0xfa, 0x09, 0xd0, 0x97, 0x7c, 0x13, 0xde,
+    0x1d, 0xd4, 0x94, 0x19, 0xde, 0x8b, 0x4d, 0xe7, 0xee, 0x1f, 0xdf, 0xe5,
+    0x3b, 0xdd, 0xbd, 0x13, 0x9c, 0xec, 0xcd, 0xb6, 0xb6, 0xbb, 0x3f, 0xbd,
+    0x54, 0xca, 0x47, 0x5c, 0x05, 0x3c, 0x03, 0x30, 0x9d, 0x56, 0xf6, 0xc6,
+    0x48, 0x6b, 0x74, 0x49, 0x58, 0xa2, 0xd8, 0x45, 0x42, 0x6f, 0xe4, 0x46,
+    0x27, 0x92, 0x83, 0x78, 0x97, 0x55, 0x5b, 0x82, 0xce, 0x2a, 0x08, 0x41,
+    0xb9, 0x7a, 0x66, 0x0f, 0x3c, 0x5b, 0xdf, 0x8d, 0x1d, 0x02, 0x11, 0xa4,
+    0xa7, 0x0a, 0x80, 0x1e, 0xbb, 0x7a, 0xc9, 0x2f, 0xb9, 0x35, 0xc8, 0xd7,
+    0x98, 0x04, 0x29, 0xaa, 0x4b, 0x88, 0x66, 0x73, 0xe4, 0x59, 0xc4, 0x3e,
+    0x50, 0xad, 0xe5, 0x64, 0x54, 0xf0, 0x29, 0x38, 0xee, 0xc0, 0x00, 0xc4,
+    0x22, 0x16, 0xf2, 0xc5, 0x46, 0x5c, 0xee, 0x9e, 0xf2, 0x9a, 0xe7, 0xfd,
+    0x62, 0x50, 0xa2, 0xeb, 0x47, 0x56, 0x4c, 0xe4, 0x75, 0x46, 0xe4, 0xd5,
+    0x25, 0xec, 0xe0, 0x35, 0x33, 0x31, 0x34, 0x1b, 0xcb, 0x72, 0x78, 0x1c,
+    0x4d, 0x3a, 0x19, 0x2e, 0xc4, 0xb7, 0xa4, 0x80, 0xd2, 0x91, 0xeb, 0x2a,
+    0x1d, 0xf2, 0xd1, 0xa3, 0xae, 0xac, 0x41, 0xae, 0xc2, 0x44, 0xd2, 0x3f,
+    0xb4, 0x87, 0x8d, 0x69, 0x6c, 0x67, 0xd6, 0x85, 0xee, 0xd6, 0x3b, 0x03,
+    0xdc, 0x58, 0x46, 0x07, 0x73, 0xb4, 0xb0, 0x3f, 0x5e, 0xc1, 0x13, 0x2c,
+    0x36, 0x58, 0xd0, 0x1c, 0x34, 0x3e, 0x01, 0x88, 0xfa, 0xb1, 0x9a, 0x03,
+    0x85, 0x4f, 0x4c, 0xd2, 0xac, 0xd9, 0x12, 0x09, 0xaa, 0x5f, 0x20, 0x06,
+    0x1f, 0x0a, 0x44, 0x28, 0x50, 0xd1, 0x8f, 0x51, 0x8a, 0x1d, 0xfa, 0xaa,
+    0x46, 0x33, 0xac, 0x0c, 0xb3, 0x10, 0xcf, 0x24, 0x4d, 0x0f, 0xcd, 0xee,
+    0xd9, 0x64, 0x4a, 0x1a, 0x84, 0x0f, 0xff, 0x48, 0x8d, 0x79, 0xd4, 0x43,
+    0x70, 0x1c, 0x7e, 0x7e, 0x12, 0x43, 0x51, 0x4a, 0x7e, 0x45, 0x9e, 0xa4,
+    0x3c, 0x12, 0xbd, 0x95, 0xe9, 0xd6, 0xd4, 0x3f, 0xbf, 0x03, 0xae, 0x9e,
+    0x24, 0x1a, 0x36, 0xbd, 0xea, 0x5d, 0x65, 0xff, 0x9f, 0x95, 0x70, 0xda,
+    0xb0, 0x53, 0x6a, 0x5f, 0x64, 0x7b, 0xb6, 0x7a, 0x8d, 0xa2, 0xd4, 0x9c,
+    0xb1, 0xf9, 0xe6, 0x14, 0x62, 0x3b, 0xe7, 0x5b, 0x40, 0x9d, 0xf4, 0x19,
+    0xb5, 0x50, 0xc8, 0xbd, 0x76, 0xd3, 0xbc, 0x0e, 0x6d, 0x62, 0x91, 0x73,
+    0x3e, 0x7f, 0xbf, 0xd0, 0xf0, 0x33, 0xf8, 0x6a, 0x9f, 0xa6, 0xad, 0xc3,
+    0xa0, 0x8f, 0x45, 0x99, 0x86, 0xa7, 0x49, 0x18, 0x8a, 0xed, 0xf1, 0x7d,
+    0x39, 0xf4, 0xb4, 0xf9, 0x82, 0x62, 0xd0, 0xa1, 0xb8, 0x3f, 0xe8, 0x25,
+    0xf7, 0xb1, 0x59, 0xce, 0x31, 0xba, 0x1d, 0x0b, 0x1f, 0x3d, 0x6c, 0x8b,
+    0xd2, 0xc5, 0x4e, 0x8e, 0xe8, 0x09, 0x9e, 0x1f, 0xf3, 0x67, 0x6f, 0x09,
+    0x03, 0x9d, 0xfe, 0x57, 0x6d, 0x9b, 0xce, 0x99, 0x7b, 0x01, 0x04, 0x52,
+    0xf5, 0x41, 0x7e, 0x38, 0x56, 0xb8, 0x71, 0x44, 0x43, 0x2c, 0x5e, 0x92,
+    0x9d, 0x95, 0xff, 0x0b, 0xf8, 0xfa, 0x89, 0x2c, 0x58, 0xde, 0xc5, 0x4e,
+    0x02, 0xe3, 0x82, 0xf7, 0xdc, 0x92, 0xa8, 0x7c, 0x39, 0x32, 0x76, 0x68,
+    0x9c, 0x73, 0x75, 0x1f, 0xbc, 0x6b, 0x46, 0x33, 0x5a, 0xdb, 0x94, 0x8c,
+    0x76, 0x79, 0x7e, 0x9b, 0xcc, 0x37, 0xeb, 0xed, 0xdc, 0xd5, 0xee, 0x2b,
+    0x30, 0x3f, 0x7b, 0x9b, 0xac, 0x38, 0x8f, 0xf1, 0x5e, 0xec, 0xa0, 0x46,
+    0x2c, 0xd1, 0x27, 0x19, 0x60, 0xec, 0xe2, 0xa7, 0x45, 0x61, 0x2d, 0xa8,
+    0x7e, 0xa9, 0xf8, 0x93, 0xa4, 0x23, 0x3e, 0xd8, 0x9c, 0xcc, 0xb3, 0xee,
+    0xc3, 0x1c, 0xfb, 0xbb, 0xad, 0xec, 0x73, 0x66, 0x31, 0x5d, 0x88, 0x9a,
+    0xec, 0x84, 0x91, 0x1e, 0x58, 0xdd, 0xb0, 0x01, 0x46, 0x18, 0x43, 0x64,
+    0xe2, 0xad, 0xac, 0x5a, 0x63, 0x4c, 0x32, 0x6b, 0xfd, 0xff, 0x66, 0x6d,
+    0xb4, 0x66, 0x88, 0xec, 0xfe, 0x23, 0xaa, 0x3a, 0x2a, 0xd5, 0xff, 0xed,
+    0x3a, 0x13, 0x9a, 0xae, 0x73, 0xc5, 0x62, 0x32, 0x47, 0x89, 0x19, 0x7f,
+    0x2c, 0x88, 0x62, 0x34, 0xc2, 0x90, 0xa9, 0x59, 0x7c, 0x45, 0xdb, 0x98,
+    0xaf, 0xf4, 0xba, 0x4e, 0x45, 0x55, 0xfc, 0x70, 0xa9, 0xfd, 0xb4, 0xa3,
+    0xd9, 0xa8, 0xfb, 0xe2, 0xe6, 0xf9, 0x60, 0xc1, 0x42, 0x70, 0x3d, 0xa5,
+    0x28, 0xcc, 0xd3, 0x54, 0x87, 0xda, 0x93, 0x91, 0x42, 0xa8, 0x8b, 0x62,
+    0xf3, 0x4e, 0xb7, 0x86, 0xfa, 0x52, 0x19, 0x69, 0xe3, 0x6c, 0xd1, 0xc3,
+    0x23, 0x82, 0xf7, 0x1d, 0xa1, 0x80, 0x92, 0xcd, 0x5e, 0x1a, 0x62, 0x3e,
+    0x1b, 0x31, 0x9d, 0x0d, 0xa8, 0x25, 0x3e, 0x83, 0xae, 0x36, 0xce, 0xfd,
+    0xac, 0xf7, 0x35, 0x7f, 0x74, 0xf4, 0x66, 0xa3, 0x5f, 0x00, 0xe5, 0x30,
+    0xc1, 0x11, 0x70, 0x00, 0xb5, 0xd9, 0xd4, 0x6e, 0x95, 0xc4, 0xbc, 0x5b,
+    0x7d, 0x62, 0x6c, 0xd5, 0xc0, 0x1e, 0x81, 0xc0, 0x61, 0x69, 0x13, 0x63,
+    0xbc, 0x7f, 0x70, 0x3f, 0x3d, 0x96, 0x18, 0x39, 0xef, 0x51, 0xc6, 0xe9,
+    0xcc, 0x59, 0xda, 0xc7, 0x5d, 0xb5, 0x59, 0xb0, 0xf2, 0x99, 0x5a, 0x36,
+    0x21, 0x0d, 0xcc, 0x97, 0x16, 0x2b, 0x61, 0x3d, 0x0a, 0xd1, 0x6e, 0x05,
+    0x86, 0x42, 0xff, 0xd8, 0xa7, 0x5c, 0x02, 0xcf, 0x90, 0x6b, 0x4e, 0xee,
+    0x4e, 0xca, 0xdb, 0xd3, 0xfe, 0x7e, 0x9b, 0xe2, 0xf0, 0xa3, 0x45, 0x6d,
+    0xa9, 0x92, 0xba, 0xce, 0xc6, 0x2e, 0x0a, 0xbc, 0xb2, 0x7a, 0x57, 0x07,
+    0x33, 0xc2, 0xa7, 0x16, 0x25, 0x06, 0x36, 0x83, 0x35, 0x31, 0x87, 0x18,
+    0x83, 0xa3, 0xc2, 0x88, 0x55, 0xcc, 0xe4, 0x84, 0x4c, 0xce, 0xb9, 0xeb,
+    0xd5, 0xb2, 0xbe, 0x3d, 0x76, 0x85, 0x10, 0x07, 0x83, 0xfa, 0x1c, 0x42,
+    0xbc, 0xa3, 0x4c, 0x29, 0x49, 0xe6, 0xc0, 0x30, 0x59, 0xe0, 0xc6, 0xbe,
+    0xa7, 0x48, 0x4a, 0xcf, 0x0e, 0x8e, 0xb7, 0x38, 0xf2, 0xa6, 0x26, 0xd3,
+    0x88, 0x06, 0x99, 0x46, 0x19, 0x65, 0x1c, 0x91, 0x8e, 0xae, 0x90, 0x78,
+    0x77, 0x7f, 0xe0, 0xc2, 0x51, 0x6f, 0xb6, 0x44, 0x15, 0xf9, 0xc5, 0x8a,
+    0x6c, 0x33, 0xd5, 0x90, 0x17, 0xc2, 0xca, 0x4e, 0xe1, 0x1f, 0xef, 0x02,
+    0x43, 0x05, 0x3f, 0x1e, 0xb1, 0x13, 0x23, 0x1f, 0xd6, 0xc2, 0xac, 0xc4,
+    0x49, 0x7a, 0x86, 0x06, 0x4b, 0xa1, 0x55, 0x6a, 0x75, 0x91, 0x4e, 0x6b,
+    0x86, 0x95, 0xa7, 0xbc, 0xdc, 0x64, 0xdb, 0x81, 0xc6, 0xa5, 0x33, 0x38,
+    0x98, 0xbb, 0xac, 0x03, 0xf0, 0xba, 0x49, 0xcf, 0x1c, 0xce, 0xe2, 0x3d,
+    0xe5, 0x06, 0xbc, 0x5e, 0xd0, 0xf7, 0x1c, 0xbb, 0x52, 0xa1, 0x47, 0x98,
+    0x12, 0xef, 0x1c, 0xb9, 0x53, 0xec, 0x67, 0x2c, 0xf0, 0x7d, 0x85, 0x9e,
+    0x45, 0x87, 0x00, 0x67, 0x2f, 0xa5, 0x19, 0x9f, 0x3e, 0x20, 0x8c, 0xe9,
+    0xfa, 0x8a, 0xd8, 0x02, 0x6e, 0x16, 0xc4, 0x43, 0xff, 0x08, 0x3f, 0xf3,
+    0x76, 0x53, 0x95, 0x17, 0x6e, 0x74, 0xfe, 0x7e, 0x87, 0x66, 0xc9, 0xe8,
+    0x8d, 0x21, 0xea, 0xd2, 0x4d, 0xc7, 0x9c, 0x5a, 0xef, 0xd5, 0xe1, 0x12,
+    0x85, 0x22, 0x40, 0x3c, 0x9d, 0x89, 0x4f, 0x12, 0xb5, 0x01, 0x95, 0x0e,
+    0x9b, 0xd3, 0x38, 0x5e, 0x21, 0x5a, 0x4e, 0x7e, 0xce, 0xf7, 0xa6, 0x5a,
+    0x63, 0x78, 0x40, 0xba, 0x9f, 0x29, 0xf0, 0x75, 0xb6, 0x8b, 0xd9, 0x4c,
+    0xab, 0xb9, 0xf4, 0xe9, 0x1f, 0x39, 0x01, 0xb3, 0xfc, 0x2c, 0xa4, 0x74,
+    0xa9, 0xa9, 0x90, 0xed, 0x77, 0xd8, 0x0c, 0x6d, 0x5c, 0x7b, 0xfc, 0xbd,
+    0x96, 0x96, 0xcb, 0x9b, 0x9f, 0x88, 0x86, 0x5c, 0x3c, 0x0a, 0xde, 0x28,
+    0x7c, 0xf0, 0x91, 0x1c, 0x06, 0x52, 0xbe, 0xad, 0xc8, 0xef, 0xa5, 0xd3,
+    0x1e, 0x29, 0xbd, 0x1d, 0xd5, 0xba, 0xf4, 0x83, 0x2d, 0x36, 0x9a, 0x8c,
+    0x8d, 0x83, 0xac, 0x3f, 0xea, 0xd2, 0x2e, 0xfb, 0xf1, 0xaa, 0x7a, 0x2e,
+    0xce, 0xd3, 0x90, 0x9f, 0x3c, 0x2c, 0xee, 0xed, 0xf8, 0xfc, 0x3c, 0x0e,
+    0x5f, 0xd1, 0xda, 0x9c, 0x32, 0x52, 0xcd, 0x09, 0xa1, 0x53, 0x33, 0x37,
+    0xe0, 0x37, 0x95, 0xb2, 0x8d, 0x03, 0x46, 0x1f, 0xb5, 0x99, 0x65, 0x54,
+    0x61, 0xa2, 0xdc, 0xe9, 0x87, 0x4d, 0x41, 0xdf, 0xd1, 0xb5, 0x2c, 0x7a,
+    0x46, 0x08, 0x5e, 0x0f, 0xcc, 0x80, 0x96, 0x52, 0x98, 0xa0, 0x82, 0x52,
+    0x6d, 0x62, 0x6f, 0xd9, 0x48, 0xc1, 0x36, 0x0c, 0x5c, 0x7f, 0xad, 0x2c,
+    0x27, 0xcf, 0x17, 0xee, 0xfa, 0xca, 0x14, 0xe7, 0x88, 0xc4, 0x20, 0xb2,
+    0xa1, 0xd2, 0x66, 0xe8, 0x81, 0xce, 0x35, 0x2b, 0x30, 0x54, 0x16, 0x9e,
+    0x42, 0x77, 0x16, 0x3b, 0x84, 0x77, 0x42, 0x71, 0x33, 0xf8, 0x62, 0x9e,
+    0xd4, 0x1d, 0x1d, 0xf3, 0x91, 0x60, 0x97, 0xd8, 0x10, 0x29, 0xc8, 0xf9,
+    0xfa, 0xca, 0x0a, 0xe9, 0x50, 0xe1, 0xcc, 0xa7, 0xe3, 0x77, 0xc2, 0x93,
+    0x68, 0x50, 0x1a, 0x98, 0xd7, 0x68, 0x40, 0x80, 0x12, 0x64, 0xa7, 0x1d,
+    0xb4, 0x52, 0x85, 0x7b, 0x0e, 0x85, 0x0a, 0x59, 0x6a, 0xc8, 0xe4, 0x4b,
+    0xff, 0xd7, 0x0d, 0x7d, 0x9e, 0xef, 0x07, 0x2f, 0x6d, 0x46, 0x05, 0xf9,
+    0x05, 0xb1, 0x97, 0x94, 0x23, 0xc5, 0x2a, 0x99, 0xcc, 0x9c, 0xc2, 0x82,
+    0x97, 0xbc, 0x24, 0x9b, 0xe4, 0xf2, 0xb3, 0x12, 0x84, 0xa0, 0x2a, 0xc4,
+    0x7d, 0x29, 0x4d, 0xa4, 0x97, 0xd0, 0x85, 0xa6, 0x39, 0x18, 0xd2, 0xfb,
+    0xa7, 0x08, 0x53, 0x75, 0x6b, 0xbd, 0xe3, 0x98, 0x4c, 0x94, 0xdd, 0xd4,
+    0x86, 0x94, 0xc2, 0x6a, 0x14, 0x23, 0xdd, 0x69, 0xae, 0x53, 0xec, 0x83,
+    0x58, 0x8e, 0x87, 0x7b, 0xf1, 0xcf, 0xff, 0x34, 0xda, 0x39, 0x67, 0xba,
+    0x90, 0xc5, 0xec, 0xe0, 0xb3, 0xad, 0xad, 0x3d, 0x4c, 0x8e, 0x3f, 0x08,
+    0x62, 0x80, 0x5b, 0x2d, 0xf8, 0xe1, 0x67, 0x61, 0x79, 0xf5, 0xc9, 0xbe,
+    0x74, 0x1b, 0x72, 0x02, 0x56, 0xc6, 0xf8, 0xd5, 0x87, 0x3a, 0x08, 0x7b,
+    0x35, 0x8f, 0xdf, 0xdf, 0x87, 0x3e, 0x09, 0xf7, 0xd2, 0x74, 0xbb, 0xec,
+    0x8c, 0x49, 0x0c, 0xb5, 0x3a, 0x6b, 0x33, 0x43, 0x52, 0xe2, 0x2f, 0x71,
+    0x3e, 0x6f, 0x59, 0x52, 0x50, 0x8f, 0xdb, 0xa6, 0x52, 0xa7, 0x5d, 0xda,
+    0x16, 0x71, 0xb2, 0x52, 0xd7, 0x3e, 0x2d, 0xf6, 0x98, 0x53, 0x0f, 0x8f,
+    0xc1, 0x79, 0xd0, 0xcf, 0xe0, 0xc8, 0x22, 0x27, 0x41, 0x14, 0xe8, 0xb8,
+    0xed, 0x65, 0x3c, 0xaa, 0x11, 0x72, 0x41, 0xa8, 0xd8, 0x0b, 0x35, 0x81,
+    0xec, 0xa6, 0x12, 0x30, 0x23, 0x0b, 0x71, 0x7a, 0x28, 0xd9, 0x01, 0x82,
+    0x35, 0xd1, 0x64, 0x6d, 0xf3, 0x63, 0x69, 0x78, 0xb4, 0x93, 0x1e, 0x05,
+    0xc9, 0xb3, 0xbc, 0xb6, 0xc4, 0x5e, 0xb6, 0x2a, 0x6e, 0xec, 0x91, 0x4a,
+    0x5c, 0xa2, 0x5c, 0xea, 0x2b, 0xe3, 0x33, 0x1a, 0xb3, 0x70, 0xd5, 0x39,
+    0x77, 0x3e, 0xa2, 0x96, 0xd5, 0x10, 0x75, 0x8a, 0x91, 0xc6, 0xbc, 0xb6,
+    0x86, 0xa6, 0x8f, 0xd3, 0x50, 0x09, 0xa3, 0x9a, 0x1f, 0xd0, 0xd7, 0xd7,
+    0x23, 0xa0, 0x32, 0xd0, 0x69, 0x33, 0x2f, 0x18, 0xf2, 0x6f, 0xe2, 0xbc,
+    0x2f, 0x7f, 0xf5, 0x46, 0x81, 0x2e, 0xad, 0x14, 0xc9, 0x57, 0x10, 0xa4,
+    0x71, 0xa9, 0xa4, 0x05, 0x50, 0xcb, 0x93, 0xc7, 0x53, 0x84, 0x68, 0xa5,
+    0x7c, 0x65, 0xc0, 0xe0, 0x37, 0xd6, 0xc3, 0xbb, 0x36, 0xef, 0x22, 0x9e,
+    0x09, 0x32, 0xa5, 0xa6, 0x73, 0x61, 0xb6, 0x3c, 0x5a, 0xbe, 0x2f, 0x63,
+    0x01, 0x35, 0xfe, 0xd8, 0x98, 0xd5, 0x7e, 0xfd, 0x68, 0xd8, 0x96, 0x51,
+    0x6e, 0x3a, 0x17, 0x90, 0x16, 0xeb, 0x03, 0xfa, 0x0a, 0x83, 0x1a, 0xc9,
+    0x48, 0x14, 0x31, 0x32, 0x07, 0x7d, 0xa8, 0xa8, 0x64, 0xd8, 0xba, 0xcf,
+    0x87, 0xc5, 0x0e, 0xc3, 0x1c, 0x5b, 0xfe, 0x31, 0x98, 0xea, 0x25, 0x29,
+    0x9c, 0x77, 0xf2, 0x9f, 0x5e, 0x16, 0x11, 0x6b, 0x29, 0x08, 0xab, 0xb0,
+    0x57, 0xd8, 0x3d, 0x85, 0xdc, 0x3b, 0x69, 0xea, 0xd5, 0xe6, 0x90, 0xfa,
+    0x95, 0x8d, 0xcc, 0x3c, 0x2d, 0x86, 0x07, 0xc6, 0x7e, 0x8d, 0xc4, 0x7a,
+    0x3a, 0xcd, 0x61, 0xa4, 0x1f, 0xd9, 0x6f, 0x07, 0xa3, 0x45, 0xe8, 0x41,
+    0xed, 0x51, 0x14, 0xe4, 0x3d, 0x20, 0x3b, 0x11, 0x9e, 0x93, 0xc3, 0x2e,
+    0xcd, 0x29, 0x85, 0xf0, 0x61, 0x68, 0x8e, 0x19, 0xdc, 0x20, 0x0a, 0xbd,
+    0xc0, 0x15, 0x90, 0x08, 0x96, 0xcf, 0x9b, 0xf3, 0xb5, 0x7b, 0xe4, 0x9a,
+    0x97, 0x22, 0x93, 0x40, 0xd4, 0xde, 0x7a, 0x6e, 0x6b, 0xc4, 0x16, 0x9e,
+    0x1c, 0x98, 0x9b, 0x83, 0x6e, 0x4d, 0xde, 0x11, 0x4f, 0x22, 0xed, 0x2d,
+    0xe1, 0xb3, 0xfa, 0x86, 0xb0, 0xd2, 0x53, 0xd2, 0x34, 0x8a, 0x58, 0xdc,
+    0x8c, 0xd9, 0x60, 0xd3, 0x46, 0x0a, 0xde, 0x48, 0xa3, 0xda, 0x5b, 0x74,
+    0x3e, 0x4c, 0x51, 0xa6, 0x02, 0x20, 0xc6, 0x0d, 0xdb, 0x13, 0x42, 0xad,
+    0xc6, 0x90, 0xb1, 0xe0, 0xb0, 0xac, 0xdc, 0xa7, 0x48, 0xf8, 0x2d, 0x8f,
+    0xd7, 0xd9, 0x10, 0xeb, 0xd8, 0xdb, 0xf0, 0x53, 0x67, 0xa9, 0x03, 0x3e,
+    0x97, 0xbf, 0xe6, 0xc3, 0xa8, 0x87, 0x3a, 0x91, 0xb8, 0xcf, 0x88, 0x5b,
+    0x0d, 0x06, 0xe1, 0xe2, 0x39, 0x74, 0xc8, 0x59, 0xe0, 0x90, 0x9f, 0xc9,
+    0x0a, 0x74, 0xa3, 0xb2, 0xae, 0x69, 0x79, 0xfa, 0x0d, 0xf2, 0xee, 0xde,
+    0xec, 0x88, 0xbf, 0x09, 0x54, 0xd6, 0xbe, 0xbb, 0x25, 0x91, 0xe4, 0x66,
+    0xd2, 0x08, 0x78, 0xda, 0x9d, 0x07, 0xc3, 0x0b, 0x3f, 0x1a, 0xd9, 0xf4,
+    0xb2, 0x2d, 0x69, 0x74, 0xb1, 0x78, 0x5f, 0xc1, 0xaf, 0x7f, 0x6d, 0x17,
+    0xfc, 0x2c, 0x67, 0x62, 0xce, 0xb4, 0x41, 0x6e, 0x21, 0x4b, 0x5c, 0x77,
+    0xa1, 0x1f, 0xfe, 0xe6, 0x28, 0xc8, 0x52, 0xd1, 0x8e, 0x66, 0x88, 0x65,
+    0x0c, 0x58, 0xec, 0x1c, 0x71, 0x4c, 0x8a, 0xc0, 0xef, 0x3e, 0x34, 0xf7,
+    0x90, 0x67, 0x28, 0x16, 0x20, 0x3a, 0x2c, 0x3f, 0x51, 0x53, 0x15, 0x1c,
+    0x6c, 0x75, 0x0e, 0xe1, 0xb4, 0xf3, 0x7f, 0x60, 0x3a, 0x81, 0x34, 0x82,
+    0x51, 0x5e, 0x75, 0xb0, 0x5c, 0x37, 0x87, 0x2d, 0xd5, 0xc5, 0x2c, 0xab,
+    0x33, 0x8a, 0x60, 0x49, 0x2c, 0xde, 0x90, 0x12, 0x11, 0x1f, 0x4b, 0x27,
+    0x15, 0x92, 0xa2, 0xf1, 0x1a, 0xde, 0x35, 0x34, 0x4d, 0x52, 0xcd, 0xc0,
+    0x71, 0x46, 0x7f, 0x3e, 0x21, 0x92, 0x5f, 0xc8, 0x25, 0xd4, 0x2c, 0xf4,
+    0xd9, 0x38, 0xde, 0xa5, 0xae, 0x83, 0xe3, 0x50, 0x9b, 0x1b, 0xad, 0x4b,
+    0xd8, 0x3f, 0x0a, 0x23, 0x40, 0x1e, 0x46, 0x7a, 0x71, 0x06, 0xac, 0x9e,
+    0x06, 0xb8, 0x96, 0xef, 0x07, 0xef, 0x38, 0xe9, 0x79, 0xaa, 0x64, 0x44,
+    0xa9, 0xa3, 0xc5, 0x1d, 0x5d, 0xd3, 0xa7, 0x01, 0xef, 0xf6, 0x3b, 0x15,
+    0x00, 0x0c, 0xf7, 0x59, 0x4a, 0x1c, 0x12, 0x20, 0x89, 0xa8, 0x4e, 0x7b,
+    0xf8, 0x9d, 0x02, 0xa6, 0x5e, 0x19, 0x7e, 0xb8, 0x5f, 0x46, 0xd9, 0xb1,
+    0xbe, 0x25, 0x2c, 0x3c, 0xe7, 0x5d, 0x3b, 0x3f, 0x6f, 0x6e, 0x94, 0x83,
+    0xc3, 0x8e, 0x85, 0x65, 0xff, 0xe9, 0x8e, 0x32, 0xcc, 0x68, 0x51, 0x14,
+    0xbf, 0x94, 0x21, 0x3f, 0x85, 0xa8, 0x76, 0x44, 0xe6, 0xca, 0x20, 0x84,
+    0xec, 0x83, 0x84, 0x64, 0xfb, 0x80, 0x01, 0x73, 0x76, 0x21, 0xd3, 0xf0,
+    0x7b, 0x74, 0x5c, 0xbf, 0x71, 0xe6, 0x34, 0xff, 0x58, 0xe8, 0x6f, 0x88,
+    0xa6, 0xad, 0xcf, 0x93, 0x2a, 0xc5, 0xc5, 0x23, 0x32, 0xc8, 0xec, 0xbd,
+    0xf9, 0x54, 0x3d, 0xda, 0xe4, 0x81, 0x74, 0x94, 0xbf, 0x36, 0x72, 0x11,
+    0xf0, 0x8a, 0x8f, 0x1b, 0x55, 0x47, 0x70, 0x7d, 0x61, 0xf0, 0x7b, 0x11,
+    0x56, 0xdb, 0xbc, 0xe5, 0x72, 0xf2, 0xbd, 0x0b, 0xa0, 0x80, 0x03, 0x1a,
+    0xc6, 0xe9, 0xfc, 0xcd, 0xde, 0x42, 0xae, 0x1a, 0x7d, 0x90, 0x5d, 0x21,
+    0x5b, 0x3d, 0x69, 0x6f, 0x42, 0x42, 0xf2, 0x8a, 0xc8, 0xfc, 0xb9, 0xa9,
+    0xdf, 0x18, 0xc4, 0x97, 0x91, 0x21, 0x28, 0xfd, 0x82, 0x8a, 0xe7, 0xac,
+    0xe5, 0x5d, 0x33, 0x7b, 0x78, 0x0a, 0x48, 0x43, 0xfe, 0xfe, 0xcf, 0x09,
+    0x5f, 0xed, 0x18, 0x33, 0x0c, 0xab, 0x8a, 0x5d, 0x63, 0xd5, 0x43, 0x0b,
+    0xde, 0x75, 0x56, 0xef, 0x11, 0x05, 0x8c, 0xbb, 0xc0, 0x10, 0x4e, 0x85,
+    0x70, 0xe1, 0x7e, 0x62, 0xb6, 0x3a, 0x84, 0x80, 0x17, 0xab, 0x38, 0x59,
+    0x0b, 0xe2, 0xb1, 0x31, 0xb8, 0xb5, 0xf5, 0xad, 0xf6, 0xbf, 0x5b, 0xfb,
+    0x69, 0xc8, 0xb3, 0xce, 0x65, 0xd4, 0x8e, 0x04, 0xc5, 0xc4, 0x09, 0xba,
+    0x36, 0xc9, 0x90, 0xe0, 0xc2, 0x21, 0x3a, 0x94, 0x83, 0xa5, 0xd1, 0xb2,
+    0xe1, 0xae, 0x6a, 0x28, 0x22, 0x59, 0x79, 0x72, 0x82, 0x42, 0x89, 0x42,
+    0x9c, 0xc3, 0xdf, 0x8d, 0x15, 0x22, 0x14, 0xb3, 0xfd, 0x2a, 0x85, 0xbe,
+    0xd3, 0x12, 0xa5, 0x3b, 0x0c, 0x99, 0xb2, 0xe5, 0x43, 0x8d, 0xd7, 0xc0,
+    0xa1, 0xb6, 0xb2, 0xae, 0x42, 0x4a, 0xc0, 0xe5, 0x09, 0xa2, 0xf6, 0xa4,
+    0xbc, 0x01, 0xee, 0x94, 0xd2, 0x0b, 0xeb, 0x28, 0x80, 0xc9, 0x7a, 0x07,
+    0xd7, 0x4b, 0xee, 0x01, 0x10, 0x48, 0xcc, 0xc6, 0x03, 0x99, 0x9d, 0x67,
+    0x2a, 0xbd, 0xa0, 0x6f, 0x51, 0xa4, 0x75, 0x50, 0xe1, 0x84, 0x8e, 0xda,
+    0x7b, 0x5e, 0x9e, 0x78, 0x18, 0x2a, 0x6b, 0xfa, 0xef, 0x87, 0x81, 0xe9,
+    0x48, 0x3f, 0x29, 0x2d, 0xfb, 0x15, 0xd2, 0x15, 0xb5, 0x5c, 0xed, 0x45,
+    0x48, 0x30, 0xec, 0x00, 0x55, 0x15, 0x13, 0xc7, 0x11, 0xc4, 0x29, 0xef,
+    0x0f, 0xa8, 0xa6, 0xef, 0x19, 0x41, 0xc2, 0xb6, 0x11, 0xdc, 0xe8, 0xf4,
+    0xa7, 0x03, 0x80, 0x2d, 0x92, 0xad, 0x7e, 0x7e, 0x8a, 0x71, 0xa4, 0x6c,
+    0x16, 0xb9, 0x84, 0xf5, 0x8d, 0x94, 0xc5, 0xd5, 0x82, 0x29, 0x42, 0x22,
+    0x1f, 0x06, 0xca, 0xdd, 0xbf, 0x74, 0x0f, 0x14, 0x79, 0x26, 0x9c, 0x79,
+    0x30, 0xcb, 0x01, 0x02, 0x76, 0x22, 0x4f, 0x54, 0xff, 0x49, 0xa3, 0x03,
+    0x35, 0x23, 0x45, 0x91, 0xac, 0xed, 0x13, 0x31, 0xa4, 0x4e, 0x51, 0xe8,
+    0x9c, 0x5b, 0xe4, 0xcf, 0x41, 0xd3, 0xa0, 0x86, 0x7f, 0x3a, 0x4d, 0xaf,
+    0xa7, 0x49, 0x63, 0x47, 0x86, 0x08, 0x88, 0xcf, 0x01, 0x7a, 0xc4, 0xf5,
+    0x29, 0x67, 0x8a, 0xd4, 0xdd, 0x6a, 0x6d, 0x81, 0xb8, 0x29, 0x9d, 0x7c,
+    0x32, 0x4e, 0x8f, 0x0c, 0x9f, 0x8c, 0x7e, 0x76, 0xa3, 0xd4, 0x32, 0x80,
+    0xd0, 0x79, 0x7d, 0x56, 0x99, 0x6d, 0x0b, 0x88, 0xfc, 0x98, 0xdb, 0xaf,
+    0x13, 0xf3, 0xb2, 0x20, 0x3f, 0x19, 0xe1, 0x83, 0x70, 0xd2, 0x26, 0xd0,
+    0xd2, 0xad, 0x11, 0xeb, 0x3b, 0x31, 0x03, 0x55, 0x62, 0xca, 0xb5, 0x87,
+    0x31, 0x7a, 0x11, 0x4c, 0xf2, 0xc3, 0xc2, 0x1c, 0x42, 0x94, 0x7b, 0xe6,
+    0x29, 0x86, 0x70, 0x8e, 0x51, 0x4a, 0xa3, 0xf2, 0xf0, 0xed, 0xa1, 0xc6,
+    0x18, 0xff, 0xf2, 0xff, 0xe0, 0x07, 0x85, 0xf1, 0x93, 0x5a, 0x83, 0x1c,
+    0x4c, 0xa9, 0x9b, 0xc5, 0x0c, 0xc4, 0xf0, 0xde, 0x71, 0x93, 0x78, 0xd1,
+    0x3b, 0xcc, 0x5b, 0x51, 0x1f, 0xd7, 0x21, 0x12, 0x57, 0xd5, 0x2a, 0xea,
+    0x64, 0x08, 0x0e, 0xf0, 0x3d, 0x42, 0xe7, 0xdf, 0xc8, 0xea, 0x42, 0x2b,
+    0x41, 0x55, 0x85, 0xb8, 0x54, 0xa4, 0xc9, 0x3f, 0xce, 0xfc, 0x1a, 0xde,
+    0x73, 0x08, 0xaa, 0x09, 0x25, 0x08, 0xa0, 0xdc, 0x64, 0xb7, 0xe7, 0xcc,
+    0xde, 0x85, 0xa6, 0xc3, 0xe9, 0xe1, 0x43, 0x71, 0x86, 0x05, 0x55, 0x86,
+    0x47, 0xf8, 0x71, 0xbd, 0xf5, 0xd7, 0x38, 0x64, 0x7f, 0x71, 0x63, 0xe1,
+    0x22, 0x39, 0x99, 0xc3, 0xdf, 0x27, 0x5d, 0xdd, 0xd0, 0x57, 0x99, 0xd5,
+    0x97, 0xcd, 0xd4, 0x2e, 0xc1, 0x25, 0x3d, 0x2e, 0x03, 0x0b, 0x04, 0x20,
+    0x70, 0xec, 0x46, 0x6c, 0x4b, 0x55, 0x16, 0x02, 0x00, 0x71, 0xfd, 0x8a,
+    0xa0, 0x1e, 0x5f, 0x41, 0xe6, 0x96, 0x58, 0xbe, 0x02, 0x73, 0x91, 0x71,
+    0xb2, 0x7e, 0xc4, 0xcd, 0xce, 0xa5, 0x26, 0xee, 0xff, 0x8c, 0x9a, 0x4c,
+    0xf4, 0x0a, 0x89, 0xba, 0x14, 0x6e, 0x06, 0x86, 0xb0, 0xba, 0x41, 0xdd,
+    0x27, 0xf8, 0xc3, 0x46, 0x4f, 0x39, 0xac, 0x2c, 0x8a, 0x69, 0x09, 0xb7,
+    0x36, 0x0f, 0xe0, 0x8d, 0x31, 0x0f, 0xc3, 0xee, 0x3a, 0x6a, 0x9e, 0x96,
+    0x91, 0xf5, 0x6a, 0x12, 0x98, 0x5a, 0xc3, 0xf3, 0xb8, 0x9b, 0x07, 0xdb,
+    0x8e, 0x2a, 0xb0, 0x91, 0x86, 0xb5, 0xc7, 0xe9, 0x06, 0xe1, 0x4e, 0x83,
+    0x28, 0x3a, 0x0e, 0x67, 0xe5, 0x7e, 0x88, 0x2a, 0x31, 0xd2, 0xfe, 0xf6,
+    0x19, 0x3d, 0x09, 0xd1, 0xef, 0x5d, 0xe1, 0x15, 0x2d, 0xb4, 0xec, 0x23,
+    0xc2, 0x0c, 0x7a, 0xbf, 0xd3, 0x6f, 0xf7, 0x8a, 0x3b, 0x3a, 0x0f, 0x20,
+    0xc4, 0x78, 0xbe, 0x46, 0x30, 0x0f, 0xc2, 0xd0, 0x8c, 0x23, 0xb7, 0xfa,
+    0x3c, 0x19, 0x35, 0x53, 0x5f, 0xf9, 0x94, 0xf5, 0x23, 0xbe, 0xb3, 0x56,
+    0x42, 0xa1, 0x27, 0xff, 0xac, 0xbf, 0x72, 0x7e, 0x89, 0xbe, 0xb9, 0x6d,
+    0x2d, 0xc4, 0x3f, 0x6c, 0x7f, 0xc4, 0x7e, 0x01, 0x09, 0xc8, 0x35, 0x80,
+    0x99, 0x8f, 0x1c, 0x43, 0xd3, 0xb2, 0x4a, 0xb7, 0x08, 0x06, 0x63, 0xcd,
+    0x8a, 0x5e, 0x64, 0xa2, 0x93, 0xa5, 0x15, 0xa0, 0x38, 0xa0, 0xf2, 0x1c,
+    0xab, 0xe1, 0x2d, 0x19, 0x30, 0xee, 0x9b, 0x87, 0x42, 0x54, 0xfb, 0xcc,
+    0xfe, 0x2a, 0xcd, 0x54, 0xf5, 0xeb, 0x52, 0x6b, 0xd4, 0x1d, 0xa3, 0x7c,
+    0xec, 0xf2, 0x56, 0x51, 0x54, 0xab, 0x66, 0xb0, 0x73, 0x49, 0x3e, 0xc4,
+    0x89, 0xac, 0xb0, 0xc1, 0x41, 0x6f, 0x19, 0xd6, 0x41, 0xbd, 0xc2, 0xe2,
+    0x1a, 0x56, 0xb3, 0x01, 0xc9, 0xdf, 0x46, 0xe7, 0xa1, 0x42, 0xfa, 0x1c,
+    0x18, 0x86, 0xe2, 0x07, 0xe4, 0xfe, 0x19, 0x03, 0x7d, 0xc4, 0x51, 0x78,
+    0x29, 0x68, 0x73, 0x70, 0x82, 0x98, 0x34, 0x2e, 0x41, 0x59, 0xd5, 0x20,
+    0x36, 0xe3, 0xe5, 0x2c, 0xbe, 0x76, 0x23, 0x5d, 0xb1, 0xf0, 0xda, 0xee,
+    0x65, 0x54, 0xd9, 0xa1, 0x77, 0x6e, 0xd8, 0x56, 0xcb, 0x6a, 0x35, 0xb5,
+    0xaa, 0x97, 0x22, 0x28, 0x4d, 0x74, 0x13, 0x96, 0x59, 0x3d, 0x3a, 0xe2,
+    0x26, 0xde, 0xd3, 0xc7, 0xed, 0x97, 0x98, 0xa8, 0x4a, 0x6b, 0x4b, 0xd1,
+    0x52, 0xca, 0x84, 0xd6, 0x19, 0x7a, 0x6c, 0x0d, 0xb4, 0x28, 0x4f, 0xb1,
+    0xa2, 0xcc, 0x07, 0x08, 0x57, 0xc9, 0x32, 0xd4, 0xe0, 0xef, 0x96, 0x9a,
+    0x31, 0x1e, 0x68, 0x1d, 0x7b, 0x57, 0x26, 0x62, 0xa4, 0x26, 0xaf, 0xc7,
+    0xd0, 0xab, 0xb6, 0x9e, 0x00, 0x6d, 0xfe, 0x29, 0x30, 0x53, 0xcd, 0xb8,
+    0x4e, 0x30, 0x4e, 0xa5, 0xcc, 0xf6, 0xab, 0xca, 0x4d, 0x74, 0x40, 0xc2,
+    0xb4, 0xfb, 0x3f, 0x75, 0x0a, 0x9d, 0x88, 0xa3, 0xb0, 0x5b, 0x4e, 0x88,
+    0x50, 0x90, 0xcb, 0x5c, 0xcd, 0xc7, 0xff, 0x75, 0x97, 0xc4, 0x1b, 0xe9,
+    0x03, 0x8a, 0xa7, 0x62, 0x32, 0x98, 0x60, 0x39, 0x56, 0xe5, 0x25, 0xed,
+    0xba, 0x58, 0x67, 0xa3, 0xe8, 0x23, 0xd1, 0x55, 0xb3, 0xa5, 0xc0, 0xc9,
+    0x75, 0x14, 0x91, 0xe6, 0x7d, 0x0e, 0xe3, 0xac, 0xc8, 0x6b, 0xa7, 0xdb,
+    0x36, 0xe8, 0x44, 0x92, 0x72, 0xf2, 0x6d, 0x10, 0xeb, 0xd0, 0x7a, 0xdd,
+    0x00, 0x9b, 0xf8, 0x65, 0xaa, 0xef, 0xed, 0xfb, 0x84, 0x5f, 0xfb, 0xd8,
+    0xe9, 0xa8, 0x71, 0xab, 0x20, 0x98, 0x4f, 0x21, 0x7d, 0x33, 0xe2, 0xb1,
+    0x3f, 0x95, 0x9c, 0x28, 0xf5, 0xd5, 0x83, 0x01, 0xe9, 0x71, 0x68, 0xa9,
+    0x3d, 0x9e, 0x49, 0xfb, 0x6c, 0x83, 0x5f, 0x48, 0x9d, 0x91, 0x00, 0xab,
+    0x54, 0x17, 0x11, 0x5b, 0x9d, 0x0a, 0x17, 0x8e, 0x3a, 0xbc, 0xd5, 0x33,
+    0xcd, 0x2a, 0x5b, 0x14, 0x39, 0xe4, 0x30, 0x45, 0xde, 0x6e, 0xde, 0x92,
+    0x7f, 0xb5, 0x91, 0x5d, 0x5b, 0xe4, 0x18, 0x17, 0x7c, 0x22, 0x1e, 0x2d,
+    0x97, 0x8b, 0x6f, 0xe0, 0x54, 0x2e, 0x25, 0xbc, 0x5f, 0xef, 0x27, 0x1b,
+    0x95, 0x71, 0xcc, 0x29, 0x96, 0x30, 0x82, 0xb1, 0x99, 0x98, 0x28, 0x36,
+    0x5f, 0xd6, 0xf9, 0x13, 0xb3, 0x3d, 0x14, 0x91, 0x8a, 0x2f, 0xbf, 0x6e,
+    0x8c, 0x57, 0xf6, 0x8e, 0x32, 0xf2, 0xd3, 0xa5, 0x1b, 0x2b, 0xba, 0xc8,
+    0x0d, 0xa4, 0xd3, 0xc2, 0x16, 0x1f, 0x5f, 0xb6, 0x89, 0x77, 0xa9, 0xf3,
+    0x7b, 0xb8, 0x11, 0x23, 0x41, 0xd6, 0xe0, 0x47, 0x3c, 0x94, 0xe0, 0xed,
+    0xa9, 0xb1, 0x0e, 0x90, 0x38, 0xdd, 0x60, 0xcd, 0x75, 0x00, 0x36, 0x3a,
+    0x42, 0xbb, 0xfd, 0xd7, 0xc6, 0x16, 0x38, 0xb4, 0xc0, 0x1d, 0xb6, 0x46,
+    0x5c, 0x2f, 0x70, 0x95, 0x8d, 0x74, 0x68, 0xb2, 0xb5, 0xae, 0x73, 0x22,
+    0xa1, 0xca, 0x5d, 0xd4, 0x28, 0x1a, 0xd2, 0x19, 0x1c, 0x43, 0x5e, 0x12,
+    0x16, 0x15, 0xb4, 0x97, 0x64, 0x10, 0x07, 0x48, 0xf8, 0xe3, 0xfb, 0x3e,
+    0xa5, 0x05, 0xcd, 0xc1, 0x29, 0xf0, 0x67, 0xb7, 0x24, 0x02, 0xac, 0x76,
+    0x91, 0x64, 0x63, 0x46, 0xfb, 0xfd, 0xaa, 0x5b, 0x3f, 0xeb, 0xe0, 0xb2,
+    0x5a, 0x8d, 0xde, 0xdc, 0x92, 0x0c, 0x1e, 0xfc, 0x82, 0x55, 0xc7, 0x8a,
+    0xe3, 0x28, 0x57, 0xfe, 0x10, 0xe1, 0xa3, 0x5a, 0x9e, 0x67, 0x86, 0xf4,
+    0xa5, 0xf5, 0xa0, 0xbd, 0xa4, 0x3c, 0xda, 0xf3, 0x83, 0x27, 0x2f, 0x55,
+    0x73, 0xb6, 0x74, 0x3e, 0xd3, 0xc9, 0x84, 0x1d, 0xff, 0x61, 0x01, 0x56,
+    0x30, 0x2a, 0x23, 0x57, 0xbc, 0x88, 0xa7, 0x2f, 0x6f, 0x95, 0x91, 0x4e,
+    0x5b, 0x41, 0xd9, 0x95, 0x1f, 0x09, 0x95, 0x79, 0x36, 0xe3, 0x7f, 0xbd,
+    0x4b, 0x09, 0x4e, 0x7f, 0x6a, 0x58, 0x6e, 0xd0, 0x60, 0xaf, 0xf1, 0x8f,
+    0x4c, 0xc5, 0x5a, 0x5c, 0xb7, 0x74, 0x83, 0x3c, 0xb3, 0x7e, 0xdc, 0x76,
+    0x89, 0xa5, 0xca, 0xd7, 0x75, 0x35, 0xb2, 0x4c, 0x0a, 0x67, 0x2b, 0x7a,
+    0xe8, 0xac, 0x9e, 0x26, 0xa3, 0xae, 0x87, 0x66, 0x12, 0x4e, 0x74, 0xc8,
+    0xd8, 0x6d, 0x89, 0x9c, 0x34, 0x63, 0x61, 0x33, 0x1b, 0x6a, 0x78, 0x7f,
+    0x2f, 0xa7, 0x9b, 0xe7, 0x42, 0x0d, 0xcb, 0xc9, 0xf0, 0xa6, 0xb5, 0x38,
+    0x66, 0x80, 0xca, 0x7a, 0xa9, 0xe4, 0x93, 0xe3, 0xfc, 0x7d, 0x38, 0x7d,
+    0x7a, 0x2c, 0x03, 0xb4, 0x35, 0xde, 0x1b, 0x2e, 0x29, 0x24, 0x40, 0x93,
+    0x6c, 0x52, 0x21, 0xd6, 0x70, 0x88, 0xfd, 0xc7, 0x5c, 0x94, 0x95, 0xc0,
+    0x03, 0xce, 0x1b, 0xb3, 0x0e, 0x87, 0xac, 0xa0, 0x88, 0xcd, 0x20, 0x3d,
+    0x88, 0x6f, 0xac, 0x29, 0x2e, 0xcc, 0x7d, 0xa7, 0x09, 0x16, 0xc0, 0xcc,
+    0x55, 0x43, 0x19, 0xdc, 0x5e, 0xc4, 0xe5, 0x7c, 0xfb, 0x50, 0x01, 0x41,
+    0xe1, 0x70, 0x84, 0x3e, 0x60, 0x88, 0x05, 0x27, 0x4b, 0x6c, 0x59, 0x9a,
+    0x01, 0x50, 0xec, 0x74, 0x6a, 0x98, 0x57, 0xfe, 0xf5, 0x63, 0xc3, 0x60,
+    0x55, 0x23, 0x33, 0xf9, 0x2d, 0xf0, 0x68, 0xff, 0xad, 0x61, 0xdb, 0x5e,
+    0xdb, 0x0c, 0x54, 0x68, 0x8c, 0x4b, 0x64, 0x94, 0x3c, 0xa8, 0xb1, 0x31,
+    0x61, 0xf3, 0xb3, 0xed, 0x8f, 0xd5, 0x07, 0x27, 0xbf, 0xa3, 0xa2, 0x42,
+    0x4a, 0xa1, 0x5e, 0xc9, 0xb3, 0x9a, 0x0f, 0xbb, 0xf7, 0xc7, 0x4d, 0x0b,
+    0xee, 0xbd, 0xce, 0x9e, 0x8c, 0x14, 0x7e, 0x06, 0x6e, 0x6d, 0x9b, 0xdd,
+    0x22, 0xc6, 0xc2, 0x62, 0xa5, 0x45, 0xc1, 0xe1, 0x97, 0xe2, 0x50, 0x25,
+    0xcc, 0x9b, 0xc4, 0x5d, 0x2d, 0x45, 0x10, 0xad, 0xa8, 0x4f, 0x27, 0xc3,
+    0x1a, 0x2c, 0xef, 0x38, 0x2d, 0xa7, 0xaf, 0xe5, 0x23, 0x7a, 0x8f, 0xbf,
+    0x9c, 0xd0, 0xb6, 0x31, 0x5c, 0xaa, 0xd2, 0x8c, 0xd8, 0x91, 0x00, 0xa1,
+    0x8b, 0x4d, 0x3e, 0x27, 0x22, 0x6c, 0x0f, 0x64, 0x95, 0x89, 0xa6, 0x29,
+    0x90, 0xf9, 0xa9, 0x24, 0x24, 0xb8, 0x71, 0x56, 0x7a, 0xc5, 0xa9, 0x26,
+    0x9f, 0xf6, 0x2a, 0xa6, 0xf1, 0xca, 0x2a, 0x17, 0x14, 0x8c, 0x8d, 0xf2,
+    0x44, 0x7d, 0x49, 0x4e, 0x9b, 0x4f, 0xef, 0x72, 0x7e, 0xe8, 0x0f, 0x45,
+    0xb3, 0x3d, 0x61, 0xf5, 0x9d, 0x3f, 0x9a, 0xe3, 0x93, 0xdd, 0x3d, 0x02,
+    0x84, 0x7d, 0xd4, 0x84, 0xa8, 0x23, 0xe9, 0x43, 0xb6, 0x66, 0xf2, 0xb7,
+    0x35, 0xcf, 0xa3, 0x2f, 0xbe, 0x48, 0x0e, 0xaa, 0xfe, 0xe9, 0x7e, 0xb0,
+    0x4d, 0xb3, 0x6b, 0x69, 0xdc, 0xef, 0x20, 0xec, 0xce, 0x6c, 0xad, 0x7a,
+    0x20, 0x35, 0xf2, 0xfd, 0x09, 0xe1, 0xdb, 0xca, 0x2a, 0x55, 0xf7, 0x60,
+    0xca, 0xf3, 0x85, 0x12, 0xe6, 0x05, 0x4f, 0xc8, 0x6e, 0x76, 0xda, 0x5f,
+    0x45, 0x1e, 0xed, 0xdf, 0x57, 0x4c, 0xeb, 0x7e, 0x28, 0xf7, 0x39, 0xc4,
+    0xd0, 0x10, 0x32, 0xa9, 0xcc, 0x25, 0xd9, 0x0b, 0x8c, 0x8a, 0xf6, 0x6c,
+    0x84, 0xde, 0x09, 0x8c, 0xf6, 0xa4, 0x95, 0xb3, 0x65, 0x5e, 0x49, 0x36,
+    0x8c, 0x51, 0x85, 0x62, 0xcc, 0xe6, 0x2a, 0x3d, 0xdc, 0x68, 0x08, 0x41,
+    0x73, 0x18, 0x74, 0x10, 0xe5, 0x18, 0xfa, 0xbe, 0x2f, 0xaa, 0x98, 0x3c,
+    0x7c, 0x44, 0x43, 0x3f, 0xd6, 0x27, 0xd3, 0x28, 0xf0, 0x2b, 0xeb, 0xf2,
+    0x46, 0xfc, 0xf6, 0x3f, 0xc7, 0xa8, 0xc0, 0xf0, 0x17, 0xef, 0x35, 0xde,
+    0x55, 0x30, 0xef, 0xf7, 0x7b, 0x57, 0xf3, 0x9f, 0x00, 0xb5, 0x49, 0x1e,
+    0xc4, 0x6a, 0xea, 0x0e, 0x40, 0x95, 0x47, 0x55, 0x32, 0x4f, 0x4f, 0x24,
+    0x5a, 0x10, 0xaa, 0x1f, 0x5b, 0x9b, 0xc1, 0xb3, 0xaa, 0xa3, 0x40, 0x32,
+    0x56, 0x80, 0xbf, 0x38, 0xbc, 0x89, 0xad, 0xa8, 0x0e, 0x8f, 0x8e, 0x14,
+    0x17, 0x5a, 0x9b, 0x25, 0x85, 0x85, 0xa7, 0x43, 0xc8, 0x19, 0x21, 0xf9,
+    0xa3, 0xdc, 0xb9, 0xc8, 0x70, 0x7b, 0xc8, 0x42, 0x38, 0x50, 0xb9, 0xcf,
+    0x90, 0x6e, 0x88, 0x7f, 0x5a, 0x56, 0xc8, 0xd7, 0x84, 0x7b, 0x69, 0xe1,
+    0x31, 0x6d, 0xe9, 0xc7, 0x7f, 0x39, 0x78, 0x52, 0xa2, 0x0c, 0xc7, 0x3b,
+    0x89, 0x05, 0x9d, 0x66, 0xc6, 0xea, 0x48, 0x75, 0xa5, 0xd6, 0x89, 0x8e,
+    0x47, 0xdf, 0x81, 0x28, 0x94, 0xc7, 0x98, 0xd4, 0x1c, 0x6f, 0x95, 0xdd,
+    0x20, 0x74, 0xe9, 0xde, 0xb5, 0x3b, 0x87, 0xa1, 0x1a, 0x1e, 0xee, 0xc7,
+    0xbc, 0xa4, 0x12, 0x30, 0x92, 0x60, 0x9f, 0x0d, 0x4d, 0x23, 0x1f, 0xa0,
+    0xea, 0x07, 0x84, 0x10, 0xb3, 0xd3, 0x2a, 0x2f, 0x27, 0xdb, 0x27, 0x76,
+    0xb8, 0x43, 0xe2, 0x9a, 0xfc, 0x9b, 0x81, 0x43, 0xd2, 0xbc, 0xc2, 0xbb,
+    0x40, 0xbd, 0xe8, 0x10, 0xd5, 0xca, 0xd2, 0x10, 0x5e, 0x18, 0xfe, 0x45,
+    0x1d, 0xc2, 0xf9, 0x99, 0x50, 0xbe, 0x7e, 0xca, 0x1a, 0x45, 0x17, 0x99,
+    0x03, 0x9d, 0x2b, 0x68, 0xb7, 0x76, 0x3e, 0x68, 0x41, 0x81, 0x6d, 0xe3,
+    0x77, 0xbe, 0x4e, 0xc9, 0x41, 0xb7, 0x8a, 0xb7, 0xa7, 0x59, 0xfa, 0x04,
+    0x7b, 0xde, 0xd0, 0x3f, 0x7a, 0x57, 0xa3, 0xf1, 0x9e, 0x0a, 0x66, 0x98,
+    0xb0, 0xc1, 0xc2, 0xb4, 0x7a, 0x3b, 0x2f, 0x54, 0x3b, 0x66, 0xe6, 0x6b,
+    0xc5, 0x2c, 0xa1, 0xb1, 0xd2, 0xee, 0xd8, 0x30, 0xf3, 0xa9, 0x2f, 0xe8,
+    0xf0, 0x3e, 0xd8, 0x2b, 0x9a, 0x75, 0x58, 0x59, 0xc7, 0x3a, 0x39, 0xa1,
+    0x58, 0x19, 0x87, 0x3f, 0x90, 0xe5, 0xb3, 0xb6, 0xfe, 0x39, 0x34, 0xc8,
+    0x4c, 0x21, 0x7b, 0x96, 0x9e, 0x3e, 0x38, 0x48, 0x3e, 0xaa, 0x0b, 0x1b,
+    0xbf, 0xa9, 0x45, 0x83, 0x8e, 0x38, 0xf3, 0x96, 0xb8, 0x24, 0x23, 0xc1,
+    0xd3, 0x5c, 0x77, 0xeb, 0x6f, 0xf8, 0x16, 0xa8, 0x94, 0xbc, 0xab, 0x2a,
+    0x20, 0x52, 0xec, 0x9a, 0x5c, 0xd9, 0x99, 0xb4, 0x84, 0x50, 0x90, 0xbb,
+    0xf7, 0x80, 0x51, 0x61, 0x95, 0x61, 0xaa, 0x03, 0xd6, 0xd4, 0xa9, 0x73,
+    0x86, 0x3b, 0xf1, 0x7e, 0xca, 0x7c, 0xfb, 0xf9, 0x33, 0xe6, 0x96, 0x66,
+    0x13, 0x7a, 0x35, 0xae, 0x71, 0xcc, 0x13, 0x4b, 0x5e, 0x73, 0xbd, 0xf8,
+    0xf2, 0x5e, 0x51, 0x5c, 0x50, 0x09, 0x3c, 0x59, 0xfa, 0xd0, 0xd4, 0x8e,
+    0xe0, 0x21, 0xb4, 0x97, 0xa4, 0x7d, 0xeb, 0x17, 0xef, 0x4c, 0xf4, 0xd0,
+    0x0b, 0xf5, 0x42, 0xaf, 0x07, 0x8e, 0xe9, 0x5f, 0x2b, 0xce, 0xb4, 0xf9,
+    0x17, 0xea, 0x9e, 0x83, 0x94, 0xf5, 0x1d, 0x49, 0x91, 0x42, 0x65, 0x84,
+    0x77, 0x56, 0xc0, 0x4f, 0x67, 0x37, 0xed, 0xa3, 0x18, 0x22, 0x69, 0xd7,
+    0x40, 0xfb, 0x39, 0xfd, 0xc2, 0x37, 0x68, 0x98, 0x30, 0x6a, 0x33, 0xad,
+    0x2f, 0xf2, 0x3d, 0x5c, 0xe0, 0x4a, 0x29, 0x38, 0xe5, 0xe0, 0x5c, 0xb3,
+    0x79, 0xd5, 0x8c, 0xcd, 0x25, 0xad, 0xab, 0xd3, 0x75, 0x2f, 0x54, 0x3a,
+    0xfe, 0x8e, 0x0d, 0x3f, 0xfa, 0x6e, 0xcc, 0x80, 0x26, 0x08, 0x7f, 0xa3,
+    0x9e, 0xba, 0x80, 0x4c, 0x36, 0x4c, 0x4d, 0x74, 0xc0, 0x3f, 0xd1, 0xb3,
+    0xad, 0xa3, 0xc8, 0xcf, 0x7a, 0x73, 0xb7, 0x09, 0x67, 0x3b, 0xf8, 0x6f,
+    0x7a, 0x26, 0x57, 0x65, 0x83, 0xcf, 0x18, 0x3c, 0x86, 0x2c, 0xb4, 0xcd,
+    0xe8, 0x74, 0xfa, 0x63, 0xd4, 0xb4, 0x36, 0x36, 0xd9, 0xb0, 0xeb, 0x29,
+    0xe3, 0x3a, 0x7f, 0x06, 0x80, 0x29, 0x4c, 0x86, 0x94, 0x49, 0x42, 0x22,
+    0x57, 0x0c, 0x4f, 0xfa, 0x08, 0xb5, 0x12, 0xbe, 0x76, 0xf5, 0x52, 0x10,
+    0x47, 0x48, 0x1f, 0xbd, 0x87, 0x51, 0xd1, 0x39, 0xc8, 0x50, 0x7c, 0xfa,
+    0x92, 0xe7, 0xea, 0x40, 0x55, 0xf7, 0x61, 0x9f, 0x19, 0xc2, 0x65, 0x23,
+    0x6d, 0xe0, 0x41, 0xb9, 0x5b, 0xb7, 0x8c, 0x9a, 0xee, 0x50, 0x53, 0xa6,
+    0xe8, 0x80, 0x14, 0x8c, 0xeb, 0x2a, 0xc1, 0x44, 0xda, 0x6d, 0x90, 0x96,
+    0xb8, 0xf1, 0xc4, 0x0d, 0xf1, 0xd8, 0x8e, 0xd0, 0xb4, 0x73, 0x49, 0xe5,
+    0x34, 0xab, 0x00, 0x0f, 0x0b, 0x7b, 0xc3, 0x7d, 0x53, 0x1d, 0x75, 0xef,
+    0x27, 0xfb, 0xdf, 0x29, 0xfd, 0x61, 0xb3, 0x71, 0x25, 0xac, 0x62, 0x2d,
+    0xaa, 0x1a, 0x2a, 0x55, 0x6e, 0x11, 0x50, 0x4b, 0x2c, 0x3d, 0xd8, 0x8d,
+    0xb9, 0xcb, 0xc2, 0x21, 0x77, 0x4e, 0x40, 0x56, 0x45, 0xc1, 0x07, 0x79,
+    0xdb, 0x66, 0x2f, 0x6d, 0x4d, 0xac, 0x2b, 0x2d, 0x29, 0xff, 0xa1, 0x79,
+    0x10, 0x03, 0x72, 0x09, 0xe8, 0xe9, 0x31, 0xd5, 0x6f, 0x42, 0x97, 0x3e,
+    0x09, 0xf0, 0x4a, 0xb5, 0xe6, 0x73, 0x94, 0xc1, 0xb4, 0x94, 0xa1, 0xd9,
+    0x44, 0xe8, 0x50, 0xe2, 0x6c, 0x82, 0xea, 0x89, 0x06, 0xd6, 0x44, 0xe9,
+    0x53, 0xd0, 0x5c, 0xcf, 0x0a, 0x3b, 0x89, 0x50, 0x8d, 0x1e, 0x44, 0xbd,
+    0xb2, 0xb6, 0x68, 0xf4, 0xbb, 0x2d, 0x65, 0x95, 0x5c, 0xb5, 0xdc, 0xe2,
+    0xb7, 0x70, 0x86, 0xfd, 0x5b, 0xcc, 0x99, 0x41, 0x5d, 0x22, 0x11, 0xa8,
+    0x22, 0x8c, 0xc1, 0x73, 0x70, 0x5b, 0x31, 0x11, 0xc3, 0xdb, 0x7f, 0xca,
+    0x2b, 0xcb, 0xeb, 0x7d, 0x2b, 0xd1, 0x32, 0xe6, 0xf8, 0x22, 0x22, 0x69,
+    0xea, 0xb7, 0xcd, 0x25, 0x22, 0x33, 0x2f, 0x83, 0x3f, 0xb7, 0x2d, 0x22,
+    0x61, 0x24, 0x01, 0xb3, 0xe9, 0xd0, 0xf6, 0x21, 0xe6, 0x2d, 0xea, 0x0e,
+    0x53, 0x7a, 0x97, 0xcd, 0xcf, 0x6c, 0xe2, 0xd5, 0x8b, 0xdc, 0xe9, 0xe0,
+    0xfd, 0xd0, 0xa0, 0xbf, 0xa5, 0x39, 0x7e, 0xd4, 0xdd, 0xfe, 0x1a, 0xce,
+    0xb0, 0x85, 0x8e, 0xc1, 0x05, 0x36, 0xf9, 0xd3, 0x6a, 0x35, 0xab, 0x53,
+    0x1d, 0xc2, 0xa0, 0xfa, 0xc2, 0x6b, 0x8b, 0x8c, 0x2d, 0x5d, 0x5f, 0xb8,
+    0x18, 0x43, 0x53, 0xb9, 0x5d, 0x08, 0x07, 0xd1, 0x8f, 0xc6, 0xe9, 0xef,
+    0xaf, 0x3b, 0xbb, 0x60, 0xaa, 0x28, 0xac, 0x4c, 0x03, 0x5d, 0xc8, 0x05,
+    0xba, 0x82, 0x5c, 0xcb, 0xc6, 0x2a, 0x13, 0xf6, 0xfc, 0x54, 0xf3, 0xea,
+    0x20, 0xce, 0xcf, 0x05, 0x00, 0xb9, 0x98, 0x0b, 0x9f, 0x96, 0xe0, 0x7b,
+    0x85, 0x8e, 0x43, 0xbd, 0xf2, 0x3e, 0x17, 0x19, 0x8d, 0x23, 0x72, 0x85,
+    0x93, 0xdf, 0x3a, 0x21, 0x94, 0x34, 0x32, 0x53, 0x02, 0xba, 0x34, 0xba,
+    0xa5, 0x2e, 0x5c, 0x0b, 0x1e, 0x3f, 0xa9, 0x83, 0x92, 0x63, 0x0b, 0x12,
+    0xc9, 0xf8, 0x35, 0xef, 0x78, 0xa0, 0xee, 0xc0, 0xbb, 0x14, 0xd4, 0x68,
+    0x39, 0xa0, 0x00, 0x38, 0x77, 0x1e, 0xfc, 0x94, 0xb4, 0xd4, 0xc1, 0x98,
+    0xe1, 0x43, 0x8e, 0xc6, 0xa7, 0x58, 0x33, 0x1b, 0xa3, 0x73, 0xf7, 0x4c,
+    0x49, 0x9d, 0xc0, 0xb8, 0xbf, 0x30, 0x84, 0x2e, 0x5a, 0x8b, 0x6c, 0xa5,
+    0xde, 0xb5, 0x6a, 0x79, 0x67, 0x54, 0xe7, 0x8c, 0x3c, 0xf3, 0x70, 0x1b,
+    0x3d, 0x35, 0x23, 0x65, 0x17, 0xc9, 0x74, 0x11, 0x0b, 0xb1, 0x64, 0xc0,
+    0x65, 0xa3, 0x9e, 0x5a, 0x7b, 0xa2, 0xda, 0xe1, 0xf4, 0xeb, 0xb8, 0x13,
+    0x90, 0x30, 0xc1, 0x72, 0x6a, 0x2a, 0x13, 0xe3, 0x36, 0xe1, 0x05, 0x47,
+    0x56, 0x42, 0xf2, 0x59, 0x44, 0x12, 0x23, 0x27, 0xe4, 0xfe, 0xae, 0x83,
+    0x39, 0x0f, 0x4c, 0x85, 0x3f, 0xaf, 0x97, 0x2e, 0xae, 0x3c, 0x12, 0x0e,
+    0xfd, 0x5b, 0xfd, 0x8e, 0x58, 0x58, 0x4a, 0xbd, 0x05, 0x98, 0x6b, 0x82,
+    0x03, 0x02, 0x0a, 0x2d, 0x1c, 0x19, 0x0f, 0x95, 0x12, 0x5d, 0x8c, 0x1e,
+    0x7b, 0x49, 0xbb, 0x83, 0xe2, 0xd2, 0x53, 0x60, 0xe1, 0xab, 0xd2, 0x8b,
+    0x02, 0xeb, 0x49, 0x27, 0xd7, 0xda, 0x22, 0xd3, 0x26, 0x6f, 0x3e, 0x5b,
+    0x3f, 0x33, 0xcb, 0xa8, 0x08, 0x98, 0xa6, 0xc5, 0x35, 0xc1, 0x81, 0xc1,
+    0xd6, 0x28, 0xe5, 0xba, 0x50, 0xe9, 0x14, 0x1a, 0x0b, 0x0a, 0x8a, 0x9e,
+    0xa3, 0xaa, 0xbc, 0x3b, 0x38, 0x5b, 0xe0, 0x1f, 0xf6, 0xb8, 0x95, 0x79,
+    0xa4, 0x45, 0x5f, 0xc4, 0x63, 0x86, 0xd0, 0x15, 0xe0, 0x25, 0x6e, 0x5f,
+    0x8d, 0x75, 0x25, 0x67, 0xea, 0xf3, 0x92, 0x33, 0xd1, 0x07, 0xf3, 0x43,
+    0x21, 0x42, 0x40, 0x70, 0x9b, 0x8e, 0x0b, 0x41, 0x54, 0x30, 0x73, 0xd0,
+    0x49, 0xe4, 0x70, 0xf6, 0xd3, 0x7d, 0x59, 0xd6, 0x1f, 0x06, 0xfc, 0x12,
+    0x89, 0x9f, 0x26, 0x09, 0x34, 0xf6, 0x64, 0x56, 0x37, 0x68, 0x59, 0x33,
+    0x9c, 0xa0, 0xfa, 0x65, 0x70, 0xb3, 0xe1, 0x29, 0xd1, 0x5b, 0xaf, 0xe7,
+    0xa5, 0x39, 0x64, 0x38, 0x8b, 0xb1, 0xd6, 0xce, 0xa4, 0xb4, 0xb6, 0xdb,
+    0x01, 0xb4, 0xf9, 0xb7, 0x1f, 0x8f, 0xcd, 0x28, 0xe6, 0x27, 0x47, 0xf2,
+    0x53, 0x1d, 0xea, 0xb4, 0x53, 0xfa, 0xe0, 0x22, 0xea, 0xc5, 0xd2, 0xfc,
+    0x4e, 0x45, 0xcf, 0xef, 0xaa, 0xea, 0xaf, 0x7e, 0x77, 0xe2, 0x39, 0x1c,
+    0x5d, 0x9c, 0x77, 0x7b, 0x71, 0xb5, 0x11, 0xef, 0xc7, 0xf8, 0xba, 0x2b,
+    0x7b, 0x15, 0xfa, 0x2d, 0xd5, 0xd8, 0xe0, 0xee, 0xbe, 0x10, 0xd6, 0xdb,
+    0x47, 0xf1, 0x11, 0xcc, 0x35, 0x4c, 0x2d, 0xa8, 0x12, 0x12, 0x23, 0x78,
+    0x0b, 0xd3, 0xb8, 0x90, 0x8a, 0x1d, 0xc4, 0x90, 0x4b, 0x7e, 0x35, 0xb9,
+    0x9f, 0x5b, 0x68, 0x97, 0x9c, 0x09, 0xc3, 0x0d, 0x0a, 0x20, 0xd9, 0x25,
+    0x07, 0xeb, 0x56, 0xb5, 0xd6, 0x93, 0x31, 0x3d, 0x71, 0x7c, 0x0f, 0x48,
+    0x26, 0x32, 0x0f, 0x1b, 0x43, 0x75, 0xc2, 0xcd, 0xf6, 0xaa, 0x88, 0x38,
+    0x7b, 0xe9, 0xc0, 0x98, 0x51, 0xa4, 0x06, 0x15, 0x7f, 0x11, 0x0b, 0x91,
+    0xcb, 0x59, 0x92, 0x1c, 0xa1, 0x44, 0x63, 0xa4, 0x3a, 0xad, 0xd7, 0x1d,
+    0x9e, 0x63, 0xfb, 0xb9, 0x7d, 0x43, 0x80, 0x79, 0xe8, 0x01, 0xba, 0x08,
+    0x47, 0x78, 0x57, 0xd6, 0x0b, 0x38, 0x94, 0x64, 0xac, 0x64, 0x77, 0xdc,
+    0xb8, 0xa9, 0xa5, 0xa2, 0x62, 0x70, 0x36, 0x4f, 0x39, 0xd9, 0xae, 0x2f,
+    0x15, 0xd3, 0x07, 0xc4, 0x01, 0x03, 0x96, 0x5e, 0x51, 0xa7, 0x15, 0x2a,
+    0x9d, 0x22, 0x74, 0xae, 0x8a, 0xd4, 0xb9, 0x91, 0xed, 0xad, 0xa7, 0x76,
+    0xad, 0x38, 0x33, 0xef, 0x3c, 0xe4, 0xd0, 0x7c, 0x6e, 0x53, 0xae, 0x0c,
+    0x7a, 0xdf, 0x2c, 0x18, 0xeb, 0xc4, 0x8c, 0xfe, 0xab, 0x10, 0xcd, 0xaf,
+    0x8f, 0x88, 0x3f, 0xac, 0xe3, 0x20, 0xed, 0x0c, 0x62, 0x81, 0x2e, 0x12,
+    0xa9, 0xa5, 0xe7, 0xd5, 0x3a, 0xef, 0x40, 0xb4, 0x91, 0x52, 0x4c, 0xfd,
+    0xd5, 0xb8, 0x98, 0x19, 0xcd, 0x1b, 0xa9, 0x17, 0xe7, 0x9a, 0xda, 0x8a,
+    0xb4, 0x8f, 0x1a, 0x5c, 0x78, 0xd2, 0x28, 0x7a, 0xb6, 0x66, 0xac, 0x73,
+    0xd4, 0x11, 0xc0, 0x81, 0xff, 0x71, 0x57, 0x4c, 0x23, 0x90, 0x2a, 0xd8,
+    0x67, 0x7a, 0x6a, 0x58, 0xb7, 0x5b, 0xbe, 0x80, 0x62, 0x17, 0x10, 0x90,
+    0xc1, 0xb7, 0x2c, 0xbe, 0xbe, 0x97, 0x2e, 0x85, 0x36, 0x07, 0x8e, 0x63,
+    0xfc, 0x38, 0xc5, 0x66, 0x20, 0x33, 0x2b, 0xe8, 0x25, 0x25, 0xc1, 0x11,
+    0xba, 0x5b, 0x12, 0xd9, 0x06, 0x4d, 0xfc, 0x49, 0x20, 0x27, 0x6b, 0x79,
+    0x92, 0x8b, 0xde, 0x22, 0x39, 0xf9, 0x2e, 0xc9, 0x1b, 0xb9, 0x97, 0x2f,
+    0xc3, 0x37, 0xf5, 0xa3, 0x6b, 0xd3, 0x3b, 0x94, 0xa5, 0x56, 0xb7, 0x81,
+    0x7c, 0x9d, 0x28, 0xff, 0x57, 0xe7, 0x02, 0xa1, 0xd1, 0x3a, 0x3d, 0xac,
+    0x74, 0x45, 0xb3, 0xab, 0x95, 0xec, 0x68, 0x8a, 0x9c, 0xf7, 0x43, 0xa4,
+    0x14, 0x0d, 0x68, 0x40, 0x5f, 0x7e, 0x25, 0x8a, 0x47, 0x3f, 0x9c, 0xaf,
+    0x88, 0x0b, 0x4a, 0xc0, 0x98, 0xc2, 0x57, 0xf4, 0xde, 0x04, 0x09, 0x37,
+    0x9c, 0x87, 0x83, 0xb6, 0xa5, 0xa8, 0x5e, 0xc4, 0xec, 0x2e, 0xfd, 0xc9,
+    0xf3, 0x85, 0x4f, 0x7d, 0xb8, 0xba, 0x6e, 0x6d, 0xc0, 0xd2, 0x37, 0xb2,
+    0xba, 0x17, 0xad, 0x29, 0xf8, 0x71, 0x74, 0x0c, 0x93, 0x1e, 0x07, 0x34,
+    0xec, 0xc3, 0x5f, 0x15, 0x21, 0x49, 0x0f, 0xa7, 0x7e, 0x72, 0x79, 0x66,
+    0xfd, 0x3e, 0x29, 0xce, 0x12, 0xeb, 0x57, 0x88, 0xd8, 0xcc, 0x14, 0x96,
+    0x33, 0x44, 0x64, 0x6c, 0x34, 0x55, 0xb3, 0x76, 0xc9, 0xa7, 0x3f, 0x7b,
+    0x16, 0x9d, 0x7e, 0x95, 0x4c, 0xfa, 0xc9, 0x46, 0x17, 0x18, 0x18, 0x78,
+    0xe7, 0xfb, 0x6b, 0x86, 0xf4, 0x25, 0x3a, 0x0b, 0x4a, 0xcd, 0x1a, 0x51,
+    0xde, 0xa4, 0x45, 0xdd, 0xdb, 0xc9, 0x9f, 0xa9, 0xc3, 0x58, 0xb2, 0x43,
+    0x90, 0x8b, 0xc1, 0x59, 0x47, 0x1a, 0x89, 0xcb, 0x9c, 0x6d, 0x46, 0x1f,
+    0x0d, 0xe9, 0xfa, 0xd8, 0xe9, 0xde, 0xdb, 0xf5, 0x22, 0x9b, 0xe3, 0xef,
+    0xb4, 0x0c, 0xc7, 0x34, 0xd0, 0x2a, 0x0f, 0x0b, 0x8e, 0x11, 0x88, 0x91,
+    0xb7, 0xce, 0x92, 0xf2, 0x83, 0x3c, 0xd2, 0xf8, 0x42, 0x32, 0x82, 0x48,
+    0xad, 0x67, 0x44, 0x45, 0x59, 0xac, 0x57, 0xb7, 0x7e, 0x1b, 0xce, 0xca,
+    0x51, 0xfb, 0x1b, 0x12, 0x39, 0xaf, 0xe4, 0xfb, 0xdb, 0xc5, 0xb7, 0xcc,
+    0x4a, 0x5d, 0xc4, 0xa6, 0x95, 0xaf, 0x5b, 0x39, 0x4e, 0x47, 0xc5, 0x50,
+    0x67, 0x92, 0x84, 0x62, 0xeb, 0x81, 0x77, 0x24, 0xda, 0x27, 0x64, 0xfe,
+    0xe4, 0x83, 0x40, 0x33, 0xc8, 0xb1, 0xaa, 0xbb, 0xbf, 0x13, 0xc3, 0x18,
+    0x9a, 0x24, 0x06, 0xbd, 0x0a, 0x07, 0xa3, 0xd6, 0xd8, 0x38, 0x32, 0x73,
+    0x8d, 0x40, 0x5f, 0xc2, 0x3f, 0xeb, 0xd2, 0x0e, 0x3d, 0x6d, 0xf5, 0x72,
+    0x5a, 0xa6, 0x56, 0x22, 0x41, 0xe5, 0x0c, 0xb5, 0x0c, 0xda, 0xcd, 0x46,
+    0xbc, 0xd7, 0x98, 0x89, 0x5e, 0x97, 0x54, 0x4f, 0x4b, 0xc0, 0x27, 0x51,
+    0x0d, 0x20, 0x3f, 0x55, 0x78, 0xdc, 0x5a, 0x79, 0x08, 0xed, 0xd3, 0xaa,
+    0x9c, 0xc3, 0x7d, 0x75, 0x76, 0x81, 0xa4, 0xe0, 0xfc, 0x90, 0x6a, 0x83,
+    0x37, 0x53, 0xb8, 0xb5, 0xd9, 0x7a, 0xd9, 0x7d, 0xeb, 0x50, 0x72, 0xd3,
+    0x5d, 0xed, 0x22, 0xfb, 0x6e, 0x67, 0x79, 0x9c, 0xb9, 0xea, 0xac, 0xc1,
+    0x6d, 0x68, 0xf5, 0x12, 0xaa, 0x54, 0x90, 0xd8, 0x7f, 0xe0, 0xf4, 0xdd,
+    0x3b, 0x88, 0xe3, 0xec, 0x7f, 0x1c, 0x2b, 0x08, 0x32, 0xc6, 0x05, 0x53,
+    0xae, 0xa4, 0x46, 0xa7, 0xf3, 0xe6, 0xcb, 0xe7, 0x04, 0xc1, 0x52, 0xa7,
+    0xfe, 0x68, 0x55, 0xc1, 0x91, 0xb2, 0x9a, 0x3b, 0x05, 0xc6, 0xae, 0x15,
+    0x89, 0xdc, 0xb2, 0x0b, 0xeb, 0x19, 0x96, 0x62, 0xe3, 0x67, 0xc5, 0xdc,
+    0xf5, 0xe8, 0xbe, 0x16, 0xbe, 0xf6, 0xe4, 0x0b, 0xeb, 0x99, 0x82, 0x65,
+    0x0a, 0x97, 0xf5, 0xc2, 0x19, 0x1c, 0x1e, 0xa1, 0xf1, 0x75, 0x06, 0xa7,
+    0xdb, 0x97, 0x68, 0x94, 0x0b, 0xea, 0xc4, 0xda, 0x70, 0x72, 0x3e, 0x9f,
+    0xfc, 0x20, 0x4e, 0x54, 0xfb, 0x18, 0x01, 0x74, 0x9a, 0x24, 0x1d, 0x20,
+    0x3a, 0x25, 0xe1, 0xd8, 0xaf, 0xe3, 0x76, 0xe0, 0x47, 0x53, 0x86, 0xd9,
+    0x3f, 0xc2, 0x46, 0x4a, 0x02, 0x05, 0xaf, 0xbf, 0x49, 0x12, 0x22, 0x66,
+    0x81, 0xf5, 0x9d, 0xdd, 0xae, 0x7f, 0xf5, 0x99, 0x2b, 0x89, 0xa6, 0x25,
+    0x30, 0xd6, 0xb3, 0x00, 0xa4, 0x62, 0xd2, 0xb3, 0x8e, 0xdd, 0xc2, 0x04,
+    0x62, 0x17, 0x44, 0xa3, 0x62, 0xf7, 0x8c, 0x56, 0x00, 0x4f, 0x98, 0xfe,
+    0x7a, 0xdf, 0x9d, 0x47, 0xab, 0xc9, 0xb7, 0x0e, 0x0d, 0x02, 0x54, 0x6a,
+    0xab, 0xf9, 0x22, 0xb9, 0x11, 0xb3, 0xec, 0x17, 0xb9, 0xc9, 0x86, 0xf6,
+    0x66, 0x97, 0x1f, 0xa9, 0x38, 0xd8, 0x66, 0x8e, 0x41, 0xd9, 0x9a, 0x35,
+    0xfd, 0x19, 0x64, 0xcb, 0x1e, 0x77, 0x80, 0xd4, 0x6d, 0xea, 0x00, 0xf5,
+    0x9b, 0xc9, 0x55, 0xef, 0x80, 0x14, 0x79, 0xab, 0xf5, 0x5e, 0xb0, 0x4b,
+    0x73, 0x52, 0x17, 0x2a, 0xd7, 0x68, 0x79, 0x6a, 0xf1, 0xc0, 0x04, 0xce,
+    0x33, 0xd2, 0x18, 0xad, 0x39, 0x4d, 0xda, 0x40, 0x49, 0xce, 0x00, 0xca,
+    0x89, 0xf3, 0xbd, 0x13, 0xe5, 0x7a, 0x03, 0x99, 0xa3, 0x4b, 0x29, 0xcd,
+    0x18, 0xbd, 0xc8, 0xd7, 0x30, 0xcd, 0x4f, 0x65, 0xdc, 0xca, 0xc2, 0x9f,
+    0x84, 0x2d, 0x83, 0xf6, 0x69, 0x0d, 0x55, 0x08, 0x5b, 0x6c, 0x87, 0x53,
+    0xda, 0x13, 0x2a, 0x34, 0xf7, 0xea, 0x13, 0xec, 0x14, 0x90, 0xe8, 0x94,
+    0xdc, 0xa6, 0xcf, 0xe9, 0x9b, 0x99, 0x63, 0x48, 0xf3, 0x34, 0xac, 0xf2,
+    0x78, 0x76, 0x90, 0x46, 0xd8, 0x7d, 0x2b, 0xc1, 0xd2, 0xdd, 0xf1, 0xda,
+    0x23, 0xc8, 0x3c, 0xd6, 0x58, 0x2e, 0xaf, 0x2c, 0xf6, 0x8a, 0xb3, 0x93,
+    0x0e, 0x4f, 0x82, 0x7e, 0x26, 0x88, 0x0b, 0x3b, 0xe4, 0xe9, 0x85, 0x2b,
+    0x99, 0xca, 0xdc, 0xad, 0x84, 0x26, 0xee, 0x35, 0x6a, 0x50, 0xc4, 0xae,
+    0x95, 0x30, 0x0d, 0x09, 0xef, 0xdb, 0x4b, 0x4c, 0x9b, 0x0f, 0x04, 0x0a,
+    0x6e, 0xf0, 0x92, 0x43, 0x06, 0xb9, 0x73, 0x16, 0x79, 0x15, 0x3f, 0x08,
+    0xcc, 0x78, 0x2b, 0x35, 0x8c, 0xa3, 0x2a, 0x6e, 0xf6, 0x5c, 0x61, 0xf3,
+    0xc6, 0x4b, 0x8a, 0xbc, 0x75, 0x1f, 0x4a, 0x00, 0x4e, 0x5f, 0x9e, 0x24,
+    0x03, 0x2d, 0x86, 0x26, 0xa7, 0x78, 0xb7, 0xc3, 0x6f, 0x74, 0x6d, 0x32,
+    0x34, 0xcd, 0x37, 0x42, 0x56, 0x24, 0x83, 0x7f, 0xa8, 0x1b, 0x9b, 0xae,
+    0x97, 0x55, 0x2d, 0xba, 0x67, 0x75, 0x67, 0xca, 0xa5, 0xd1, 0x6e, 0xd6,
+    0x48, 0xaf, 0xeb, 0x71, 0xdc, 0x31, 0xfb, 0x3b, 0xe3, 0x7c, 0x64, 0x9d,
+    0xe5, 0x5a, 0xe4, 0x87, 0x6e, 0xed, 0xed, 0xca, 0xb6, 0x51, 0xfd, 0x73,
+    0xef, 0x7c, 0xbc, 0x15, 0x69, 0xfd, 0x9f, 0x1f, 0x0f, 0x17, 0x1a, 0x8d,
+    0x73, 0x61, 0x7d, 0xf1, 0x09, 0x97, 0x06, 0xbe, 0x90, 0x38, 0xdf, 0xac,
+    0xfd, 0xe2, 0x87, 0xe8, 0xc1, 0xc3, 0x9b, 0x83, 0x79, 0xa6, 0xdd, 0x6d,
+    0x58, 0x4d, 0x03, 0x26, 0x99, 0x1d, 0x2e, 0x47, 0xb0, 0x20, 0x3f, 0x84,
+    0xaf, 0xfa, 0xf9, 0xf1, 0x62, 0xd5, 0x80, 0xb8, 0x6e, 0x69, 0x7e, 0x53,
+    0x80, 0x05, 0xc4, 0x2f, 0xba, 0xed, 0x0d, 0x75, 0xca, 0x01, 0xde, 0x6e,
+    0xf0, 0xd3, 0x23, 0x9b, 0x1e, 0xae, 0x02, 0x57, 0xeb, 0x40, 0xf2, 0x55,
+    0x89, 0xd7, 0x70, 0xd6, 0x45, 0xe7, 0x67, 0xd3, 0x3e, 0x21, 0xda, 0xb6,
+    0xae, 0xe5, 0xe6, 0x82, 0x0c, 0x3e, 0x3e, 0xe8, 0xbe, 0x85, 0x3d, 0x79,
+    0x75, 0x90, 0x9b, 0x9c, 0x01, 0x88, 0x8d, 0x5a, 0x34, 0x1d, 0x10, 0x83,
+    0x85, 0x08, 0xea, 0x88, 0x51, 0x29, 0xea, 0x95, 0x40, 0x2f, 0x16, 0x90,
+    0xec, 0x1b, 0xb7, 0x22, 0x81, 0xcb, 0x1b, 0x8c, 0xf5, 0xe2, 0xfd, 0xcb,
+    0x1f, 0xe7, 0xb0, 0x4b, 0x4d, 0x7c, 0x7d, 0x11, 0x17, 0x20, 0x89, 0x8b,
+    0x4a, 0x80, 0xa3, 0x10, 0x6f, 0x68, 0x09, 0x01, 0x68, 0x86, 0x3b, 0x2a,
+    0xfb, 0x48, 0x80, 0xa0, 0xd1, 0xdb, 0x3f, 0x91, 0x44, 0x58, 0x83, 0xc6,
+    0x85, 0x77, 0x6b, 0xb1, 0x35, 0x4a, 0x03, 0xa2, 0xcf, 0x2f, 0xbd, 0xcd,
+    0x4b, 0xfa, 0x5a, 0x5e, 0x8f, 0x8b, 0x95, 0x62, 0xaa, 0xe7, 0x3b, 0x54,
+    0xb1, 0xec, 0xd5, 0x85, 0x4f, 0xd9, 0x59, 0x56, 0xb4, 0xec, 0xc1, 0x21,
+    0xc5, 0xa6, 0x35, 0x1d, 0x7b, 0x60, 0xe1, 0xb1, 0x7c, 0x8f, 0x47, 0xa1,
+    0xf1, 0x13, 0x4b, 0xaf, 0x23, 0xcb, 0x5e, 0xe2, 0x74, 0x16, 0x16, 0x96,
+    0x3b, 0xff, 0xbf, 0x26, 0x5f, 0x68, 0xd5, 0x64, 0xc6, 0x62, 0xaf, 0x4a,
+    0xfc, 0x0f, 0x27, 0x3e, 0x96, 0x5b, 0x7c, 0xeb, 0x78, 0x81, 0x3c, 0x0a,
+    0x63, 0xd5, 0x6b, 0x3c, 0xa9, 0xd4, 0x37, 0x03, 0x3b, 0x5c, 0x62, 0x7a,
+    0xd5, 0x69, 0xbe, 0x44, 0x50, 0xab, 0x0a, 0x54, 0x31, 0x5c, 0x44, 0x52,
+    0xfe, 0xde, 0xbb, 0x10, 0x80, 0x79, 0xb2, 0x69, 0xc5, 0x75, 0x8b, 0xba,
+    0x1d, 0x4d, 0x2d, 0xfa, 0xc8, 0x0e, 0xc0, 0xaf, 0xc2, 0x31, 0xa1, 0x53,
+    0xc7, 0x9f, 0x3e, 0x1f, 0x38, 0x8c, 0x1e, 0x00, 0x78, 0x76, 0xb6, 0xb5,
+    0x68, 0xa4, 0x68, 0xe9, 0xba, 0xda, 0x97, 0xca, 0x16, 0xde, 0xba, 0xa1,
+    0xb7, 0x17, 0x26, 0xb3, 0x4b, 0x4b, 0x4e, 0x21, 0x9c, 0xaf, 0xce, 0xf0,
+    0x52, 0x41, 0x13, 0x87, 0x75, 0xc4, 0xd7, 0x34, 0x0c, 0x2d, 0xfe, 0xc1,
+    0xb6, 0x60, 0x84, 0xd2, 0x57, 0xc2, 0xb2, 0x6c, 0xa6, 0x97, 0x51, 0xea,
+    0x49, 0x07, 0x7d, 0xac, 0x15, 0x75, 0x71, 0x67, 0x2c, 0xdf, 0x09, 0x0c,
+    0x63, 0x38, 0x6a, 0x25, 0xf3, 0x9b, 0x5d, 0x5d, 0x63, 0xe7, 0x20, 0xa3,
+    0xf5, 0x6f, 0x8c, 0x77, 0x91, 0xb0, 0x6d, 0xad, 0x01, 0x1d, 0x40, 0x65,
+    0xcd, 0x31, 0xbf, 0xb2, 0x0a, 0x1f, 0xf9, 0xb0, 0x34, 0x7f, 0x6a, 0xfe,
+    0xca, 0x2e, 0x28, 0xc4, 0x5b, 0xdb, 0xa9, 0xd4, 0xdc, 0xe6, 0x3a, 0x0a,
+    0xeb, 0xe2, 0xc5, 0xb8, 0xbe, 0xad, 0x8d, 0x7d, 0xa2, 0x5e, 0x88, 0xad,
+    0xb8, 0xda, 0x41, 0x12, 0x1f, 0xc5, 0x85, 0xa1, 0x83, 0x3d, 0xc7, 0xbb,
+    0x6d, 0x55, 0x63, 0xd0, 0x8b, 0x06, 0x76, 0x96, 0xf5, 0x0b, 0xd9, 0x2f,
+    0x45, 0xf4, 0x9b, 0xc8, 0x18, 0xba, 0xbd, 0x30, 0xdc, 0x4d, 0x47, 0xde,
+    0xbc, 0xc0, 0xc0, 0xca, 0x9f, 0xd7, 0xda, 0xcb, 0xd8, 0xdd, 0x7e, 0x98,
+    0x25, 0xfd, 0x9f, 0xa4, 0x22, 0x5d, 0x4b, 0x63, 0x1b, 0xfa, 0x78, 0xdb,
+    0x3d, 0x39, 0xcc, 0x26, 0x00, 0x70, 0x0e, 0xac, 0xf7, 0x30, 0xc0, 0x8c,
+    0x97, 0xbe, 0x57, 0xeb, 0x1a, 0xc0, 0xfd, 0x4c, 0x81, 0x69, 0x54, 0x1b,
+    0xd4, 0x8c, 0xb2, 0xe7, 0xf0, 0x5f, 0x0e, 0x46, 0x95, 0x7a, 0x2b, 0x0c,
+    0x69, 0x37, 0x89, 0x45, 0x6a, 0xb2, 0x9f, 0xa8, 0x99, 0xd2, 0x6c, 0xa0,
+    0x9d, 0xc0, 0x36, 0x65, 0x2f, 0x37, 0xe3, 0xc8, 0xba, 0x4f, 0xd2, 0x4c,
+    0x69, 0x2e, 0x15, 0x2c, 0x92, 0x13, 0x44, 0x96, 0xa5, 0xe9, 0x90, 0x24,
+    0x0a, 0x94, 0x44, 0x16, 0x6a, 0x8e, 0x4a, 0x7b, 0xf4, 0x65, 0x41, 0xd0,
+    0x4e, 0xf3, 0xf2, 0x6d, 0x8e, 0xc0, 0x70, 0xdf, 0x56, 0x2f, 0x11, 0x80,
+    0x03, 0x42, 0xb5, 0x9c, 0x59, 0xea, 0xe1, 0x2d, 0xc7, 0xd1, 0x29, 0x4a,
+    0xce, 0x78, 0x83, 0x8f, 0x9b, 0xd4, 0x6b, 0x91, 0xd8, 0x7b, 0xd1, 0x03,
+    0xc1, 0xe8, 0x84, 0xbc, 0xca, 0x64, 0xdd, 0xac, 0xdd, 0x39, 0xaf, 0x7c,
+    0x5d, 0x7a, 0x5f, 0xc3, 0x8b, 0x0f, 0xd7, 0x18, 0x43, 0x4a, 0x8e, 0x3f,
+    0x2f, 0x02, 0x91, 0xa2, 0xdc, 0x3e, 0x2c, 0x9c, 0x3b, 0x3c, 0xe3, 0xd4,
+    0x9a, 0xb3, 0x59, 0x43, 0xd4, 0x75, 0x1c, 0x4b, 0x0b, 0xad, 0x84, 0x2d,
+    0xbd, 0x05, 0x66, 0xdb, 0x0a, 0xda, 0x77, 0x75, 0x46, 0x78, 0x99, 0x44,
+    0xdf, 0x12, 0x58, 0xa9, 0x3a, 0x5f, 0x04, 0x18, 0x81, 0xa2, 0x2d, 0xcf,
+    0x9c, 0x35, 0x8d, 0x67, 0x73, 0x9e, 0x8d, 0xe4, 0xc9, 0x9d, 0x15, 0x80,
+    0xe3, 0x36, 0xf9, 0xbd, 0xf2, 0x65, 0xb2, 0x10, 0xa9, 0xe8, 0x2a, 0x03,
+    0x9d, 0x03, 0x11, 0xe5, 0xcc, 0x32, 0x12, 0xef, 0xee, 0x22, 0xa3, 0x0c,
+    0x35, 0x28, 0xc0, 0x17, 0x9b, 0x43, 0x75, 0x5f, 0x2c, 0xbf, 0xeb, 0xc4,
+    0xf2, 0xa0, 0x6e, 0xcb, 0x06, 0x1c, 0x5c, 0xd9, 0xe8, 0x56, 0xaf, 0xe4,
+    0x2c, 0x6a, 0x8a, 0x9e, 0xea, 0x34, 0x60, 0x09, 0x94, 0xe7, 0xb2, 0x50,
+    0x4b, 0xc9, 0xeb, 0xce, 0xd2, 0x7f, 0x1d, 0xc1, 0x22, 0xe1, 0x71, 0x1f,
+    0xac, 0xb7, 0xb9, 0x5c, 0x8e, 0x44, 0xe9, 0x51, 0x58, 0x5c, 0x0e, 0x12,
+    0x34, 0xb5, 0xab, 0xa1, 0x0d, 0xf1, 0xc6, 0x71, 0xf0, 0x51, 0x6f, 0xa8,
+    0x72, 0xde, 0xad, 0x42, 0xe6, 0x39, 0x28, 0xb0, 0x66, 0xf8, 0xcb, 0x09,
+    0xb2, 0x82, 0x5a, 0x02, 0x15, 0xca, 0x17, 0xa9, 0x63, 0xd8, 0xac, 0x18,
+    0x49, 0xf7, 0xfa, 0x6d, 0xad, 0x3f, 0xf5, 0x2a, 0xd2, 0x1a, 0x9e, 0x4f,
+    0xdc, 0xb1, 0xb5, 0x5b, 0x93, 0x59, 0x44, 0x72, 0x0c, 0xf4, 0x7e, 0xe4,
+    0x62, 0x10, 0x64, 0xad, 0x2d, 0xb0, 0x2e, 0xcb, 0xf8, 0xd9, 0xbb, 0xf9,
+    0xfc, 0xc5, 0xe1, 0x31, 0x6e, 0x0e, 0x8b, 0x12, 0x62, 0x25, 0x92, 0xd6,
+    0xb0, 0x0d, 0x78, 0x7e, 0x03, 0x13, 0x65, 0xe0, 0xa3, 0x5d, 0x33, 0xc7,
+    0x04, 0x8b, 0xe7, 0x45, 0xa8, 0x9f, 0xd1, 0x70, 0x27, 0x32, 0x6e, 0x50,
+    0x48, 0x6a, 0xd3, 0x32, 0xcb, 0xca, 0xd5, 0xcd, 0xd4, 0x0a, 0x76, 0x8e,
+    0x6b, 0xb1, 0x73, 0x68, 0x38, 0xf5, 0x73, 0xb2, 0x46, 0x7a, 0xb5, 0xff,
+    0xea, 0x52, 0xc9, 0x5b, 0x56, 0xff, 0xf0, 0x35, 0x4b, 0xae, 0x88, 0x61,
+    0x8a, 0x3c, 0xb9, 0x78, 0x1c, 0x51, 0xaa, 0x5d, 0xaf, 0xe0, 0xe7, 0x8c,
+    0x03, 0x85, 0x6a, 0x1f, 0xca, 0xb9, 0x8c, 0xf4, 0x37, 0xea, 0xae, 0x54,
+    0xf1, 0xb8, 0x4c, 0x94, 0x42, 0xcf, 0x2a, 0x8d, 0x13, 0xef, 0x66, 0xf8,
+    0x1b, 0xbe, 0x5d, 0x9a, 0x24, 0x12, 0xb5, 0xe8, 0xe8, 0x44, 0x6b, 0x95,
+    0xd6, 0xed, 0x98, 0xd8, 0x10, 0xeb, 0x19, 0xe5, 0x42, 0x01, 0xaa, 0x1c,
+    0x6a, 0x62, 0xd2, 0xf0, 0xc3, 0x33, 0x4d, 0xf0, 0x3e, 0x76, 0x8d, 0xec,
+    0xbb, 0xb9, 0xeb, 0x14, 0x77, 0x02, 0x39, 0xb7, 0x75, 0x21, 0x3a, 0xa5,
+    0xef, 0x04, 0xb3, 0x20, 0x50, 0xaf, 0xed, 0x99, 0x0b, 0xec, 0x12, 0x6d,
+    0xad, 0x9f, 0x23, 0x02, 0xc0, 0x01, 0x5a, 0xfe, 0xfc, 0xee, 0xa9, 0xc1,
+    0x23, 0x51, 0x71, 0xb0, 0xe6, 0xee, 0xcc, 0xcd, 0x6a, 0x59, 0xcf, 0xad,
+    0xff, 0x4b, 0x36, 0xbf, 0x2a, 0xaf, 0x56, 0xae, 0xd7, 0x35, 0x47, 0xc4,
+    0x11, 0xef, 0x66, 0x18, 0xd1, 0xec, 0x2a, 0x5c, 0xca, 0xfe, 0x8f, 0x8b,
+    0xa2, 0x80, 0x57, 0x42, 0xe5, 0xa5, 0xb4, 0x7a, 0x34, 0xd0, 0x1b, 0xca,
+    0xb3, 0x7f, 0x2c, 0x54, 0x47, 0x50, 0xf0, 0xdd, 0xde, 0x87, 0xc0, 0x8f,
+    0x3a, 0x79, 0x49, 0x50, 0xe9, 0x4a, 0xe2, 0x74, 0x08, 0x18, 0x61, 0xaa,
+    0x17, 0xe4, 0x44, 0xdf, 0xeb, 0xf8, 0x2f, 0x5f, 0x06, 0x19, 0x06, 0x13,
+    0xec, 0x14, 0x47, 0x04, 0x51, 0x03, 0x55, 0x62, 0x78, 0x73, 0x7d, 0xe9,
+    0x15, 0xff, 0xd3, 0xb2, 0x5c, 0x54, 0x79, 0xca, 0x58, 0x10, 0x86, 0x66,
+    0x4d, 0x6a, 0x73, 0x13, 0x20, 0x60, 0xd1, 0xaa, 0x54, 0xa8, 0xf3, 0x45,
+    0x1c, 0x02, 0x23, 0xc6, 0x43, 0xee, 0xb4, 0xf4, 0xed, 0xa3, 0x59, 0xb7,
+    0xb3, 0x4e, 0xda, 0xdf, 0x5f, 0x12, 0xed, 0xb0, 0x03, 0x93, 0xc7, 0xb7,
+    0xa9, 0x52, 0xdb, 0x91, 0x39, 0x4f, 0x0d, 0x6d, 0x31, 0x08, 0xf5, 0x91,
+    0x90, 0xe5, 0x11, 0xbf, 0x33, 0x4d, 0x3f, 0x7b, 0xc8, 0x46, 0xbf, 0x8f,
+    0x27, 0x61, 0xc3, 0x6c, 0xea, 0xfa, 0xaf, 0xeb, 0x92, 0xd1, 0x86, 0xb4,
+    0x50, 0x64, 0x6c, 0xba, 0xdf, 0x1f, 0xe9, 0xc6, 0x2f, 0xad, 0x8d, 0x95,
+    0xe7, 0xfe, 0xcb, 0xbf, 0xcc, 0xba, 0xbd, 0xcc, 0x62, 0x85, 0x62, 0x7a,
+    0x96, 0x85, 0x02, 0x1c, 0xc1, 0x8f, 0x4b, 0xfc, 0x4f, 0xea, 0x69, 0x8b,
+    0x1c, 0x83, 0x81, 0x34, 0x15, 0x12, 0x16, 0x6f, 0x9c, 0x0e, 0xa4, 0x83,
+    0xb6, 0x28, 0x2f, 0xd7, 0x6d, 0x2e, 0x98, 0x6a, 0xe7, 0x6f, 0x53, 0x83,
+    0x18, 0x43, 0x75, 0x25, 0x97, 0x14, 0x15, 0x8d, 0x2f, 0x7f, 0x72, 0x1a,
+    0x07, 0x42, 0x2a, 0x7a, 0xe4, 0x7e, 0xc4, 0x7a, 0x6a, 0xc9, 0x0f, 0xeb,
+    0x4b, 0x60, 0x56, 0x15, 0x51, 0x23, 0x5d, 0xfa, 0x0e, 0x56, 0x06, 0x35,
+    0x89, 0x89, 0x77, 0x55, 0xd3, 0xd7, 0x22, 0x2f, 0x41, 0xc5, 0x70, 0x3f,
+    0x57, 0x80, 0xc6, 0xab, 0x30, 0x7e, 0xd8, 0x2b, 0xd2, 0xd2, 0xa2, 0xfc,
+    0xf9, 0x32, 0x22, 0x9e, 0x63, 0x67, 0x8a, 0x55, 0xac, 0x4e, 0x66, 0x98,
+    0xe6, 0x20, 0xea, 0xbd, 0x64, 0xe9, 0xd5, 0x06, 0x33, 0x33, 0xbf, 0xe2,
+    0x89, 0x49, 0x91, 0x92, 0x4e, 0xf9, 0xcc, 0x23, 0xad, 0x26, 0x1a, 0xb1,
+    0x01, 0x40, 0x9b, 0x3f, 0x30, 0x5c, 0x88, 0xaf, 0xce, 0x83, 0xc3, 0x45,
+    0x90, 0xdc, 0xa6, 0x20, 0x3e, 0x15, 0x96, 0x25, 0xdf, 0xe1, 0xa6, 0xd6,
+    0x78, 0xaf, 0xda, 0xc0, 0x0c, 0xf1, 0x21, 0x03, 0xf9, 0x7f, 0xb5, 0xfd,
+    0x59, 0x20, 0x3d, 0x73, 0xad, 0xfb, 0x2b, 0x5f, 0x88, 0xbc, 0x17, 0xaf,
+    0x1c, 0xaa, 0x5d, 0x17, 0x8f, 0xb7, 0x60, 0x9c, 0xc7, 0xc4, 0xe4, 0xf4,
+    0xdb, 0xa9, 0x39, 0xb0, 0xd1, 0xb4, 0x6b, 0x4b, 0x20, 0xaf, 0xd5, 0xcc,
+    0xd9, 0x68, 0x17, 0x4c, 0x9a, 0xd4, 0x35, 0x25, 0x17, 0x3b, 0xc3, 0x41,
+    0x7b, 0x05, 0xe9, 0xe8, 0xdd, 0x02, 0x9d, 0x0f, 0x6a, 0xd7, 0xf5, 0xfa,
+    0xae, 0xf2, 0x5b, 0xfe, 0xc4, 0x44, 0x62, 0xd6, 0xc4, 0x8e, 0x4b, 0x28,
+    0x6a, 0x87, 0x3c, 0xe3, 0xf8, 0x01, 0xb5, 0xf9, 0x77, 0x4e, 0x07, 0x8f,
+    0x40, 0x02, 0x72, 0x81, 0xa9, 0x6e, 0xa8, 0x84, 0x1f, 0xfe, 0x2e, 0x06,
+    0x83, 0xb8, 0x14, 0x2b, 0xf8, 0x6e, 0x8b, 0xb2, 0xed, 0xff, 0xc5, 0x90,
+    0x09, 0x86, 0xef, 0xe7, 0x64, 0xb3, 0x3f, 0x10, 0xe1, 0x47, 0xff, 0x4f,
+    0xac, 0x76, 0x45, 0xa8, 0xba, 0xac, 0xab, 0x82, 0x07, 0x86, 0x8a, 0x24,
+    0xf5, 0xc0, 0x01, 0x5f, 0x54, 0x8b, 0xdc, 0xbd, 0xd6, 0x28, 0x05, 0x56,
+    0xfd, 0x13, 0xdf, 0x93, 0x9b, 0x68, 0x03, 0x90, 0x2c, 0x08, 0xcc, 0x0b,
+    0xf9, 0x14, 0x44, 0x84, 0x79, 0x15, 0xab, 0xbc, 0x54, 0x1b, 0x76, 0xe3,
+    0xfa, 0xf8, 0x32, 0xab, 0xf2, 0xcd, 0xed, 0x04, 0x15, 0x94, 0xb4, 0xb3,
+    0xcc, 0x09, 0xf1, 0xb2, 0x35, 0x60, 0x0b, 0x05, 0xa1, 0x31, 0xd6, 0x6d,
+    0xc6, 0x46, 0x6d, 0xe4, 0xe7, 0xbc, 0x5f, 0x3a, 0x72, 0xfd, 0x42, 0xb0,
+    0x0e, 0xbb, 0xd2, 0xeb, 0x50, 0x26, 0x60, 0x38, 0xd6, 0x96, 0x1b, 0x5b,
+    0x9d, 0xcc, 0xb4, 0x98, 0x9f, 0xe8, 0xf2, 0x95, 0xa3, 0x11, 0x9a, 0xcb,
+    0x6d, 0x56, 0x87, 0x4b, 0x95, 0xb9, 0x41, 0xa3, 0x89, 0x2d, 0x2c, 0x29,
+    0xe8, 0x29, 0x86, 0x47, 0x3e, 0x91, 0x2a, 0x59, 0x7d, 0x9c, 0x03, 0x9d,
+    0x2d, 0xff, 0x05, 0x50, 0x21, 0x88, 0x12, 0x55, 0x2b, 0x25, 0x0c, 0x0c,
+    0x59, 0xa9, 0x1f, 0xbd, 0x1c, 0xa0, 0xf9, 0xc2, 0x23, 0x4b, 0xaa, 0xbe,
+    0x10, 0x4f, 0xf7, 0x5a, 0x25, 0x49, 0xb2, 0xc8, 0xdc, 0xf7, 0xb1, 0x45,
+    0xdf, 0xbb, 0x15, 0xd9, 0x48, 0x49, 0x01, 0x27, 0xf6, 0xdc, 0x59, 0x48,
+    0xb7, 0xd7, 0x5e, 0x46, 0xde, 0x2c, 0x27, 0x64, 0xf9, 0xc2, 0xc5, 0x37,
+    0x21, 0x9a, 0xbf, 0x62, 0x14, 0xdd, 0x13, 0x26, 0x9f, 0x62, 0x65, 0x55,
+    0xe8, 0xd7, 0x6f, 0x10, 0x5c, 0xd7, 0x19, 0x16, 0x1b, 0x87, 0xd3, 0x74,
+    0xd2, 0x8a, 0x89, 0x15, 0x17, 0xd8, 0x83, 0x8f, 0x3f, 0x38, 0x98, 0x9b,
+    0x25, 0x03, 0xc7, 0x7c, 0x35, 0x88, 0x53, 0x48, 0xca, 0xd6, 0x4d, 0x20,
+    0x23, 0x54, 0x15, 0x51, 0xda, 0xfb, 0x7e, 0x41, 0xbc, 0x88, 0xf5, 0x53,
+    0xf6, 0xe2, 0x54, 0xe6, 0xa8, 0xb1, 0x04, 0xac, 0xd1, 0xd6, 0x37, 0xd2,
+    0xa9, 0x6f, 0x96, 0xc0, 0x6a, 0xb1, 0xd4, 0xcf, 0x1e, 0xda, 0xda, 0x72,
+    0x43, 0xaa, 0x7b, 0x7d, 0x39, 0x19, 0x11, 0x06, 0x2a, 0x73, 0x87, 0xe6,
+    0xdb, 0x8a, 0xcf, 0x66, 0xf2, 0x77, 0xc9, 0x0a, 0xe2, 0x13, 0x90, 0xd6,
+    0x1b, 0xa6, 0xfb, 0xfd, 0xda, 0x63, 0x80, 0x81, 0x55, 0x7a, 0x4b, 0xea,
+    0x79, 0x4d, 0xa9, 0x46, 0x2b, 0xb1, 0xa5, 0x98, 0x8d, 0x34, 0x32, 0x07,
+    0xc6, 0xff, 0x98, 0x17, 0xd1, 0x55, 0x85, 0xc6, 0x8d, 0x0a, 0x3b, 0x58,
+    0x1e, 0x82, 0x24, 0xa2, 0xef, 0x83, 0xed, 0xf6, 0xe2, 0x79, 0x1b, 0x2b,
+    0x46, 0x7e, 0x94, 0x5b, 0xc8, 0x5a, 0x93, 0xef, 0xca, 0x76, 0xc7, 0xef,
+    0x71, 0xce, 0x15, 0x33, 0x91, 0xef, 0x46, 0xa9, 0x58, 0xd8, 0x6d, 0xa9,
+    0x47, 0x45, 0x35, 0xbb, 0xce, 0x96, 0xb7, 0x44, 0xd4, 0x7a, 0x90, 0xd4,
+    0xcb, 0x18, 0xbc, 0x7b, 0x64, 0xf3, 0x8e, 0xf5, 0xd5, 0xf7, 0x82, 0xdb,
+    0xff, 0xd6, 0x50, 0x17, 0xdf, 0x9a, 0x11, 0x75, 0x85, 0x36, 0xc8, 0x0c,
+    0x44, 0xcc, 0xdc, 0x76, 0xfc, 0x9f, 0x3e, 0x84, 0x8f, 0xea, 0xc6, 0xb1,
+    0xfa, 0x97, 0x75, 0x31, 0xe8, 0xc2, 0x81, 0x7b, 0x39, 0x14, 0xad, 0xdf,
+    0x67, 0xf2, 0x44, 0xe0, 0xc4, 0x7a, 0x21, 0x63, 0x74, 0x73, 0x41, 0xf4,
+    0xb5, 0xbd, 0x87, 0x36, 0xd0, 0x64, 0xb6, 0x8e, 0x98, 0xd2, 0x79, 0x5f,
+    0x4d, 0x22, 0x8c, 0xc1, 0x41, 0x4c, 0xea, 0xb7, 0xab, 0x4b, 0x2e, 0xca,
+    0x35, 0x14, 0xd3, 0x90, 0x9e, 0xd6, 0x94, 0x3e, 0x7e, 0xe4, 0x57, 0x09,
+    0x22, 0x3c, 0xe6, 0xbe, 0x04, 0x95, 0x75, 0xf8, 0xe0, 0x42, 0xe9, 0xe2,
+    0x5e, 0x2e, 0x2a, 0xc6, 0x48, 0x55, 0x42, 0x39, 0xc4, 0x81, 0x6a, 0xc6,
+    0x19, 0xea, 0x4c, 0x63, 0x60, 0x11, 0xdf, 0xe7, 0xde, 0x4d, 0x0f, 0xec,
+    0x0c, 0x8f, 0x21, 0xe7, 0x94, 0x72, 0x24, 0x4d, 0xc0, 0x44, 0x30, 0x63,
+    0x18, 0x06, 0x9b, 0xb9, 0x63, 0xc2, 0x94, 0x6d, 0x78, 0xba, 0x36, 0x58,
+    0xe3, 0x07, 0x0f, 0xd4, 0x16, 0xe5, 0xc7, 0x58, 0xb1, 0x5e, 0x96, 0x25,
+    0x80, 0xc0, 0x0c, 0x4d, 0xf1, 0xda, 0x8b, 0xc6, 0x66, 0x56, 0x1e, 0x7c,
+    0x64, 0x6b, 0x2c, 0xb2, 0x8c, 0xed, 0x07, 0xa7, 0x52, 0x70, 0xbd, 0x68,
+    0xd3, 0x48, 0x18, 0x38, 0xa6, 0x60, 0x18, 0x97, 0x4a, 0xd0, 0x88, 0xed,
+    0x4c, 0x99, 0xad, 0x88, 0x56, 0xec, 0x2b, 0xd7, 0xb4, 0xd6, 0xc6, 0x43,
+    0x58, 0xf6, 0x9b, 0xfb, 0x28, 0xa7, 0xb4, 0xaa, 0x61, 0xc4, 0x09, 0x0b,
+    0xa7, 0x51, 0x7a, 0xd3, 0x2f, 0x84, 0xeb, 0x9e, 0xc9, 0xc9, 0xac, 0x7e,
+    0x80, 0x2e, 0xa6, 0x88, 0x84, 0xd2, 0x54, 0xca, 0xe6, 0xf1, 0x7c, 0x97,
+    0x7c, 0x8a, 0x8a, 0x66, 0x7f, 0x00, 0x4b, 0x73, 0x3f, 0x2e, 0xfb, 0xcc,
+    0xe5, 0x07, 0xe6, 0x4e, 0xa1, 0x8e, 0xfc, 0x62, 0xb7, 0xd7, 0xbe, 0xa4,
+    0x4a, 0x65, 0xd7, 0xe2, 0xaa, 0x0c, 0xdd, 0x93, 0x93, 0x63, 0x56, 0x46,
+    0xe5, 0xe5, 0xf5, 0x47, 0xb1, 0xe4, 0x4e, 0x60, 0x97, 0x83, 0x82, 0x23,
+    0x84, 0x37, 0x20, 0xbd, 0xb5, 0x8b, 0x9d, 0x5d, 0xc8, 0xca, 0xe1, 0xa8,
+    0x5a, 0xc4, 0xaa, 0xe2, 0x79, 0xda, 0x1d, 0x48, 0x60, 0x4c, 0x2e, 0x06,
+    0x95, 0xb4, 0x76, 0x42, 0xa0, 0x6e, 0x52, 0x52, 0x0f, 0xf8, 0x24, 0x81,
+    0x21, 0x6f, 0x67, 0x27, 0x9e, 0xe5, 0xf9, 0x9b, 0x8c, 0x82, 0x90, 0x90,
+    0xdd, 0xe7, 0xd4, 0x24, 0x54, 0xa7, 0x26, 0x41, 0xd2, 0x54, 0x50, 0x6a,
+    0x66, 0xf0, 0xd5, 0x68, 0xaf, 0xd1, 0xd2, 0x00, 0x66, 0xa1, 0x9e, 0x1b,
+    0xab, 0xe6, 0x43, 0xa2, 0xb8, 0x05, 0x2f, 0xae, 0x9b, 0xce, 0x15, 0xa2,
+    0x5b, 0xd1, 0xb5, 0x53, 0x66, 0x6e, 0xc9, 0x44, 0x7b, 0x8c, 0x5d, 0x94,
+    0x63, 0x3c, 0xa5, 0xc5, 0x81, 0x48, 0xd7, 0x98, 0x6b, 0xb7, 0xce, 0xe4,
+    0xd9, 0xaf, 0x1c, 0xa9, 0x76, 0x8c, 0x1b, 0x4b, 0x5c, 0x1e, 0x9c, 0x98,
+    0xef, 0x74, 0x40, 0xe3, 0xf1, 0x48, 0x8c, 0x14, 0x66, 0xe4, 0x7d, 0xbd,
+    0xff, 0xcf, 0xae, 0xf8, 0x36, 0x79, 0x83, 0x76, 0xe7, 0x66, 0x36, 0x12,
+    0x60, 0x17, 0x2f, 0xb0, 0x2f, 0x22, 0x32, 0x4b, 0x42, 0x65, 0xed, 0x76,
+    0x6e, 0x4c, 0x9d, 0xb9, 0x54, 0x9b, 0x98, 0x8b, 0x79, 0x8b, 0x0e, 0xaf,
+    0x9c, 0x8c, 0xa9, 0x58, 0xaa, 0xa2, 0xde, 0x1a, 0x9b, 0x6d, 0x75, 0x0f,
+    0xd2, 0xd4, 0x28, 0xdc, 0xca, 0xcd, 0x91, 0x66, 0xd0, 0xd9, 0xab, 0x3c,
+    0x22, 0x55, 0x36, 0x87, 0x4f, 0x41, 0x24, 0x5c, 0xee, 0x5a, 0x54, 0x1a,
+    0xe0, 0xf5, 0x2c, 0x01, 0x98, 0xa3, 0x54, 0x6e, 0x6f, 0xdc, 0x88, 0xf7,
+    0x86, 0xba, 0xe2, 0x8d, 0x84, 0x95, 0x78, 0x84, 0x8c, 0xc1, 0xae, 0x8c,
+    0x7f, 0xa7, 0x91, 0xbc, 0x6d, 0x3b, 0x48, 0x7a, 0x42, 0xa0, 0xc0, 0x0a,
+    0xfe, 0xda, 0xbc, 0xe7, 0xa6, 0x76, 0xcb, 0xca, 0x68, 0xb0, 0xda, 0xb3,
+    0x2e, 0x4c, 0x57, 0x50, 0xeb, 0xbb, 0x0a, 0x35, 0x94, 0x80, 0xab, 0xcf,
+    0xa7, 0xdc, 0xab, 0x31, 0x54, 0xef, 0xe0, 0x77, 0xa5, 0x7e, 0x9e, 0x76,
+    0x96, 0x62, 0x92, 0x25, 0xf1, 0xa1, 0xa5, 0x91, 0x06, 0x9e, 0x2f, 0x81,
+    0xd8, 0x5f, 0x2e, 0xe4, 0xe8, 0xda, 0x9f, 0xe1, 0x62, 0xe1, 0x30, 0xd0,
+    0x16, 0x02, 0xc6, 0xeb, 0x3a, 0x43, 0x4e, 0x64, 0x07, 0x77, 0xf2, 0xda,
+    0x0d, 0xf5, 0xd3, 0x1c, 0x26, 0x4c, 0xcd, 0xa4, 0xb3, 0xc5, 0xd6, 0x73,
+    0xb4, 0xbc, 0xc0, 0x07, 0x64, 0x98, 0xfb, 0xf6, 0x32, 0xe4, 0xe1, 0xca,
+    0x74, 0x4c, 0x64, 0xad, 0x04, 0x53, 0x1b, 0x99, 0x24, 0x7b, 0x2e, 0xd7,
+    0x3e, 0x07, 0xba, 0x7a, 0x08, 0x7b, 0xb1, 0xb0, 0x11, 0x3f, 0x4e, 0x66,
+    0xd8, 0xa5, 0x4e, 0x72, 0x67, 0xa6, 0xbe, 0x38, 0x76, 0xcf, 0x72, 0x07,
+    0x9a, 0x57, 0x2f, 0x29, 0x6d, 0x55, 0xcd, 0x69, 0xed, 0xcf, 0x59, 0x5e,
+    0xd9, 0xe5, 0x29, 0x5b, 0xd0, 0x4d, 0x85, 0xea, 0x44, 0x0c, 0xac, 0x2d,
+    0x76, 0x28, 0x65, 0x39, 0x2a, 0xfc, 0x9f, 0xe8, 0xd8, 0xce, 0x5c, 0x56,
+    0xc0, 0x33, 0xa4, 0xcc, 0x32, 0xa6, 0x00, 0xd8, 0x9d, 0x9d, 0x0a, 0x28,
+    0x27, 0x15, 0x42, 0x8e, 0xeb, 0xb0, 0xef, 0x6f, 0xb8, 0x93, 0xe2, 0xdf,
+    0x6e, 0x17, 0x46, 0x67, 0x59, 0x05, 0x92, 0xad, 0x87, 0xc6, 0x06, 0x35,
+    0xc8, 0x4c, 0x05, 0x1c, 0x9f, 0xf4, 0xa4, 0xa4, 0xa1, 0x8d, 0x11, 0xc7,
+    0xab, 0x4b, 0x9b, 0x3a, 0x71, 0xcb, 0x2d, 0x1f, 0xec, 0x61, 0xa0, 0x66,
+    0x5f, 0x3d, 0xa3, 0x95, 0x39, 0x7f, 0x98, 0x34, 0x79, 0x32, 0x15, 0x94,
+    0xa0, 0x16, 0xa4, 0xf3, 0x45, 0x7b, 0x31, 0xfe, 0xf2, 0xe3, 0x65, 0x01,
+    0xc1, 0xf7, 0xcd, 0xcb, 0x59, 0x52, 0xbb, 0xf6, 0xa4, 0x12, 0x22, 0x9e,
+    0x5f, 0xd0, 0x50, 0x8a, 0x43, 0x62, 0xfd, 0x22, 0x21, 0xfb, 0xae, 0x08,
+    0x57, 0xc7, 0x00, 0xa6, 0x48, 0x2e, 0xcb, 0x0b, 0x76, 0x08, 0xf9, 0xd4,
+    0x14, 0x9a, 0xb5, 0xcd, 0xb8, 0x33, 0xc3, 0x0d, 0x2a, 0x3a, 0xf0, 0xe2,
+    0x5f, 0x0e, 0x1f, 0xa1, 0x1c, 0x71, 0x38, 0x2e, 0x8e, 0x93, 0x13, 0x27,
+    0xa2, 0x4a, 0xdc, 0x95, 0x1e, 0x26, 0x30, 0x5f, 0xdd, 0xc4, 0x15, 0x8e,
+    0xa8, 0xfd, 0x80, 0xf4, 0x9e, 0x31, 0x80, 0xc9, 0xa0, 0xf7, 0x61, 0xb5,
+    0x55, 0x40, 0xb4, 0x7f, 0xd8, 0xb2, 0x6b, 0x58, 0xba, 0x34, 0xba, 0x78,
+    0xa0, 0xee, 0xa2, 0xc4, 0x73, 0x19, 0xc7, 0xdf, 0x1b, 0x46, 0x3c, 0xe0,
+    0x7c, 0xb3, 0xf9, 0x7c, 0x35, 0xd5, 0xf0, 0xbf, 0x2c, 0xed, 0xa4, 0x20,
+    0x95, 0x0b, 0x05, 0x7a, 0xce, 0xdc, 0x81, 0x95, 0xf3, 0x12, 0x8a, 0x7f,
+    0xcb, 0xa8, 0xdc, 0x77, 0xbf, 0x8b, 0xdf, 0xf6, 0xb0, 0xce, 0xce, 0x0b,
+    0xdf, 0xe9, 0xcf, 0x92, 0x02, 0x20, 0x82, 0x81, 0x9c, 0x03, 0x72, 0xe8,
+    0x41, 0x6b, 0xbe, 0xb6, 0x87, 0x8b, 0xf9, 0x9e, 0x49, 0x77, 0xc5, 0xcf,
+    0x73, 0x9d, 0xf6, 0x1c, 0x42, 0x7c, 0xa8, 0xbb, 0xe3, 0x24, 0x70, 0x9f,
+    0xef, 0x28, 0xce, 0x45, 0x13, 0x13, 0x5f, 0xad, 0x02, 0x2a, 0xb4, 0x14,
+    0x80, 0x66, 0xe1, 0x6b, 0x29, 0x72, 0x77, 0xa3, 0x04, 0x36, 0x28, 0x8d,
+    0xc6, 0x39, 0xa3, 0x29, 0x59, 0xbf, 0x1e, 0x69, 0xcc, 0x8f, 0x25, 0x28,
+    0xb8, 0x24, 0x7c, 0xea, 0xe9, 0x4c, 0x43, 0x6e, 0x6c, 0x7b, 0x1d, 0x41,
+    0x7f, 0xd9, 0xd9, 0x59, 0x1e, 0x45, 0x76, 0xcc, 0x26, 0x6e, 0xe1, 0x80,
+    0x73, 0x4d, 0x79, 0x3c, 0x5c, 0x1d, 0x78, 0xf3, 0xf9, 0x75, 0x2c, 0x9d,
+    0x9d, 0x8e, 0x90, 0x23, 0xf3, 0xf9, 0xd7, 0x68, 0x14, 0xf3, 0x09, 0x2f,
+    0xa1, 0x86, 0xb1, 0x9d, 0xe2, 0x3c, 0xd3, 0x16, 0xc4, 0xdf, 0x7c, 0xcf,
+    0xc5, 0xf2, 0x3e, 0x67, 0x8b, 0xc8, 0x3e, 0x23, 0x17, 0xbf, 0x75, 0x1e,
+    0xf3, 0x35, 0xee, 0x9f, 0x14, 0xae, 0xc1, 0x5b, 0xe7, 0x92, 0x68, 0xb8,
+    0x0f, 0x95, 0x67, 0x1b, 0x55, 0xe7, 0x90, 0x6f, 0x72, 0xa0, 0x78, 0xd2,
+    0x57, 0xca, 0x0a, 0x92, 0x62, 0x8d, 0x20, 0x52, 0x84, 0xb3, 0xae, 0x8e,
+    0x22, 0x3d, 0x36, 0x3a, 0xfe, 0x68, 0x2d, 0x89, 0x8f, 0x51, 0x5b, 0x87,
+    0x87, 0x21, 0x69, 0x1a, 0x90, 0x97, 0x9e, 0x2f, 0x91, 0xae, 0x32, 0x17,
+    0x08, 0x0b, 0x3e, 0x65, 0x8a, 0xaa, 0x8e, 0xf3, 0x7b, 0x43, 0xc4, 0x2d,
+    0x05, 0xac, 0x7a, 0xd9, 0x29, 0x41, 0xf8, 0x80, 0x64, 0x99, 0x98, 0xc3,
+    0xb8, 0x4b, 0x4a, 0x4b, 0x48, 0x2a, 0xbd, 0x38, 0x42, 0x3a, 0xf1, 0x67,
+    0x03, 0x1d, 0xd8, 0x00, 0x50, 0xc9, 0xce, 0x3a, 0x34, 0xe5, 0xac, 0x5f,
+    0x36, 0x55, 0xf4, 0xf2, 0xa6, 0x09, 0x04, 0x20, 0x64, 0x56, 0xa1, 0x15,
+    0x65, 0x4d, 0x07, 0x7e, 0x47, 0xf7, 0x34, 0x30, 0x3a, 0xbe, 0x49, 0xc1,
+    0x75, 0xa3, 0x7d, 0xe5, 0x0e, 0xba, 0xdf, 0x81, 0xc0, 0x94, 0xf8, 0xec,
+    0x1d, 0x81, 0x63, 0x48, 0x12, 0x16, 0x82, 0x12, 0x8b, 0x2a, 0xf7, 0x6e,
+    0x23, 0xa4, 0x11, 0x8b, 0x70, 0xb3, 0x8a, 0xce, 0xd0, 0xdf, 0xc4, 0x6f,
+    0x65, 0x01, 0xe4, 0x6e, 0x61, 0x58, 0x78, 0x2a, 0x4b, 0x9a, 0x1b, 0x65,
+    0x94, 0xc4, 0xc5, 0x9d, 0x95, 0xc6, 0x12, 0x6f, 0xfc, 0x8a, 0x5e, 0x7f,
+    0xc8, 0xbe, 0xa9, 0xf0, 0x65, 0xb9, 0xa7, 0xe5, 0xa9, 0x39, 0xc3, 0x7a,
+    0x79, 0x05, 0x72, 0x77, 0x1f, 0xf7, 0x2b, 0x29, 0xf5, 0xb9, 0xce, 0x20,
+    0x82, 0x01, 0x21, 0xa0, 0x0c, 0xd5, 0x7c, 0x7b, 0xe5, 0x9a, 0xea, 0xdb,
+    0x71, 0xa6, 0xef, 0x57, 0xca, 0x0d, 0x55, 0x3e, 0x3c, 0x9e, 0xac, 0x6c,
+    0x18, 0x4e, 0xe9, 0xc4, 0x67, 0x00, 0x1d, 0xc3, 0xf6, 0x88, 0x9d, 0xd5,
+    0xb4, 0x1a, 0xa8, 0xde, 0xfa, 0x8c, 0xe8, 0xb5, 0x8a, 0xec, 0x6c, 0x94,
+    0x62, 0x63, 0x00, 0xaf, 0x8a, 0x91, 0x4b, 0x1b, 0x01, 0x90, 0x72, 0xa5,
+    0x0a, 0x03, 0x50, 0xc7, 0x0d, 0x66, 0xaf, 0xca, 0xae, 0xe5, 0x7f, 0x00,
+    0x00, 0x01, 0x0a
+};
+
+void h264_get_video_info(VideoDecodeInfo *info)
+{
+    info->profile   = GST_VAAPI_PROFILE_H264_MAIN;
+    info->width     = H264_CLIP_WIDTH;
+    info->height    = H264_CLIP_HEIGHT;
+    info->data      = h264_clip;
+    info->data_size = H264_CLIP_DATA_SIZE;
+}
diff --git a/tests/test-h264.h b/tests/test-h264.h
new file mode 100644 (file)
index 0000000..93b79ca
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  test-h264.h - H.264 test data
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+*/
+
+#ifndef TEST_H264_H
+#define TEST_H264_H
+
+#include <glib.h>
+#include "test-decode.h"
+
+void h264_get_video_info(VideoDecodeInfo *info);
+
+#endif /* TEST_H264_H */
diff --git a/tests/test-jpeg.c b/tests/test-jpeg.c
new file mode 100644 (file)
index 0000000..ab7aff0
--- /dev/null
@@ -0,0 +1,2080 @@
+/*
+ *  test-jpeg.c - JPEG test data
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+*/
+
+#include "test-jpeg.h"
+
+#define JPEG_CLIP_WIDTH            320
+#define JPEG_CLIP_HEIGHT           240
+#define JPEG_CLIP_DATA_SIZE      24481
+
+/* Data dump of a 320x240 VC-1 video clip (jpeg.raw), it has a single frame */
+static const guchar jpeg_clip[JPEG_CLIP_DATA_SIZE] = {
+  0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
+  0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43,
+  0x00, 0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04, 0x04, 0x05,
+  0x05, 0x05, 0x06, 0x07, 0x0c, 0x08, 0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b,
+  0x0b, 0x09, 0x0c, 0x11, 0x0f, 0x12, 0x12, 0x11, 0x0f, 0x11, 0x11, 0x13,
+  0x16, 0x1c, 0x17, 0x13, 0x14, 0x1a, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18,
+  0x1a, 0x1d, 0x1d, 0x1f, 0x1f, 0x1f, 0x13, 0x17, 0x22, 0x24, 0x22, 0x1e,
+  0x24, 0x1c, 0x1e, 0x1f, 0x1e, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x05, 0x05,
+  0x05, 0x07, 0x06, 0x07, 0x0e, 0x08, 0x08, 0x0e, 0x1e, 0x14, 0x11, 0x14,
+  0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+  0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+  0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+  0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+  0x1e, 0x1e, 0xff, 0xc0, 0x00, 0x11, 0x08, 0x00, 0xf0, 0x01, 0x40, 0x03,
+  0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x00,
+  0x1d, 0x00, 0x00, 0x02, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x03, 0x06, 0x07, 0x02,
+  0x08, 0x01, 0x00, 0x09, 0xff, 0xc4, 0x00, 0x43, 0x10, 0x00, 0x02, 0x01,
+  0x03, 0x02, 0x04, 0x04, 0x05, 0x02, 0x04, 0x03, 0x07, 0x03, 0x04, 0x03,
+  0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, 0x00, 0x21, 0x06, 0x12, 0x31,
+  0x41, 0x13, 0x22, 0x51, 0x61, 0x07, 0x14, 0x32, 0x71, 0x81, 0x91, 0xa1,
+  0x15, 0x23, 0x42, 0xb1, 0x52, 0xc1, 0xd1, 0x08, 0x24, 0x33, 0x62, 0xe1,
+  0xf0, 0xf1, 0x16, 0x43, 0x72, 0x25, 0x26, 0x34, 0x82, 0x17, 0x53, 0x83,
+  0x93, 0xff, 0xc4, 0x00, 0x19, 0x01, 0x00, 0x02, 0x03, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03,
+  0x00, 0x01, 0x04, 0x05, 0xff, 0xc4, 0x00, 0x2b, 0x11, 0x00, 0x02, 0x02,
+  0x01, 0x04, 0x02, 0x02, 0x02, 0x01, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x01, 0x02, 0x11, 0x03, 0x04, 0x12, 0x21, 0x31, 0x22, 0x41,
+  0x13, 0x32, 0x05, 0x51, 0x14, 0x23, 0x42, 0x61, 0x33, 0x52, 0x91, 0xb1,
+  0xc1, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11,
+  0x00, 0x3f, 0x00, 0xcc, 0xb8, 0xce, 0xf5, 0x70, 0x83, 0x8b, 0x2f, 0x40,
+  0x79, 0xe2, 0x4b, 0x8c, 0xe8, 0x17, 0xd8, 0x48, 0xdf, 0xe9, 0xa8, 0x2d,
+  0xbc, 0x52, 0xa1, 0xb3, 0x2d, 0x34, 0xa8, 0x00, 0xc1, 0xc2, 0x67, 0x6f,
+  0x5f, 0xdb, 0x53, 0xf1, 0x9d, 0x08, 0x97, 0x8b, 0xef, 0x72, 0x0d, 0xc7,
+  0xcf, 0xcf, 0xb7, 0x4f, 0xfd, 0xc3, 0xa4, 0x33, 0x47, 0x15, 0x0d, 0x1c,
+  0xac, 0x55, 0x89, 0x70, 0x42, 0xb7, 0x4c, 0x1c, 0xf4, 0xd6, 0x13, 0x97,
+  0x3f, 0xb3, 0x2d, 0x74, 0xfc, 0x6f, 0xc3, 0xe1, 0xc2, 0xbd, 0x4c, 0x8a,
+  0x71, 0x82, 0x5a, 0x3c, 0x63, 0x56, 0x4b, 0x1f, 0x10, 0xf0, 0xfd, 0x7b,
+  0xaa, 0x0b, 0xa5, 0x2a, 0xf3, 0x79, 0x40, 0x69, 0x00, 0x39, 0xfc, 0xeb,
+  0x13, 0xf0, 0x62, 0x7e, 0x5e, 0x65, 0x00, 0xb6, 0xdb, 0x6b, 0xa1, 0x48,
+  0x88, 0x4a, 0x82, 0x36, 0xf6, 0xd4, 0xb7, 0xec, 0x1d, 0x87, 0xa5, 0xae,
+  0x57, 0x24, 0x8b, 0x84, 0x2a, 0x28, 0x28, 0xcd, 0x34, 0x8a, 0xb3, 0x2b,
+  0x19, 0xe3, 0x91, 0x5c, 0x91, 0x83, 0xb6, 0xdd, 0x35, 0x41, 0xba, 0xd7,
+  0x25, 0x35, 0xbe, 0x69, 0xb0, 0x43, 0x46, 0xa4, 0xe7, 0x3e, 0xc7, 0x59,
+  0xcf, 0x0d, 0x41, 0x39, 0xba, 0x2c, 0x71, 0xd4, 0xcb, 0x1c, 0x64, 0x67,
+  0x0a, 0xdb, 0x67, 0x3e, 0x9a, 0x7f, 0x7c, 0xba, 0x25, 0x45, 0x9a, 0xb2,
+  0xdf, 0x24, 0x85, 0x6a, 0xb2, 0x10, 0x77, 0xe7, 0x5c, 0xf5, 0x3e, 0x9d,
+  0x34, 0x8d, 0x9f, 0x17, 0x3f, 0xb2, 0x64, 0x85, 0xd3, 0x33, 0xfa, 0xd9,
+  0xcd, 0x5d, 0x4b, 0xd4, 0x33, 0x12, 0xd2, 0x31, 0x6e, 0xbe, 0xa7, 0x3a,
+  0x6b, 0xc3, 0x7c, 0x9f, 0xf0, 0xd9, 0xca, 0x9e, 0x6c, 0xfd, 0xf4, 0x0b,
+  0xdb, 0xe6, 0x4f, 0x30, 0x4d, 0xb3, 0xd3, 0x4d, 0xf8, 0x76, 0x13, 0x1c,
+  0xab, 0x24, 0x83, 0x03, 0x9f, 0x97, 0xec, 0x74, 0x68, 0x7a, 0xe8, 0xbc,
+  0xd8, 0x69, 0xa9, 0xa3, 0x9c, 0x9d, 0x98, 0x95, 0x07, 0x61, 0x81, 0xbe,
+  0xfd, 0x34, 0xf2, 0xa9, 0x20, 0x82, 0x21, 0x24, 0xd8, 0x8c, 0x75, 0x43,
+  0x8c, 0xef, 0xdb, 0x48, 0xa8, 0x9d, 0x92, 0xea, 0xaa, 0x47, 0x2a, 0x34,
+  0x60, 0x07, 0xf5, 0x20, 0x7a, 0x6a, 0xc5, 0x27, 0x87, 0x24, 0x2f, 0x05,
+  0x41, 0xcc, 0x6c, 0x31, 0xd3, 0x4e, 0x42, 0x19, 0x58, 0xbe, 0xc5, 0x35,
+  0x5c, 0x6b, 0x24, 0xbc, 0xde, 0x2c, 0x24, 0xb2, 0x8c, 0x90, 0x0f, 0xb6,
+  0xda, 0x87, 0x83, 0x2e, 0xa2, 0x5b, 0x8c, 0x94, 0xd2, 0xc9, 0xbb, 0x6d,
+  0x8c, 0x6c, 0xac, 0x31, 0xb0, 0xd3, 0xca, 0xea, 0x4e, 0x68, 0x1f, 0xc2,
+  0x66, 0x78, 0xd4, 0x1f, 0x38, 0x19, 0x03, 0xd8, 0xea, 0x92, 0xb4, 0xb2,
+  0xd3, 0x5f, 0x84, 0xb1, 0x1e, 0x53, 0xf5, 0x67, 0xdc, 0x77, 0xd5, 0x9a,
+  0xb1, 0x3d, 0xd1, 0xda, 0x5d, 0x38, 0xc4, 0xc1, 0x1d, 0x8a, 0xa4, 0xd4,
+  0xc5, 0xe2, 0xa0, 0x1d, 0x39, 0x72, 0x47, 0xb8, 0xf7, 0xd5, 0x52, 0x86,
+  0xd7, 0x6e, 0x8e, 0x18, 0xea, 0xa0, 0xb9, 0x20, 0x9a, 0x51, 0x85, 0xa7,
+  0x64, 0x6e, 0x6f, 0x5d, 0xfd, 0x35, 0x77, 0x85, 0xc5, 0x5d, 0x2a, 0x3b,
+  0x90, 0x4b, 0x27, 0xf3, 0x36, 0xf6, 0xd6, 0x69, 0x55, 0x55, 0x24, 0xb7,
+  0x29, 0x62, 0x81, 0x3f, 0x9b, 0x03, 0x98, 0x99, 0xf9, 0x80, 0x07, 0x07,
+  0x18, 0xfb, 0x9c, 0x6a, 0x07, 0x81, 0x26, 0x9c, 0x18, 0xc9, 0x6a, 0x39,
+  0xeb, 0xa3, 0x82, 0x86, 0x6f, 0x1a, 0x76, 0x7e, 0x54, 0x0a, 0xb8, 0xdf,
+  0xed, 0xab, 0x5d, 0x3d, 0x38, 0xa1, 0x52, 0xe6, 0xa6, 0x29, 0x2e, 0x52,
+  0x0c, 0x73, 0xf2, 0x73, 0x01, 0x26, 0x73, 0x80, 0x7d, 0x14, 0x6f, 0xf8,
+  0xd7, 0x1c, 0x23, 0x6d, 0x82, 0x0a, 0x46, 0xa8, 0xa7, 0xa7, 0xcd, 0x5c,
+  0x91, 0xff, 0x00, 0x31, 0x07, 0xd4, 0x89, 0xb6, 0xd9, 0xec, 0x31, 0xd4,
+  0xf7, 0xd4, 0xf4, 0xd5, 0x4d, 0x15, 0x73, 0xd4, 0x49, 0x1a, 0xd5, 0x33,
+  0x29, 0x8d, 0x40, 0x5c, 0x0f, 0xfe, 0x2a, 0xbb, 0xe3, 0xef, 0xdf, 0x03,
+  0x52, 0x97, 0xa1, 0xeb, 0x0c, 0x62, 0x2b, 0x96, 0x2a, 0x98, 0xea, 0x2a,
+  0x4c, 0x93, 0x4b, 0x3b, 0x2a, 0x33, 0x4c, 0x4b, 0x60, 0x06, 0x3f, 0x4f,
+  0x31, 0xf5, 0x39, 0xce, 0x3b, 0x69, 0x61, 0x3e, 0x74, 0xa8, 0x8f, 0x0c,
+  0x8a, 0x70, 0x37, 0xc7, 0x37, 0xdb, 0xdb, 0x53, 0xde, 0xc4, 0xbc, 0xe5,
+  0xa4, 0x51, 0x0c, 0x21, 0xcf, 0x88, 0x13, 0xe9, 0x5c, 0x12, 0x06, 0x74,
+  0x38, 0x65, 0x91, 0x55, 0xa2, 0x45, 0x58, 0x97, 0x60, 0x1b, 0xea, 0xfb,
+  0x0f, 0x6c, 0xff, 0x00, 0xa6, 0xa0, 0xcd, 0xa0, 0xb5, 0x28, 0xd3, 0x32,
+  0xac, 0x3c, 0xa5, 0xe4, 0x7c, 0x28, 0x0b, 0xe6, 0xc9, 0xd7, 0x70, 0xc6,
+  0x60, 0x79, 0x21, 0x90, 0xf3, 0xf8, 0x7f, 0x4b, 0x0e, 0x80, 0xff, 0x00,
+  0xde, 0xfa, 0xea, 0xb4, 0x55, 0x53, 0xd7, 0x37, 0x38, 0x0a, 0xe1, 0x41,
+  0x1c, 0xbe, 0x50, 0xb9, 0xdf, 0x61, 0xa8, 0x22, 0xcc, 0x91, 0xba, 0x9d,
+  0x98, 0xb9, 0x63, 0xef, 0xbe, 0xa1, 0x36, 0x8e, 0xf8, 0x5a, 0x08, 0xaa,
+  0xee, 0x71, 0xa5, 0x6c, 0xf2, 0x45, 0x4e, 0x5c, 0xb4, 0x92, 0x20, 0x04,
+  0xa8, 0x03, 0x3b, 0x0f, 0xbe, 0x34, 0xce, 0xb5, 0x6c, 0x86, 0xa9, 0x84,
+  0x92, 0x48, 0xa8, 0xe3, 0x9c, 0x4a, 0xa3, 0x94, 0x31, 0xef, 0xb7, 0xf9,
+  0xe9, 0x47, 0x0b, 0xc6, 0x2a, 0x0d, 0x42, 0x24, 0xca, 0xb2, 0x02, 0x07,
+  0x23, 0x6d, 0x90, 0x3b, 0xe7, 0x4e, 0xe7, 0xa2, 0xf0, 0xe8, 0x5a, 0xa2,
+  0xa4, 0x0e, 0x48, 0xce, 0xc0, 0xf5, 0x3f, 0x6d, 0x26, 0x53, 0x51, 0x97,
+  0x26, 0x1c, 0xb1, 0x79, 0x1f, 0x04, 0x7c, 0x35, 0x4d, 0x40, 0x2f, 0x52,
+  0x34, 0x51, 0xc8, 0xcb, 0xe1, 0x16, 0x46, 0x77, 0xc8, 0x27, 0x9b, 0x6d,
+  0xbf, 0x1a, 0xb0, 0x52, 0xda, 0xcd, 0x69, 0x92, 0xae, 0xb7, 0x3e, 0x00,
+  0x25, 0x82, 0xe3, 0xf7, 0xd5, 0x52, 0xdb, 0x71, 0x88, 0xcc, 0x4c, 0x50,
+  0xb4, 0x2a, 0xad, 0xb4, 0x85, 0xb7, 0x1e, 0xf8, 0xd5, 0x8e, 0xa6, 0xf3,
+  0x5e, 0xd6, 0x7a, 0x81, 0x4a, 0x91, 0xc8, 0xdc, 0xbc, 0x85, 0x97, 0xfa,
+  0x57, 0xa1, 0x3a, 0xc1, 0x9b, 0x0e, 0x4c, 0xb2, 0xdd, 0x01, 0x19, 0x31,
+  0xc9, 0x3a, 0xa1, 0x35, 0xc6, 0xf9, 0x68, 0xfe, 0x16, 0xca, 0xb4, 0xfe,
+  0x13, 0xb4, 0x8d, 0xc9, 0x18, 0x39, 0x63, 0xd8, 0x12, 0x7b, 0x0c, 0x01,
+  0xaa, 0x25, 0x7d, 0x52, 0xb5, 0x67, 0x8e, 0xb1, 0x85, 0x93, 0x94, 0x28,
+  0x20, 0xe4, 0x80, 0x3a, 0x81, 0xa3, 0x2a, 0xa3, 0xa7, 0x2c, 0xdc, 0xa4,
+  0xb7, 0x2e, 0xd9, 0xf4, 0xf6, 0xd2, 0xba, 0x88, 0xcb, 0xca, 0xbc, 0x83,
+  0x7c, 0xe3, 0x5b, 0x63, 0x8f, 0x64, 0x52, 0xb0, 0x94, 0x47, 0x91, 0x99,
+  0xa8, 0x7c, 0x09, 0xa1, 0xa8, 0x61, 0x04, 0xe8, 0x32, 0xbf, 0xe1, 0xce,
+  0x08, 0x03, 0xdb, 0x56, 0x9a, 0x6a, 0x51, 0x53, 0x4a, 0x23, 0xa7, 0x5f,
+  0xe7, 0x8f, 0xe6, 0x28, 0x27, 0x0a, 0x70, 0x37, 0xcf, 0xbe, 0x33, 0xa0,
+  0xac, 0xd4, 0xf1, 0xf8, 0x54, 0xa9, 0x38, 0x60, 0xa2, 0x24, 0x0d, 0xca,
+  0x33, 0xd4, 0x01, 0x9d, 0x59, 0xb8, 0xd2, 0xd3, 0x45, 0xc3, 0x95, 0x74,
+  0xb0, 0xd0, 0xd7, 0x23, 0x89, 0x69, 0x23, 0x95, 0xd9, 0x58, 0x33, 0x07,
+  0x61, 0xb8, 0xdb, 0xfe, 0x9d, 0x74, 0xc2, 0xf7, 0x15, 0xc6, 0xc7, 0x55,
+  0x18, 0x53, 0xb8, 0x1e, 0x9e, 0xda, 0x1e, 0x3a, 0x5a, 0x58, 0xe6, 0x92,
+  0x72, 0xaa, 0xae, 0xf9, 0xe6, 0x62, 0x7a, 0x92, 0x73, 0xa9, 0xa3, 0xff,
+  0x00, 0x84, 0x06, 0x73, 0xe8, 0x71, 0xa1, 0xee, 0x0e, 0xb1, 0xdb, 0x65,
+  0x24, 0x02, 0x4b, 0x80, 0x06, 0xa7, 0x6e, 0x80, 0xa3, 0xae, 0x5c, 0x9f,
+  0x2e, 0x08, 0xf5, 0x07, 0x5f, 0x79, 0x0e, 0x71, 0xa5, 0xb4, 0x15, 0x92,
+  0x52, 0x55, 0x29, 0x18, 0xe4, 0x66, 0xc3, 0x7e, 0x74, 0xff, 0x00, 0xc1,
+  0x1e, 0x28, 0x65, 0x3d, 0x57, 0xa9, 0xef, 0xa7, 0x55, 0x3a, 0x0a, 0x82,
+  0x28, 0x61, 0x0f, 0x42, 0xfb, 0xf3, 0x1c, 0x15, 0x0b, 0xf8, 0xd2, 0xbf,
+  0xe1, 0x61, 0x79, 0x39, 0x0a, 0x1c, 0x80, 0x5c, 0xfa, 0x67, 0xb6, 0x9f,
+  0xdb, 0x14, 0xa5, 0x34, 0x9c, 0x87, 0x07, 0x7d, 0x72, 0x88, 0x42, 0xfb,
+  0xe9, 0x30, 0x7e, 0x4c, 0x18, 0xbe, 0x40, 0xa8, 0x69, 0x4a, 0x44, 0x63,
+  0x8d, 0x41, 0x39, 0x27, 0xf1, 0xa6, 0x56, 0xda, 0x39, 0x1a, 0x60, 0x3b,
+  0x91, 0x80, 0x35, 0x6d, 0xf8, 0x4d, 0x69, 0xb1, 0x5c, 0x78, 0xba, 0x2a,
+  0x6e, 0x21, 0x93, 0x92, 0x8e, 0x48, 0x5f, 0xff, 0x00, 0x73, 0xc3, 0x1c,
+  0xfb, 0x10, 0x0b, 0x7a, 0x75, 0xd6, 0x87, 0x3f, 0xc2, 0xca, 0xb8, 0xde,
+  0x6a, 0xeb, 0x40, 0x59, 0xa0, 0x8a, 0x46, 0x11, 0x46, 0xc7, 0xcc, 0xca,
+  0x0e, 0xc5, 0x4f, 0x7d, 0xb4, 0x53, 0x77, 0xe3, 0xfb, 0x2b, 0x63, 0x7d,
+  0x06, 0xfc, 0x2a, 0x5e, 0x1e, 0x6b, 0x3c, 0x34, 0x17, 0xaa, 0x01, 0xe2,
+  0x46, 0x00, 0xf9, 0x82, 0x4f, 0x2f, 0x41, 0xb1, 0xdf, 0x6d, 0x58, 0xef,
+  0x50, 0x7c, 0x36, 0x9a, 0x9a, 0x5a, 0x19, 0xe9, 0x12, 0x71, 0xbe, 0xf1,
+  0x46, 0xc5, 0x94, 0xf4, 0xc8, 0x27, 0xd3, 0xf3, 0xa5, 0x1c, 0x2d, 0x62,
+  0xa4, 0x7a, 0x29, 0x4d, 0xc6, 0xbe, 0x3b, 0x7f, 0x82, 0x71, 0x22, 0x49,
+  0x80, 0xd9, 0xea, 0x73, 0x9f, 0xce, 0x9e, 0xd2, 0xdd, 0x38, 0x0e, 0xd4,
+  0x04, 0x00, 0xa5, 0x5b, 0x05, 0xc3, 0x49, 0xe1, 0x19, 0x33, 0xf9, 0xc6,
+  0x3f, 0x4d, 0x66, 0xd3, 0xe3, 0xcd, 0x1b, 0x5b, 0x52, 0xff, 0x00, 0x23,
+  0x31, 0x6e, 0x4a, 0x9a, 0x46, 0x79, 0x71, 0xf8, 0x67, 0xc3, 0x55, 0xb0,
+  0x3d, 0x45, 0x97, 0x89, 0x54, 0xd4, 0xf5, 0x5a, 0x6a, 0xa5, 0x0a, 0x48,
+  0xf4, 0xc8, 0xef, 0xd3, 0x48, 0x2d, 0xdc, 0x05, 0x56, 0xd5, 0xb4, 0xf6,
+  0xea, 0x9a, 0x39, 0x56, 0x6a, 0x99, 0x00, 0x47, 0xe4, 0x21, 0x4a, 0xe7,
+  0xb1, 0xef, 0xb6, 0xb7, 0xbb, 0x47, 0x14, 0xf0, 0x9d, 0x64, 0x89, 0x47,
+  0x4d, 0x24, 0x30, 0x92, 0xdc, 0xa8, 0x92, 0x40, 0x10, 0x13, 0xe8, 0x36,
+  0xc6, 0x75, 0x64, 0x9c, 0x42, 0x90, 0x88, 0xcb, 0x47, 0x12, 0x9d, 0xb7,
+  0x20, 0x01, 0xae, 0x87, 0xc7, 0xb9, 0x72, 0x37, 0xe1, 0xbf, 0x67, 0xf3,
+  0x9f, 0x8a, 0x2a, 0x64, 0x8f, 0x8c, 0xb8, 0x82, 0x30, 0xfc, 0xa9, 0xfc,
+  0x4a, 0xa4, 0xed, 0xdc, 0xf8, 0xad, 0xa4, 0x97, 0x3a, 0xc7, 0x89, 0x92,
+  0x27, 0x84, 0x32, 0x32, 0x73, 0x37, 0x9b, 0x1b, 0x9e, 0x87, 0x56, 0xdb,
+  0xf5, 0xad, 0x62, 0xe2, 0xeb, 0xe5, 0x55, 0x44, 0x8c, 0xfe, 0x25, 0xc6,
+  0xa5, 0x95, 0x7b, 0x00, 0x64, 0x63, 0xaa, 0x1d, 0xd6, 0x56, 0x9e, 0xbe,
+  0x57, 0x41, 0xcc, 0x39, 0x88, 0x51, 0xe8, 0x35, 0x9c, 0xcd, 0x3f, 0xb3,
+  0x24, 0xa3, 0x2f, 0x35, 0x6a, 0x4b, 0x08, 0x29, 0xcb, 0xdf, 0xae, 0xfa,
+  0x26, 0xe0, 0xd1, 0x73, 0xaa, 0x02, 0x39, 0xb3, 0x83, 0x83, 0xfe, 0x5a,
+  0x5d, 0x12, 0x4a, 0x57, 0x94, 0x61, 0x79, 0x8f, 0x73, 0xa2, 0x23, 0x49,
+  0x04, 0xa2, 0x05, 0xf3, 0x3e, 0x36, 0x3f, 0xf5, 0xd4, 0x08, 0xb0, 0xf0,
+  0xcc, 0x4b, 0x4c, 0x79, 0xd8, 0x6d, 0x30, 0xc0, 0x3e, 0xfa, 0x87, 0x89,
+  0x68, 0xbc, 0x1b, 0x87, 0x88, 0xd1, 0xb0, 0xf1, 0x94, 0x30, 0x24, 0x75,
+  0xd4, 0x31, 0x5c, 0x66, 0xf1, 0xe1, 0xa1, 0x47, 0xc4, 0x68, 0x06, 0x40,
+  0x1d, 0x70, 0x37, 0xfd, 0x74, 0xc2, 0xfb, 0x4e, 0xe6, 0x18, 0xdf, 0x9d,
+  0x98, 0xc5, 0x91, 0xbf, 0xf8, 0x4e, 0x08, 0x1a, 0x0c, 0x9c, 0x2a, 0x2e,
+  0x5d, 0x08, 0xe0, 0x85, 0xe5, 0x90, 0xc2, 0xbb, 0x93, 0xd0, 0x68, 0x8a,
+  0x75, 0x64, 0xa6, 0x32, 0x28, 0xf3, 0x83, 0x8d, 0xba, 0x1f, 0x43, 0xa1,
+  0xe9, 0x25, 0x10, 0xdc, 0x12, 0x5c, 0xe0, 0x86, 0xf2, 0x9f, 0x7d, 0x3d,
+  0xa6, 0xa4, 0x92, 0x76, 0x03, 0x99, 0x10, 0xb6, 0xe4, 0x1f, 0x7d, 0x54,
+  0x45, 0xa0, 0x1a, 0x2a, 0x8a, 0x85, 0x98, 0x4c, 0x67, 0x22, 0x44, 0x3c,
+  0xc4, 0x9d, 0xf5, 0x75, 0xa3, 0xaf, 0x59, 0xa2, 0x8d, 0xe1, 0x95, 0x24,
+  0x57, 0x50, 0x7d, 0xc1, 0xf4, 0xc6, 0xab, 0xb2, 0x70, 0xed, 0xc3, 0xc4,
+  0x63, 0x17, 0x86, 0xc9, 0xca, 0x49, 0x3c, 0xdd, 0xb5, 0xf6, 0xcb, 0x47,
+  0x35, 0x34, 0xe9, 0x1a, 0x48, 0x4a, 0x44, 0xaf, 0xe2, 0xc6, 0xaf, 0x8d,
+  0xce, 0x0e, 0x7e, 0xda, 0x6f, 0xd4, 0xd0, 0xb1, 0x6f, 0xa4, 0x59, 0x12,
+  0xf7, 0x14, 0x15, 0x5e, 0x11, 0x3c, 0xc3, 0x18, 0x75, 0xec, 0x74, 0x6d,
+  0x96, 0x0a, 0x58, 0xee, 0xa6, 0x48, 0x54, 0x2c, 0x75, 0x28, 0x59, 0x73,
+  0xb8, 0xcf, 0x70, 0x74, 0x92, 0x8a, 0x4a, 0x0a, 0x8a, 0x59, 0x96, 0x7f,
+  0x0e, 0x9e, 0xad, 0xd8, 0xb4, 0x0f, 0xfe, 0x21, 0xfe, 0x1f, 0xef, 0xfa,
+  0x68, 0xae, 0x1a, 0x92, 0x49, 0xa8, 0xe5, 0x12, 0x48, 0xce, 0x12, 0x5f,
+  0x26, 0xfd, 0x0f, 0xa8, 0xd2, 0x66, 0xf7, 0x0b, 0x71, 0xae, 0x03, 0x78,
+  0x86, 0x9a, 0xa2, 0x9a, 0x17, 0xa5, 0xb5, 0x43, 0xfc, 0xc6, 0x89, 0xb9,
+  0x14, 0x1e, 0xe7, 0x7d, 0xbf, 0xd3, 0x59, 0xc5, 0x9a, 0x92, 0x15, 0xa7,
+  0x8e, 0x26, 0x86, 0x46, 0xac, 0xf1, 0x49, 0x98, 0xb6, 0xd8, 0x39, 0xdf,
+  0x27, 0xb6, 0x0f, 0x6d, 0x6c, 0x54, 0x6a, 0x95, 0x02, 0x29, 0x65, 0x24,
+  0xca, 0x23, 0xfa, 0x86, 0xc7, 0x39, 0xdf, 0xfb, 0x7e, 0xfa, 0xab, 0x71,
+  0x8d, 0x25, 0x35, 0x3d, 0xd1, 0xe7, 0x76, 0x31, 0xc1, 0x30, 0xf1, 0x58,
+  0x29, 0xfa, 0xe4, 0x1b, 0x15, 0xfc, 0xee, 0x7f, 0x1a, 0xac, 0x19, 0x29,
+  0xb1, 0xd8, 0x1f, 0x20, 0xaf, 0x5c, 0x69, 0x21, 0x45, 0x3e, 0x49, 0x1c,
+  0x0f, 0x0c, 0x46, 0xdb, 0x10, 0x47, 0x5c, 0x0c, 0x02, 0xc7, 0xae, 0x4f,
+  0x4d, 0x75, 0x44, 0xf1, 0x07, 0x0e, 0xc0, 0xa3, 0xa3, 0x06, 0x96, 0x51,
+  0x21, 0x27, 0x1f, 0xe0, 0x5f, 0xb9, 0xfe, 0xda, 0x46, 0x6a, 0x67, 0x92,
+  0x59, 0x26, 0xa7, 0x79, 0x23, 0x55, 0xd8, 0x21, 0xfa, 0x98, 0x74, 0xeb,
+  0x8d, 0x1d, 0x0d, 0x4c, 0x8a, 0x64, 0x91, 0x89, 0x42, 0x1b, 0x99, 0x54,
+  0x11, 0xb9, 0xfc, 0x7d, 0xf5, 0xa4, 0xdf, 0x10, 0x5b, 0xcc, 0x6a, 0x79,
+  0x1d, 0x97, 0x9a, 0x10, 0xac, 0x47, 0xaa, 0xef, 0xa5, 0xb4, 0xcc, 0xd2,
+  0x4a, 0x22, 0x2c, 0xa8, 0xe7, 0xb4, 0x87, 0x1b, 0x7a, 0xe7, 0x4d, 0x4c,
+  0xae, 0xf5, 0x45, 0x98, 0x02, 0x5c, 0x73, 0x1f, 0x4d, 0xf7, 0xd7, 0xeb,
+  0x7c, 0xd1, 0x2c, 0x35, 0x08, 0xd4, 0xc7, 0x92, 0x6c, 0x2b, 0x33, 0x0e,
+  0x60, 0xbb, 0xef, 0xbf, 0x6e, 0xdf, 0xa6, 0xa1, 0x05, 0xb2, 0x24, 0xb8,
+  0x25, 0xc9, 0x25, 0x8f, 0x36, 0xfa, 0x82, 0xae, 0xa5, 0x29, 0x60, 0x0c,
+  0x06, 0xe3, 0x1f, 0xae, 0x8d, 0xb8, 0x47, 0x1c, 0x55, 0x07, 0xc2, 0xa9,
+  0x2c, 0x87, 0x3c, 0xa7, 0xaa, 0x8f, 0x63, 0xe9, 0xa4, 0xb7, 0xa6, 0x32,
+  0x4e, 0x90, 0x73, 0x0c, 0x28, 0xe6, 0x38, 0xf5, 0xd4, 0x02, 0x7e, 0x28,
+  0xf9, 0x4b, 0x70, 0x9a, 0x9a, 0xbd, 0xaa, 0x11, 0xbc, 0x8d, 0x91, 0x8e,
+  0xc7, 0xef, 0xab, 0x62, 0x55, 0x25, 0xca, 0x89, 0x57, 0xc5, 0x63, 0x4e,
+  0x76, 0x92, 0x32, 0x7a, 0x7a, 0x7e, 0x87, 0x1a, 0xa4, 0x26, 0x54, 0x95,
+  0xd5, 0x9b, 0x85, 0xff, 0x00, 0xfc, 0x57, 0x1e, 0xa7, 0x4a, 0x66, 0x7c,
+  0x55, 0xbd, 0x26, 0x7e, 0xa9, 0x53, 0x4f, 0x51, 0x1c, 0x4a, 0xcc, 0x6a,
+  0x89, 0xdc, 0x93, 0x84, 0xe5, 0xf7, 0xd3, 0x2a, 0x74, 0x96, 0x4a, 0x69,
+  0x97, 0xc4, 0x09, 0x19, 0x19, 0x24, 0xf4, 0xeb, 0xa5, 0x15, 0x33, 0x78,
+  0x26, 0xbd, 0xa6, 0xe6, 0x66, 0x7c, 0x2a, 0x38, 0xfe, 0x91, 0xe9, 0xa6,
+  0x7e, 0x1b, 0x25, 0xa6, 0x09, 0x26, 0x24, 0x73, 0xa0, 0x0c, 0x73, 0xd7,
+  0x1f, 0xf8, 0xd1, 0x35, 0xd3, 0x1f, 0xac, 0xc7, 0xfd, 0x35, 0x21, 0x64,
+  0xe9, 0x0a, 0x8c, 0x46, 0x79, 0xc0, 0xdb, 0x9b, 0xdf, 0x51, 0x59, 0xe9,
+  0x7e, 0x66, 0xf5, 0x0a, 0x15, 0xca, 0x2b, 0x73, 0xb6, 0xfd, 0x86, 0x88,
+  0x48, 0x8c, 0xaa, 0x4c, 0x43, 0x2b, 0xbe, 0xda, 0x71, 0xc3, 0x76, 0xe9,
+  0x21, 0xfe, 0x7b, 0xaf, 0x99, 0xdb, 0x39, 0xf6, 0xd1, 0x98, 0x10, 0xe2,
+  0xa5, 0x39, 0xa5, 0x2c, 0xa7, 0xa0, 0x03, 0x41, 0xd5, 0x40, 0x85, 0x9e,
+  0x37, 0xce, 0x64, 0xe5, 0xc1, 0x27, 0xa1, 0x3a, 0x32, 0x5c, 0x78, 0x87,
+  0x1d, 0x73, 0xa8, 0xfe, 0x5c, 0xcd, 0x59, 0xe1, 0xc8, 0xab, 0x24, 0x52,
+  0x27, 0x9c, 0x1f, 0x4c, 0x63, 0x1f, 0xdb, 0x41, 0x3a, 0xf6, 0x00, 0x3d,
+  0x45, 0x24, 0x94, 0xf2, 0x98, 0x88, 0xc1, 0xf5, 0xd4, 0xd3, 0xda, 0xfc,
+  0x68, 0x52, 0x96, 0x45, 0x67, 0x86, 0x68, 0xc4, 0xa1, 0xb3, 0x83, 0xcd,
+  0xdc, 0x7d, 0x86, 0xa6, 0xb9, 0xd3, 0xc9, 0xcf, 0x12, 0xc0, 0xbe, 0x45,
+  0xc0, 0x03, 0xd1, 0x40, 0xe9, 0xa6, 0x75, 0x17, 0xa9, 0x85, 0x9e, 0x92,
+  0x8d, 0x59, 0x55, 0x0b, 0xb6, 0x58, 0x0d, 0x94, 0xf4, 0x0a, 0x4f, 0xed,
+  0xa4, 0x2c, 0x91, 0x95, 0x32, 0x14, 0xca, 0x5b, 0x44, 0x95, 0xf5, 0x1c,
+  0xbc, 0x8e, 0xa2, 0x36, 0xc1, 0x77, 0x1d, 0x48, 0xd5, 0xba, 0x9a, 0xdb,
+  0x24, 0x86, 0x2a, 0x68, 0x91, 0x9d, 0xdb, 0x08, 0x8b, 0xcb, 0xb9, 0x3e,
+  0x9a, 0x8e, 0x3a, 0xe9, 0xe1, 0x26, 0x07, 0x44, 0x56, 0x2d, 0x8c, 0x95,
+  0xdf, 0x4c, 0xa8, 0x3c, 0x29, 0x1a, 0x28, 0xea, 0x64, 0x78, 0xd9, 0x66,
+  0x59, 0x04, 0x88, 0x3a, 0x01, 0xdb, 0xef, 0xd3, 0xf4, 0xd3, 0x3e, 0x47,
+  0x77, 0x22, 0x16, 0x9b, 0x27, 0x04, 0x45, 0x2d, 0xbd, 0xda, 0x69, 0x2b,
+  0xe9, 0xeb, 0x60, 0x89, 0xd9, 0xa9, 0xa3, 0xa5, 0x32, 0xe4, 0x8c, 0xee,
+  0x4e, 0x40, 0x51, 0xb6, 0xa9, 0x74, 0xf4, 0xed, 0xcc, 0x55, 0xb1, 0xe5,
+  0xd6, 0xf3, 0x5b, 0x61, 0x9a, 0xff, 0x00, 0x60, 0xf9, 0xee, 0x1c, 0xe3,
+  0x79, 0x6a, 0x65, 0x31, 0x05, 0x96, 0x92, 0x47, 0x11, 0x07, 0x00, 0x64,
+  0xae, 0x07, 0x43, 0xee, 0x73, 0x9c, 0x1d, 0xf5, 0x4b, 0xe0, 0x4b, 0x7d,
+  0x96, 0x3b, 0xe4, 0x53, 0xf1, 0x0d, 0x34, 0x86, 0x28, 0x58, 0x23, 0x44,
+  0x98, 0x0a, 0xc4, 0x11, 0xe6, 0x3e, 0xa3, 0xed, 0xff, 0x00, 0x4d, 0x0f,
+  0xd2, 0x7e, 0x5e, 0xca, 0xa6, 0x9a, 0xbf, 0x62, 0xab, 0x4f, 0x0f, 0x57,
+  0xc1, 0x43, 0x4b, 0x75, 0xaa, 0xa6, 0x78, 0xa9, 0xaa, 0x8f, 0x2d, 0x3c,
+  0xa4, 0xec, 0xe0, 0x75, 0xfd, 0xf5, 0xe8, 0xcf, 0x86, 0xb7, 0x29, 0x2b,
+  0xb8, 0x6e, 0x18, 0xa6, 0x6c, 0xcd, 0x4c, 0x04, 0x6d, 0xee, 0xb8, 0xf2,
+  0x9f, 0xd3, 0x4c, 0xab, 0xed, 0x96, 0xdb, 0xcd, 0x84, 0x51, 0xa2, 0x45,
+  0xf2, 0x92, 0xc4, 0xa6, 0x06, 0x88, 0x00, 0x14, 0x63, 0x2a, 0x57, 0x1d,
+  0x34, 0x2f, 0x06, 0xd9, 0xaa, 0x2c, 0xf4, 0xf3, 0x47, 0x55, 0x22, 0x49,
+  0x24, 0x8c, 0x30, 0xcb, 0xdd, 0x54, 0x60, 0x67, 0xdf, 0x1a, 0xd7, 0x8e,
+  0x1b, 0x65, 0xb8, 0xd7, 0x0c, 0x7b, 0x58, 0x48, 0xe1, 0xfb, 0x79, 0xbc,
+  0xcd, 0x72, 0x7a, 0x68, 0x24, 0x69, 0x54, 0x64, 0x32, 0x03, 0xca, 0xc3,
+  0xb8, 0xcf, 0xaf, 0xf9, 0x68, 0xf8, 0x68, 0x69, 0x61, 0x04, 0x45, 0x4d,
+  0x02, 0x02, 0x72, 0x71, 0x18, 0x19, 0x3a, 0x23, 0x7d, 0x55, 0x38, 0xeb,
+  0x8b, 0xa0, 0xe1, 0xe8, 0x8c, 0x08, 0x04, 0x95, 0xae, 0xb9, 0x44, 0xcf,
+  0xd2, 0x3d, 0x4e, 0x9d, 0x63, 0x5d, 0x25, 0x6c, 0x0f, 0x8e, 0x78, 0x6e,
+  0xeb, 0x53, 0x23, 0xd7, 0x58, 0xaa, 0x42, 0x54, 0x4a, 0x04, 0x6f, 0x0b,
+  0x72, 0x85, 0x2a, 0x06, 0xc5, 0x72, 0x30, 0x0e, 0x7b, 0xfb, 0xeb, 0x14,
+  0xe3, 0x19, 0x78, 0x8a, 0x9e, 0xe5, 0xf2, 0xf7, 0xa7, 0xaa, 0x15, 0x51,
+  0x6c, 0x04, 0xec, 0x58, 0x72, 0xf6, 0x03, 0x7c, 0x6a, 0xfd, 0x6e, 0xe2,
+  0x7f, 0x88, 0x57, 0x27, 0x15, 0x16, 0xda, 0x69, 0x6a, 0x62, 0x0f, 0xbf,
+  0xf2, 0x70, 0x9f, 0xf8, 0xd7, 0x5c, 0x6b, 0x6a, 0xe3, 0xae, 0x2e, 0xa4,
+  0xa3, 0x82, 0xb6, 0xcb, 0x49, 0x4f, 0xf2, 0xef, 0xce, 0x24, 0x59, 0x57,
+  0x3b, 0x8c, 0x1c, 0x8e, 0x62, 0x7d, 0xfa, 0x6a, 0xb7, 0x19, 0x9a, 0x8e,
+  0x4e, 0x8f, 0x34, 0x71, 0x50, 0xf1, 0x38, 0x92, 0xec, 0xb9, 0xc0, 0x35,
+  0x53, 0x2f, 0xea, 0xe7, 0x59, 0x84, 0x71, 0x73, 0x49, 0x22, 0xe7, 0x04,
+  0x31, 0xdf, 0x5a, 0x5f, 0x15, 0x48, 0xe9, 0xc4, 0xd7, 0x99, 0x1a, 0x36,
+  0x58, 0x23, 0xab, 0x97, 0x2c, 0x47, 0x52, 0x64, 0x3d, 0x35, 0x9f, 0x53,
+  0x52, 0xd4, 0x2d, 0x1b, 0xd6, 0x3a, 0xaa, 0xc5, 0x25, 0x43, 0x04, 0xf3,
+  0x79, 0xba, 0x9e, 0xda, 0xc9, 0x36, 0xab, 0x83, 0x3c, 0xfe, 0xcc, 0x85,
+  0x56, 0x35, 0x04, 0x18, 0xcb, 0x39, 0xdb, 0x39, 0xfd, 0xf5, 0x24, 0x23,
+  0xc3, 0x8d, 0x99, 0x8e, 0xfd, 0x0f, 0xbe, 0x88, 0x86, 0x9f, 0xc4, 0x26,
+  0x42, 0x3c, 0xa8, 0x32, 0x75, 0xc3, 0x46, 0x67, 0x94, 0x3b, 0x82, 0x91,
+  0x2f, 0x4d, 0xb3, 0xb6, 0x84, 0xa3, 0x9a, 0x05, 0x06, 0xba, 0x29, 0x58,
+  0x75, 0x70, 0x18, 0xfd, 0xce, 0xa7, 0xbf, 0x57, 0xbc, 0xd7, 0x45, 0x46,
+  0x93, 0x09, 0x0c, 0x62, 0x12, 0x40, 0xd8, 0x90, 0x49, 0xce, 0x84, 0xab,
+  0x7c, 0x05, 0xf0, 0xf6, 0x03, 0x6d, 0x07, 0x2e, 0x49, 0xcf, 0xeb, 0xa5,
+  0x86, 0xb8, 0x54, 0x4b, 0x3c, 0xb1, 0x4e, 0x08, 0x40, 0x4e, 0x07, 0x36,
+  0x74, 0xe7, 0x87, 0xa6, 0x9a, 0xa6, 0x9d, 0x8c, 0x7b, 0xc9, 0x4e, 0x07,
+  0x36, 0xfd, 0x06, 0x90, 0x40, 0xb8, 0x32, 0x30, 0xe8, 0x50, 0xff, 0x00,
+  0x96, 0xaf, 0x1c, 0x07, 0x4e, 0x23, 0xb4, 0xbc, 0xb2, 0x79, 0x44, 0x8d,
+  0x91, 0xb7, 0x5d, 0x1c, 0x08, 0x13, 0x41, 0x73, 0xe5, 0x0b, 0xce, 0xd8,
+  0xf3, 0x6c, 0x74, 0x25, 0x45, 0xc6, 0x9d, 0x24, 0xb8, 0xcf, 0x1c, 0x73,
+  0xc8, 0xd1, 0x48, 0xac, 0x44, 0x5d, 0x48, 0xd9, 0x48, 0xc7, 0xa0, 0x38,
+  0xd2, 0xcb, 0x95, 0x3c, 0xd4, 0xb7, 0x59, 0x24, 0x15, 0x29, 0x35, 0x20,
+  0x93, 0x9c, 0x28, 0x18, 0x3e, 0xbc, 0xb9, 0xec, 0x75, 0xfa, 0xd5, 0x5f,
+  0x25, 0x0c, 0x73, 0xac, 0x30, 0xa8, 0x59, 0xf7, 0x04, 0xef, 0x91, 0xe9,
+  0xa6, 0x3e, 0x43, 0x53, 0xa7, 0x63, 0x08, 0x2e, 0x10, 0x57, 0x94, 0x9a,
+  0x5a, 0x42, 0x7f, 0x9b, 0xc8, 0x5f, 0xc3, 0xce, 0xfe, 0xa7, 0xfd, 0x75,
+  0x6a, 0xb4, 0x52, 0xcf, 0x35, 0x72, 0x3a, 0x55, 0xf8, 0x74, 0xb1, 0x27,
+  0x99, 0x00, 0xc7, 0x30, 0xed, 0x8d, 0xf6, 0xd5, 0x0a, 0x20, 0x83, 0x3c,
+  0x9e, 0x54, 0x24, 0x92, 0x80, 0xec, 0x09, 0x39, 0x3a, 0xb8, 0x70, 0xf5,
+  0x47, 0x3d, 0x02, 0xc5, 0xcf, 0xba, 0x80, 0x31, 0xed, 0xdb, 0x48, 0x71,
+  0xe6, 0x8b, 0x94, 0xf7, 0x16, 0xd8, 0x04, 0xe0, 0xbb, 0xc2, 0x79, 0xe3,
+  0x62, 0x40, 0xef, 0x81, 0xe8, 0x75, 0xf1, 0xa9, 0x1e, 0x48, 0x8c, 0x35,
+  0x51, 0x2b, 0x21, 0x1f, 0x4b, 0x0c, 0x82, 0x34, 0x9a, 0xe6, 0x2e, 0x12,
+  0xd9, 0x8c, 0x56, 0xfa, 0xa6, 0x86, 0x74, 0xf3, 0x01, 0xda, 0x4f, 0xf9,
+  0x4f, 0xb7, 0x6d, 0x7d, 0xb1, 0x5c, 0xea, 0x2a, 0xad, 0xbe, 0x2c, 0x0e,
+  0x60, 0xa8, 0x21, 0x83, 0x20, 0x3d, 0x18, 0x1c, 0x11, 0xfa, 0xea, 0x2c,
+  0x39, 0x12, 0xab, 0x12, 0xa1, 0x6a, 0xc1, 0xae, 0xbc, 0x22, 0x99, 0xf1,
+  0x6d, 0x93, 0x78, 0x0c, 0x09, 0x26, 0x36, 0x3e, 0x56, 0x07, 0xa8, 0x1a,
+  0xac, 0xbc, 0x33, 0x51, 0xce, 0x52, 0x60, 0xd0, 0xbf, 0x39, 0x5f, 0x04,
+  0x8c, 0x96, 0x00, 0xf4, 0xfb, 0x1f, 0x5d, 0x5c, 0xe8, 0xb8, 0x88, 0x21,
+  0xf9, 0x6b, 0xcb, 0x2a, 0xcc, 0x84, 0xf8, 0xa0, 0x0c, 0xba, 0x8e, 0xcd,
+  0x8f, 0xea, 0x07, 0xae, 0xbe, 0x71, 0x9d, 0x95, 0x6f, 0xf6, 0xea, 0x5a,
+  0x9a, 0x09, 0xd7, 0xc7, 0x8b, 0x78, 0xa4, 0x4e, 0x92, 0x0f, 0x42, 0x7b,
+  0x68, 0xa3, 0x36, 0xbe, 0xcc, 0xd3, 0xa7, 0xc9, 0x2c, 0x7c, 0x48, 0xa2,
+  0xd6, 0xca, 0x5e, 0x4e, 0x45, 0x26, 0x08, 0x49, 0xca, 0xef, 0x9e, 0xfd,
+  0x34, 0x4d, 0xe7, 0xc3, 0xa7, 0xa5, 0x58, 0x39, 0xd5, 0xe4, 0x75, 0xc9,
+  0x03, 0x62, 0xbf, 0x8d, 0x09, 0x52, 0xe4, 0x43, 0x25, 0x1d, 0x50, 0x6f,
+  0x1a, 0x17, 0xc4, 0x6a, 0xe3, 0x0d, 0x11, 0x07, 0x7c, 0xff, 0x00, 0xae,
+  0xa0, 0xb9, 0x97, 0x79, 0x12, 0x69, 0x25, 0x67, 0x79, 0x06, 0x58, 0x9e,
+  0xb9, 0xd3, 0xce, 0x92, 0xe5, 0x59, 0x02, 0xb3, 0x3c, 0x8a, 0x07, 0xd3,
+  0xf4, 0x9c, 0xe8, 0x2a, 0xf4, 0x31, 0xb4, 0x8d, 0x9c, 0xef, 0x80, 0x71,
+  0xe9, 0xdb, 0x47, 0x40, 0xb9, 0x46, 0x61, 0xf5, 0x76, 0xd1, 0xf6, 0xdb,
+  0x1c, 0x97, 0xc9, 0x79, 0x96, 0x64, 0xa7, 0x8e, 0x22, 0x64, 0x9e, 0x46,
+  0xec, 0xa0, 0xe3, 0xf5, 0x3a, 0x19, 0xc9, 0x46, 0x2e, 0x4c, 0xc9, 0xa8,
+  0xe9, 0x15, 0xda, 0x0a, 0x67, 0xaa, 0x91, 0x55, 0x06, 0xed, 0xb9, 0x3e,
+  0x9a, 0xb9, 0x51, 0xdb, 0x65, 0x86, 0xdc, 0xa9, 0x19, 0x08, 0xc7, 0xbe,
+  0x3a, 0xe8, 0x8b, 0x6d, 0x3d, 0xb2, 0x28, 0xe6, 0x36, 0xb2, 0x1c, 0x09,
+  0x44, 0x63, 0xcd, 0x92, 0xd9, 0xd5, 0xda, 0xa6, 0xca, 0xd4, 0xfc, 0x25,
+  0x4a, 0xf2, 0x14, 0xf1, 0x9a, 0x56, 0xf2, 0xe7, 0x7c, 0xb6, 0xe3, 0x6f,
+  0xd7, 0x59, 0x33, 0x6a, 0x16, 0x2a, 0xbf, 0x62, 0x31, 0x64, 0x58, 0xe6,
+  0x9b, 0x33, 0x35, 0xa4, 0x96, 0x66, 0x82, 0x8d, 0x90, 0xb9, 0x33, 0x90,
+  0x40, 0xf4, 0xcf, 0xae, 0xae, 0x37, 0xdb, 0x34, 0xaf, 0x6a, 0xf9, 0x11,
+  0x16, 0x39, 0x23, 0x00, 0x7d, 0xc6, 0x35, 0x3a, 0x58, 0xea, 0x63, 0xf0,
+  0x2b, 0x17, 0xfe, 0x32, 0xb8, 0x21, 0x40, 0xdc, 0x6c, 0x7b, 0xfa, 0xfb,
+  0x6b, 0xb9, 0x78, 0x90, 0xd2, 0x31, 0xa7, 0xaf, 0xa7, 0x2f, 0x0c, 0x47,
+  0x1e, 0x2c, 0x6b, 0xe6, 0x66, 0x1e, 0xda, 0x44, 0xf3, 0x4b, 0x23, 0x4f,
+  0x13, 0xe8, 0x7f, 0xe4, 0x33, 0x47, 0x22, 0xac, 0x6e, 0xd0, 0x8e, 0x9e,
+  0xc9, 0xf2, 0x74, 0x86, 0x77, 0x41, 0x95, 0x19, 0x6d, 0xb7, 0xc7, 0xae,
+  0x8c, 0xa1, 0x96, 0x2f, 0x94, 0x59, 0x0b, 0x79, 0x1b, 0xa1, 0xc6, 0x98,
+  0x55, 0x5f, 0x53, 0xc2, 0x47, 0x36, 0xc9, 0x96, 0x49, 0x90, 0x98, 0xd2,
+  0x43, 0xca, 0x59, 0x7d, 0x4e, 0xda, 0x22, 0xc7, 0x60, 0xab, 0x9e, 0xde,
+  0x93, 0x25, 0x20, 0x82, 0x09, 0x14, 0x4a, 0xbc, 0xfe, 0x52, 0xca, 0x73,
+  0x83, 0x8e, 0xac, 0x36, 0x38, 0x3e, 0xc7, 0x5b, 0x74, 0xd3, 0x9c, 0xbe,
+  0xc6, 0x0c, 0x49, 0xfb, 0x2a, 0x95, 0xb7, 0xba, 0x6f, 0x9c, 0x6a, 0x3a,
+  0x5e, 0x71, 0x3f, 0xd2, 0x24, 0x65, 0xc2, 0x83, 0xdf, 0xef, 0xa6, 0x7c,
+  0x3c, 0x87, 0xe5, 0x5e, 0x49, 0x01, 0xf1, 0x41, 0xf3, 0x16, 0x18, 0x3c,
+  0xbd, 0x8e, 0x35, 0xdf, 0x11, 0xda, 0x61, 0xc1, 0x8a, 0x78, 0x44, 0xad,
+  0xcf, 0x91, 0x85, 0xc1, 0x23, 0xd3, 0x3a, 0xfa, 0x9e, 0x05, 0x02, 0x88,
+  0x69, 0xe5, 0xa9, 0x91, 0x7c, 0x24, 0x88, 0x09, 0x76, 0xe5, 0xee, 0x47,
+  0xe0, 0xe4, 0x68, 0xb5, 0x18, 0x9d, 0xd2, 0x18, 0xe2, 0xab, 0x83, 0xa9,
+  0xa6, 0x91, 0xe4, 0x25, 0x5f, 0xe9, 0xd9, 0x7d, 0xf1, 0xa6, 0x91, 0xd0,
+  0xd1, 0x85, 0x5a, 0x84, 0x60, 0x8b, 0x3e, 0x25, 0x0b, 0x9c, 0x05, 0x63,
+  0x8e, 0x6c, 0x67, 0xbe, 0x46, 0x92, 0x48, 0x09, 0xf2, 0x29, 0xc1, 0x03,
+  0x3a, 0x7d, 0x5f, 0x6b, 0xf0, 0x69, 0xe9, 0x92, 0xbe, 0x12, 0x95, 0x31,
+  0xc6, 0xac, 0x87, 0x39, 0xc0, 0x2a, 0x08, 0x3f, 0xbe, 0xb3, 0x4d, 0x52,
+  0xab, 0xa1, 0x32, 0x74, 0x45, 0xc4, 0x10, 0xd3, 0xb3, 0xc3, 0x55, 0x4d,
+  0x23, 0x4b, 0xcd, 0xb3, 0xf3, 0x30, 0x24, 0x37, 0x7c, 0xfe, 0x83, 0xf4,
+  0xd7, 0x74, 0x12, 0x52, 0xca, 0x82, 0x29, 0x1c, 0x09, 0x06, 0x06, 0xfd,
+  0x34, 0x2c, 0xce, 0xca, 0xe1, 0x0e, 0x32, 0x57, 0x25, 0xc0, 0xdd, 0xbd,
+  0x33, 0xa1, 0x95, 0x17, 0xc4, 0x75, 0x63, 0xb9, 0x39, 0x07, 0x53, 0x6e,
+  0xf8, 0x51, 0x1f, 0x45, 0xda, 0xc9, 0x6e, 0xa8, 0xa8, 0x12, 0xad, 0x2c,
+  0x4e, 0x59, 0x50, 0x15, 0x58, 0x50, 0xb9, 0x63, 0xef, 0x8e, 0x9d, 0x33,
+  0xa7, 0xb6, 0xae, 0x1f, 0xe2, 0x53, 0x22, 0x1a, 0x7b, 0x65, 0x53, 0x97,
+  0xc1, 0x52, 0xd1, 0x15, 0x18, 0xf7, 0x27, 0x4f, 0x7e, 0x0f, 0x71, 0x1c,
+  0x56, 0x9e, 0x12, 0xa8, 0xad, 0x8e, 0x8d, 0xdd, 0x68, 0xd9, 0x52, 0xb3,
+  0xc2, 0x4e, 0x63, 0xbe, 0x79, 0x5c, 0xfe, 0x32, 0x33, 0xdb, 0xf3, 0xab,
+  0xec, 0xdc, 0x61, 0x59, 0x3d, 0x96, 0x7a, 0xaa, 0x2a, 0x38, 0x9f, 0x9d,
+  0x39, 0xa0, 0x2d, 0x9c, 0x0d, 0xf0, 0x79, 0x94, 0xfe, 0x4e, 0x85, 0x69,
+  0xe3, 0x35, 0xcc, 0xa9, 0x95, 0xf1, 0xc2, 0xae, 0x4c, 0x17, 0x80, 0x38,
+  0xaa, 0x7a, 0x4b, 0x55, 0x35, 0x0d, 0xca, 0x95, 0x95, 0x10, 0x94, 0x12,
+  0x73, 0x67, 0x90, 0x0e, 0xc7, 0x6d, 0x68, 0xf0, 0xcb, 0x1c, 0xd1, 0x2c,
+  0xb1, 0x38, 0x74, 0x61, 0x95, 0x20, 0xec, 0x75, 0x90, 0xd0, 0xf1, 0x7d,
+  0xa9, 0x69, 0x4d, 0x15, 0x55, 0x15, 0x0b, 0xd4, 0x16, 0x69, 0x48, 0x4d,
+  0x83, 0x39, 0xea, 0x48, 0xc7, 0xa9, 0xd0, 0x75, 0x9c, 0x57, 0x79, 0x85,
+  0xfc, 0x6a, 0x6a, 0xd5, 0xa5, 0x45, 0x3b, 0x45, 0x1a, 0x0f, 0x0c, 0x7e,
+  0x3b, 0xf6, 0xd0, 0xad, 0x7c, 0x34, 0xbe, 0x32, 0x96, 0xe4, 0x37, 0x16,
+  0xad, 0x41, 0x53, 0x76, 0x6b, 0x37, 0x5b, 0xcd, 0xb6, 0x86, 0x51, 0x0d,
+  0x5c, 0xfe, 0x1b, 0x1d, 0xfe, 0x82, 0xd8, 0xfd, 0x3a, 0x69, 0x1d, 0xca,
+  0x8f, 0x82, 0x2b, 0xa9, 0xde, 0xef, 0x5c, 0xd4, 0x92, 0x2c, 0x6e, 0x26,
+  0x7a, 0x89, 0x1f, 0xcd, 0xb7, 0x62, 0x4e, 0xe4, 0x7f, 0xcb, 0xfb, 0x6a,
+  0x8b, 0x4f, 0x37, 0x13, 0xdd, 0x2a, 0x24, 0x28, 0x68, 0x9c, 0xcc, 0x7f,
+  0x99, 0x2b, 0xf3, 0x2f, 0x20, 0xc6, 0xf9, 0x1f, 0xa7, 0x7d, 0x2c, 0xb9,
+  0x5b, 0x28, 0x64, 0x95, 0xbf, 0x8f, 0xf1, 0x3d, 0x24, 0x4b, 0x8c, 0x98,
+  0xe9, 0x50, 0xcb, 0x8f, 0xf4, 0xd1, 0x43, 0xf2, 0x73, 0xc9, 0xcc, 0x63,
+  0xc0, 0x6f, 0x52, 0xdf, 0xa0, 0x8e, 0x30, 0xf8, 0x8d, 0x51, 0x24, 0x92,
+  0xd2, 0xda, 0xa5, 0x11, 0x52, 0xae, 0x52, 0x24, 0x89, 0x79, 0x7c, 0x9d,
+  0xbe, 0xdd, 0xb6, 0xd4, 0x7c, 0x03, 0x7d, 0xe2, 0xeb, 0xed, 0x44, 0x76,
+  0x5b, 0x4d, 0x5c, 0x54, 0x28, 0x01, 0x92, 0x59, 0x79, 0x01, 0x60, 0x32,
+  0x32, 0xc7, 0x3d, 0x7a, 0x8f, 0x4d, 0x65, 0x9c, 0x45, 0x76, 0xa2, 0xa4,
+  0xaa, 0x96, 0x2b, 0x7b, 0x3b, 0x53, 0x87, 0x22, 0x27, 0x91, 0x40, 0x76,
+  0x1d, 0xbe, 0xd9, 0xd1, 0xdc, 0x1f, 0xc5, 0xf7, 0xa5, 0x34, 0xb6, 0x4b,
+  0x2d, 0x33, 0x47, 0x3c, 0xf3, 0x79, 0x8d, 0x39, 0xc4, 0xb2, 0x92, 0x73,
+  0xe6, 0x6c, 0x74, 0x03, 0xdc, 0x0e, 0xa7, 0x4d, 0xc2, 0xf2, 0x39, 0xdb,
+  0x17, 0x8d, 0xc9, 0xca, 0xdb, 0x28, 0x1c, 0x62, 0x3c, 0x4b, 0xb5, 0xd9,
+  0x47, 0xd0, 0x2e, 0x13, 0x78, 0x8b, 0xdc, 0x8e, 0x73, 0xbe, 0x94, 0x5c,
+  0x62, 0xa1, 0xa3, 0x31, 0x3c, 0x71, 0x7f, 0xbb, 0xc8, 0xbf, 0xe2, 0xe8,
+  0x74, 0xc7, 0x89, 0xa1, 0xa9, 0x6e, 0x2a, 0xba, 0xf3, 0x30, 0x78, 0xcd,
+  0x74, 0xe7, 0x04, 0x63, 0x6e, 0x76, 0xdb, 0xf1, 0xa5, 0x35, 0x54, 0x72,
+  0x4c, 0xa2, 0x9c, 0x4a, 0xa4, 0x7d, 0x5c, 0xad, 0xb7, 0x4e, 0xc0, 0xe9,
+  0xf4, 0xfd, 0x03, 0x3f, 0xb3, 0x01, 0xe4, 0xf9, 0xa2, 0xb1, 0x44, 0x79,
+  0x63, 0xea, 0x7f, 0xe6, 0x3a, 0x31, 0x6d, 0x63, 0x90, 0xbc, 0x84, 0x72,
+  0x85, 0xc7, 0x36, 0x0e, 0xc3, 0xf1, 0xaf, 0x94, 0xf5, 0x46, 0x89, 0x92,
+  0x13, 0x44, 0xf1, 0xb1, 0x50, 0x57, 0xc4, 0xdb, 0x27, 0x44, 0x45, 0x77,
+  0xa2, 0x69, 0x58, 0xd4, 0x48, 0xef, 0x57, 0x1b, 0x7f, 0xc2, 0x44, 0xf2,
+  0xae, 0xff, 0x00, 0xf7, 0xbe, 0xaf, 0xc2, 0xae, 0x4c, 0x15, 0xd5, 0x95,
+  0xda, 0xdb, 0x5d, 0x5c, 0x6f, 0x98, 0xe2, 0x95, 0xd3, 0x19, 0x07, 0xc3,
+  0xc6, 0x47, 0xae, 0x35, 0x0d, 0x25, 0xb2, 0xba, 0xae, 0x46, 0x8a, 0x2a,
+  0x66, 0x2c, 0xa4, 0x73, 0x0c, 0x7d, 0x20, 0xf4, 0x27, 0x57, 0x19, 0x2b,
+  0x94, 0x4c, 0x2a, 0x15, 0x0c, 0x4e, 0xbb, 0x60, 0xff, 0x00, 0xa6, 0x99,
+  0x70, 0xa5, 0x31, 0x4a, 0x0a, 0xa9, 0xd4, 0x78, 0x93, 0xcd, 0x29, 0x76,
+  0xed, 0xb1, 0xd6, 0x5e, 0xdf, 0x03, 0x0a, 0xb4, 0x1c, 0x33, 0x24, 0x7c,
+  0xb4, 0x2b, 0x2a, 0x3d, 0x44, 0xaa, 0x64, 0x73, 0xd0, 0x2a, 0x82, 0x32,
+  0x3d, 0xfa, 0xeb, 0xbb, 0xb5, 0x49, 0xa5, 0x46, 0xa3, 0xa6, 0x99, 0xbc,
+  0x15, 0xc2, 0xe0, 0x1d, 0x89, 0x03, 0x1f, 0xa6, 0xac, 0x75, 0xee, 0xf4,
+  0xd5, 0xd2, 0xc9, 0x51, 0x1b, 0x20, 0x92, 0x97, 0x11, 0xb6, 0x36, 0xfa,
+  0xba, 0x67, 0xf1, 0xaa, 0x95, 0x73, 0x47, 0x33, 0x15, 0x41, 0xd3, 0xbf,
+  0xae, 0xb6, 0x6d, 0xa4, 0x40, 0x15, 0x12, 0x54, 0xcd, 0x1d, 0x3a, 0xe0,
+  0x07, 0x38, 0xc0, 0xe8, 0x34, 0xc5, 0xe0, 0x64, 0x41, 0x1b, 0x6c, 0x54,
+  0x6c, 0x3d, 0x34, 0xbe, 0xdd, 0xe2, 0x45, 0x71, 0x0e, 0x9f, 0x50, 0xdc,
+  0x1d, 0x3e, 0xf0, 0xe7, 0xa8, 0x4c, 0xcc, 0xc0, 0xef, 0xbe, 0xaa, 0x3d,
+  0x94, 0x28, 0x65, 0xc3, 0x6e, 0x37, 0xd3, 0x0b, 0x65, 0x63, 0xd2, 0xb2,
+  0xbc, 0x6f, 0xb8, 0x6c, 0x91, 0xed, 0xaf, 0xd2, 0xd0, 0xcb, 0xe1, 0xb1,
+  0x5c, 0x72, 0xaf, 0x56, 0x63, 0x80, 0x34, 0xbe, 0x17, 0x4e, 0x40, 0x7b,
+  0x8c, 0xfe, 0xfa, 0x94, 0x59, 0xa6, 0x50, 0xc8, 0x92, 0xa2, 0xcc, 0x87,
+  0xf9, 0x6e, 0x9c, 0xde, 0xb8, 0xd0, 0xf4, 0x94, 0xe9, 0x05, 0x75, 0x50,
+  0x0a, 0x02, 0xca, 0xc2, 0x55, 0xfb, 0x91, 0x83, 0xfd, 0xbf, 0x7d, 0x07,
+  0xc2, 0x12, 0x78, 0xb6, 0x7c, 0xe3, 0xfe, 0x1b, 0x60, 0x0f, 0x63, 0xa3,
+  0x2b, 0x65, 0x29, 0x71, 0xa7, 0x32, 0x48, 0xb1, 0xc4, 0x62, 0x39, 0x76,
+  0x3b, 0x64, 0x11, 0x81, 0xa9, 0x40, 0x47, 0xb1, 0x17, 0x18, 0x43, 0x3f,
+  0xf1, 0x9a, 0x0a, 0xda, 0x2a, 0x66, 0x91, 0xd5, 0x5c, 0x4e, 0x14, 0xee,
+  0xc1, 0x46, 0x41, 0xfd, 0xf5, 0x15, 0x92, 0xeb, 0x5d, 0x68, 0xa5, 0xf9,
+  0xb6, 0x71, 0x2b, 0x99, 0x83, 0xcb, 0x4e, 0xe7, 0x39, 0xce, 0x70, 0x40,
+  0xec, 0x71, 0xdf, 0x5f, 0xae, 0x55, 0x15, 0x17, 0xdb, 0x89, 0x96, 0xd9,
+  0x28, 0x86, 0x9e, 0x89, 0x49, 0x91, 0xe4, 0x7f, 0x0c, 0xc9, 0xb6, 0x4f,
+  0x2e, 0x77, 0xea, 0x31, 0xf8, 0xd0, 0x6f, 0x1a, 0xca, 0x6a, 0x24, 0x97,
+  0x2e, 0xae, 0xc1, 0x06, 0x5b, 0x3c, 0xc4, 0x75, 0x27, 0xd7, 0x52, 0x93,
+  0x54, 0xce, 0x8e, 0x2a, 0x9c, 0x29, 0xa3, 0x43, 0xab, 0xb3, 0x5a, 0x38,
+  0xae, 0x85, 0x2b, 0x56, 0x23, 0x1c, 0xc1, 0x7c, 0xb2, 0xa7, 0xd6, 0x87,
+  0xd0, 0xfa, 0x8d, 0x51, 0x78, 0xa3, 0x86, 0x2e, 0x16, 0xb8, 0xfc, 0x59,
+  0x23, 0x33, 0xc4, 0x36, 0x33, 0x46, 0x3f, 0x72, 0x3b, 0x6a, 0xcd, 0xc0,
+  0xb7, 0xe8, 0xa9, 0x7f, 0xfa, 0x7c, 0xbf, 0xcb, 0x5e, 0x63, 0xe1, 0x9c,
+  0xec, 0x3d, 0xb5, 0x7f, 0x0c, 0x93, 0x47, 0xb8, 0x0c, 0xa7, 0xa8, 0xd2,
+  0x37, 0x38, 0x3a, 0x7c, 0x99, 0xa7, 0x97, 0x26, 0x9d, 0xd7, 0xa3, 0xcf,
+  0xf6, 0xe0, 0xaf, 0x1c, 0xc3, 0x38, 0xe8, 0x41, 0xfb, 0x6d, 0xa6, 0xd6,
+  0x8a, 0x3a, 0x99, 0xec, 0xb5, 0x66, 0x2a, 0x81, 0x4e, 0xbb, 0x82, 0x4a,
+  0x92, 0x09, 0x2d, 0xd3, 0x6f, 0xb6, 0x8e, 0xf8, 0xad, 0x45, 0x4f, 0x6f,
+  0xe2, 0xaa, 0x24, 0xa3, 0x8c, 0x43, 0x1d, 0x54, 0x1c, 0xcd, 0x1a, 0x0c,
+  0x2f, 0x30, 0x27, 0xcd, 0xf7, 0xd7, 0x74, 0x73, 0x46, 0x6c, 0xc9, 0x47,
+  0x17, 0xf2, 0xf0, 0xdc, 0xcd, 0x8d, 0xf7, 0x3d, 0x75, 0x32, 0x4e, 0xe9,
+  0x0c, 0xcd, 0x3d, 0xf0, 0x8b, 0x06, 0xb1, 0xd3, 0xc9, 0x41, 0x6f, 0xf1,
+  0x50, 0xa8, 0x74, 0x97, 0x99, 0x64, 0xcf, 0x5d, 0xf3, 0xfa, 0xeb, 0x5e,
+  0xe1, 0xa5, 0x3c, 0x79, 0xf1, 0x16, 0x8a, 0x9a, 0xd1, 0x0d, 0x55, 0xae,
+  0x8d, 0x60, 0xe4, 0x90, 0xcd, 0x27, 0x3b, 0x04, 0x2b, 0xfc, 0xc2, 0x01,
+  0xff, 0x00, 0x10, 0x3f, 0xbe, 0xb3, 0x6b, 0x5f, 0x83, 0x15, 0x39, 0x12,
+  0x29, 0x2e, 0x58, 0x88, 0x80, 0xe8, 0x0f, 0xa9, 0x1a, 0x63, 0xc3, 0xb7,
+  0x4e, 0x29, 0xb4, 0xde, 0x3e, 0x6a, 0x82, 0xb1, 0xe2, 0x98, 0x73, 0x24,
+  0x6d, 0x1a, 0xe7, 0x00, 0xec, 0x40, 0xfc, 0x77, 0xd2, 0xf2, 0xe4, 0x86,
+  0xeb, 0x92, 0xe8, 0xcb, 0x29, 0xf2, 0x8b, 0xdd, 0xd1, 0x28, 0xed, 0xb7,
+  0xaa, 0x9b, 0x75, 0x2d, 0x4c, 0x6f, 0x0c, 0x32, 0xbc, 0x4a, 0x92, 0x1f,
+  0x3e, 0x15, 0xb1, 0xe6, 0x1e, 0xbb, 0x68, 0xde, 0x0b, 0xe0, 0xbe, 0x17,
+  0xe2, 0x0b, 0xdd, 0x7b, 0x5c, 0xe5, 0xa8, 0x89, 0xe3, 0x8b, 0xe6, 0xa1,
+  0x2b, 0x22, 0x88, 0x9b, 0x0a, 0x32, 0x47, 0xe7, 0x72, 0x35, 0x44, 0xe2,
+  0x5a, 0x49, 0xe4, 0xba, 0xc7, 0x70, 0x84, 0x08, 0xe6, 0x91, 0x33, 0x50,
+  0x06, 0xc0, 0x38, 0xeb, 0xb7, 0xbe, 0x73, 0xf7, 0xce, 0x9e, 0xf0, 0x7c,
+  0x52, 0xbd, 0xa1, 0x1e, 0x4d, 0xbc, 0x09, 0x48, 0x76, 0x0f, 0xe6, 0xf3,
+  0x6f, 0x9c, 0x7a, 0x7f, 0xd3, 0x5c, 0xb8, 0xe5, 0x58, 0x5b, 0xcb, 0x1e,
+  0x53, 0x33, 0xef, 0xa7, 0x67, 0xce, 0x0f, 0xf8, 0x75, 0x5d, 0xc5, 0x57,
+  0xab, 0x8d, 0x5b, 0xa1, 0x78, 0x69, 0xb9, 0x9d, 0xd8, 0x37, 0xd6, 0xd9,
+  0xf2, 0xa0, 0xf6, 0xc1, 0x3a, 0x9b, 0x8a, 0x6a, 0x20, 0xe1, 0xf4, 0x92,
+  0x89, 0xd4, 0xad, 0x74, 0x51, 0x08, 0x84, 0x6c, 0x30, 0xf1, 0xa0, 0xfa,
+  0x57, 0x1d, 0x80, 0xdf, 0x57, 0xee, 0x1b, 0xe2, 0xfa, 0x8a, 0x3b, 0x74,
+  0x96, 0xfa, 0x0a, 0x95, 0xa6, 0x09, 0x2f, 0x95, 0xd9, 0x72, 0x5d, 0xb1,
+  0xbe, 0x07, 0xa6, 0x4e, 0xaa, 0x3c, 0x6d, 0xc5, 0x7c, 0x41, 0x57, 0x53,
+  0x2a, 0x57, 0xdb, 0xed, 0x13, 0xa0, 0xc8, 0x69, 0x85, 0x0a, 0x17, 0x91,
+  0x7a, 0x0c, 0xb9, 0x05, 0x81, 0xe8, 0x76, 0x23, 0x5b, 0xf4, 0xb9, 0xf1,
+  0xea, 0x9d, 0xc1, 0xb5, 0x43, 0xa1, 0x35, 0x2e, 0x8c, 0xb5, 0x65, 0xa9,
+  0xaf, 0x97, 0xc4, 0xaa, 0x9d, 0xdc, 0x86, 0xca, 0xa3, 0x1c, 0x80, 0x3d,
+  0x46, 0x88, 0x58, 0x23, 0x07, 0x38, 0x27, 0xee, 0x74, 0xc6, 0xe3, 0x70,
+  0x8a, 0xa0, 0x08, 0x7e, 0x4a, 0x3a, 0x52, 0x3f, 0x98, 0x0a, 0x1e, 0xa3,
+  0xbe, 0x83, 0xe1, 0x4b, 0x8d, 0x9e, 0xe7, 0xc4, 0xb3, 0x59, 0xa7, 0x95,
+  0x48, 0x10, 0x12, 0x18, 0xb7, 0x2a, 0xb3, 0x02, 0x36, 0xfd, 0x37, 0xd6,
+  0xa6, 0xdd, 0xf2, 0xc2, 0xb3, 0xf2, 0x4f, 0x43, 0x44, 0x5a, 0xb2, 0xb2,
+  0x39, 0x5d, 0x62, 0x52, 0xd1, 0xac, 0x6a, 0x0f, 0xf3, 0x3f, 0xa7, 0x39,
+  0xfe, 0x9f, 0x5f, 0xd3, 0xbe, 0xad, 0x22, 0xf8, 0xfc, 0x4b, 0x6c, 0xa2,
+  0xb8, 0xcf, 0x6d, 0x7a, 0x3a, 0xaf, 0x07, 0xc2, 0x92, 0x45, 0x1f, 0xcb,
+  0x94, 0xaf, 0x42, 0x3d, 0x0e, 0x3b, 0x63, 0xfa, 0x75, 0x35, 0x87, 0x84,
+  0xc5, 0xf3, 0x88, 0x63, 0xb1, 0x59, 0x68, 0xe3, 0xa9, 0x9a, 0x37, 0x06,
+  0xb8, 0x01, 0x88, 0x69, 0xc7, 0xac, 0x87, 0xb1, 0x3e, 0x9d, 0x75, 0xe8,
+  0x7e, 0x1e, 0xf8, 0x79, 0x62, 0xb6, 0xf0, 0xf1, 0xb4, 0xc9, 0x09, 0x96,
+  0x39, 0x7c, 0xd2, 0xa8, 0x1c, 0xab, 0xcc, 0x7a, 0xf2, 0x81, 0xd3, 0xf5,
+  0xd1, 0x3d, 0x3a, 0xca, 0xa9, 0x85, 0x1c, 0x7f, 0x22, 0xb3, 0xcb, 0xf5,
+  0x34, 0xfc, 0xe3, 0x07, 0x63, 0xeb, 0xa1, 0x16, 0x90, 0xac, 0x98, 0x63,
+  0xbf, 0x5c, 0xe3, 0x5e, 0xac, 0x8f, 0xe1, 0x7f, 0x05, 0x2c, 0x85, 0xcd,
+  0xa8, 0xb0, 0x23, 0xe9, 0x69, 0xdc, 0x81, 0xf6, 0xdf, 0x5c, 0x5d, 0x7e,
+  0x16, 0x70, 0x75, 0x6d, 0x32, 0xc5, 0x15, 0xb8, 0xd1, 0xba, 0x7d, 0x32,
+  0xc0, 0xe4, 0x37, 0xe7, 0x3d, 0x46, 0x97, 0x0d, 0x16, 0x48, 0xaa, 0x6e,
+  0xcb, 0x8e, 0x96, 0x48, 0xc9, 0xfe, 0x09, 0xd8, 0xae, 0x37, 0x1a, 0x7b,
+  0xe8, 0xa2, 0xad, 0x6a, 0x4e, 0x7a, 0x5f, 0x08, 0x4a, 0x14, 0x15, 0x67,
+  0x24, 0x10, 0x18, 0x1e, 0xd8, 0x07, 0xa6, 0x94, 0xd1, 0x5c, 0xae, 0xf6,
+  0x5b, 0xe5, 0x6f, 0x0b, 0x5d, 0x29, 0x62, 0x47, 0x99, 0x4c, 0x4c, 0x40,
+  0xc0, 0x52, 0x08, 0xc3, 0x7b, 0x83, 0x8d, 0x7a, 0x0b, 0x82, 0xb8, 0x6a,
+  0x9b, 0x84, 0xec, 0xa6, 0x86, 0x12, 0x66, 0x2f, 0x33, 0x3b, 0x38, 0x5d,
+  0xdb, 0x24, 0xe3, 0x3f, 0x8c, 0x0d, 0x65, 0x9f, 0xed, 0x01, 0x62, 0x9a,
+  0xae, 0xb0, 0x5f, 0xe8, 0x23, 0xfe, 0x65, 0x2a, 0xac, 0x53, 0x28, 0x19,
+  0x66, 0xe6, 0x3b, 0x6d, 0xfa, 0x7e, 0xba, 0xbc, 0x9a, 0x5f, 0x15, 0x7d,
+  0x93, 0x26, 0x0e, 0x0a, 0x79, 0xb3, 0xc8, 0x6a, 0xd6, 0x38, 0xdc, 0x44,
+  0xec, 0xdf, 0x50, 0x1e, 0x51, 0x93, 0xad, 0x1f, 0x86, 0xb8, 0x56, 0x86,
+  0x8e, 0x96, 0x5a, 0x8b, 0xad, 0x6c, 0x75, 0xf7, 0x06, 0x24, 0x53, 0x25,
+  0x31, 0xe6, 0x55, 0x51, 0xd1, 0xbd, 0xf3, 0xfb, 0x67, 0x59, 0x9d, 0x82,
+  0xc9, 0x5f, 0x50, 0xcd, 0x4b, 0x77, 0xb9, 0xc9, 0x46, 0x01, 0xf3, 0x43,
+  0x19, 0x2c, 0xfd, 0x7e, 0x9d, 0xb6, 0x1e, 0xfd, 0x71, 0xe9, 0xad, 0x83,
+  0x82, 0xeb, 0xec, 0x7c, 0x2b, 0x42, 0x20, 0xac, 0x95, 0x90, 0x22, 0x05,
+  0xf1, 0xa5, 0x39, 0xe5, 0x03, 0xa0, 0x19, 0xdf, 0x03, 0x5c, 0xfd, 0x2e,
+  0x9a, 0x0a, 0x4d, 0x4d, 0x70, 0x2b, 0x0e, 0x15, 0x16, 0xdb, 0x14, 0xd4,
+  0xb5, 0x65, 0x65, 0x9a, 0xa2, 0x96, 0x24, 0x11, 0xc4, 0x1c, 0xe1, 0x10,
+  0x05, 0xe6, 0x8c, 0x1d, 0x83, 0x0c, 0xe7, 0x27, 0x62, 0x75, 0x50, 0xbc,
+  0x3c, 0x31, 0x40, 0x1a, 0xa9, 0xe3, 0x86, 0x28, 0xb2, 0xbb, 0x26, 0x02,
+  0xe4, 0xee, 0x4e, 0x37, 0x3b, 0xea, 0xdd, 0xc4, 0xfc, 0x5f, 0xc3, 0xb3,
+  0x55, 0xca, 0xd4, 0xa6, 0x59, 0x63, 0xa9, 0x1c, 0xa5, 0xd6, 0x12, 0xbc,
+  0x8c, 0x77, 0x27, 0x27, 0xec, 0x75, 0x97, 0xfc, 0x4c, 0xbd, 0xd2, 0x57,
+  0xc9, 0x45, 0x6b, 0xb5, 0xac, 0x92, 0xa1, 0x72, 0xd3, 0xc8, 0xfd, 0x5d,
+  0xb3, 0x85, 0xfc, 0x60, 0xe8, 0x73, 0x60, 0x59, 0x73, 0xa8, 0x63, 0x92,
+  0xa5, 0xd8, 0x39, 0x60, 0xb7, 0x70, 0xc4, 0x5c, 0x4d, 0x6b, 0xa2, 0x9e,
+  0xba, 0x13, 0x41, 0x72, 0x86, 0xe1, 0x55, 0x2b, 0xe3, 0xc2, 0x81, 0x58,
+  0xf8, 0x64, 0x9c, 0x2a, 0xef, 0x8d, 0xce, 0x75, 0xbd, 0x7c, 0x19, 0xf8,
+  0x6f, 0x6e, 0xe1, 0xbb, 0x5b, 0x54, 0xdd, 0x12, 0x9e, 0xaa, 0xf1, 0x3a,
+  0x7f, 0x3b, 0x1b, 0xf8, 0x00, 0xff, 0x00, 0x42, 0xff, 0x00, 0x99, 0xfb,
+  0x6a, 0x9b, 0xf0, 0xaf, 0x86, 0xe8, 0xa8, 0xab, 0x1e, 0xbe, 0xbd, 0x44,
+  0xd5, 0x2a, 0x02, 0xd3, 0x29, 0xc0, 0x45, 0x73, 0xd4, 0xe4, 0xfe, 0x9f,
+  0x9d, 0x69, 0xca, 0x12, 0x95, 0xa4, 0x96, 0xa6, 0x59, 0x10, 0xca, 0x87,
+  0xf9, 0x3c, 0xbb, 0x02, 0x3a, 0x01, 0xeb, 0xae, 0x9e, 0x1c, 0xf1, 0xde,
+  0xe1, 0x1e, 0x90, 0xec, 0x4e, 0x8f, 0x1f, 0x71, 0x08, 0xab, 0xa8, 0xe2,
+  0x6b, 0xba, 0x48, 0x42, 0xc2, 0x2b, 0xa6, 0x0b, 0xca, 0x30, 0x48, 0xe7,
+  0x6e, 0xfa, 0x56, 0x68, 0xd5, 0x7c, 0xb3, 0x4e, 0x52, 0x2e, 0x6c, 0x2a,
+  0x06, 0xc9, 0xfb, 0xea, 0xc1, 0xc4, 0x66, 0x25, 0xe2, 0x1b, 0x97, 0x8a,
+  0x55, 0x54, 0xd6, 0x4b, 0x82, 0x4f, 0x7e, 0x73, 0xa5, 0xcd, 0x5b, 0x68,
+  0x84, 0x34, 0x6f, 0x39, 0x72, 0x06, 0xea, 0x91, 0x13, 0xbf, 0xa6, 0x4e,
+  0x9e, 0x80, 0xdc, 0xb7, 0xbb, 0x42, 0xd9, 0x28, 0xa4, 0x69, 0x0c, 0x18,
+  0x0f, 0x01, 0xf3, 0x73, 0xc8, 0x7d, 0xfb, 0x77, 0xfd, 0x3f, 0x5d, 0x10,
+  0x94, 0x74, 0xb1, 0xc7, 0x35, 0x74, 0xd4, 0x08, 0xc8, 0x8f, 0xc8, 0x85,
+  0x48, 0xe6, 0x66, 0x3d, 0xcf, 0x36, 0x36, 0xf7, 0xc9, 0xd3, 0x4a, 0x29,
+  0x20, 0x92, 0x9d, 0x9c, 0x7c, 0xda, 0xc5, 0xc9, 0xe5, 0x0c, 0xa3, 0xcb,
+  0xb6, 0xc7, 0x19, 0xce, 0x34, 0x65, 0x0a, 0x2a, 0x70, 0x65, 0x5d, 0xa5,
+  0xed, 0xf4, 0x37, 0x25, 0xad, 0x71, 0x22, 0xcd, 0x3c, 0x38, 0x92, 0x26,
+  0x52, 0x30, 0x50, 0x9c, 0x15, 0x23, 0xef, 0x8c, 0x9d, 0x66, 0xcc, 0xd5,
+  0xd3, 0x1a, 0x8a, 0xbb, 0xc2, 0x22, 0x75, 0x3f, 0xfb, 0x7d, 0x31, 0xe8,
+  0x3f, 0xb6, 0xad, 0xd6, 0x3a, 0x8a, 0x51, 0x4d, 0x2b, 0x23, 0x72, 0xa2,
+  0x2a, 0xf3, 0x85, 0x3b, 0x92, 0x37, 0xd5, 0x6a, 0x4a, 0x79, 0x67, 0xaf,
+  0x58, 0x99, 0x8e, 0xc0, 0x02, 0x71, 0x8f, 0xce, 0xa1, 0xbd, 0x17, 0xb7,
+  0x57, 0xab, 0xd3, 0x33, 0x47, 0x95, 0x1e, 0x6c, 0xec, 0x40, 0x18, 0xdc,
+  0x69, 0x69, 0x50, 0x89, 0x21, 0xcf, 0x16, 0xd4, 0x51, 0x57, 0x33, 0x54,
+  0x5a, 0xe3, 0x96, 0x9a, 0x90, 0xb7, 0x86, 0x91, 0xbb, 0xf3, 0x90, 0x40,
+  0x01, 0x8e, 0x70, 0x3b, 0xe7, 0x1e, 0x9a, 0xa5, 0x5c, 0x33, 0x1a, 0x1f,
+  0x50, 0x71, 0x9f, 0x6d, 0x34, 0x8e, 0xea, 0x6a, 0x03, 0x25, 0x53, 0x20,
+  0x55, 0xc9, 0x18, 0x1f, 0x56, 0x7a, 0x69, 0x5d, 0x5f, 0x33, 0xc8, 0x59,
+  0x17, 0x2b, 0x9e, 0x50, 0xa7, 0xbe, 0x4e, 0xb7, 0x3a, 0xa5, 0x43, 0x10,
+  0x45, 0x86, 0xde, 0x64, 0x8b, 0xe6, 0x0a, 0x9e, 0x57, 0x3b, 0x9f, 0x5e,
+  0xe7, 0x47, 0x5c, 0x2e, 0x73, 0xd1, 0x8f, 0x06, 0x9e, 0x34, 0x03, 0xa2,
+  0x67, 0xaa, 0xfb, 0xfb, 0xe9, 0xc5, 0x24, 0x42, 0x1b, 0x4c, 0x54, 0xa5,
+  0x70, 0xc1, 0x41, 0x03, 0x3d, 0xf1, 0xbe, 0xab, 0xf7, 0x57, 0x57, 0x06,
+  0x1e, 0x5c, 0x31, 0x38, 0x07, 0x3d, 0x3b, 0x1d, 0x13, 0xe1, 0x10, 0x29,
+  0x6e, 0x8a, 0x38, 0x42, 0xa2, 0x9e, 0x62, 0x7e, 0x7e, 0x69, 0x79, 0x5d,
+  0xf1, 0xf5, 0xab, 0x0c, 0xfe, 0x31, 0xb6, 0xab, 0xa1, 0x82, 0x46, 0x00,
+  0x19, 0xc6, 0xda, 0x7b, 0xc4, 0xd5, 0x14, 0x4c, 0x29, 0x61, 0xa3, 0x62,
+  0xea, 0xb1, 0x00, 0x77, 0xd8, 0x10, 0x31, 0xa4, 0x72, 0xe0, 0x81, 0xeb,
+  0xd7, 0x48, 0x28, 0x69, 0xc3, 0x17, 0x7a, 0xa8, 0xae, 0x94, 0x74, 0x11,
+  0x95, 0x58, 0x4c, 0x86, 0x46, 0x23, 0xea, 0x27, 0x38, 0xc6, 0x7d, 0x37,
+  0xd3, 0x7f, 0x88, 0x52, 0x98, 0xea, 0xad, 0x92, 0x54, 0x42, 0x66, 0xa5,
+  0xf1, 0x5c, 0x4b, 0xca, 0x3a, 0x74, 0xc7, 0xe9, 0xa4, 0x1c, 0x3f, 0x02,
+  0xa7, 0x10, 0x51, 0xd5, 0xce, 0x00, 0x8c, 0x2f, 0x2c, 0x67, 0xd5, 0xb2,
+  0x3f, 0xeb, 0xa6, 0xff, 0x00, 0x11, 0x24, 0x35, 0x37, 0x33, 0x42, 0x8c,
+  0x24, 0x8e, 0x0a, 0x6f, 0x17, 0x38, 0xc6, 0x0f, 0x36, 0xff, 0x00, 0xd8,
+  0x69, 0xa9, 0x9a, 0xa2, 0x9d, 0xc6, 0x8e, 0xed, 0xd1, 0xd2, 0x55, 0xdc,
+  0xeb, 0xa1, 0xf9, 0x8a, 0x9a, 0x87, 0x34, 0xab, 0x94, 0xc6, 0x59, 0x90,
+  0x6f, 0x93, 0xbf, 0xb8, 0x3b, 0x76, 0x07, 0x3a, 0x86, 0xbe, 0x99, 0x60,
+  0xa2, 0x8a, 0x51, 0x3a, 0x48, 0x5d, 0x1b, 0x1c, 0x9b, 0x80, 0x01, 0xd8,
+  0x7e, 0x9a, 0x67, 0xf0, 0xfe, 0xe5, 0x4e, 0xb5, 0xe2, 0x09, 0x56, 0x34,
+  0x9a, 0xa9, 0x42, 0x2b, 0x9f, 0xeb, 0x5c, 0x12, 0xc8, 0x7d, 0x71, 0xb6,
+  0x89, 0xbe, 0x51, 0xd3, 0x43, 0xc3, 0x6f, 0x14, 0x14, 0xfe, 0x1c, 0xb5,
+  0x35, 0xd2, 0x95, 0x2b, 0xf4, 0x80, 0x0f, 0xfd, 0x3f, 0x7d, 0x18, 0x70,
+  0x96, 0xdc, 0x8e, 0x25, 0x66, 0xdf, 0x50, 0x94, 0xce, 0xd8, 0x3c, 0x8c,
+  0xe8, 0xbc, 0xad, 0xff, 0x00, 0x31, 0x1a, 0xd2, 0xf8, 0x2a, 0xfa, 0x95,
+  0x51, 0x0a, 0x3a, 0x89, 0x57, 0xc7, 0x85, 0x54, 0x33, 0x67, 0xeb, 0xf7,
+  0xc6, 0xb3, 0x14, 0x12, 0x47, 0x2a, 0x4b, 0x9e, 0x56, 0x55, 0xc7, 0x4f,
+  0xdf, 0x47, 0xdb, 0xe9, 0xdc, 0x89, 0x24, 0x8e, 0x69, 0x3c, 0x58, 0xc0,
+  0x20, 0xe7, 0x7d, 0x23, 0x24, 0x2c, 0x76, 0xa3, 0x12, 0xcb, 0x1a, 0x63,
+  0x5f, 0x8b, 0x8d, 0x2c, 0x7c, 0x65, 0x6b, 0x95, 0xc7, 0x3c, 0x26, 0x9b,
+  0xc9, 0xf6, 0xe6, 0x20, 0xe9, 0xcf, 0x0e, 0xdb, 0x79, 0x28, 0xe9, 0xeb,
+  0x4c, 0x69, 0x53, 0x12, 0x02, 0x15, 0x17, 0x62, 0x8d, 0xd8, 0xe4, 0x63,
+  0x3d, 0x08, 0xdf, 0x3d, 0x75, 0x56, 0xe2, 0x4a, 0xa9, 0xae, 0x94, 0xb6,
+  0xea, 0xa9, 0x9d, 0x9a, 0x5a, 0x34, 0x31, 0xb0, 0x27, 0x24, 0x8d, 0x59,
+  0xb8, 0x3e, 0xfb, 0x4d, 0x05, 0xa4, 0xc7, 0xe2, 0x10, 0x00, 0xcf, 0xeb,
+  0xac, 0xba, 0xcd, 0xff, 0x00, 0x12, 0x94, 0x7f, 0x66, 0x5c, 0xf8, 0x9c,
+  0x31, 0xa4, 0xbd, 0x0b, 0xae, 0x94, 0xf5, 0x35, 0x57, 0x24, 0x9c, 0x2a,
+  0xd2, 0x4a, 0xbb, 0xa2, 0xc6, 0xb8, 0x52, 0x77, 0xd8, 0x8f, 0x5e, 0xbb,
+  0xea, 0xe7, 0xc0, 0x33, 0x4b, 0x5e, 0xcd, 0x6f, 0xa6, 0xa0, 0x98, 0x56,
+  0x49, 0x11, 0x90, 0x2f, 0x3a, 0x9e, 0x60, 0x33, 0xcd, 0xbf, 0xdc, 0x77,
+  0xd2, 0x9a, 0xea, 0xda, 0x4b, 0x8d, 0xb8, 0xd5, 0xd3, 0xef, 0x24, 0x4d,
+  0xfc, 0xc0, 0x3b, 0x80, 0x0e, 0xfa, 0xe3, 0xfd, 0x9f, 0xa6, 0xa9, 0x8f,
+  0x8d, 0xe3, 0x7a, 0x58, 0x64, 0x92, 0x94, 0xb3, 0x78, 0xf2, 0xe3, 0xca,
+  0x85, 0x81, 0x3f, 0xe5, 0xfb, 0xe9, 0x2b, 0x4d, 0x1d, 0x42, 0x70, 0x97,
+  0x4c, 0xcb, 0x8b, 0x1a, 0xcb, 0x3d, 0xac, 0x86, 0xff, 0x00, 0x59, 0x70,
+  0x8e, 0xb8, 0xc9, 0xc8, 0xb1, 0x78, 0x2c, 0x47, 0x29, 0x52, 0x1e, 0x33,
+  0xbe, 0xcf, 0x9e, 0xfa, 0xfb, 0xc3, 0x3c, 0x45, 0xf2, 0x97, 0x07, 0xaa,
+  0xaa, 0xa7, 0x6a, 0x88, 0x79, 0x1a, 0x29, 0x23, 0x56, 0xe5, 0x3b, 0xff,
+  0x00, 0x50, 0x3e, 0xda, 0xf4, 0x9d, 0xc7, 0xe1, 0x87, 0x09, 0x71, 0xc5,
+  0x44, 0x57, 0x1b, 0xe5, 0xba, 0x4f, 0x1a, 0x35, 0x18, 0x96, 0x39, 0x0c,
+  0x52, 0x3f, 0xff, 0x00, 0x2c, 0x75, 0x03, 0xb6, 0x7a, 0x6a, 0x7a, 0xcf,
+  0x84, 0x1c, 0x0b, 0x47, 0x69, 0x31, 0x52, 0xd9, 0xe4, 0xfe, 0x5e, 0x09,
+  0x26, 0xa5, 0xcf, 0x3e, 0x3f, 0xc5, 0x93, 0xbe, 0xb5, 0xc7, 0xf1, 0xca,
+  0x0a, 0xa0, 0xcd, 0x0f, 0x48, 0xa3, 0xd3, 0x3c, 0xf1, 0x76, 0xe2, 0x2b,
+  0xd4, 0x42, 0xa2, 0xec, 0xb6, 0xf8, 0x3f, 0x85, 0x48, 0xe9, 0x4f, 0x13,
+  0xc9, 0x4f, 0xcf, 0x18, 0x20, 0x79, 0x4a, 0xbe, 0xc7, 0x9b, 0x6c, 0xed,
+  0x8d, 0xf4, 0xca, 0xdf, 0x52, 0xf7, 0x38, 0x17, 0x99, 0x05, 0x4f, 0x24,
+  0x79, 0x76, 0x07, 0x00, 0x1f, 0x5d, 0x6b, 0x7c, 0x75, 0xc1, 0x75, 0x1c,
+  0x69, 0xc3, 0x27, 0x86, 0xed, 0x2b, 0x4b, 0x4b, 0x0c, 0x72, 0x46, 0xf9,
+  0x71, 0xca, 0xaa, 0x17, 0xd9, 0x47, 0xbe, 0xa4, 0xb6, 0xfc, 0x19, 0x16,
+  0xfb, 0x04, 0x74, 0x34, 0xf7, 0x58, 0xc4, 0xf8, 0xe5, 0x92, 0x4f, 0x00,
+  0xe1, 0x86, 0x37, 0xfe, 0xad, 0x36, 0x1a, 0x79, 0x63, 0xfa, 0x93, 0x26,
+  0x99, 0xc1, 0xd2, 0xe4, 0xf2, 0xa7, 0x19, 0x54, 0xc8, 0x95, 0x55, 0x12,
+  0x42, 0x39, 0x49, 0x52, 0x83, 0x7e, 0x8b, 0xd3, 0x1a, 0x6f, 0xf0, 0x5b,
+  0xe1, 0x07, 0x11, 0xf1, 0xb5, 0xca, 0x1a, 0xc3, 0x1c, 0xf6, 0xdb, 0x42,
+  0x38, 0xf1, 0x2b, 0xdc, 0x63, 0x98, 0x67, 0xa4, 0x7f, 0xe2, 0x6f, 0xed,
+  0xaf, 0x57, 0xf0, 0x2f, 0xc2, 0x2e, 0x18, 0xe1, 0xe0, 0x2a, 0xeb, 0x28,
+  0xa9, 0xee, 0x97, 0x2e, 0x6e, 0x6f, 0x98, 0xa8, 0x8f, 0x98, 0x27, 0xb2,
+  0xa9, 0xd8, 0x7d, 0xfa, 0xea, 0xf4, 0xf8, 0xa7, 0x41, 0x1c, 0x68, 0xa8,
+  0x8b, 0xb0, 0x54, 0x18, 0x03, 0xf1, 0xad, 0x31, 0x80, 0xd5, 0x8b, 0x81,
+  0x67, 0x06, 0x70, 0xb5, 0x9f, 0x84, 0xac, 0xd1, 0xda, 0xec, 0xb4, 0xa2,
+  0x18, 0x86, 0xf2, 0x3b, 0x79, 0xa4, 0x99, 0xfb, 0xbb, 0xb7, 0x56, 0x27,
+  0x4f, 0x34, 0x2a, 0x4a, 0x09, 0xeb, 0x83, 0xa9, 0x1a, 0x42, 0xcb, 0x82,
+  0x34, 0xc4, 0x86, 0x25, 0x47, 0x53, 0x49, 0xc8, 0xa4, 0x8e, 0xb8, 0xce,
+  0xa0, 0xa0, 0xac, 0x4a, 0x99, 0x5c, 0x67, 0x74, 0x38, 0x23, 0x5c, 0xd5,
+  0x49, 0x88, 0xcf, 0xdb, 0x1a, 0x4d, 0x6b, 0x99, 0xe3, 0xba, 0x4a, 0xc4,
+  0xe1, 0x1d, 0xb1, 0xfa, 0x77, 0xd5, 0xd1, 0x76, 0x3c, 0xbe, 0xb4, 0xd1,
+  0xda, 0x2a, 0xa4, 0xa6, 0xe6, 0xf1, 0x92, 0x26, 0x64, 0x55, 0xea, 0xc4,
+  0x02, 0x70, 0x3d, 0xcf, 0xe7, 0x59, 0x27, 0x0d, 0xdc, 0xe9, 0xaf, 0xfc,
+  0x3f, 0x70, 0x14, 0x37, 0xea, 0x5b, 0x6c, 0xaf, 0x2f, 0x8d, 0x53, 0x1c,
+  0xc9, 0x99, 0xe3, 0x20, 0x8c, 0x0f, 0x36, 0x01, 0xf7, 0x6d, 0xfa, 0x0d,
+  0x6c, 0xaa, 0x43, 0x2e, 0x7a, 0x8d, 0x79, 0x63, 0xe3, 0x1c, 0x6f, 0x07,
+  0xc4, 0xab, 0xbc, 0x64, 0x15, 0xcb, 0xab, 0xa6, 0xfb, 0x10, 0xca, 0x0f,
+  0xfd, 0xfd, 0xf5, 0x8f, 0x59, 0xe3, 0x14, 0xc4, 0x67, 0x7c, 0x07, 0x3d,
+  0x86, 0xae, 0xa6, 0xf1, 0xf2, 0xc6, 0x76, 0xf1, 0x5c, 0xb3, 0x25, 0x64,
+  0x47, 0x21, 0x80, 0x04, 0xe7, 0x23, 0x6d, 0xfd, 0x06, 0xa6, 0x58, 0x6e,
+  0xb6, 0x8b, 0x85, 0x3f, 0xf1, 0xa8, 0x12, 0xbe, 0x87, 0xc4, 0x1b, 0xcd,
+  0x1f, 0x37, 0x32, 0xfb, 0x6f, 0xb6, 0x46, 0xaa, 0xdc, 0x1d, 0x7a, 0xac,
+  0xb3, 0x5e, 0xa9, 0xe5, 0x49, 0x0f, 0x82, 0xf2, 0x72, 0xcc, 0xa4, 0xed,
+  0xca, 0x7a, 0x9c, 0x7e, 0x9a, 0xd9, 0xb8, 0x9a, 0x4b, 0x5c, 0xf6, 0xb8,
+  0xd2, 0x3a, 0x87, 0xa8, 0xe6, 0x41, 0x18, 0x43, 0x16, 0x39, 0x97, 0xa8,
+  0xdf, 0x3d, 0x80, 0xd7, 0x2b, 0x0e, 0x24, 0xed, 0x27, 0xc9, 0x96, 0x00,
+  0x97, 0x3e, 0x1b, 0xe1, 0x3b, 0x85, 0xbd, 0x6a, 0xa8, 0x2d, 0xa1, 0x15,
+  0x9d, 0x9d, 0x0d, 0x3b, 0x91, 0x90, 0x47, 0x42, 0x0e, 0x40, 0x3e, 0xda,
+  0xce, 0xab, 0xb8, 0x52, 0x25, 0xbf, 0x41, 0x55, 0x43, 0x89, 0xd2, 0x22,
+  0xee, 0x61, 0x99, 0x72, 0xcb, 0xb1, 0x23, 0x3e, 0xa0, 0x6a, 0xdf, 0x6b,
+  0x35, 0x34, 0xa1, 0xe9, 0xe9, 0x29, 0x66, 0x78, 0x26, 0x3c, 0xd0, 0xb4,
+  0x9f, 0x48, 0x1d, 0xf7, 0xef, 0xbe, 0x35, 0xfa, 0x0a, 0x86, 0xc4, 0x93,
+  0xff, 0x00, 0x0a, 0x32, 0xd6, 0x73, 0xf8, 0x11, 0xc9, 0x10, 0xc1, 0x1b,
+  0xf4, 0xc7, 0x7e, 0x9a, 0xd9, 0x87, 0x0b, 0x4b, 0x73, 0x8d, 0x30, 0xc9,
+  0x78, 0x2a, 0xba, 0xae, 0x59, 0x05, 0xbe, 0xaa, 0x99, 0x24, 0xab, 0x8d,
+  0x1b, 0xc3, 0x90, 0x30, 0x5f, 0x10, 0x0f, 0xe9, 0xdf, 0x62, 0x71, 0xd3,
+  0xed, 0xae, 0xb8, 0x8b, 0x88, 0xa9, 0x25, 0xa6, 0xf9, 0x95, 0x72, 0xf0,
+  0x42, 0x07, 0x8d, 0x86, 0xc4, 0x91, 0x63, 0xa8, 0xc1, 0xed, 0x9d, 0xb4,
+  0x9b, 0x88, 0xaa, 0xaf, 0x74, 0x9c, 0xa2, 0xae, 0x90, 0x46, 0x86, 0x40,
+  0x1d, 0x8a, 0x6e, 0x7a, 0xec, 0x7d, 0xf6, 0xd6, 0x7b, 0xc7, 0x46, 0x94,
+  0x5e, 0xb1, 0x49, 0x17, 0x20, 0x68, 0xd5, 0xa4, 0x6c, 0xec, 0xcd, 0xf6,
+  0xfc, 0xe8, 0x31, 0xe9, 0xa3, 0x82, 0x4f, 0x22, 0xec, 0xb9, 0x45, 0x41,
+  0x5a, 0x33, 0xfe, 0x32, 0x88, 0x0e, 0x29, 0xbb, 0xbb, 0x10, 0x8a, 0x2b,
+  0x67, 0x39, 0x27, 0xa9, 0xf1, 0x0e, 0x97, 0x50, 0xbc, 0x3c, 0xe1, 0xde,
+  0x15, 0x9f, 0x1b, 0x85, 0x27, 0x6d, 0x1b, 0xc5, 0x4b, 0x2d, 0x47, 0x17,
+  0xde, 0x7c, 0x4f, 0xf8, 0x6b, 0x5f, 0x38, 0x07, 0xff, 0x00, 0xf4, 0x3b,
+  0x6b, 0xf5, 0x05, 0x0b, 0x4a, 0xc0, 0x47, 0xf4, 0xf5, 0x63, 0x8f, 0xdb,
+  0x4c, 0x7d, 0x99, 0xe7, 0xf6, 0x67, 0x75, 0x35, 0xb3, 0x4c, 0xea, 0xef,
+  0x4e, 0xab, 0x10, 0xc7, 0x94, 0x36, 0xe7, 0xf3, 0x8d, 0x47, 0x25, 0xc2,
+  0xae, 0xaa, 0x9b, 0x7c, 0xc4, 0x80, 0x91, 0x84, 0x63, 0x8d, 0xf4, 0x5d,
+  0x72, 0x43, 0x0c, 0x4d, 0x1b, 0x46, 0xdb, 0x0c, 0x82, 0x47, 0x7d, 0x2c,
+  0x89, 0x83, 0x92, 0x80, 0xf2, 0xe3, 0xaf, 0xbe, 0x95, 0x96, 0xe5, 0xd8,
+  0x1b, 0xda, 0x54, 0x86, 0x9c, 0x39, 0x17, 0xf3, 0x86, 0xd8, 0xdc, 0xef,
+  0xa2, 0xae, 0xeb, 0x43, 0x25, 0xd6, 0x1a, 0x6a, 0xe0, 0x48, 0x68, 0x18,
+  0xa9, 0x53, 0x82, 0xa7, 0x98, 0x60, 0xff, 0x00, 0x7d, 0x15, 0xc2, 0x54,
+  0xdf, 0x54, 0x84, 0x63, 0xcb, 0xb1, 0xf5, 0xd5, 0x4e, 0xfd, 0x5f, 0x3b,
+  0xf1, 0x7b, 0xbb, 0xb6, 0x4c, 0x4e, 0x23, 0x5f, 0x60, 0x32, 0x31, 0xa7,
+  0x41, 0xf2, 0x83, 0x8b, 0x0b, 0xbc, 0x59, 0x1a, 0x98, 0x37, 0xcb, 0xc8,
+  0x25, 0x55, 0x19, 0x23, 0x9b, 0x24, 0x7e, 0x7b, 0xe8, 0x1b, 0x4a, 0xab,
+  0xd5, 0xc4, 0x65, 0x1c, 0xcc, 0x18, 0x60, 0x74, 0xdb, 0x1a, 0xb5, 0xc1,
+  0x50, 0x95, 0x36, 0xf8, 0xa7, 0x45, 0x1e, 0x2c, 0x43, 0x1b, 0x9e, 0xa4,
+  0x6c, 0x47, 0xe7, 0x55, 0x4a, 0x80, 0x61, 0xb9, 0x4b, 0x2a, 0x46, 0xd1,
+  0xa3, 0x13, 0xca, 0x06, 0xe4, 0x12, 0x7a, 0x69, 0xcb, 0xc3, 0x25, 0x16,
+  0x5a, 0x89, 0x12, 0x47, 0x91, 0xf5, 0x0d, 0xf5, 0x55, 0xe2, 0x66, 0x4a,
+  0x69, 0x0d, 0x44, 0x67, 0xcf, 0x9f, 0xd0, 0xe9, 0x9b, 0xd4, 0x4c, 0x82,
+  0x92, 0x26, 0x86, 0x68, 0xda, 0xa1, 0x80, 0x42, 0xd1, 0xf6, 0xe8, 0x71,
+  0xbf, 0x5d, 0x53, 0x78, 0xb6, 0xa1, 0xa3, 0xe2, 0x1a, 0x8a, 0x0c, 0x3a,
+  0xc3, 0x4f, 0x21, 0x8c, 0xc6, 0xdd, 0x43, 0x03, 0xe6, 0xcf, 0xbe, 0x46,
+  0xaf, 0x3e, 0x54, 0xfc, 0x50, 0x49, 0x86, 0x96, 0x79, 0x5b, 0xc4, 0x73,
+  0x92, 0x7a, 0xeb, 0x87, 0xcf, 0x36, 0x74, 0x4b, 0x18, 0xe5, 0xa7, 0x8e,
+  0x48, 0x54, 0x05, 0x2b, 0xa2, 0xf8, 0x7e, 0xdf, 0x51, 0x57, 0x5c, 0xb2,
+  0x47, 0x1a, 0x48, 0x91, 0x9e, 0x66, 0x0f, 0x9c, 0x1c, 0x1e, 0x87, 0x1a,
+  0x5a, 0xe8, 0xb3, 0xba, 0x41, 0xfc, 0x3e, 0x38, 0x6b, 0xe4, 0x6c, 0x3c,
+  0x11, 0x16, 0x89, 0x39, 0x72, 0x09, 0x6d, 0xc1, 0x3f, 0x63, 0x83, 0xa8,
+  0x6d, 0xa9, 0x1d, 0x4b, 0x9a, 0xaa, 0x89, 0x32, 0x5c, 0x31, 0xa8, 0x90,
+  0x8e, 0x63, 0xd3, 0xaf, 0xf6, 0xc6, 0xac, 0x17, 0xb1, 0x59, 0x32, 0xcc,
+  0x95, 0x0b, 0x0a, 0xf9, 0x08, 0x41, 0x1a, 0x72, 0xa8, 0xff, 0x00, 0x97,
+  0x19, 0xd2, 0x9b, 0x3c, 0xd1, 0xc0, 0x94, 0x91, 0x14, 0x42, 0xf2, 0xc0,
+  0xf0, 0x37, 0x30, 0xcf, 0x29, 0x23, 0x63, 0xa6, 0x23, 0x7e, 0x9f, 0x95,
+  0x60, 0xdc, 0x2d, 0x22, 0xcb, 0x0c, 0x88, 0xcf, 0x29, 0xa9, 0x86, 0x63,
+  0x24, 0x4c, 0xa4, 0xe5, 0x81, 0x1d, 0xf1, 0xf6, 0xd5, 0xba, 0x3a, 0xb8,
+  0xab, 0xf8, 0x6e, 0x38, 0x48, 0x65, 0x9e, 0x4f, 0x17, 0x92, 0x10, 0x3e,
+  0x97, 0x56, 0xff, 0x00, 0x3c, 0xe3, 0x3e, 0xda, 0x43, 0xc3, 0x4d, 0x10,
+  0xb9, 0x1f, 0x91, 0x4c, 0xcb, 0x4e, 0x18, 0xbc, 0x8c, 0x00, 0x51, 0xb7,
+  0x98, 0x31, 0x3d, 0xbb, 0x0f, 0x4d, 0xb5, 0xf2, 0x9f, 0xf9, 0xbc, 0x49,
+  0x0c, 0x85, 0x84, 0x8b, 0x34, 0x26, 0xa2, 0x6c, 0x9c, 0x98, 0xf2, 0x32,
+  0xc0, 0x1e, 0xfb, 0xe3, 0xf4, 0xd1, 0xa6, 0x5a, 0x85, 0x4a, 0xc8, 0x61,
+  0x91, 0x7c, 0xa9, 0x22, 0x81, 0x20, 0x1f, 0x4b, 0x0e, 0x87, 0xd3, 0xef,
+  0xa2, 0x62, 0x63, 0x4d, 0x2a, 0x54, 0x14, 0xe5, 0x0c, 0x4a, 0xb2, 0xe7,
+  0xb6, 0x86, 0x42, 0xf2, 0x09, 0x9d, 0xfe, 0xb2, 0xdc, 0xf9, 0xf7, 0x27,
+  0x4c, 0xae, 0x54, 0xc1, 0x6d, 0xf4, 0xd5, 0x87, 0xac, 0xab, 0xca, 0xdf,
+  0x71, 0xd3, 0x43, 0x66, 0xcb, 0x21, 0x30, 0x14, 0xb9, 0xff, 0x00, 0x31,
+  0x1e, 0x28, 0x66, 0x5c, 0x83, 0x8d, 0x98, 0x7d, 0xf4, 0x1d, 0xd1, 0x15,
+  0x2c, 0xd5, 0x6a, 0xb1, 0xf3, 0x34, 0x28, 0xd2, 0x28, 0x0c, 0x40, 0x20,
+  0x03, 0xb1, 0xc7, 0x51, 0xa7, 0xd1, 0x47, 0xf3, 0x02, 0xcc, 0x5d, 0xb9,
+  0xd4, 0xc6, 0xeb, 0x9f, 0x42, 0x08, 0x1a, 0x89, 0x21, 0x8d, 0x2e, 0x8f,
+  0x04, 0xcb, 0x98, 0xca, 0xb0, 0xfb, 0x8d, 0x4b, 0x24, 0xe3, 0xc1, 0x4b,
+  0xb2, 0x99, 0x3c, 0x08, 0xe4, 0x32, 0x25, 0x24, 0x72, 0xec, 0xdc, 0xf2,
+  0x16, 0xc8, 0xef, 0xb6, 0x33, 0x8d, 0x6b, 0x3f, 0x09, 0x67, 0xa2, 0xb4,
+  0xf1, 0xc5, 0x80, 0xc1, 0x75, 0x49, 0x12, 0xa2, 0xa1, 0x44, 0xa8, 0xb1,
+  0x91, 0xb6, 0x3a, 0x80, 0x7b, 0x7f, 0xae, 0xa9, 0x13, 0x9b, 0x5d, 0xb1,
+  0x27, 0xa2, 0xaf, 0x94, 0xc0, 0xc8, 0xc7, 0xc1, 0x65, 0x21, 0x81, 0x5c,
+  0xe0, 0x65, 0x7e, 0xda, 0x55, 0x45, 0x55, 0x15, 0x1d, 0xca, 0x39, 0x29,
+  0xe4, 0x2b, 0x89, 0x39, 0xe1, 0x60, 0x70, 0xcb, 0x83, 0xdb, 0xdb, 0x52,
+  0x16, 0x9f, 0x28, 0xe7, 0x38, 0xf2, 0x7b, 0xea, 0x4b, 0xcd, 0x6d, 0xbe,
+  0xef, 0x4d, 0x45, 0x0d, 0xb6, 0x69, 0xe8, 0x66, 0x1b, 0xce, 0xb9, 0x21,
+  0x0f, 0xf9, 0x68, 0x8b, 0xdf, 0x11, 0x4f, 0x47, 0x75, 0xa3, 0xa0, 0xa6,
+  0xb4, 0xcd, 0x58, 0x95, 0x07, 0x0c, 0xe8, 0xdb, 0x2f, 0xa9, 0x3b, 0x1d,
+  0x65, 0x3f, 0x07, 0x3e, 0x2c, 0x45, 0x7e, 0xa7, 0x92, 0xd3, 0x5c, 0x39,
+  0x6e, 0x09, 0x1f, 0x2a, 0x11, 0xd2, 0x53, 0x8e, 0xb8, 0xed, 0xd3, 0x5a,
+  0x65, 0x96, 0xed, 0x53, 0x25, 0xa9, 0x5a, 0xb5, 0x39, 0x6b, 0x5c, 0x9e,
+  0x6c, 0x2e, 0x00, 0x1a, 0xd3, 0x43, 0x93, 0x2c, 0xf4, 0x2b, 0x04, 0x61,
+  0x96, 0x24, 0xe5, 0x27, 0x73, 0xeb, 0xed, 0xa2, 0x5d, 0xd5, 0x17, 0x2d,
+  0xf6, 0xd2, 0x9b, 0x5c, 0xc5, 0x61, 0x52, 0xdb, 0x93, 0xbe, 0x74, 0x75,
+  0x44, 0x88, 0xf0, 0x1d, 0x1d, 0x96, 0xd9, 0x29, 0x94, 0x75, 0x07, 0x6c,
+  0x68, 0x2a, 0xc9, 0xb6, 0x03, 0x27, 0x73, 0x8d, 0x41, 0x2c, 0x98, 0x5c,
+  0x73, 0x76, 0xd0, 0xd3, 0x4b, 0x90, 0xbe, 0x6e, 0x9b, 0xea, 0x14, 0x1d,
+  0x03, 0x79, 0x80, 0x3b, 0xfb, 0xe8, 0x95, 0x21, 0x77, 0x63, 0x8d, 0x2e,
+  0xa5, 0x94, 0x39, 0x07, 0x47, 0x9f, 0x32, 0x11, 0xea, 0x35, 0x08, 0x2c,
+  0xbb, 0xd4, 0x72, 0x82, 0x01, 0xfb, 0x68, 0x2a, 0x75, 0x21, 0x10, 0x8f,
+  0xa8, 0xef, 0xae, 0x6e, 0x44, 0x9a, 0xd1, 0x1b, 0x74, 0xd1, 0x74, 0x91,
+  0x86, 0x95, 0x41, 0xc0, 0x5e, 0xe4, 0x9c, 0x76, 0xd0, 0xc8, 0xbf, 0x56,
+  0x35, 0xa2, 0xa8, 0xcc, 0x18, 0x3b, 0x91, 0xac, 0xd7, 0xe3, 0x77, 0x06,
+  0xd5, 0x5f, 0x0c, 0x17, 0xdb, 0x72, 0xc6, 0x65, 0x82, 0x13, 0x1c, 0xca,
+  0xcc, 0x17, 0x2a, 0x0e, 0x41, 0xcf, 0x73, 0xbf, 0x4d, 0x5a, 0x6c, 0xf7,
+  0x8a, 0x09, 0xa4, 0x6a, 0x68, 0x2a, 0x01, 0x62, 0xc7, 0xcb, 0xe8, 0x7d,
+  0x34, 0xf2, 0x0a, 0x98, 0xd9, 0x4c, 0x13, 0xae, 0x53, 0x3b, 0xfa, 0x1f,
+  0xbe, 0xb3, 0xc5, 0xc3, 0x53, 0x8d, 0xa1, 0x52, 0x71, 0xc8, 0xb6, 0xa6,
+  0x79, 0x49, 0xa9, 0xe5, 0x8d, 0xf9, 0x1e, 0x32, 0x0e, 0x31, 0x9e, 0xda,
+  0xbd, 0x58, 0xab, 0x26, 0x7b, 0x4c, 0x34, 0x4a, 0x04, 0xd5, 0x0a, 0xa3,
+  0x94, 0xbf, 0x51, 0xe8, 0x3e, 0xda, 0xd4, 0xef, 0x5c, 0x07, 0xc3, 0x37,
+  0x69, 0x3c, 0x6f, 0x0e, 0x4a, 0x67, 0x0d, 0x9c, 0xc0, 0xc0, 0x64, 0xfd,
+  0x88, 0x3a, 0x92, 0xd1, 0xc2, 0xdc, 0x37, 0x60, 0xcc, 0xf1, 0xc6, 0xd3,
+  0x54, 0x0f, 0x31, 0x79, 0xbc, 0xc7, 0xf4, 0xe9, 0xac, 0x7a, 0x5d, 0x04,
+  0xb1, 0xcd, 0xb6, 0xf8, 0x11, 0x0d, 0x3b, 0x83, 0xe4, 0x49, 0xc2, 0xfc,
+  0x39, 0x72, 0xac, 0x8a, 0x37, 0xbb, 0xc5, 0x4c, 0xb4, 0x44, 0x15, 0x6a,
+  0x67, 0x4c, 0xb3, 0x83, 0x82, 0x18, 0x10, 0x46, 0x3a, 0x68, 0x3e, 0x36,
+  0xb1, 0x35, 0x92, 0xa6, 0x3a, 0xfa, 0x31, 0x31, 0xa5, 0x3b, 0x2a, 0x46,
+  0x76, 0x88, 0xf4, 0xdf, 0x3f, 0x7e, 0xba, 0xb0, 0x71, 0x0d, 0xfe, 0x0a,
+  0x78, 0xcc, 0xb3, 0x55, 0x88, 0x3c, 0xb9, 0x89, 0x72, 0x00, 0x3e, 0x99,
+  0xc9, 0x03, 0x1f, 0xe9, 0xaa, 0x5c, 0x7f, 0x16, 0x2d, 0x36, 0x62, 0xd4,
+  0xf5, 0xd7, 0x1f, 0xe2, 0x21, 0x9f, 0x99, 0x97, 0x93, 0x9d, 0x87, 0xa8,
+  0xe6, 0x1e, 0x50, 0x07, 0xa0, 0x27, 0x5b, 0xd4, 0x03, 0xd8, 0x9f, 0x42,
+  0xfa, 0x4e, 0x17, 0xae, 0x37, 0x75, 0xbc, 0xd7, 0xd5, 0x8a, 0xce, 0x64,
+  0x23, 0xc0, 0x66, 0xce, 0x33, 0xbe, 0x73, 0xed, 0xd3, 0x54, 0x1f, 0x8a,
+  0x94, 0x33, 0xc1, 0xc4, 0x9e, 0x38, 0xa4, 0x30, 0xc1, 0x34, 0x4a, 0x50,
+  0x21, 0xe6, 0x24, 0x8c, 0x0d, 0xbf, 0xd3, 0x57, 0x4b, 0xc7, 0xc5, 0x4e,
+  0x1b, 0xbc, 0x56, 0xc9, 0x0d, 0xb2, 0xd7, 0x74, 0xab, 0x90, 0x27, 0x24,
+  0x2b, 0x4d, 0xf4, 0xc4, 0xc3, 0x6c, 0x9c, 0xed, 0x81, 0xef, 0x81, 0xaa,
+  0xb9, 0x5b, 0x9d, 0x7c, 0x82, 0xbe, 0xf1, 0x0c, 0xa2, 0x9f, 0x18, 0x8e,
+  0x57, 0xab, 0x40, 0x99, 0xea, 0x72, 0xc0, 0x04, 0x03, 0xdb, 0x9b, 0xf5,
+  0x3a, 0xcb, 0x2c, 0x79, 0x25, 0x26, 0x9a, 0x2f, 0xf8, 0xae, 0x5d, 0x99,
+  0xbf, 0x10, 0xd1, 0x49, 0x51, 0xc4, 0xf7, 0x18, 0x60, 0x4f, 0x11, 0x9e,
+  0xb6, 0x5c, 0x8e, 0x9d, 0x5c, 0xef, 0xaf, 0xd7, 0x27, 0xa6, 0xb5, 0xdb,
+  0x7f, 0x87, 0xc5, 0x2b, 0x7c, 0xcb, 0x6e, 0xee, 0x9d, 0xbd, 0x8e, 0xae,
+  0x8b, 0x69, 0xaa, 0x9a, 0xff, 0x00, 0x51, 0x41, 0x6c, 0xa6, 0xf1, 0xee,
+  0x97, 0x4a, 0xa9, 0x92, 0x05, 0xce, 0xc0, 0x73, 0x12, 0x58, 0x9f, 0xe9,
+  0x03, 0x1a, 0x33, 0x8c, 0x3e, 0x03, 0xf1, 0x3d, 0x05, 0x8e, 0xba, 0xf1,
+  0xf3, 0xf4, 0xf5, 0xa6, 0x91, 0x11, 0xd2, 0x08, 0x54, 0x97, 0x75, 0xc6,
+  0x64, 0x3f, 0xfe, 0xbe, 0x9b, 0xe7, 0xdb, 0x57, 0x91, 0x78, 0xd9, 0x96,
+  0x78, 0x9b, 0x6d, 0xa3, 0x19, 0xab, 0xa9, 0x96, 0x56, 0x26, 0x49, 0x1e,
+  0x42, 0x06, 0x01, 0x63, 0x9d, 0x4b, 0x6a, 0x89, 0x5d, 0x59, 0x83, 0x79,
+  0xbd, 0x31, 0xa8, 0xe7, 0xa6, 0x90, 0x30, 0x52, 0xaf, 0xcf, 0x9d, 0xd7,
+  0x97, 0x7d, 0x3c, 0xb6, 0x5b, 0xda, 0x9a, 0x8f, 0xc7, 0x64, 0x09, 0x2c,
+  0xa5, 0x17, 0x04, 0x67, 0x0a, 0x71, 0x81, 0xf7, 0xff, 0x00, 0xc6, 0xb1,
+  0xa7, 0xb8, 0xcc, 0xe0, 0x19, 0x67, 0xb8, 0x47, 0x6d, 0x82, 0x59, 0x67,
+  0x93, 0x96, 0x30, 0xa4, 0x6b, 0x3c, 0xb8, 0x39, 0x9e, 0xe9, 0x51, 0x3a,
+  0x93, 0x99, 0x27, 0x66, 0x5c, 0xf6, 0x19, 0x3a, 0xd3, 0x69, 0x68, 0xd3,
+  0xe6, 0x5a, 0xa2, 0xa6, 0x30, 0xe3, 0x9b, 0x11, 0xa9, 0x18, 0xc0, 0xf5,
+  0xfb, 0xeb, 0x39, 0xbb, 0xd2, 0x9a, 0x6b, 0xbd, 0x44, 0x1c, 0xc4, 0xf2,
+  0xc8, 0x70, 0x71, 0xef, 0xa7, 0xec, 0xa4, 0x83, 0x8a, 0xa2, 0xc1, 0xc3,
+  0xb5, 0x8d, 0x08, 0x62, 0x42, 0xb8, 0x65, 0x1e, 0x56, 0x19, 0x04, 0xea,
+  0xc5, 0xc2, 0xd4, 0xf0, 0xdc, 0x38, 0x80, 0x07, 0x89, 0xe9, 0xbc, 0xa7,
+  0x2c, 0x06, 0x42, 0x9c, 0x8f, 0xb6, 0xda, 0xa7, 0xd2, 0x18, 0xd6, 0x8c,
+  0xc6, 0xc0, 0x99, 0x41, 0x05, 0x5b, 0xdb, 0x5a, 0x0f, 0x00, 0xa5, 0x6a,
+  0x8a, 0x79, 0x62, 0x85, 0xd9, 0x2a, 0x33, 0x0b, 0xbe, 0x3c, 0xb8, 0xe5,
+  0xce, 0x33, 0xeb, 0xb8, 0x3a, 0x73, 0x9d, 0x2b, 0xfd, 0x06, 0x32, 0xe2,
+  0xee, 0x1c, 0xb0, 0xd8, 0xfe, 0x21, 0xd0, 0x0a, 0xab, 0xbd, 0x45, 0x55,
+  0x35, 0x34, 0x70, 0x4c, 0x44, 0x6a, 0x3e, 0xb2, 0xbc, 0xc5, 0x48, 0x1e,
+  0xf8, 0xeb, 0xd3, 0x3a, 0xcd, 0x38, 0xa6, 0xcf, 0x4b, 0x5d, 0xc6, 0xb7,
+  0xab, 0xa4, 0xf5, 0x11, 0x52, 0xc5, 0x2c, 0x8e, 0xeb, 0x19, 0x04, 0x99,
+  0x25, 0x7d, 0xf9, 0x17, 0x19, 0xe9, 0x83, 0xbf, 0xdb, 0xd7, 0x56, 0xab,
+  0xdd, 0xd6, 0x3b, 0xab, 0x19, 0xa2, 0x6e, 0x49, 0xa1, 0x25, 0x1c, 0x31,
+  0xfa, 0x58, 0x10, 0x33, 0xf6, 0xdb, 0x55, 0x8f, 0x88, 0x15, 0xd4, 0xa6,
+  0x3b, 0x5c, 0x14, 0x30, 0x39, 0xae, 0x87, 0x9d, 0xab, 0x66, 0x32, 0x65,
+  0x67, 0x91, 0xfb, 0xa6, 0xdb, 0x00, 0x30, 0x3f, 0x1a, 0xcc, 0xa5, 0xf2,
+  0x64, 0xe3, 0xa2, 0xd1, 0x52, 0x2f, 0xfc, 0x3e, 0x8a, 0x65, 0x48, 0xc4,
+  0xb2, 0x87, 0x0a, 0xa5, 0x86, 0x00, 0x04, 0x1c, 0x6d, 0xed, 0x8d, 0x4d,
+  0x69, 0xe2, 0xbb, 0xc5, 0x34, 0x4b, 0x1c, 0x12, 0xc5, 0x1a, 0xa8, 0x21,
+  0x93, 0xc3, 0x18, 0x66, 0xf5, 0x3d, 0xce, 0x87, 0xe2, 0x58, 0xd9, 0x2b,
+  0xa3, 0xb6, 0x42, 0xe1, 0xc5, 0x10, 0xc0, 0x23, 0x6c, 0xb9, 0xc1, 0x63,
+  0xf8, 0x27, 0x1a, 0x0c, 0x4b, 0x19, 0x5e, 0x42, 0xac, 0x58, 0x7f, 0xc4,
+  0x38, 0xfa, 0x4e, 0xb5, 0xf4, 0x39, 0x16, 0x7b, 0x15, 0xc6, 0xe7, 0x73,
+  0xae, 0x35, 0xb5, 0x0c, 0x25, 0x00, 0x9e, 0x71, 0xd1, 0x11, 0x7d, 0x00,
+  0xec, 0x75, 0x2d, 0x4c, 0x40, 0x1a, 0x98, 0xa9, 0xd5, 0xb1, 0x16, 0x64,
+  0x4d, 0xf3, 0xe5, 0x27, 0xae, 0x74, 0x82, 0xd1, 0x72, 0xa9, 0xb7, 0x64,
+  0x42, 0xd9, 0x89, 0x98, 0x97, 0x18, 0xea, 0x0e, 0xad, 0x36, 0xf9, 0xc5,
+  0x6c, 0x2c, 0x88, 0x03, 0x10, 0x79, 0xe2, 0x5f, 0x62, 0x3a, 0x7e, 0xfa,
+  0xb4, 0x6c, 0xd3, 0x83, 0x50, 0xc0, 0xb3, 0xd4, 0xc5, 0x5b, 0x01, 0xf0,
+  0x96, 0x58, 0xb9, 0x26, 0xe6, 0x53, 0x82, 0xc3, 0x6e, 0xde, 0xa7, 0x18,
+  0xd3, 0x7b, 0x2c, 0x71, 0x52, 0xdf, 0xed, 0xf5, 0xf1, 0x0c, 0x53, 0x73,
+  0x9a, 0x1a, 0x96, 0x1f, 0xff, 0x00, 0x66, 0x3f, 0xb6, 0x30, 0x7f, 0x3a,
+  0x5d, 0x65, 0x45, 0x8a, 0xa5, 0xa1, 0x9d, 0xfc, 0x0d, 0xd8, 0xb6, 0xdc,
+  0xc0, 0x95, 0xdf, 0x18, 0xfb, 0x8e, 0xba, 0xea, 0xcf, 0x3a, 0xcb, 0x69,
+  0xbc, 0xa5, 0x53, 0xb1, 0x95, 0x58, 0xbb, 0x39, 0x3d, 0xf9, 0x87, 0x2e,
+  0x3e, 0xc7, 0x23, 0xf1, 0xa2, 0x43, 0x3d, 0x93, 0x49, 0x11, 0xa7, 0x9a,
+  0x78, 0x60, 0x3e, 0x54, 0x6f, 0x5c, 0xe0, 0x69, 0x84, 0x15, 0x08, 0xd6,
+  0x41, 0x4f, 0x50, 0x39, 0x8b, 0x49, 0x98, 0x37, 0xdd, 0x98, 0x03, 0xd3,
+  0xf7, 0xd0, 0x15, 0x14, 0xb5, 0x0e, 0x94, 0xf7, 0x17, 0x85, 0x9a, 0x39,
+  0x23, 0x0b, 0x20, 0x88, 0xe4, 0x82, 0x36, 0x39, 0xd7, 0x0e, 0xc6, 0x98,
+  0x2c, 0x94, 0x75, 0x0d, 0xe4, 0x60, 0x40, 0xce, 0xe1, 0xbd, 0xff, 0x00,
+  0x7d, 0x50, 0xf4, 0x7e, 0x6a, 0xa9, 0xff, 0x00, 0x85, 0x53, 0x49, 0x48,
+  0x18, 0x4b, 0x04, 0xce, 0x84, 0x77, 0xc6, 0x73, 0x9f, 0xdb, 0x45, 0xb2,
+  0x4b, 0x2d, 0xe2, 0x63, 0xcc, 0x59, 0xbc, 0x2e, 0x60, 0x01, 0xc6, 0x0e,
+  0x3d, 0x75, 0xc9, 0x84, 0x5d, 0xe9, 0x25, 0xa8, 0x5c, 0x53, 0x55, 0x27,
+  0xf5, 0x46, 0x70, 0x8c, 0xc7, 0x3e, 0x56, 0x1d, 0x8e, 0x74, 0x4d, 0x9a,
+  0x41, 0x58, 0xd4, 0x8d, 0x2e, 0x56, 0xaa, 0x37, 0x30, 0xb8, 0x23, 0xa8,
+  0x39, 0xe5, 0x38, 0xfd, 0xb5, 0x54, 0x49, 0x15, 0xae, 0x28, 0xa3, 0x2f,
+  0xc4, 0xd3, 0x54, 0x48, 0xac, 0xf0, 0x48, 0x82, 0x52, 0x71, 0xb1, 0x63,
+  0x8d, 0x89, 0xf5, 0xeb, 0xa5, 0xdc, 0xb8, 0x6f, 0x11, 0x5b, 0x0f, 0x1e,
+  0x42, 0xae, 0x3a, 0x2f, 0xae, 0xad, 0x9c, 0x49, 0x56, 0xf4, 0xf6, 0xfa,
+  0x3b, 0x8d, 0x1c, 0x41, 0xd3, 0xc3, 0xe4, 0x92, 0x22, 0xde, 0x5d, 0xb2,
+  0x37, 0xfd, 0x35, 0x4b, 0x37, 0xba, 0xda, 0x89, 0x8a, 0x9a, 0x6a, 0x78,
+  0x81, 0x18, 0xe9, 0x80, 0x07, 0xaf, 0xbf, 0x6d, 0x15, 0x18, 0x72, 0x7d,
+  0xd9, 0x75, 0xf8, 0x4f, 0x7c, 0xa5, 0xb3, 0xf1, 0xc5, 0xb2, 0xbe, 0xa9,
+  0x4a, 0x94, 0x94, 0x02, 0xfc, 0xd8, 0x18, 0xf7, 0xd7, 0xb7, 0xa8, 0xea,
+  0xe9, 0xea, 0x29, 0xa3, 0x9a, 0x98, 0xa3, 0x41, 0x22, 0x86, 0x46, 0x43,
+  0x90, 0x41, 0xe8, 0x75, 0xe0, 0x2b, 0x7c, 0x15, 0x0b, 0x02, 0x4d, 0x3d,
+  0x3a, 0x87, 0xce, 0x41, 0xe5, 0xc1, 0x03, 0x5e, 0x90, 0xff, 0x00, 0x67,
+  0x6e, 0x2a, 0x6b, 0x85, 0xa4, 0xd8, 0x2b, 0x80, 0x13, 0x52, 0xe5, 0xa9,
+  0xb2, 0x73, 0x94, 0xcf, 0x4d, 0x32, 0x2c, 0xa8, 0x48, 0xdd, 0xe0, 0x99,
+  0x55, 0xf1, 0xeb, 0xdf, 0x45, 0xbc, 0xbc, 0x89, 0x91, 0xbe, 0xfa, 0x4b,
+  0x4a, 0xdc, 0xca, 0x07, 0x71, 0xa2, 0x26, 0x9f, 0x92, 0x22, 0x19, 0xbb,
+  0x69, 0xa8, 0x68, 0x45, 0x44, 0xfe, 0x5e, 0xb8, 0xd2, 0xca, 0xa9, 0xfa,
+  0xf9, 0xbb, 0xe9, 0x7c, 0xb5, 0x8a, 0xb2, 0x31, 0x2c, 0xaa, 0xbe, 0xa5,
+  0x80, 0xc0, 0xd2, 0xea, 0xdb, 0xac, 0x14, 0xea, 0xd3, 0xb3, 0x3b, 0xc0,
+  0x33, 0xe7, 0x8d, 0x4b, 0xef, 0xd7, 0xb6, 0xac, 0x83, 0xbb, 0x75, 0x63,
+  0xa5, 0x49, 0x8d, 0x8f, 0x95, 0x89, 0x20, 0xea, 0xd1, 0x4a, 0xcc, 0x62,
+  0x04, 0xee, 0x35, 0xe7, 0xeb, 0xd7, 0x12, 0x5c, 0xab, 0x49, 0xa9, 0x49,
+  0x24, 0xa3, 0x89, 0x1f, 0xc2, 0x86, 0x15, 0xf3, 0x4b, 0x29, 0x39, 0x39,
+  0xed, 0xca, 0x36, 0x1b, 0x9f, 0x5e, 0x9a, 0xdb, 0x12, 0xbd, 0xa8, 0xf8,
+  0x7e, 0x0a, 0xaa, 0x85, 0x31, 0x4e, 0xd0, 0x2b, 0x14, 0x3d, 0x41, 0x2a,
+  0x09, 0xce, 0x91, 0x8b, 0x3a, 0xc9, 0x26, 0x97, 0xa0, 0x20, 0xd4, 0x9d,
+  0x20, 0x6b, 0xcb, 0x78, 0x77, 0x50, 0x3a, 0xe4, 0x67, 0x46, 0x51, 0x1f,
+  0x19, 0x25, 0x88, 0x0c, 0x17, 0x52, 0x07, 0xdf, 0x1a, 0xa5, 0x35, 0xf2,
+  0xbe, 0xe3, 0xc4, 0x51, 0x43, 0x48, 0x61, 0x9e, 0x30, 0xa7, 0xc6, 0x04,
+  0x79, 0x90, 0x9d, 0xfa, 0xfd, 0xb5, 0x64, 0xa4, 0xb8, 0x2d, 0x3b, 0xc5,
+  0x29, 0x39, 0x05, 0x82, 0xe7, 0xd7, 0x3a, 0xa8, 0xe5, 0x8e, 0x44, 0xf6,
+  0xbe, 0x86, 0x5a, 0x92, 0x69, 0x3e, 0x80, 0xa3, 0xe1, 0x1b, 0x65, 0x4c,
+  0x4b, 0x2d, 0x7f, 0x96, 0x44, 0x5e, 0x42, 0xb1, 0xca, 0x76, 0x23, 0xb8,
+  0xc6, 0x30, 0x74, 0x8a, 0xe4, 0x38, 0x96, 0xc7, 0x7b, 0xa7, 0xb7, 0x5b,
+  0x64, 0x96, 0xe7, 0x4b, 0x3a, 0x99, 0x14, 0x48, 0x33, 0x22, 0x28, 0x38,
+  0xe5, 0x2d, 0xd8, 0x6e, 0x34, 0xcb, 0x8e, 0xea, 0x64, 0xb4, 0x66, 0x7a,
+  0xdb, 0xd5, 0xb2, 0xdf, 0x04, 0x8e, 0x79, 0x92, 0x49, 0xf9, 0x5c, 0x8c,
+  0xfd, 0x41, 0x71, 0x92, 0x7d, 0xbb, 0xea, 0x9b, 0x37, 0xc5, 0xce, 0x1b,
+  0xa5, 0xb4, 0x34, 0x34, 0x13, 0xd6, 0xd6, 0x4c, 0xb1, 0xf2, 0xc2, 0x44,
+  0x44, 0x79, 0xb1, 0xf5, 0x1e, 0xbe, 0x53, 0xe9, 0xae, 0x16, 0x3c, 0x9a,
+  0x95, 0x36, 0xa1, 0x0a, 0xff, 0x00, 0x3e, 0x8c, 0xdf, 0x14, 0xa5, 0xe8,
+  0xb8, 0xcd, 0xc4, 0x73, 0x50, 0x31, 0xa6, 0xb8, 0xd3, 0xc9, 0x4c, 0xdc,
+  0x9c, 0xfb, 0xb6, 0x46, 0x3e, 0xfa, 0xad, 0xdf, 0xbe, 0x23, 0x59, 0xe8,
+  0x22, 0x59, 0x85, 0x55, 0x2c, 0x93, 0xf3, 0xf2, 0xad, 0x3b, 0x31, 0x63,
+  0x8c, 0xe3, 0x99, 0xb1, 0xd0, 0x7e, 0x7b, 0xeb, 0x22, 0x96, 0xb2, 0xf9,
+  0xc6, 0x55, 0xf3, 0x09, 0x1a, 0x69, 0x51, 0x5c, 0xb9, 0x54, 0x41, 0x15,
+  0x3c, 0x64, 0xf4, 0xe6, 0xc6, 0xe4, 0x9d, 0xc6, 0x0e, 0x4f, 0x6d, 0x29,
+  0x96, 0x2e, 0x1c, 0xa4, 0xac, 0xe6, 0xbe, 0x5c, 0x64, 0x75, 0x89, 0x5d,
+  0x65, 0xa7, 0xa3, 0x42, 0x5d, 0x88, 0x38, 0xc1, 0x6f, 0xe9, 0xff, 0x00,
+  0xa7, 0x4d, 0x76, 0x71, 0xbc, 0x95, 0x52, 0xec, 0xd4, 0xb0, 0x3f, 0x6c,
+  0xb6, 0x71, 0xad, 0xde, 0xcf, 0xc4, 0xb7, 0x65, 0xaa, 0xb9, 0xf1, 0x15,
+  0xb6, 0x8a, 0x8a, 0x37, 0xc8, 0x86, 0x29, 0x5e, 0x50, 0xa4, 0xfd, 0x44,
+  0xe4, 0x6e, 0x7a, 0x0c, 0x69, 0x7c, 0xf7, 0xbe, 0x04, 0xb4, 0xc4, 0x63,
+  0xa2, 0xa9, 0x6a, 0xf9, 0x1b, 0x67, 0x10, 0xc2, 0x79, 0xa5, 0xfc, 0x9c,
+  0x05, 0xfd, 0xfa, 0xea, 0xab, 0x57, 0x37, 0x0e, 0x04, 0x0d, 0x64, 0xe1,
+  0xaa, 0x8a, 0x97, 0x00, 0x7f, 0x32, 0xb6, 0x76, 0x92, 0x34, 0xce, 0xd9,
+  0xe5, 0x18, 0xe6, 0x39, 0x23, 0xfd, 0x34, 0xef, 0x87, 0xb8, 0x16, 0x77,
+  0xa4, 0xf9, 0xaa, 0xc7, 0x8a, 0xd9, 0xce, 0xbe, 0x21, 0x62, 0x8a, 0x18,
+  0x67, 0xb8, 0xe7, 0xfa, 0x74, 0xdb, 0x1d, 0x08, 0xb5, 0xd1, 0x61, 0x86,
+  0xe5, 0x77, 0x7b, 0x64, 0xa2, 0x38, 0xad, 0xbc, 0x27, 0x6a, 0x68, 0xf1,
+  0xcd, 0x33, 0x8f, 0x98, 0xe5, 0x3d, 0x08, 0x41, 0xfd, 0x47, 0xfe, 0x6f,
+  0x53, 0xaa, 0xcd, 0xde, 0xf1, 0xc2, 0x23, 0x99, 0x5c, 0x5d, 0x2f, 0x72,
+  0xa1, 0xc2, 0xd5, 0x56, 0xce, 0x4c, 0x63, 0xd9, 0x46, 0x7a, 0x7a, 0x0c,
+  0x0d, 0xb4, 0xba, 0xae, 0xc1, 0x49, 0x3d, 0xda, 0x4a, 0x5a, 0x2a, 0xe1,
+  0x58, 0x15, 0xb9, 0x66, 0xa9, 0x79, 0x76, 0x62, 0x33, 0xe5, 0x1d, 0xc9,
+  0x1b, 0xe7, 0x1b, 0x68, 0xb8, 0xe2, 0xe1, 0x7a, 0x08, 0x42, 0xd4, 0xd5,
+  0xc4, 0xd2, 0x01, 0x90, 0x24, 0xc9, 0x1c, 0xd8, 0xe9, 0x8f, 0x4f, 0x4d,
+  0x1b, 0x65, 0xb4, 0x4c, 0xb7, 0xba, 0xfb, 0x4f, 0x1d, 0x56, 0xdc, 0x69,
+  0x2b, 0x65, 0xa3, 0xaa, 0xa7, 0xa9, 0x99, 0x20, 0x70, 0x7c, 0xc4, 0x19,
+  0x1b, 0x3f, 0x8e, 0xda, 0xd3, 0xf8, 0x67, 0xe3, 0x45, 0xd6, 0x39, 0x61,
+  0x8a, 0xfb, 0x8a, 0x88, 0x73, 0xca, 0xd2, 0x20, 0x0a, 0xe4, 0x7b, 0x8e,
+  0x87, 0xfb, 0xeb, 0x23, 0xbe, 0xc6, 0x0f, 0x13, 0xdc, 0x9a, 0x60, 0xc5,
+  0x8d, 0x54, 0x9c, 0x80, 0x0c, 0xec, 0x1c, 0xe8, 0xfa, 0x63, 0x1b, 0xc6,
+  0x09, 0x5c, 0x82, 0x30, 0x41, 0xd2, 0x6e, 0xa3, 0xb4, 0xe3, 0xe4, 0xf1,
+  0x67, 0xde, 0x31, 0xa0, 0xa3, 0x8f, 0x8a, 0x6b, 0xaa, 0xed, 0xc9, 0x10,
+  0xb7, 0x4c, 0xcd, 0x3d, 0x17, 0x21, 0xdb, 0x0c, 0xd9, 0xc9, 0x1d, 0xb0,
+  0x0e, 0x31, 0xdb, 0x43, 0x54, 0x02, 0xd4, 0x54, 0xca, 0x18, 0x85, 0xe6,
+  0x8c, 0xe3, 0xf2, 0x34, 0xc6, 0x44, 0x89, 0xa9, 0x8d, 0x3c, 0x69, 0x1b,
+  0x33, 0x1f, 0x21, 0x2b, 0xba, 0x3f, 0x62, 0x3e, 0xe7, 0x63, 0xf7, 0xd0,
+  0x56, 0x5a, 0x0f, 0xe2, 0x17, 0xcb, 0x75, 0xa2, 0x6a, 0xc4, 0xa7, 0x8e,
+  0x79, 0x04, 0x52, 0x36, 0x39, 0xb9, 0x3c, 0xd9, 0x07, 0x1e, 0xb9, 0xc6,
+  0xb3, 0x28, 0xed, 0x95, 0x02, 0x9d, 0xc4, 0xb0, 0xf0, 0x55, 0x82, 0x6b,
+  0xfd, 0xfa, 0x9e, 0x85, 0x00, 0x31, 0x31, 0x1e, 0x33, 0x90, 0x71, 0x1c,
+  0x7d, 0xcf, 0xf6, 0x1f, 0x9d, 0x50, 0xfe, 0x32, 0x5a, 0xa9, 0x6d, 0x5f,
+  0x10, 0xaf, 0x94, 0xd4, 0x34, 0xc1, 0x29, 0x29, 0xeb, 0x4a, 0x46, 0x46,
+  0xf8, 0x05, 0x43, 0x72, 0x93, 0xeb, 0xb9, 0xd7, 0xaa, 0xed, 0x16, 0x5a,
+  0x5e, 0x13, 0x85, 0xe8, 0x28, 0xd8, 0x62, 0x48, 0xd9, 0xaa, 0x4f, 0xf5,
+  0xc8, 0x01, 0x1e, 0x6d, 0xba, 0x36, 0x3f, 0x1a, 0xf3, 0x97, 0x19, 0xdd,
+  0x29, 0xeb, 0x6d, 0x7c, 0x55, 0x0d, 0x25, 0x12, 0xb0, 0xae, 0xba, 0x1a,
+  0xb8, 0xea, 0xa4, 0x39, 0x91, 0x52, 0x2e, 0x60, 0xa9, 0xf6, 0x20, 0x92,
+  0x4f, 0xe3, 0x4d, 0xc9, 0xe5, 0x51, 0x06, 0x8c, 0xe2, 0x09, 0xd0, 0x37,
+  0x32, 0x8d, 0xba, 0x11, 0x9d, 0x6e, 0x3c, 0x2b, 0x55, 0x40, 0x7e, 0x16,
+  0xd1, 0x5b, 0xe5, 0xa3, 0x9e, 0x3a, 0xd4, 0x91, 0xea, 0x22, 0xa9, 0x59,
+  0x30, 0x00, 0x6c, 0x13, 0xe5, 0xfb, 0x05, 0xdf, 0xdb, 0x59, 0x07, 0x04,
+  0x59, 0xc5, 0xfb, 0x89, 0xe8, 0x6d, 0x23, 0x64, 0xa8, 0x90, 0xf3, 0x9f,
+  0x45, 0x00, 0xb1, 0xfe, 0xdf, 0xdb, 0x5e, 0x9c, 0x8b, 0xe1, 0xfc, 0xf1,
+  0xd1, 0x22, 0x55, 0xc9, 0x4d, 0x6f, 0xa5, 0x5a, 0x7c, 0x86, 0x73, 0x9e,
+  0x45, 0x1b, 0x00, 0x07, 0xae, 0xb8, 0xda, 0xdc, 0xfa, 0x88, 0xc9, 0x43,
+  0x12, 0xbf, 0xd8, 0x13, 0x52, 0xfe, 0xd3, 0x05, 0xae, 0xe1, 0xda, 0x81,
+  0x0c, 0xdc, 0xd3, 0x89, 0x91, 0xdc, 0xb4, 0x8d, 0xcb, 0xe6, 0x6d, 0xf2,
+  0x73, 0xf9, 0xd2, 0xdb, 0x9d, 0x0d, 0xb1, 0xa9, 0x84, 0x1e, 0x19, 0x04,
+  0xe0, 0xb3, 0x03, 0xe6, 0xce, 0x3f, 0xb6, 0xac, 0x9c, 0x4b, 0x5a, 0x69,
+  0x0c, 0xf0, 0xa4, 0x81, 0xe3, 0xe6, 0x60, 0xa5, 0x98, 0x2f, 0x32, 0xee,
+  0x01, 0xdf, 0xf1, 0xac, 0xd2, 0x82, 0x99, 0xea, 0xeb, 0x64, 0xa3, 0xa7,
+  0xac, 0x20, 0x80, 0x59, 0xf1, 0xd0, 0x0c, 0xe0, 0x8c, 0xfd, 0xce, 0x9d,
+  0xa5, 0xb9, 0xa4, 0xdf, 0x65, 0x20, 0x49, 0x2d, 0x46, 0xdd, 0x5b, 0x3b,
+  0x02, 0x5e, 0x19, 0xd4, 0x90, 0xc7, 0xae, 0x73, 0xd0, 0xeb, 0x93, 0x1c,
+  0x7f, 0x26, 0xf4, 0x7e, 0x1a, 0x04, 0x76, 0x0f, 0xcd, 0x8f, 0x36, 0x40,
+  0x23, 0xaf, 0xa6, 0xfa, 0x7d, 0xf2, 0x49, 0x6e, 0x81, 0xe3, 0x3e, 0x6e,
+  0x6e, 0xad, 0xeb, 0xed, 0x9d, 0x71, 0x4f, 0x46, 0x95, 0xd0, 0xb3, 0xd3,
+  0x00, 0x42, 0xec, 0xc0, 0x9e, 0x87, 0x5b, 0x5c, 0x87, 0x29, 0x95, 0x65,
+  0xa4, 0x44, 0x8a, 0x58, 0x02, 0x61, 0x8f, 0x98, 0x1f, 0x5c, 0x76, 0xd3,
+  0xfe, 0x1e, 0x30, 0xac, 0x54, 0xb5, 0x04, 0x12, 0x23, 0x1e, 0x1c, 0xdb,
+  0xe0, 0x80, 0x7b, 0xff, 0x00, 0x6d, 0x7c, 0xb8, 0x50, 0x48, 0xb0, 0x1f,
+  0x05, 0x59, 0x59, 0x71, 0xcc, 0xfd, 0x40, 0xc7, 0x5c, 0xe8, 0x5a, 0x39,
+  0xdd, 0x64, 0x68, 0xe4, 0x05, 0x56, 0x4c, 0x07, 0x1d, 0x41, 0xdf, 0xd7,
+  0x4d, 0xc5, 0x3b, 0x56, 0x6a, 0xd2, 0xcf, 0x91, 0x85, 0x7a, 0xad, 0x05,
+  0xc3, 0xc3, 0x0c, 0x4a, 0x33, 0x07, 0xe7, 0x53, 0xb3, 0x6f, 0x9f, 0xdc,
+  0x68, 0x9a, 0x98, 0x20, 0xb8, 0x55, 0x5d, 0x24, 0x85, 0x4d, 0x27, 0xcc,
+  0xc7, 0x12, 0x53, 0xc6, 0x83, 0x79, 0x31, 0x8e, 0x62, 0x7f, 0xd7, 0xd8,
+  0xe8, 0x6f, 0x97, 0x82, 0x96, 0x7a, 0xa4, 0xa8, 0x54, 0x94, 0xbc, 0x79,
+  0x8b, 0x7c, 0xf2, 0x80, 0x71, 0x91, 0xe8, 0x74, 0x55, 0xa2, 0x17, 0x7a,
+  0xba, 0x66, 0xa5, 0x1e, 0x2c, 0x49, 0x19, 0x8f, 0x9a, 0x56, 0x3e, 0x47,
+  0x61, 0xb9, 0xc8, 0xec, 0x0e, 0x9b, 0x66, 0xd7, 0xc9, 0x1d, 0x96, 0xb2,
+  0xa5, 0x65, 0x31, 0x46, 0xdc, 0xf1, 0x16, 0xdf, 0x27, 0x66, 0x1a, 0x6f,
+  0x14, 0x74, 0xa9, 0x4c, 0xce, 0x39, 0xb9, 0xea, 0x25, 0x74, 0xf0, 0x94,
+  0x67, 0x93, 0x7d, 0x8e, 0x4e, 0xf8, 0xd4, 0x14, 0xd4, 0xd3, 0x5b, 0x78,
+  0x82, 0xa6, 0x9a, 0xb6, 0x9d, 0x23, 0xe6, 0x50, 0x33, 0x17, 0xd0, 0xa0,
+  0xee, 0x37, 0xf7, 0xce, 0xbe, 0x56, 0xd2, 0x9b, 0x4d, 0xc9, 0x6b, 0x23,
+  0x8c, 0xcb, 0x09, 0x7f, 0xa4, 0x37, 0x4e, 0xf8, 0x3e, 0x9b, 0x6a, 0x30,
+  0xa2, 0x88, 0x69, 0xcc, 0x94, 0x57, 0x52, 0x7c, 0xc6, 0x35, 0x2a, 0x1d,
+  0x47, 0x7e, 0xbb, 0xe9, 0x90, 0x53, 0x4f, 0x78, 0x92, 0xa2, 0x17, 0x02,
+  0x0a, 0xef, 0x2c, 0x52, 0x2e, 0xde, 0x14, 0x9d, 0x41, 0xfd, 0x8e, 0xba,
+  0xe2, 0x2a, 0x64, 0xf9, 0x68, 0xaf, 0x14, 0x39, 0x28, 0xdc, 0xae, 0xd9,
+  0x39, 0xc0, 0x3d, 0x0f, 0xe3, 0xa6, 0x34, 0x05, 0x75, 0x4d, 0x2d, 0x4f,
+  0x0e, 0x35, 0x62, 0x00, 0x67, 0x49, 0x42, 0xbb, 0x2f, 0x73, 0xeb, 0xf7,
+  0xef, 0xaa, 0x0d, 0x87, 0x08, 0x45, 0x4d, 0x75, 0x4d, 0x02, 0xc6, 0x40,
+  0x59, 0x85, 0x42, 0x46, 0xeb, 0x80, 0x41, 0x18, 0x7f, 0xc7, 0x43, 0xaa,
+  0x4d, 0xd6, 0xa6, 0x1b, 0x87, 0x10, 0x22, 0x50, 0xa2, 0xc5, 0x12, 0xc9,
+  0x9d, 0x97, 0xea, 0xc6, 0x7a, 0x6a, 0xf1, 0x72, 0x0f, 0x47, 0x53, 0x41,
+  0x75, 0x2e, 0xb2, 0xbc, 0x54, 0xd1, 0x34, 0x8a, 0x06, 0xcf, 0x19, 0x18,
+  0x20, 0xfd, 0x8e, 0x35, 0x47, 0xe2, 0x8a, 0x38, 0x2d, 0x97, 0xea, 0x82,
+  0x8b, 0xcb, 0x4f, 0x54, 0x9e, 0x3d, 0x39, 0xce, 0x70, 0x1b, 0x7f, 0xdb,
+  0xa6, 0xad, 0x19, 0x73, 0xae, 0x0b, 0x50, 0xa6, 0x6a, 0x1b, 0x5b, 0xd7,
+  0xdc, 0x5f, 0xcc, 0xe7, 0x96, 0x3c, 0x8c, 0xfd, 0x8f, 0xed, 0xa7, 0x1f,
+  0x04, 0xaf, 0xcf, 0x6b, 0xe3, 0xfb, 0x7a, 0x00, 0x43, 0xd6, 0x54, 0xaa,
+  0x6c, 0x70, 0x00, 0x3d, 0x7f, 0xf1, 0xac, 0xb3, 0xe7, 0x95, 0x6d, 0xed,
+  0x14, 0xb2, 0xb4, 0xd2, 0x48, 0xc7, 0xc4, 0x24, 0xe7, 0xec, 0x33, 0xab,
+  0xef, 0xc0, 0x0a, 0x09, 0x27, 0xf8, 0x89, 0x63, 0x25, 0x39, 0xb1, 0x52,
+  0xa4, 0x7b, 0x0e, 0xa7, 0xf6, 0xd1, 0xc4, 0x44, 0x4f, 0x6e, 0xb1, 0x5e,
+  0x75, 0x2a, 0xa1, 0x01, 0x1b, 0x01, 0xe9, 0xeb, 0xa4, 0x7c, 0x57, 0x74,
+  0xa7, 0xb5, 0xda, 0xea, 0xeb, 0x6a, 0xe6, 0x11, 0x41, 0x04, 0x4c, 0xf2,
+  0x31, 0xec, 0x00, 0xd3, 0xa9, 0x4a, 0x99, 0x32, 0xbf, 0x4a, 0x2e, 0xb0,
+  0x7f, 0xf6, 0xa7, 0xe2, 0x94, 0xa5, 0xb0, 0xc3, 0x60, 0x81, 0xc8, 0x9e,
+  0xe0, 0xe7, 0xc4, 0x55, 0x3d, 0x23, 0x53, 0xd4, 0xfd, 0xcf, 0xf6, 0x3a,
+  0x63, 0x63, 0x51, 0x94, 0x5f, 0xf8, 0xf6, 0xff, 0x00, 0xc4, 0x77, 0x4a,
+  0xd6, 0x35, 0xf5, 0x30, 0xd0, 0x34, 0xdc, 0xa9, 0x0a, 0x30, 0x1c, 0xb1,
+  0x6f, 0x80, 0x76, 0xdf, 0x6d, 0xb5, 0xdc, 0xbc, 0x47, 0x53, 0xf3, 0xf5,
+  0x74, 0x56, 0xda, 0xc9, 0x29, 0xa8, 0x0b, 0x83, 0x1c, 0x68, 0x4a, 0xb3,
+  0x63, 0x6c, 0x92, 0x31, 0x9d, 0x56, 0x6d, 0x74, 0x5e, 0x2c, 0x1e, 0x29,
+  0xa8, 0x58, 0xff, 0x00, 0xa5, 0x55, 0xd4, 0x8f, 0x13, 0x1e, 0x9a, 0xfd,
+  0x4b, 0x14, 0x82, 0xf9, 0x0b, 0xb4, 0x4e, 0xb0, 0x44, 0xc0, 0x49, 0x21,
+  0x5e, 0xdf, 0x6d, 0x62, 0x72, 0x94, 0xd3, 0x89, 0x9d, 0xdb, 0xb4, 0x8d,
+  0xe7, 0xe0, 0x15, 0x8e, 0xe5, 0xc4, 0x17, 0xef, 0x98, 0xb9, 0x09, 0x1a,
+  0xd3, 0x42, 0x7c, 0x4e, 0x79, 0x06, 0x79, 0xdc, 0x74, 0x50, 0x7b, 0xff,
+  0x00, 0xd3, 0x5a, 0x77, 0xc5, 0x1e, 0x2b, 0xa5, 0xa2, 0x43, 0x11, 0x9c,
+  0x21, 0x07, 0x94, 0x31, 0xd8, 0x2e, 0x3a, 0x93, 0xe8, 0x06, 0xa8, 0x77,
+  0xef, 0x8a, 0x74, 0x74, 0x56, 0x18, 0x6d, 0x3c, 0x27, 0x47, 0xe1, 0xd2,
+  0xc3, 0x12, 0xc6, 0x27, 0x90, 0x00, 0x84, 0x8e, 0xbb, 0x77, 0xc7, 0xdf,
+  0x59, 0xf5, 0x4d, 0xee, 0xbe, 0xf6, 0xe6, 0x79, 0x99, 0x6e, 0x55, 0x59,
+  0x38, 0x12, 0x36, 0x51, 0x47, 0xd8, 0x6c, 0x07, 0xdf, 0x27, 0x4c, 0x86,
+  0x3f, 0x8f, 0x15, 0x47, 0xb3, 0x44, 0x31, 0x54, 0x69, 0x70, 0x5f, 0x69,
+  0xbe, 0x21, 0xf0, 0xd5, 0xaa, 0x1f, 0xfe, 0x9f, 0x2c, 0xd5, 0x55, 0x72,
+  0x00, 0x6a, 0x3c, 0x38, 0x39, 0x8c, 0x8c, 0x47, 0x9b, 0x7e, 0xc0, 0xe4,
+  0xea, 0xb1, 0xc4, 0x5c, 0x6f, 0x7c, 0xba, 0xd5, 0x43, 0x50, 0x95, 0x37,
+  0x0b, 0x65, 0x3c, 0x3f, 0x42, 0xc3, 0x10, 0x0e, 0xc7, 0xb1, 0x1b, 0xfe,
+  0xfa, 0x54, 0xd7, 0xfe, 0x21, 0xb3, 0x42, 0x89, 0x4d, 0x6d, 0xb5, 0xd3,
+  0xc1, 0x1f, 0x2f, 0x3c, 0x49, 0x16, 0x5d, 0x8e, 0x06, 0xe7, 0xbb, 0x7a,
+  0xfa, 0x7b, 0x68, 0x6a, 0xee, 0x2e, 0xbe, 0xd5, 0xce, 0xe5, 0xea, 0x68,
+  0xbc, 0x73, 0x9f, 0x0d, 0xd2, 0x21, 0xcc, 0x83, 0x3f, 0xd2, 0x3a, 0x03,
+  0xd3, 0x7c, 0x67, 0x43, 0x87, 0x14, 0x71, 0x7d, 0x46, 0x43, 0x02, 0xc6,
+  0xb8, 0x19, 0x7c, 0xe3, 0xb5, 0x48, 0xaa, 0x97, 0x87, 0x12, 0xe1, 0x70,
+  0x9f, 0xfe, 0x1d, 0x55, 0xca, 0xa5, 0xe7, 0x76, 0x63, 0xbe, 0x79, 0x00,
+  0xc1, 0xf5, 0xc6, 0xfd, 0xf4, 0x2c, 0xb7, 0xba, 0x1a, 0x1b, 0xa3, 0xcd,
+  0x3d, 0xaf, 0xf8, 0xbd, 0x48, 0x51, 0xe7, 0xa8, 0xfe, 0x45, 0x30, 0xf6,
+  0x48, 0xb1, 0xb8, 0x1b, 0xee, 0x71, 0xf9, 0xd5, 0x7e, 0xe5, 0x76, 0xb8,
+  0xd7, 0xb9, 0x5b, 0xd5, 0x55, 0x55, 0x7b, 0xf2, 0xff, 0x00, 0x2d, 0x60,
+  0xf2, 0x85, 0xf7, 0x3e, 0xfa, 0xf9, 0x4d, 0x14, 0x41, 0x61, 0x47, 0x81,
+  0x56, 0x49, 0x59, 0x7c, 0x3f, 0x12, 0x41, 0x9d, 0xf6, 0xc1, 0xf4, 0x1d,
+  0xf1, 0xa6, 0x58, 0xed, 0xa5, 0x8a, 0xa7, 0x89, 0x6a, 0x6b, 0xe3, 0x96,
+  0x28, 0xea, 0x69, 0x6c, 0x74, 0xb8, 0xc9, 0x4a, 0x38, 0xda, 0x49, 0x71,
+  0xf7, 0x18, 0x03, 0xa9, 0xd8, 0x63, 0x43, 0x50, 0xd5, 0x70, 0x8d, 0xb1,
+  0xa1, 0x06, 0xd5, 0x55, 0x57, 0x50, 0xc0, 0x06, 0x32, 0xaf, 0x29, 0x95,
+  0x8f, 0x42, 0xc4, 0xef, 0xf8, 0x18, 0xeb, 0xed, 0xa0, 0x8c, 0x36, 0xca,
+  0x59, 0x1e, 0x4a, 0xdb, 0x8d, 0xbd, 0x21, 0x58, 0x8b, 0x49, 0x1d, 0x34,
+  0xad, 0x27, 0x33, 0xf4, 0xe5, 0xcf, 0x63, 0x9d, 0xf1, 0xf7, 0xd2, 0xfb,
+  0x6d, 0x7d, 0x20, 0x68, 0xca, 0x51, 0x97, 0x8d, 0x18, 0x16, 0xe7, 0x8f,
+  0x24, 0x8e, 0xd9, 0x3d, 0x8e, 0xa5, 0x93, 0x69, 0x6c, 0xad, 0xe3, 0x28,
+  0xe8, 0xa5, 0x14, 0xbc, 0x3d, 0xc2, 0xd4, 0xd4, 0x55, 0x2d, 0xb4, 0xad,
+  0x2c, 0x61, 0xcf, 0x3f, 0xa8, 0x07, 0xd3, 0x1a, 0x45, 0x57, 0x3d, 0xd6,
+  0xe3, 0xe2, 0xd6, 0x5d, 0xee, 0x0f, 0x2e, 0x58, 0xf3, 0x2e, 0xfb, 0x7d,
+  0x87, 0x7f, 0xb6, 0xa0, 0x9e, 0xe5, 0x33, 0xdc, 0x26, 0x9e, 0x7a, 0x76,
+  0x48, 0x99, 0x88, 0x48, 0xd1, 0xbc, 0xc8, 0x99, 0xeb, 0x9e, 0xf8, 0x1f,
+  0x6d, 0x17, 0x15, 0xd1, 0x45, 0x33, 0x47, 0x6b, 0xa5, 0x8e, 0x05, 0x5e,
+  0xb2, 0x48, 0xb9, 0x73, 0xf6, 0xf4, 0xed, 0xeb, 0xa9, 0x64, 0xda, 0x21,
+  0x99, 0xa9, 0x1e, 0xa4, 0x2d, 0x3c, 0x6f, 0x22, 0x2a, 0xe1, 0x7c, 0x98,
+  0x24, 0xe7, 0x73, 0xd7, 0x5c, 0x0a, 0x7a, 0x86, 0x6c, 0x78, 0x01, 0x54,
+  0x37, 0xd2, 0xdb, 0x9d, 0x37, 0x82, 0x8a, 0xb1, 0xaa, 0xda, 0xa6, 0xab,
+  0xce, 0xf5, 0x21, 0x71, 0xcc, 0xdb, 0x8d, 0xb6, 0x27, 0xd3, 0x6d, 0x17,
+  0x5b, 0x6f, 0x4a, 0x1a, 0x7f, 0x13, 0xe7, 0x04, 0x72, 0xe3, 0x3c, 0xaa,
+  0x3a, 0x9f, 0x4c, 0xea, 0x59, 0x36, 0x9d, 0x5d, 0xe4, 0x4f, 0xfd, 0x47,
+  0x72, 0xdc, 0x9c, 0x55, 0x4a, 0x08, 0xff, 0x00, 0xf7, 0x3a, 0xee, 0x38,
+  0x7c, 0x53, 0xfc, 0xb7, 0xc2, 0x1d, 0xf5, 0x45, 0xe3, 0x59, 0x6b, 0x2d,
+  0x9c, 0x75, 0x77, 0x31, 0x48, 0xd1, 0x78, 0xb5, 0xb2, 0xca, 0x31, 0xdf,
+  0xf9, 0x87, 0xae, 0xb4, 0x1f, 0x86, 0x73, 0x58, 0xef, 0xb4, 0xb1, 0xc1,
+  0x57, 0xc4, 0x0b, 0x41, 0x76, 0x79, 0x02, 0x88, 0x27, 0x4f, 0xe5, 0x48,
+  0x4f, 0x75, 0x61, 0xd3, 0xdc, 0x69, 0x0e, 0x67, 0x2a, 0x5f, 0x66, 0x7e,
+  0x14, 0x73, 0x0a, 0x59, 0x98, 0x48, 0x39, 0x55, 0x49, 0xe9, 0xe9, 0xa9,
+  0xb8, 0xae, 0x68, 0x9e, 0xa6, 0xc9, 0xc6, 0x74, 0xd1, 0x85, 0x51, 0xe1,
+  0xc7, 0x5d, 0x1a, 0x9f, 0xa6, 0x74, 0xc7, 0x98, 0xff, 0x00, 0xf2, 0x5c,
+  0x1f, 0xbe, 0x75, 0x71, 0xe2, 0x2b, 0x35, 0xae, 0xc9, 0x4a, 0xe9, 0x7d,
+  0xbe, 0x5b, 0xbc, 0xc4, 0x72, 0x42, 0x92, 0x12, 0xf2, 0x02, 0x73, 0xba,
+  0xf6, 0x00, 0x6f, 0xa6, 0x93, 0xd0, 0xda, 0x78, 0x87, 0x83, 0xe4, 0x82,
+  0xd6, 0x21, 0xac, 0xa7, 0x8a, 0x23, 0xe1, 0x98, 0xc4, 0x71, 0x22, 0xb8,
+  0x1f, 0x54, 0x80, 0x2e, 0x49, 0xc6, 0x76, 0x2c, 0x7a, 0xe9, 0x39, 0x73,
+  0x01, 0x1c, 0x65, 0xb7, 0xc7, 0xff, 0x00, 0xd4, 0xd6, 0xc9, 0x22, 0xa7,
+  0xac, 0x68, 0x7e, 0x66, 0x00, 0x66, 0xaa, 0x40, 0x1b, 0xc1, 0x8c, 0xa8,
+  0xdb, 0xdd, 0x88, 0x38, 0xc7, 0x6c, 0xeb, 0x0a, 0xab, 0x8e, 0xcb, 0x6b,
+  0xac, 0x5a, 0x6a, 0xd7, 0x94, 0x5b, 0xbc, 0x72, 0x82, 0x32, 0x33, 0x23,
+  0xc5, 0x92, 0x09, 0xfb, 0xe3, 0xf5, 0xd6, 0xd9, 0xf0, 0x92, 0xf1, 0x41,
+  0x07, 0x06, 0x51, 0x5b, 0xae, 0x6b, 0x19, 0x58, 0xd5, 0xd6, 0x39, 0x81,
+  0x00, 0x45, 0xe6, 0xda, 0x26, 0xdf, 0x63, 0xd3, 0xf6, 0xd7, 0x9c, 0x38,
+  0xe2, 0x29, 0x1f, 0x8a, 0xab, 0x40, 0x93, 0x31, 0x53, 0xca, 0x51, 0x30,
+  0x32, 0x00, 0xc9, 0xc7, 0xeb, 0xa9, 0x0c, 0x89, 0x26, 0x56, 0x55, 0x49,
+  0x17, 0x4f, 0xf6, 0x76, 0xa9, 0xe1, 0x2b, 0x37, 0x10, 0x5c, 0xd2, 0xed,
+  0x3b, 0xc1, 0x25, 0x50, 0x11, 0x5b, 0xeb, 0x25, 0x8f, 0x1c, 0x89, 0xcc,
+  0x4f, 0x9b, 0xfc, 0x3c, 0xde, 0x5f, 0xd3, 0x5b, 0x7f, 0xc5, 0xea, 0x0b,
+  0xc5, 0x75, 0xa2, 0x8d, 0xa1, 0x9a, 0x23, 0x43, 0x1c, 0x5c, 0xd3, 0x32,
+  0xb6, 0x39, 0x98, 0xf7, 0xc0, 0xeb, 0xdb, 0xf5, 0x3a, 0xf2, 0xb5, 0xba,
+  0x9d, 0x8b, 0x2b, 0x73, 0x64, 0x03, 0xe9, 0xad, 0xc3, 0xe1, 0x2f, 0x17,
+  0xf3, 0x52, 0x0e, 0x12, 0xe2, 0x33, 0x2c, 0x96, 0xc9, 0xd7, 0x92, 0x9e,
+  0x51, 0xd6, 0x1f, 0x40, 0x4f, 0x65, 0xfe, 0xda, 0x4e, 0x45, 0xf2, 0xc1,
+  0xc2, 0xe9, 0xb0, 0x23, 0x2d, 0xde, 0x26, 0x43, 0xf1, 0x67, 0x87, 0x6e,
+  0xf6, 0x8a, 0x5a, 0x4b, 0xbb, 0x40, 0xcd, 0x47, 0x55, 0xcc, 0x91, 0xcc,
+  0x01, 0x00, 0x15, 0xeb, 0xf8, 0x3d, 0x8f, 0xb6, 0xb2, 0xca, 0x6a, 0xaa,
+  0xba, 0x5a, 0xd4, 0x96, 0x98, 0x81, 0x39, 0x6e, 0x50, 0x18, 0x64, 0x6f,
+  0xd8, 0xeb, 0xd8, 0x9f, 0x18, 0x78, 0xae, 0xd5, 0x61, 0xe1, 0x8a, 0xae,
+  0x10, 0xb4, 0x53, 0xbd, 0xc9, 0xaa, 0x23, 0x30, 0xca, 0x66, 0x97, 0xc4,
+  0x8a, 0x9d, 0x71, 0xdb, 0x3d, 0x4f, 0xdb, 0xa6, 0xbc, 0xad, 0x5d, 0x6f,
+  0x14, 0x37, 0x6a, 0x7a, 0xb4, 0x84, 0xb4, 0x62, 0x45, 0xfa, 0x17, 0x70,
+  0x33, 0xbe, 0x33, 0xd3, 0x6d, 0xb3, 0xab, 0xc1, 0x1f, 0x86, 0x3b, 0x3b,
+  0x18, 0xa9, 0x70, 0x99, 0x15, 0x4a, 0xdc, 0xeb, 0xe3, 0x3f, 0x35, 0x31,
+  0x65, 0x8f, 0x01, 0xe3, 0x4d, 0x82, 0x92, 0x36, 0xc8, 0x1b, 0x1f, 0xbe,
+  0xa3, 0xb1, 0xdc, 0x2a, 0xec, 0xb5, 0x6e, 0x20, 0x45, 0x31, 0x33, 0xf2,
+  0xba, 0x30, 0xce, 0x47, 0xb7, 0xa1, 0xd5, 0xbe, 0xed, 0x34, 0x4d, 0x0c,
+  0xc2, 0xc8, 0x8f, 0x15, 0x1d, 0x75, 0x51, 0x73, 0x14, 0x92, 0x66, 0x4c,
+  0x2e, 0x71, 0xcd, 0x8e, 0xb8, 0xc9, 0xfd, 0x74, 0x04, 0x96, 0x3f, 0x98,
+  0x77, 0xa9, 0xf0, 0x01, 0x25, 0x4e, 0xd9, 0xc6, 0x0f, 0x63, 0xf8, 0xd1,
+  0x42, 0x7b, 0xc0, 0x0e, 0xb9, 0xc1, 0x69, 0xaf, 0xb2, 0x81, 0x1d, 0x44,
+  0xf2, 0xd4, 0x56, 0xb8, 0x58, 0xa9, 0x23, 0x3b, 0xbb, 0x06, 0x53, 0xe7,
+  0x19, 0xfa, 0x71, 0x90, 0x3b, 0x93, 0xa4, 0x2b, 0x43, 0x27, 0x81, 0x2b,
+  0x0a, 0x69, 0x72, 0xaf, 0xca, 0x06, 0x31, 0xca, 0x07, 0xb6, 0x87, 0xb8,
+  0x97, 0xb7, 0x54, 0xc2, 0x82, 0x36, 0x47, 0x4c, 0x32, 0x48, 0x1b, 0xa7,
+  0xb6, 0x86, 0x86, 0xf3, 0x51, 0x51, 0xf3, 0x11, 0xbd, 0x43, 0x72, 0x8d,
+  0x95, 0xc0, 0xdd, 0x40, 0x3d, 0x3f, 0x52, 0x4e, 0x99, 0x6d, 0x34, 0xd0,
+  0xf4, 0x1f, 0x0d, 0x10, 0x5a, 0xca, 0x66, 0x58, 0xe5, 0x91, 0xe6, 0x19,
+  0x20, 0x8c, 0x12, 0xdf, 0xe1, 0xd3, 0x26, 0x06, 0x82, 0x14, 0x05, 0xea,
+  0x21, 0x46, 0x56, 0x95, 0x49, 0x18, 0x0c, 0x79, 0xba, 0x63, 0xd4, 0x74,
+  0xce, 0xb9, 0x17, 0x28, 0xe3, 0x6b, 0x05, 0x7c, 0x2b, 0x22, 0x8a, 0x79,
+  0xd0, 0x33, 0x81, 0x9c, 0x90, 0x77, 0xc0, 0xfd, 0xf5, 0xcd, 0xd6, 0x6a,
+  0xba, 0xde, 0x23, 0x9e, 0x59, 0x9e, 0x59, 0x92, 0x56, 0x56, 0x0c, 0x5b,
+  0x97, 0x62, 0x7b, 0x0e, 0xcb, 0xd7, 0x6d, 0xf5, 0xad, 0x1b, 0xd7, 0x41,
+  0x46, 0xe3, 0x3d, 0xc5, 0x2a, 0x6a, 0xe0, 0x5e, 0x77, 0x1c, 0xb2, 0xca,
+  0x59, 0x32, 0x4e, 0x36, 0xce, 0x74, 0x44, 0xd7, 0x2a, 0x4a, 0xea, 0x54,
+  0x47, 0x46, 0x8d, 0xda, 0x50, 0xae, 0x0f, 0x63, 0x82, 0x03, 0x67, 0xdb,
+  0xa7, 0xe7, 0x42, 0x4d, 0x44, 0xf6, 0x8b, 0xdd, 0x54, 0x0a, 0xf9, 0x8b,
+  0x67, 0x60, 0x1b, 0x2c, 0xc0, 0x8c, 0x93, 0xf6, 0xce, 0x8d, 0xad, 0xa6,
+  0x48, 0xec, 0xc2, 0xe3, 0x84, 0x53, 0x59, 0xe1, 0x99, 0x90, 0x27, 0x51,
+  0xb9, 0x04, 0x1f, 0x7e, 0xbf, 0xa6, 0xad, 0x8d, 0x88, 0x1c, 0x7f, 0x3d,
+  0x6f, 0x86, 0x52, 0xcb, 0xe2, 0x50, 0xc3, 0x28, 0x8c, 0xf7, 0x00, 0xee,
+  0x0e, 0x3d, 0xb4, 0x59, 0xb3, 0xd1, 0x54, 0x5b, 0xeb, 0x83, 0x9f, 0x0a,
+  0x47, 0x0d, 0x35, 0x39, 0x4e, 0x85, 0x15, 0x73, 0xfb, 0xe4, 0x6d, 0xdb,
+  0x50, 0x99, 0x69, 0xc7, 0x0b, 0xc9, 0x42, 0x81, 0x85, 0x43, 0x4c, 0x5d,
+  0x49, 0x5c, 0x2b, 0x63, 0x27, 0x19, 0xfc, 0x68, 0x6a, 0x99, 0x5a, 0x0b,
+  0x13, 0xb8, 0x95, 0xa3, 0x2e, 0xc5, 0x02, 0x11, 0xb9, 0xce, 0xfb, 0xfb,
+  0x74, 0xd5, 0x14, 0xc0, 0xe3, 0xb9, 0xd5, 0xc5, 0x6e, 0x4b, 0x6d, 0x42,
+  0xab, 0xa3, 0x60, 0x29, 0xe6, 0xdd, 0x37, 0xc6, 0x3e, 0xda, 0x8f, 0x8c,
+  0x56, 0x3b, 0x8f, 0xc9, 0xdb, 0xa0, 0x58, 0xd6, 0x4a, 0x28, 0x39, 0x07,
+  0x20, 0xd8, 0x9e, 0x62, 0x4f, 0xf7, 0xd4, 0x34, 0xf4, 0x6f, 0x2d, 0x39,
+  0x33, 0xcb, 0x1e, 0x14, 0xf5, 0xcf, 0x51, 0xe9, 0xa6, 0x86, 0x9e, 0x81,
+  0x29, 0x21, 0x34, 0xec, 0xef, 0x50, 0xc4, 0xbc, 0xac, 0x63, 0xc0, 0x51,
+  0xdb, 0x07, 0xf3, 0xf9, 0xeb, 0xa8, 0x51, 0x4b, 0xa4, 0xb5, 0x4a, 0x6b,
+  0x42, 0x54, 0xc6, 0x42, 0xab, 0x63, 0xa6, 0xdf, 0x73, 0xad, 0xcf, 0xfd,
+  0x9c, 0x78, 0x5e, 0xe2, 0x9c, 0x71, 0x15, 0xf6, 0x68, 0xa4, 0xa5, 0xb4,
+  0xd2, 0x42, 0xd2, 0x0a, 0x99, 0x94, 0xac, 0x4e, 0xdf, 0x48, 0x0a, 0xdd,
+  0x3b, 0xea, 0x8c, 0x23, 0xa7, 0x0a, 0x24, 0xa7, 0x9b, 0x2f, 0xc9, 0x86,
+  0x2d, 0xd3, 0x71, 0xd3, 0x1d, 0xf5, 0x74, 0xa1, 0xe2, 0xba, 0xcb, 0x85,
+  0xa2, 0x92, 0xd1, 0x79, 0xb8, 0x56, 0xad, 0x14, 0x51, 0x24, 0x74, 0xd4,
+  0x54, 0x31, 0x15, 0x32, 0x80, 0x4e, 0x32, 0x07, 0xdb, 0x54, 0x9d, 0x3b,
+  0x15, 0x2c, 0x3c, 0xa7, 0x66, 0xf5, 0x5d, 0xf1, 0x17, 0x84, 0x23, 0x8e,
+  0x68, 0x92, 0xff, 0x00, 0x4b, 0x2c, 0xe1, 0x8a, 0xb3, 0xae, 0x48, 0x03,
+  0xa7, 0x5c, 0x6b, 0xcd, 0x5f, 0x10, 0x6b, 0xc7, 0x17, 0x71, 0x8d, 0x4d,
+  0xe6, 0xb6, 0xae, 0xa7, 0xe4, 0xd4, 0xf8, 0x54, 0xb0, 0xa4, 0x79, 0x61,
+  0x1a, 0xf4, 0x3c, 0xc7, 0xa6, 0x7a, 0x9d, 0xba, 0x9d, 0x1a, 0xd5, 0x09,
+  0x6e, 0x4a, 0x8a, 0x5a, 0x6b, 0x4d, 0x22, 0x38, 0x25, 0xdc, 0xcf, 0x2f,
+  0x8b, 0x3f, 0x2e, 0x46, 0x32, 0x01, 0x21, 0x49, 0x24, 0x6d, 0xd7, 0x42,
+  0xd6, 0x53, 0x5e, 0x26, 0xa5, 0x7a, 0xca, 0xdb, 0x7c, 0xb1, 0x53, 0xe3,
+  0x0c, 0x4c, 0x61, 0x47, 0xdc, 0x6f, 0x8c, 0x7b, 0xef, 0xa6, 0xfc, 0x96,
+  0x5e, 0xd5, 0xec, 0x57, 0x15, 0x1c, 0x6e, 0x23, 0x5a, 0x48, 0x59, 0x56,
+  0x32, 0x70, 0xe5, 0xcb, 0x36, 0xe7, 0x39, 0xcf, 0x41, 0xfa, 0x69, 0x84,
+  0x9e, 0x1d, 0x08, 0x8e, 0x55, 0x81, 0x2a, 0xaa, 0x58, 0x79, 0xbc, 0x61,
+  0xcc, 0x07, 0xb8, 0xf5, 0x3a, 0x12, 0x2a, 0x84, 0x83, 0x95, 0x22, 0x2e,
+  0xc3, 0x2a, 0x63, 0x50, 0xd9, 0x18, 0xf7, 0x3d, 0xfe, 0xda, 0x6a, 0xb5,
+  0x55, 0xb7, 0x26, 0x94, 0xc7, 0x4b, 0x09, 0x90, 0x10, 0xa1, 0xd9, 0xb9,
+  0x79, 0x33, 0xd7, 0x1b, 0x7b, 0x01, 0xbe, 0x97, 0x63, 0x94, 0x52, 0x5c,
+  0x10, 0xd4, 0xf1, 0x15, 0x74, 0xb4, 0x9f, 0x2f, 0x23, 0xc1, 0x2b, 0x10,
+  0x10, 0x46, 0xb4, 0xa8, 0x7c, 0x31, 0xe8, 0xa4, 0xf4, 0x23, 0xd8, 0x7e,
+  0x75, 0x02, 0xd5, 0x5c, 0x82, 0xab, 0x43, 0x4a, 0x54, 0x85, 0x11, 0x86,
+  0x38, 0xe7, 0xc6, 0xfb, 0x91, 0xd0, 0x69, 0xa9, 0xb4, 0xdd, 0xa6, 0x3c,
+  0x83, 0xe5, 0xa0, 0xdf, 0xeb, 0x50, 0x0b, 0x63, 0xee, 0x37, 0xfe, 0xda,
+  0x51, 0x71, 0xa4, 0xab, 0xb7, 0xd4, 0x34, 0x2d, 0x56, 0x80, 0x48, 0x0e,
+  0xc4, 0xe1, 0x8e, 0x0e, 0x33, 0xef, 0xa9, 0xb8, 0xbd, 0xa7, 0xc8, 0x94,
+  0x3d, 0x68, 0x92, 0xbd, 0x3c, 0x55, 0x1f, 0x53, 0x09, 0x80, 0xfc, 0x68,
+  0xf4, 0x64, 0xaf, 0xa9, 0x86, 0x8a, 0x3b, 0x7a, 0x7c, 0x9c, 0x32, 0x9f,
+  0xe6, 0xbb, 0xf9, 0x00, 0xf5, 0x3b, 0x6f, 0xa5, 0x96, 0xe9, 0x2d, 0xd4,
+  0x71, 0xbd, 0x40, 0xff, 0x00, 0x7b, 0xb8, 0x33, 0x93, 0xc9, 0x92, 0xa1,
+  0x17, 0xa7, 0x5f, 0x7e, 0xa7, 0x5d, 0xd4, 0xd5, 0x5d, 0xa6, 0x6f, 0x91,
+  0x79, 0x82, 0xc1, 0x27, 0xd0, 0x22, 0xd9, 0x70, 0x7a, 0x0f, 0x7e, 0xd8,
+  0xd5, 0xa6, 0x53, 0x1b, 0xcd, 0x6f, 0xa1, 0x7a, 0xf6, 0x89, 0x78, 0x86,
+  0x08, 0x5a, 0x43, 0xcb, 0x1c, 0x14, 0xf1, 0xb0, 0x0e, 0x07, 0x60, 0xc7,
+  0x63, 0xf7, 0xd3, 0x9f, 0xfe, 0xdb, 0xa4, 0xa3, 0x4a, 0x6a, 0x88, 0xa9,
+  0x58, 0x46, 0x08, 0x9a, 0x77, 0x4f, 0x1a, 0x5e, 0x7c, 0x6d, 0xd3, 0x03,
+  0x3d, 0x4f, 0xa6, 0xab, 0xed, 0xc3, 0x91, 0xc3, 0x68, 0x89, 0x9a, 0xf4,
+  0xb1, 0xcc, 0xe4, 0xad, 0x44, 0x0f, 0x10, 0x0f, 0x18, 0x1d, 0x40, 0x6c,
+  0xe7, 0xa8, 0x1b, 0x69, 0x6a, 0xc7, 0x13, 0xd6, 0xc4, 0x94, 0x95, 0x2d,
+  0x38, 0x62, 0x39, 0xde, 0x52, 0x70, 0x49, 0xdb, 0x97, 0xdf, 0xae, 0x7f,
+  0x1a, 0x8c, 0x0d, 0xca, 0x5c, 0x23, 0xf5, 0x7a, 0xdb, 0xa4, 0x99, 0x12,
+  0xc5, 0x43, 0x54, 0x22, 0x4d, 0xe4, 0x92, 0xa0, 0x87, 0x27, 0xdc, 0x0e,
+  0xdf, 0xae, 0xbe, 0x8a, 0x17, 0x99, 0x15, 0x8b, 0xc8, 0x0e, 0x76, 0x04,
+  0xe3, 0x95, 0x7e, 0xda, 0xb3, 0xf1, 0x4d, 0xae, 0xa6, 0x82, 0x9a, 0x2a,
+  0xba, 0xca, 0xec, 0xf3, 0x80, 0x84, 0x41, 0x1e, 0x31, 0xb6, 0xc0, 0x00,
+  0x71, 0x9c, 0x7f, 0xe7, 0x55, 0xa1, 0x08, 0x5a, 0x49, 0xa6, 0xa9, 0x96,
+  0x72, 0xae, 0xdc, 0xaa, 0x07, 0x5d, 0x4a, 0x19, 0x1a, 0x6a, 0xd3, 0x23,
+  0x32, 0xa5, 0x14, 0x73, 0x27, 0x2b, 0xb8, 0xc9, 0xc3, 0x02, 0x00, 0xce,
+  0x7d, 0x3a, 0xeb, 0xbb, 0x3d, 0xda, 0x92, 0x9d, 0xd6, 0x69, 0x29, 0x9e,
+  0x49, 0x54, 0xe4, 0x3e, 0x3c, 0xa4, 0xff, 0x00, 0x96, 0xa2, 0xb6, 0xa2,
+  0xf8, 0xc9, 0xe3, 0xc7, 0x2f, 0x80, 0xc7, 0xc3, 0xe7, 0xe5, 0xcf, 0xeb,
+  0xef, 0x8c, 0x68, 0xda, 0xa8, 0xa8, 0xad, 0x95, 0x58, 0xc0, 0x9e, 0x9d,
+  0x9b, 0x20, 0x78, 0x7e, 0x61, 0xe9, 0x9d, 0xf6, 0x07, 0x54, 0x59, 0x35,
+  0x5d, 0xee, 0x79, 0x99, 0xdd, 0x22, 0x8e, 0x25, 0x29, 0x85, 0x63, 0xb1,
+  0xfc, 0x7e, 0x34, 0xbd, 0xb3, 0x57, 0x34, 0x6c, 0xae, 0x65, 0x6c, 0x81,
+  0x1a, 0x83, 0x90, 0x0f, 0xb9, 0xd1, 0x97, 0x1a, 0xb7, 0xac, 0x40, 0xb1,
+  0x43, 0xf2, 0x94, 0xea, 0x02, 0xf2, 0x2e, 0x09, 0x62, 0x3b, 0xe9, 0x32,
+  0x99, 0x21, 0x12, 0x34, 0x52, 0x14, 0x05, 0xb1, 0x19, 0x23, 0x72, 0xde,
+  0xc3, 0x50, 0x84, 0x7f, 0x10, 0xb8, 0x6b, 0x88, 0xc5, 0xfa, 0xe3, 0x79,
+  0x9e, 0xd9, 0x33, 0x50, 0xcb, 0x57, 0x37, 0x85, 0x2a, 0xee, 0x39, 0x3c,
+  0x56, 0x03, 0x3e, 0x9d, 0x07, 0xeb, 0xa1, 0x28, 0xac, 0xf3, 0xd2, 0xd2,
+  0xbd, 0x6d, 0x43, 0x72, 0x3c, 0x60, 0x15, 0x41, 0xd5, 0x75, 0x78, 0xe3,
+  0x7e, 0x27, 0xa5, 0x96, 0xef, 0x3d, 0xb7, 0xe6, 0x5c, 0xc7, 0x4b, 0x33,
+  0xaf, 0x86, 0x7f, 0xc6, 0x18, 0xe4, 0x9e, 0xdd, 0x49, 0xc7, 0xb6, 0xaa,
+  0x35, 0x57, 0x17, 0xaa, 0x2d, 0x00, 0x3c, 0xa8, 0x73, 0xef, 0x9d, 0xf5,
+  0x9b, 0x04, 0x25, 0xb5, 0xca, 0x7d, 0xff, 0x00, 0xe1, 0xc5, 0x97, 0xd9,
+  0x84, 0x47, 0x55, 0x25, 0x6d, 0x74, 0x75, 0x15, 0xb3, 0xbc, 0xc4, 0xb6,
+  0x4b, 0x39, 0xe6, 0x00, 0xfa, 0x9c, 0x9d, 0xc6, 0xfa, 0xb5, 0x9e, 0x24,
+  0xa7, 0xa5, 0xb3, 0xd3, 0xd9, 0xa9, 0xee, 0x0c, 0x20, 0x4c, 0xf3, 0x00,
+  0xa5, 0x4b, 0x39, 0xdc, 0x9f, 0x5c, 0x7f, 0xdf, 0xde, 0x91, 0x12, 0x08,
+  0x21, 0x67, 0x5f, 0xab, 0x1b, 0x6b, 0xed, 0x0a, 0x78, 0x93, 0x89, 0x64,
+  0xcb, 0x04, 0x39, 0xfc, 0xe8, 0x26, 0xf9, 0x48, 0x56, 0xf2, 0xfb, 0x6f,
+  0xba, 0x34, 0x96, 0xba, 0xab, 0x74, 0x52, 0x7f, 0xba, 0xcb, 0xcb, 0xe2,
+  0x12, 0x30, 0x3a, 0x74, 0xc6, 0xab, 0xb7, 0x68, 0xe3, 0xa7, 0xa9, 0x54,
+  0x8c, 0x89, 0x09, 0x1e, 0x66, 0x1b, 0x83, 0xed, 0x9d, 0x29, 0xaf, 0xaf,
+  0xa9, 0xa6, 0x63, 0x0d, 0x31, 0x68, 0xfc, 0x4e, 0x56, 0x66, 0x56, 0xec,
+  0x07, 0x4f, 0xdf, 0x52, 0x5a, 0xe7, 0x79, 0xa2, 0x78, 0x66, 0x60, 0xce,
+  0x4f, 0x30, 0x63, 0xd7, 0x55, 0x54, 0x54, 0xa7, 0xb8, 0xd4, 0xfe, 0x11,
+  0x58, 0x7e, 0x1f, 0xde, 0xea, 0x61, 0xa1, 0xbd, 0x5e, 0xea, 0xa9, 0xeb,
+  0xa5, 0xd9, 0x69, 0x5c, 0x08, 0xe3, 0x90, 0xfa, 0x09, 0x0e, 0x72, 0x7a,
+  0xed, 0xb6, 0xb7, 0xe8, 0x61, 0xe1, 0x1e, 0x07, 0xa2, 0x4a, 0x5a, 0x5a,
+  0x40, 0x8e, 0xc9, 0xff, 0x00, 0x06, 0x18, 0x8c, 0x92, 0x32, 0xe3, 0xa9,
+  0xf6, 0xdb, 0xae, 0xc3, 0x5e, 0x53, 0xe1, 0xb8, 0x6d, 0xf5, 0x93, 0x1a,
+  0x5a, 0xe8, 0x99, 0x9e, 0x48, 0xf9, 0x29, 0x9c, 0x3f, 0x2f, 0x85, 0x36,
+  0x57, 0x95, 0x89, 0xf4, 0xeb, 0xfa, 0xea, 0xdd, 0x74, 0xbc, 0xf1, 0x6f,
+  0x0d, 0xd3, 0x1b, 0x55, 0xce, 0xb2, 0x3b, 0x8d, 0x1b, 0x1e, 0x69, 0x8a,
+  0x8c, 0xcf, 0x32, 0x67, 0xe9, 0x62, 0x7c, 0xc5, 0x7b, 0x63, 0xa6, 0xda,
+  0x09, 0x6a, 0x31, 0xc7, 0xc2, 0xbc, 0xbd, 0x0d, 0xc7, 0x38, 0xae, 0x97,
+  0x27, 0xcf, 0x88, 0xb7, 0x3b, 0x75, 0xf6, 0xf7, 0x57, 0x58, 0x69, 0x44,
+  0x6a, 0x1d, 0xbc, 0x1f, 0x02, 0x35, 0x50, 0x17, 0x3b, 0x1d, 0xba, 0x93,
+  0xea, 0x73, 0xac, 0xca, 0xba, 0x81, 0x64, 0xad, 0x32, 0x46, 0x8c, 0xa3,
+  0xb3, 0x36, 0x0b, 0x63, 0xf4, 0xd5, 0xba, 0xf4, 0xa5, 0x78, 0x4a, 0xb3,
+  0x8a, 0x6d, 0x55, 0x54, 0xd1, 0x50, 0xd1, 0xf2, 0xc2, 0x20, 0x95, 0xb9,
+  0x5a, 0x49, 0x5b, 0xfe, 0x5e, 0xe7, 0x19, 0x39, 0xed, 0xac, 0xee, 0xd5,
+  0x7e, 0x45, 0x41, 0x1d, 0x67, 0x36, 0x32, 0xcd, 0xe2, 0x01, 0x96, 0xc9,
+  0xdf, 0x41, 0x8d, 0x39, 0x2b, 0x6a, 0x85, 0xbb, 0xbe, 0x06, 0x41, 0x15,
+  0x67, 0xf9, 0x79, 0x23, 0x0a, 0x08, 0xf2, 0x30, 0x3e, 0x9d, 0x06, 0x34,
+  0x44, 0xf1, 0xd5, 0xd2, 0x53, 0xac, 0xeb, 0x87, 0x8f, 0x62, 0x79, 0x86,
+  0x70, 0x34, 0x9f, 0x88, 0xea, 0x64, 0xa8, 0xb3, 0xd1, 0x55, 0x40, 0xad,
+  0x03, 0x34, 0x87, 0xae, 0xe4, 0xe3, 0x38, 0x3a, 0x0e, 0xa7, 0x88, 0x2e,
+  0x15, 0x36, 0x7a, 0x9a, 0x17, 0x3e, 0x27, 0x88, 0x98, 0x04, 0x1c, 0x15,
+  0xdc, 0x69, 0x98, 0xbe, 0xa0, 0x9c, 0xf1, 0x0d, 0x6c, 0xf5, 0xfc, 0xa2,
+  0x6a, 0x78, 0x51, 0xe2, 0x61, 0x1a, 0xf2, 0xb7, 0x98, 0x83, 0xed, 0x8e,
+  0x83, 0x5d, 0x0b, 0x39, 0xb7, 0x52, 0x0a, 0xcb, 0x8c, 0x4b, 0xe0, 0xcb,
+  0x1f, 0x89, 0x4e, 0x76, 0xfe, 0x68, 0xe6, 0x23, 0xd7, 0x6d, 0xd7, 0x40,
+  0xd8, 0xa9, 0xda, 0xa8, 0xb3, 0xcf, 0x0c, 0xb2, 0x78, 0x23, 0x9c, 0x0e,
+  0xc0, 0x02, 0x3a, 0xfa, 0x8d, 0x38, 0xbd, 0xdf, 0xe9, 0xae, 0xf5, 0x15,
+  0x8f, 0x53, 0x48, 0xb1, 0xca, 0x89, 0x1a, 0x52, 0xa4, 0x28, 0x23, 0x48,
+  0x54, 0x64, 0x9d, 0x80, 0xef, 0x9d, 0x0b, 0x1b, 0x16, 0x70, 0xe5, 0xea,
+  0xa8, 0xe3, 0x01, 0x7f, 0x9a, 0xaf, 0xcc, 0xb1, 0xa0, 0xf2, 0xa2, 0x67,
+  0x6f, 0xce, 0x8a, 0xbd, 0xcf, 0x34, 0xa9, 0x29, 0x41, 0xe6, 0x88, 0x22,
+  0xb1, 0x07, 0x21, 0x98, 0x64, 0x93, 0x9f, 0x5d, 0xfa, 0x68, 0x5e, 0x1f,
+  0xaa, 0x92, 0x92, 0xb6, 0x1a, 0x93, 0x1a, 0xb7, 0x33, 0x96, 0x90, 0x11,
+  0x9f, 0x21, 0xdb, 0xfe, 0xbf, 0x8d, 0x17, 0xcf, 0x51, 0x6f, 0xaf, 0xad,
+  0xa5, 0x0d, 0x84, 0x9c, 0x73, 0x00, 0x06, 0xc4, 0x7a, 0x6b, 0x5e, 0x17,
+  0xc5, 0x1d, 0x0c, 0x0f, 0xc4, 0x0e, 0xa6, 0x71, 0x55, 0x08, 0xb8, 0x4c,
+  0xed, 0x14, 0xed, 0x20, 0x56, 0x3d, 0x79, 0x90, 0x83, 0xab, 0x2f, 0x11,
+  0xc1, 0x3b, 0xdb, 0x66, 0x96, 0x01, 0x27, 0x82, 0xaa, 0xa5, 0x14, 0x8d,
+  0x89, 0x39, 0x00, 0x0f, 0xb0, 0x1f, 0xf7, 0x9d, 0x27, 0xe1, 0xca, 0x58,
+  0xee, 0x54, 0xb2, 0x41, 0x24, 0x2a, 0x0f, 0x3e, 0xd2, 0x16, 0xc9, 0x4f,
+  0xc6, 0x37, 0x18, 0xed, 0xab, 0x2c, 0x17, 0x1f, 0xfe, 0xcf, 0xa5, 0xb5,
+  0x55, 0x4f, 0x2d, 0x3c, 0xd2, 0x86, 0x85, 0x5e, 0x55, 0x3c, 0xb8, 0x2e,
+  0x00, 0xc7, 0x63, 0x91, 0x9e, 0xfd, 0x34, 0xfb, 0x34, 0xd8, 0x05, 0x1c,
+  0x36, 0xf8, 0xf8, 0x6e, 0x9a, 0xe3, 0x53, 0x0b, 0xa4, 0x10, 0xa3, 0x23,
+  0xc6, 0xad, 0xe6, 0x79, 0x5b, 0xa3, 0x7d, 0x8e, 0x3f, 0x1a, 0xab, 0x57,
+  0x61, 0xa0, 0xa7, 0x91, 0x69, 0x5a, 0x28, 0x08, 0x28, 0x27, 0xee, 0xec,
+  0x7f, 0xc4, 0x3f, 0x1a, 0x3e, 0xe8, 0x93, 0x50, 0x73, 0x5a, 0x56, 0xa1,
+  0xa5, 0x32, 0xb1, 0xf0, 0xd4, 0x21, 0xfa, 0x81, 0x20, 0x6a, 0x4a, 0x09,
+  0x29, 0xa5, 0xa5, 0x4a, 0x4a, 0x98, 0x2a, 0x24, 0xa9, 0x84, 0x37, 0xf2,
+  0x08, 0xf2, 0x87, 0x3b, 0x02, 0x7e, 0xc7, 0x54, 0x53, 0x64, 0x34, 0x86,
+  0x96, 0x8a, 0x92, 0x25, 0x8e, 0x15, 0x96, 0xac, 0x64, 0x3f, 0x8a, 0xbc,
+  0xd1, 0xae, 0xe3, 0x18, 0x19, 0xd3, 0x99, 0xa9, 0x1a, 0xa6, 0x64, 0xe7,
+  0x67, 0x92, 0x56, 0x40, 0x5c, 0x2a, 0xe0, 0x2e, 0x71, 0xb8, 0x00, 0xe3,
+  0x1e, 0xda, 0x16, 0x8a, 0xd1, 0x5b, 0x82, 0x23, 0xa6, 0x25, 0x64, 0xf2,
+  0x80, 0x1f, 0x20, 0x37, 0x5d, 0xce, 0x3a, 0xf4, 0xd8, 0xfa, 0x8d, 0x39,
+  0xa1, 0x57, 0xb7, 0xd4, 0xcf, 0x6f, 0xb8, 0x49, 0x1c, 0x50, 0x48, 0x8a,
+  0xf2, 0x2a, 0x37, 0x3c, 0xc7, 0xa7, 0xd2, 0xc3, 0xf7, 0x1a, 0x84, 0x21,
+  0xf0, 0xe8, 0x28, 0x5a, 0x28, 0xe1, 0x57, 0xab, 0xa9, 0x23, 0x99, 0x93,
+  0xa9, 0x18, 0xf5, 0x5e, 0xc3, 0xdb, 0xf4, 0xd4, 0xc6, 0xba, 0xfc, 0x94,
+  0xd3, 0x2b, 0x62, 0x86, 0x0a, 0x8c, 0x16, 0x64, 0x02, 0x36, 0xe5, 0xec,
+  0x32, 0x4e, 0xc3, 0xa6, 0xa1, 0xae, 0xac, 0xa5, 0x9f, 0xc2, 0x86, 0xd3,
+  0x6e, 0x65, 0x98, 0xcc, 0x79, 0xa6, 0x7e, 0xac, 0x4e, 0x7c, 0xbf, 0x60,
+  0x75, 0xc3, 0xfc, 0xb0, 0x0f, 0x05, 0x64, 0x4e, 0xd2, 0xb1, 0xda, 0x79,
+  0xc9, 0xc0, 0x1d, 0x49, 0x41, 0x8d, 0x87, 0xbe, 0xff, 0x00, 0x6d, 0x42,
+  0x06, 0x43, 0x7d, 0x96, 0x1b, 0x7c, 0x34, 0x56, 0x89, 0x33, 0x51, 0x51,
+  0xe7, 0xa8, 0x91, 0xa3, 0x0c, 0xfc, 0xc7, 0x6e, 0x6c, 0x9e, 0xfe, 0xfa,
+  0xee, 0x9a, 0xcb, 0x78, 0xa9, 0x55, 0x96, 0xae, 0x59, 0xa5, 0x8a, 0x12,
+  0x58, 0x78, 0x8d, 0xce, 0x71, 0xdf, 0xca, 0x3a, 0x01, 0xd3, 0x3f, 0xf6,
+  0x07, 0x96, 0x4a, 0x68, 0x22, 0x89, 0x6d, 0xe8, 0xaa, 0xe8, 0x7c, 0x4f,
+  0x1b, 0x9b, 0x97, 0x94, 0xf5, 0xdc, 0xe3, 0xd3, 0x42, 0x52, 0x56, 0x56,
+  0x55, 0x21, 0xa7, 0x8e, 0xad, 0x99, 0x64, 0x62, 0xcf, 0x32, 0x13, 0xcc,
+  0xfb, 0xf4, 0x3a, 0x84, 0x0c, 0xb8, 0x5c, 0xa8, 0x29, 0xa3, 0xf9, 0x6b,
+  0x4c, 0x4a, 0x24, 0x66, 0x21, 0xe4, 0x45, 0x05, 0xc7, 0xb0, 0x6f, 0x5f,
+  0x7f, 0xf5, 0xd7, 0x16, 0x64, 0xba, 0xb2, 0xd4, 0xd4, 0xd2, 0x52, 0xc7,
+  0x14, 0x4a, 0xc3, 0x9e, 0x57, 0x39, 0x20, 0xe3, 0xbf, 0xa9, 0xd7, 0x5f,
+  0x25, 0x49, 0x41, 0x28, 0x2c, 0x7c, 0x59, 0x0a, 0x61, 0x41, 0x18, 0x20,
+  0xed, 0xdf, 0x46, 0x56, 0xd5, 0xc5, 0xf2, 0x06, 0x0e, 0x52, 0xaf, 0x26,
+  0x19, 0xa2, 0x41, 0x85, 0x51, 0x8e, 0xff, 0x00, 0xe2, 0x3a, 0x11, 0x88,
+  0xe9, 0x2e, 0xd5, 0xe9, 0x13, 0x52, 0xc7, 0x13, 0x47, 0x33, 0xc9, 0xca,
+  0xae, 0xd8, 0x5e, 0x61, 0xdf, 0x18, 0x1f, 0x4e, 0x81, 0xab, 0xa4, 0xa3,
+  0x42, 0xc6, 0xa2, 0xbd, 0xa5, 0x99, 0x62, 0xe7, 0x96, 0x45, 0xcb, 0x1e,
+  0x6f, 0xf0, 0x80, 0x3b, 0x60, 0xe7, 0x5c, 0x56, 0xbd, 0x24, 0x94, 0xca,
+  0xa7, 0x94, 0x33, 0x1c, 0xe0, 0x1f, 0x30, 0xcf, 0xb6, 0x8c, 0xb3, 0xdd,
+  0xa1, 0xa4, 0x33, 0x53, 0x45, 0x4b, 0x1c, 0x6d, 0x24, 0x65, 0x10, 0xc9,
+  0x0a, 0xb3, 0x1e, 0x98, 0xcb, 0x7d, 0x86, 0xa0, 0x14, 0xe3, 0xd0, 0xb6,
+  0xc7, 0x1c, 0x32, 0xe5, 0xa3, 0xa7, 0x32, 0x7f, 0x49, 0x69, 0x54, 0xe4,
+  0x82, 0x3d, 0xff, 0x00, 0xb6, 0x98, 0x57, 0xd1, 0x59, 0xa3, 0xaa, 0x5a,
+  0x8a, 0xda, 0xb9, 0xe4, 0x99, 0xf7, 0xf0, 0x55, 0x42, 0x82, 0x70, 0x70,
+  0x07, 0xa0, 0x1a, 0x81, 0x6b, 0x40, 0xcb, 0xab, 0xc6, 0xc0, 0xae, 0x15,
+  0x91, 0x76, 0x07, 0xbf, 0xe9, 0xa5, 0xeb, 0x53, 0x11, 0xaa, 0x0b, 0x31,
+  0x90, 0xb6, 0x7a, 0x7f, 0x4b, 0x1f, 0x5c, 0xff, 0x00, 0x96, 0xad, 0x12,
+  0xac, 0xb4, 0x70, 0xf5, 0xb2, 0x8e, 0xf5, 0x6a, 0x9e, 0x05, 0x34, 0x94,
+  0x45, 0x50, 0xc9, 0x3c, 0x93, 0xe5, 0xe4, 0x75, 0x04, 0x74, 0x03, 0xd0,
+  0x67, 0xef, 0x8d, 0x09, 0x53, 0x6a, 0xa3, 0xa5, 0x74, 0x9e, 0x82, 0xe6,
+  0x67, 0x90, 0x02, 0xdc, 0xc0, 0x05, 0x0b, 0xbf, 0xeb, 0x9f, 0x6e, 0xdb,
+  0xf5, 0xd2, 0xf9, 0xa5, 0x2d, 0x4d, 0x24, 0x91, 0x88, 0x96, 0x25, 0x6c,
+  0x66, 0x3f, 0xbe, 0x8b, 0x8a, 0xe0, 0xfe, 0x04, 0x94, 0xb4, 0x8b, 0xcf,
+  0xcd, 0x8c, 0x86, 0x18, 0xe5, 0x03, 0x55, 0x61, 0xc3, 0x1a, 0x5d, 0x9f,
+  0x6b, 0x24, 0x9a, 0xb2, 0xa4, 0x4d, 0x59, 0x53, 0xe3, 0x15, 0x1e, 0x69,
+  0x65, 0x7e, 0x8b, 0xec, 0x7d, 0x75, 0xc5, 0xe2, 0x48, 0xab, 0x63, 0xa7,
+  0xa4, 0xa3, 0xa7, 0x59, 0x20, 0xa7, 0x53, 0x23, 0xca, 0xab, 0x8f, 0x10,
+  0x12, 0x0e, 0xe7, 0xbf, 0x6d, 0x45, 0x77, 0x45, 0xab, 0x8c, 0x2c, 0xf2,
+  0xa1, 0x91, 0xf0, 0x15, 0x00, 0xfa, 0x71, 0xa9, 0xe8, 0x84, 0x66, 0x86,
+  0x48, 0x9a, 0x75, 0x8d, 0xce, 0xc5, 0xdb, 0x7e, 0x6d, 0x52, 0x65, 0xed,
+  0xae, 0x85, 0x57, 0x9a, 0xfa, 0xb8, 0x5e, 0x08, 0xe2, 0x05, 0xa3, 0x93,
+  0x0f, 0xca, 0xaa, 0x70, 0xa7, 0xfc, 0xfd, 0x35, 0x35, 0x4c, 0xf4, 0xb1,
+  0xa7, 0xcc, 0xd4, 0x54, 0xcc, 0x95, 0x12, 0x2e, 0x70, 0xbf, 0xe2, 0xff,
+  0x00, 0x2f, 0x4d, 0x0b, 0x5f, 0x3c, 0x4a, 0xea, 0x8e, 0x24, 0x6f, 0x0d,
+  0xb0, 0x08, 0x07, 0x71, 0xed, 0xbf, 0xdb, 0x5c, 0x4b, 0x72, 0xa1, 0x33,
+  0x47, 0x1b, 0x53, 0xaa, 0xca, 0xa0, 0x2a, 0x87, 0x1e, 0x60, 0x75, 0x2c,
+  0x94, 0x49, 0xe3, 0xcd, 0x3d, 0x31, 0xf0, 0xe0, 0x54, 0x56, 0x1b, 0xb6,
+  0x31, 0x9f, 0x7d, 0x09, 0x4a, 0x88, 0x19, 0x96, 0x59, 0x0c, 0x93, 0xc5,
+  0xe6, 0x2c, 0xdd, 0x17, 0xd3, 0x5d, 0xcf, 0x0d, 0x74, 0xc7, 0x9a, 0x7a,
+  0x94, 0xa7, 0x84, 0x9c, 0x80, 0xbf, 0x57, 0xe3, 0x40, 0x56, 0xb5, 0x32,
+  0x7f, 0x22, 0x08, 0x9a, 0x56, 0xfe, 0xa9, 0x1f, 0xb9, 0xf4, 0xd5, 0xd9,
+  0x03, 0x38, 0x96, 0x10, 0x9c, 0x51, 0x79, 0xce, 0x0f, 0x3d, 0xc2, 0x76,
+  0x3f, 0xff, 0x00, 0xd1, 0xb4, 0x3c, 0x30, 0xab, 0xb4, 0x71, 0x80, 0x00,
+  0xc8, 0x3a, 0xfd, 0xc5, 0xcc, 0xff, 0x00, 0xfa, 0xbe, 0xee, 0xb1, 0x80,
+  0x49, 0xaf, 0x9c, 0x1f, 0x6f, 0xe6, 0x36, 0x8e, 0xb3, 0x52, 0xb1, 0x2b,
+  0x9c, 0x9c, 0x0c, 0x13, 0xe9, 0x8e, 0xfa, 0x16, 0x70, 0x72, 0x76, 0xce,
+  0xde, 0x15, 0x05, 0x52, 0x31, 0xcd, 0x81, 0x86, 0x3a, 0xfc, 0xc1, 0x29,
+  0xe9, 0xf0, 0x48, 0x01, 0x77, 0x27, 0x46, 0x38, 0x5c, 0x19, 0x30, 0x79,
+  0x15, 0x79, 0x8b, 0x7b, 0x7a, 0xe9, 0x69, 0x9e, 0x49, 0xa6, 0x25, 0x55,
+  0x58, 0x8e, 0xfd, 0xa3, 0xfb, 0x7b, 0xfb, 0xe9, 0x51, 0x8d, 0xb1, 0x62,
+  0xda, 0xe6, 0x92, 0x4f, 0xf7, 0x96, 0x6e, 0x50, 0xf8, 0x48, 0xd4, 0x8d,
+  0xd8, 0x6e, 0x73, 0xa6, 0x16, 0xa6, 0x2b, 0x1a, 0x13, 0xb8, 0xf5, 0xd2,
+  0xfb, 0xb3, 0x7f, 0x35, 0x23, 0xe7, 0x69, 0x02, 0x8e, 0x76, 0x63, 0xd4,
+  0x93, 0xb7, 0xf6, 0x1a, 0x71, 0x41, 0x4f, 0x23, 0xd2, 0x24, 0xf1, 0xc6,
+  0x4c, 0x60, 0x0e, 0x9f, 0x6d, 0x04, 0xf8, 0x74, 0x08, 0xd2, 0x9c, 0x3f,
+  0x97, 0x93, 0x6c, 0x60, 0xe7, 0x4c, 0xae, 0xdc, 0x61, 0x72, 0xa4, 0xe2,
+  0xda, 0x5a, 0xf5, 0x68, 0xb1, 0x35, 0xb8, 0x51, 0xb4, 0x64, 0x86, 0x19,
+  0x0b, 0x80, 0xec, 0x08, 0xf5, 0xdf, 0x42, 0xd9, 0x69, 0xa5, 0x9c, 0x16,
+  0x2d, 0x1c, 0x51, 0x03, 0x86, 0x79, 0x1b, 0x00, 0x1f, 0x4f, 0xbe, 0xac,
+  0x77, 0x2e, 0x1f, 0xb0, 0xd2, 0x59, 0x29, 0x2f, 0x55, 0xf3, 0xc7, 0xf3,
+  0x8a, 0x59, 0x0a, 0x15, 0xd9, 0xa3, 0x3e, 0x56, 0x38, 0xeb, 0xce, 0x33,
+  0xb1, 0x1d, 0x0f, 0xae, 0xb9, 0xf9, 0xfe, 0x36, 0xed, 0x87, 0x08, 0xd1,
+  0x4b, 0xa9, 0x5a, 0x4a, 0x9a, 0x34, 0x72, 0x64, 0x12, 0x39, 0x08, 0x55,
+  0x50, 0x90, 0xcc, 0x46, 0x72, 0x31, 0xdc, 0xe4, 0xfd, 0xb7, 0xd5, 0x6e,
+  0xe9, 0x6a, 0x8a, 0x86, 0x71, 0x3d, 0x43, 0xc6, 0x50, 0xe7, 0x28, 0xad,
+  0xe6, 0x18, 0x3b, 0xe4, 0x76, 0xd5, 0x9a, 0xe9, 0xc5, 0xd5, 0xfc, 0x25,
+  0x7b, 0xaa, 0xa4, 0xb1, 0x50, 0xd1, 0x8a, 0x6a, 0x92, 0xbe, 0x0c, 0xf3,
+  0xd3, 0x7f, 0x35, 0x53, 0x1b, 0x18, 0xcb, 0x6e, 0x0e, 0xe7, 0x7d, 0x57,
+  0xef, 0xcd, 0x47, 0x2a, 0xc2, 0xeb, 0x70, 0x4a, 0x8a, 0xc9, 0xc0, 0x73,
+  0x18, 0x88, 0x83, 0x1b, 0x13, 0xb8, 0x66, 0x27, 0x05, 0xba, 0xe7, 0x1b,
+  0x7b, 0xeb, 0x55, 0x49, 0xc5, 0x49, 0x8e, 0x64, 0x53, 0x9f, 0xe2, 0x14,
+  0xa0, 0xa2, 0x08, 0xa9, 0xcb, 0x1f, 0x96, 0x42, 0x77, 0x7d, 0x03, 0x1c,
+  0x46, 0x13, 0xba, 0x05, 0xe5, 0x38, 0x6f, 0x63, 0xa8, 0x2f, 0xb5, 0x75,
+  0x35, 0x12, 0xc5, 0x4d, 0x24, 0xb9, 0x8a, 0x8d, 0x4c, 0x70, 0x28, 0x18,
+  0xe5, 0x19, 0xcb, 0x1f, 0xbe, 0x75, 0xf6, 0xcb, 0x53, 0x4f, 0x9a, 0x95,
+  0xaf, 0x8d, 0xa7, 0xfe, 0x51, 0xf0, 0xdb, 0x9b, 0x74, 0x3b, 0x60, 0xfe,
+  0x3a, 0x7e, 0x75, 0x70, 0x8b, 0x5d, 0x80, 0xd0, 0x5d, 0xc2, 0xf3, 0x58,
+  0xf2, 0x54, 0x3c, 0x54, 0x94, 0xf0, 0x42, 0xe4, 0x23, 0x34, 0x29, 0xcb,
+  0x80, 0x31, 0xb7, 0xea, 0x33, 0x9f, 0x53, 0xa3, 0x38, 0x32, 0xde, 0xd7,
+  0xab, 0xb9, 0xa5, 0x32, 0xc3, 0x02, 0x4a, 0x59, 0xa4, 0xa8, 0x99, 0xb9,
+  0x42, 0x80, 0x32, 0x49, 0x6e, 0xc0, 0x01, 0x9d, 0x22, 0x9b, 0x9a, 0x03,
+  0x2c, 0x7c, 0xbe, 0x2c, 0x64, 0x61, 0xb2, 0x71, 0xae, 0xed, 0xeb, 0x22,
+  0x51, 0x38, 0x35, 0x02, 0x2a, 0x76, 0x50, 0x65, 0xc1, 0xce, 0x7b, 0xe0,
+  0xe9, 0xff, 0x00, 0x1a, 0xf4, 0x35, 0x44, 0x6f, 0x71, 0xb9, 0x41, 0x6a,
+  0x81, 0x8d, 0x21, 0x47, 0x4f, 0x10, 0xac, 0x52, 0x63, 0x3e, 0x22, 0x8e,
+  0xfb, 0xef, 0xff, 0x00, 0x9d, 0x75, 0x55, 0x2f, 0xce, 0xd3, 0xdb, 0x6f,
+  0x10, 0x9f, 0xe7, 0x4c, 0xc2, 0x19, 0x71, 0xdb, 0x6d, 0x57, 0xef, 0x01,
+  0x2b, 0x44, 0x2b, 0x02, 0x88, 0xd1, 0x00, 0x00, 0x67, 0x60, 0x31, 0xab,
+  0x7d, 0xb6, 0xc1, 0x33, 0xf0, 0x55, 0x35, 0x54, 0x15, 0x10, 0x34, 0x09,
+  0x2b, 0x2e, 0x43, 0x79, 0xa3, 0x97, 0x63, 0xb8, 0xed, 0x9c, 0x9c, 0x6a,
+  0xf1, 0xc5, 0x46, 0x5c, 0x7b, 0x1d, 0xa7, 0x95, 0x4a, 0x8e, 0xf8, 0x46,
+  0x68, 0xad, 0xd7, 0x7a, 0xba, 0x29, 0xc1, 0x8a, 0x69, 0x64, 0x0a, 0xac,
+  0x47, 0x94, 0x6f, 0xbe, 0x47, 0xa6, 0x33, 0xa6, 0x5c, 0x46, 0x69, 0xa4,
+  0xe1, 0x44, 0x34, 0xd3, 0x2c, 0x81, 0x18, 0xf8, 0x43, 0x3b, 0xa3, 0x07,
+  0x38, 0x20, 0xf7, 0xdb, 0x51, 0x5a, 0xad, 0x54, 0x55, 0xf7, 0xca, 0x05,
+  0x59, 0x98, 0x45, 0x71, 0x82, 0x58, 0xe5, 0x27, 0xcd, 0xcb, 0x2a, 0x0f,
+  0x37, 0xa6, 0xc4, 0xe8, 0x8e, 0x17, 0x84, 0x53, 0xd4, 0x49, 0x62, 0xbb,
+  0x27, 0xf3, 0x28, 0x5d, 0xbc, 0x0c, 0x9d, 0x9f, 0x27, 0x61, 0x8f, 0x40,
+  0x0e, 0x7f, 0x3a, 0xd2, 0x6e, 0x14, 0xdf, 0x28, 0xe6, 0x17, 0xf1, 0x0c,
+  0xb5, 0xb0, 0xb7, 0x2c, 0x48, 0xe7, 0xae, 0x09, 0x6c, 0x74, 0x3d, 0x36,
+  0xcf, 0x5d, 0x4d, 0x6e, 0x9e, 0xa2, 0x19, 0x62, 0x7a, 0x57, 0xa7, 0x12,
+  0xab, 0x32, 0x13, 0x2e, 0xea, 0x33, 0xb8, 0x23, 0xd4, 0xed, 0xfa, 0x6a,
+  0x5b, 0x85, 0x12, 0x10, 0xd5, 0x10, 0x85, 0x2f, 0x22, 0x91, 0xb7, 0xd0,
+  0x33, 0x90, 0x32, 0x7d, 0xb1, 0xd3, 0x40, 0x5c, 0xe6, 0x5b, 0x6d, 0xbd,
+  0xcc, 0xcc, 0x5d, 0x8a, 0x8e, 0xa3, 0x04, 0xb3, 0x0e, 0x9d, 0xff, 0x00,
+  0xec, 0x1d, 0x42, 0x9a, 0x38, 0x5b, 0xcd, 0x64, 0xcd, 0x53, 0x45, 0x3d,
+  0x5d, 0x05, 0x2b, 0x2b, 0x9e, 0x79, 0x9a, 0x52, 0xc4, 0x80, 0x77, 0xf0,
+  0xd4, 0xec, 0x09, 0xf4, 0xd1, 0x34, 0x86, 0x2a, 0xb9, 0x44, 0x76, 0xf9,
+  0x1a, 0xa0, 0xf4, 0x79, 0x64, 0x3c, 0xa4, 0xfa, 0x8e, 0xfa, 0xa2, 0xba,
+  0xc0, 0x55, 0xe5, 0x91, 0xd9, 0xe5, 0x46, 0xc2, 0xa9, 0x3b, 0x0f, 0xfc,
+  0x6a, 0xff, 0x00, 0xf0, 0xd6, 0x84, 0xdd, 0xd5, 0x56, 0x3a, 0xa2, 0xaf,
+  0x21, 0x28, 0x60, 0x43, 0x86, 0x60, 0xa0, 0x16, 0x6c, 0xfa, 0x6a, 0x15,
+  0xb9, 0x2e, 0xce, 0xe5, 0x33, 0xd1, 0xd6, 0x24, 0x63, 0xc3, 0x25, 0x18,
+  0x1e, 0x45, 0xf6, 0xd3, 0xca, 0x9a, 0xab, 0x65, 0x4c, 0x82, 0xb2, 0xad,
+  0xa1, 0x33, 0x3e, 0x09, 0x76, 0x18, 0x03, 0x6e, 0xde, 0x9a, 0x1a, 0xba,
+  0xc6, 0xf6, 0xab, 0x84, 0x8f, 0x24, 0x0d, 0x0b, 0x83, 0x82, 0xa7, 0x32,
+  0x72, 0x13, 0xd0, 0x64, 0x7a, 0xe8, 0x1a, 0x8a, 0x55, 0xaa, 0xb8, 0xf2,
+  0xbd, 0x4c, 0x06, 0x38, 0xcf, 0x21, 0x91, 0xdb, 0x93, 0x1b, 0x03, 0xf4,
+  0x9e, 0xdd, 0xb5, 0x06, 0x45, 0x46, 0x43, 0xca, 0xba, 0x3b, 0x65, 0x4d,
+  0x2c, 0x75, 0x10, 0x49, 0x2b, 0x52, 0xf2, 0x66, 0x47, 0x91, 0x79, 0x15,
+  0xcf, 0xa0, 0xfb, 0x7a, 0xe9, 0x1c, 0x72, 0x5a, 0xab, 0xae, 0x93, 0xba,
+  0x54, 0xcb, 0x41, 0x16, 0x15, 0x12, 0x3c, 0x1e, 0x46, 0x41, 0xeb, 0x8f,
+  0x5d, 0x73, 0x0d, 0x28, 0xab, 0xaf, 0x11, 0x52, 0xd4, 0x07, 0xa5, 0x89,
+  0x72, 0xf2, 0x67, 0xcb, 0xdb, 0x23, 0xdb, 0xed, 0xa9, 0xab, 0x22, 0xa4,
+  0x15, 0x5f, 0xee, 0x6f, 0xe2, 0xc6, 0x83, 0x99, 0xa4, 0xe4, 0xcf, 0x39,
+  0xe9, 0xb6, 0xfd, 0x34, 0x05, 0xec, 0x3f, 0x55, 0xc0, 0x22, 0x96, 0x49,
+  0xf3, 0x13, 0x72, 0xb9, 0xe5, 0x4f, 0x10, 0x6c, 0xb9, 0xe9, 0x9c, 0x64,
+  0xe3, 0x5f, 0x09, 0xa0, 0x69, 0xd7, 0xc4, 0x12, 0x3c, 0x6d, 0xbb, 0x3f,
+  0x26, 0x06, 0x75, 0xd5, 0x0c, 0x2a, 0xb0, 0x99, 0x0a, 0x2e, 0x7a, 0xf3,
+  0xb8, 0xc9, 0x1e, 0x9a, 0x1e, 0xa6, 0xad, 0x01, 0x6c, 0xc8, 0xc4, 0x11,
+  0x82, 0x54, 0x72, 0x92, 0x7d, 0xb5, 0x2c, 0x24, 0x88, 0xee, 0x09, 0x4d,
+  0x15, 0x63, 0x44, 0x2a, 0x92, 0x6a, 0x79, 0x14, 0x81, 0xcb, 0xb0, 0x55,
+  0x3d, 0x06, 0x7a, 0x9c, 0x6a, 0x4a, 0x6b, 0x62, 0xcc, 0xac, 0xf3, 0x7c,
+  0xa1, 0x87, 0x62, 0x25, 0x73, 0xbe, 0xdd, 0x40, 0xd2, 0x72, 0x61, 0x59,
+  0x39, 0xa4, 0x2c, 0xa8, 0x0e, 0x48, 0x51, 0x9d, 0x33, 0xa2, 0x96, 0x81,
+  0xdb, 0xe6, 0xe0, 0x89, 0x88, 0x56, 0xe5, 0xfa, 0x82, 0x9f, 0xbe, 0xfa,
+  0x96, 0x48, 0x47, 0x90, 0xca, 0xa0, 0x5e, 0x1c, 0xc3, 0x22, 0x98, 0x90,
+  0xe5, 0x42, 0x0f, 0x20, 0x1f, 0xf2, 0xfe, 0xa7, 0xf5, 0xd4, 0x10, 0xab,
+  0x46, 0x85, 0xd8, 0x0f, 0x31, 0xd8, 0x93, 0xa6, 0x72, 0xd5, 0x17, 0x89,
+  0x56, 0x33, 0x85, 0x23, 0x38, 0x6d, 0xf1, 0x9d, 0x05, 0x51, 0x19, 0x78,
+  0xb9, 0x24, 0x95, 0x37, 0x39, 0xc8, 0x19, 0x00, 0x7a, 0x7d, 0xf4, 0x36,
+  0x32, 0x8e, 0x23, 0xe4, 0x2f, 0x97, 0x78, 0xbc, 0x6c, 0xf9, 0x15, 0xba,
+  0x0f, 0x7f, 0xfa, 0xe8, 0x5a, 0x95, 0x8d, 0xe7, 0x0d, 0x53, 0x52, 0xc9,
+  0x17, 0x49, 0x18, 0x30, 0x23, 0x3e, 0xc3, 0xbe, 0x8e, 0x8e, 0xaa, 0x8a,
+  0x9c, 0x32, 0x1c, 0x29, 0xc7, 0x95, 0x89, 0xce, 0x80, 0xaa, 0xf0, 0x1a,
+  0x21, 0x15, 0x35, 0x32, 0x7f, 0x88, 0x1e, 0x5c, 0x67, 0xdf, 0x3a, 0x89,
+  0x83, 0x41, 0x31, 0x44, 0x21, 0x85, 0xa4, 0x86, 0x6c, 0x43, 0x8f, 0x2b,
+  0x14, 0xc3, 0x63, 0xfc, 0xb5, 0x09, 0xab, 0xa4, 0x40, 0xaf, 0x83, 0x2c,
+  0xa0, 0x7d, 0x4c, 0x37, 0xd0, 0x71, 0x53, 0x4d, 0x22, 0xa4, 0x50, 0xc1,
+  0x34, 0xf3, 0x31, 0xc6, 0x22, 0x56, 0x60, 0xb8, 0xfc, 0x6f, 0xab, 0x5f,
+  0x0b, 0xfc, 0x32, 0xe3, 0x2e, 0x24, 0x9a, 0x37, 0x86, 0xc1, 0x58, 0x60,
+  0xe5, 0x00, 0xcb, 0x51, 0x88, 0x50, 0x6e, 0x33, 0xf5, 0x60, 0x9c, 0x0f,
+  0x4c, 0xea, 0xec, 0x85, 0x62, 0x6b, 0xc4, 0xb2, 0x6c, 0x94, 0xa4, 0xb2,
+  0x9c, 0x00, 0xfd, 0x0e, 0x3d, 0x35, 0xf2, 0xa2, 0xae, 0xaa, 0xb9, 0x07,
+  0x8a, 0x90, 0xaf, 0x37, 0xd3, 0x91, 0xb6, 0x75, 0xb3, 0x56, 0x7c, 0x06,
+  0x96, 0xcf, 0x2c, 0xd5, 0x95, 0xd7, 0x75, 0x34, 0x71, 0x6e, 0x9e, 0x04,
+  0x21, 0x5a, 0x4f, 0xc9, 0x27, 0x97, 0xf7, 0xd5, 0x83, 0x83, 0x57, 0x86,
+  0x78, 0x76, 0xa5, 0x0f, 0xf0, 0x2a, 0x22, 0x09, 0x21, 0xe6, 0x91, 0x3c,
+  0x49, 0x37, 0xea, 0x43, 0x36, 0x71, 0xf6, 0xd6, 0x0c, 0xdf, 0x90, 0xc5,
+  0x87, 0x26, 0xc9, 0xf0, 0x64, 0xcb, 0xac, 0xc7, 0x89, 0xd4, 0x8c, 0x9b,
+  0xe1, 0xf7, 0xc2, 0x4e, 0x30, 0xe2, 0xdc, 0x55, 0x4d, 0x1c, 0x94, 0x16,
+  0xdf, 0xe9, 0xa9, 0xa8, 0x04, 0x07, 0x1f, 0xf2, 0xa9, 0xc1, 0x23, 0x7e,
+  0xba, 0xde, 0xf8, 0x1f, 0xe1, 0x0f, 0x06, 0x70, 0xd5, 0x10, 0x7a, 0x8a,
+  0x75, 0xbb, 0x5c, 0x39, 0x73, 0x24, 0xd5, 0x03, 0x2a, 0x0e, 0x07, 0xd2,
+  0x9d, 0x06, 0xfe, 0xb9, 0x3e, 0xfa, 0xb7, 0xdc, 0x78, 0xc2, 0x8e, 0x9e,
+  0x8e, 0x19, 0x62, 0x41, 0x3f, 0x38, 0xda, 0x3e, 0x81, 0x75, 0xd5, 0x97,
+  0x88, 0xa3, 0xba, 0xb8, 0x8e, 0x4a, 0x55, 0x87, 0x23, 0x20, 0x0d, 0xc7,
+  0xeb, 0xeb, 0xab, 0x7a, 0xcd, 0x33, 0x96, 0xc8, 0xcd, 0x36, 0xcc, 0xdf,
+  0xca, 0xc7, 0x3e, 0x99, 0xe7, 0x2f, 0xff, 0x00, 0x88, 0x6b, 0xab, 0x6e,
+  0xf5, 0x17, 0xbb, 0xd5, 0xc2, 0x9a, 0xd3, 0x6e, 0xad, 0xac, 0x92, 0x58,
+  0x9b, 0x9c, 0x3c, 0x92, 0xa1, 0x72, 0xc4, 0x85, 0xe8, 0x36, 0x23, 0xaf,
+  0xae, 0x99, 0x70, 0xef, 0x03, 0xc1, 0x59, 0x5d, 0xc5, 0x31, 0x59, 0xe9,
+  0x95, 0xe9, 0xe0, 0x81, 0xe9, 0xe9, 0xcc, 0xad, 0xb9, 0xc9, 0x05, 0x7e,
+  0xec, 0x40, 0xeb, 0x9d, 0x69, 0x1c, 0x5b, 0x15, 0xba, 0x4a, 0xae, 0x1d,
+  0x92, 0xe7, 0x33, 0x24, 0x51, 0x5b, 0x61, 0xe4, 0xe5, 0x6c, 0xb0, 0x24,
+  0x1f, 0xe9, 0xf4, 0x3b, 0x6f, 0xa6, 0x1c, 0x1d, 0x4b, 0x5b, 0x6f, 0xa5,
+  0xb9, 0xcf, 0x1c, 0x50, 0x47, 0x4a, 0x19, 0xa6, 0x46, 0x55, 0xda, 0x47,
+  0xe5, 0x3c, 0xa7, 0x3d, 0xc0, 0xc6, 0x7e, 0xf8, 0xd3, 0xe7, 0xe1, 0x22,
+  0x64, 0xc6, 0x94, 0xa9, 0x1e, 0x53, 0xbd, 0xb3, 0xc2, 0xe6, 0x85, 0xd5,
+  0xe3, 0x90, 0x31, 0xf1, 0x50, 0x8f, 0x30, 0xc6, 0xdc, 0xa7, 0xdf, 0x39,
+  0xfd, 0x34, 0x34, 0x4b, 0x31, 0x89, 0x62, 0x08, 0xb1, 0x21, 0x20, 0x10,
+  0x06, 0xe7, 0xef, 0xa2, 0xae, 0xd3, 0x34, 0xb7, 0x09, 0x6a, 0x27, 0x72,
+  0xf2, 0xca, 0xd9, 0x77, 0x3d, 0xcf, 0x7d, 0x45, 0x16, 0x19, 0x58, 0x91,
+  0xb6, 0x36, 0xd1, 0xc5, 0xd1, 0x81, 0xf6, 0x03, 0x5f, 0x01, 0x77, 0x66,
+  0x55, 0xc1, 0x52, 0x47, 0xdf, 0x56, 0x9e, 0x1f, 0x88, 0xa5, 0x8e, 0x33,
+  0x08, 0x01, 0xca, 0xe4, 0xae, 0x92, 0x34, 0x6a, 0xd1, 0xb6, 0x7e, 0xc3,
+  0x5a, 0x25, 0xa2, 0xd9, 0x1c, 0x74, 0x34, 0x50, 0xca, 0xeb, 0x1a, 0xb6,
+  0x09, 0x94, 0x9c, 0x05, 0x07, 0xa9, 0xfd, 0x33, 0xaa, 0x84, 0xb9, 0x6c,
+  0xa0, 0xeb, 0x35, 0xda, 0xe9, 0x07, 0x04, 0x09, 0x23, 0xb7, 0xc3, 0x1c,
+  0x36, 0xe5, 0x92, 0x45, 0x9f, 0x00, 0x18, 0xe6, 0x66, 0xc2, 0xc9, 0xbf,
+  0xd4, 0xdd, 0x40, 0x03, 0xa0, 0xce, 0xdd, 0xf5, 0x47, 0xaa, 0x7b, 0x95,
+  0x65, 0xc9, 0xaa, 0x6b, 0x6a, 0x1a, 0x67, 0x93, 0x76, 0x9b, 0x3b, 0x9d,
+  0xf3, 0xd7, 0xae, 0x72, 0x35, 0x0d, 0xd2, 0x6a, 0xba, 0x9a, 0x99, 0x16,
+  0x33, 0x53, 0x1d, 0x03, 0x4a, 0x3e, 0x5e, 0x9e, 0x59, 0x08, 0xe6, 0x03,
+  0xa3, 0x15, 0xf5, 0xc6, 0xbe, 0x73, 0x4d, 0x44, 0xfc, 0xa8, 0x43, 0xc4,
+  0x40, 0x62, 0x31, 0xea, 0x33, 0xae, 0x7d, 0xb9, 0xab, 0x7d, 0x92, 0xdf,
+  0xb1, 0xef, 0xfe, 0xab, 0xe1, 0xdb, 0x35, 0x1c, 0xd5, 0xf7, 0xdb, 0x3c,
+  0x97, 0xab, 0xc8, 0x46, 0x58, 0x04, 0xa5, 0x4c, 0x4c, 0x36, 0xf3, 0x3e,
+  0x73, 0xb8, 0xf4, 0x00, 0x1d, 0xf5, 0x93, 0x5d, 0x6a, 0x7f, 0x8a, 0xdc,
+  0x26, 0xae, 0x11, 0x47, 0x4d, 0x23, 0x31, 0x2b, 0x14, 0x43, 0x0a, 0x83,
+  0x39, 0xc0, 0xd3, 0x5e, 0x2c, 0x91, 0x66, 0xaa, 0x05, 0x0e, 0xeb, 0x93,
+  0x8f, 0x63, 0xa4, 0x44, 0xaa, 0xc7, 0x14, 0x7c, 0xc0, 0x78, 0xe7, 0x90,
+  0xb1, 0xe8, 0x0f, 0xa1, 0xd7, 0x46, 0x2d, 0xec, 0x49, 0x8f, 0x8c, 0x9b,
+  0xec, 0xec, 0x1f, 0x15, 0x73, 0x27, 0x99, 0xb3, 0xe6, 0xcf, 0xae, 0xa2,
+  0xaf, 0x44, 0x82, 0x08, 0xc8, 0x60, 0xbc, 0xc7, 0x66, 0xf7, 0xd3, 0x7a,
+  0x2b, 0x44, 0xf1, 0xe0, 0xa0, 0x0b, 0x8d, 0xb0, 0x76, 0x24, 0x6b, 0x8b,
+  0xe4, 0x3e, 0x15, 0x19, 0xf1, 0xd2, 0x2d, 0xfe, 0xa0, 0x17, 0xbf, 0xae,
+  0xab, 0x22, 0xb4, 0x8a, 0x8f, 0x62, 0x4a, 0x47, 0x69, 0x27, 0x45, 0x69,
+  0x39, 0x57, 0x1b, 0x9e, 0xde, 0xff, 0x00, 0xdb, 0x47, 0xdc, 0x2a, 0x69,
+  0xa3, 0x50, 0xd4, 0xf0, 0xc6, 0x25, 0xe8, 0xdb, 0x6d, 0x9f, 0x4c, 0x69,
+  0x13, 0x2b, 0xae, 0x02, 0xbb, 0x04, 0xd8, 0x92, 0x36, 0xfc, 0x68, 0xe6,
+  0x81, 0x10, 0x23, 0x40, 0xc4, 0xae, 0x03, 0x12, 0xdd, 0x73, 0xdf, 0xf1,
+  0xa5, 0xa4, 0x12, 0x64, 0x31, 0xc9, 0x14, 0x93, 0xe1, 0x93, 0x90, 0x92,
+  0x7a, 0x74, 0xfd, 0x35, 0xe8, 0xfa, 0x0e, 0x0d, 0xb3, 0x5b, 0x3e, 0x09,
+  0x48, 0x68, 0x96, 0x79, 0xeb, 0xaa, 0x04, 0x15, 0xf5, 0x12, 0x33, 0x79,
+  0x49, 0x5d, 0xc8, 0x51, 0x9d, 0x80, 0x42, 0xda, 0xf3, 0xfa, 0xc2, 0x12,
+  0x56, 0x2e, 0x42, 0xb8, 0x00, 0xa9, 0x03, 0xa8, 0x3b, 0xeb, 0xd0, 0xdc,
+  0x0f, 0xf1, 0x04, 0x55, 0xf0, 0x5d, 0xbe, 0xd0, 0x91, 0xc4, 0xd3, 0x52,
+  0xd3, 0x0a, 0x69, 0x55, 0x86, 0x4e, 0x00, 0xc0, 0x3f, 0x91, 0xa5, 0x67,
+  0xda, 0xaa, 0x52, 0x74, 0x90, 0x37, 0xcd, 0x99, 0xa8, 0x13, 0xc5, 0x43,
+  0x25, 0xc5, 0x1f, 0x96, 0x7a, 0x3a, 0x91, 0x32, 0xa9, 0x18, 0xf1, 0x14,
+  0x9e, 0x57, 0xc0, 0xef, 0xe6, 0x03, 0xf5, 0x1a, 0x6d, 0x7f, 0x78, 0xe4,
+  0xbd, 0x5a, 0xaa, 0xea, 0x52, 0x58, 0x52, 0x5a, 0x57, 0xdc, 0x1f, 0x36,
+  0x7a, 0x8c, 0x8f, 0x61, 0x8d, 0x7e, 0xa5, 0xa3, 0x86, 0xa0, 0x5e, 0xad,
+  0x0d, 0x21, 0x5a, 0xa8, 0x49, 0x11, 0x87, 0xd8, 0x3c, 0x6c, 0x83, 0x60,
+  0x3b, 0x79, 0x94, 0x7e, 0xba, 0xe6, 0xae, 0x2a, 0x9b, 0x9d, 0x8f, 0x87,
+  0x1c, 0x6f, 0x50, 0xb2, 0xc7, 0x18, 0x3f, 0xf2, 0x82, 0x57, 0xfb, 0x0d,
+  0x74, 0x62, 0xd4, 0x95, 0xa3, 0xac, 0xb9, 0x42, 0xca, 0x8a, 0xb1, 0x00,
+  0x96, 0x9e, 0x59, 0xe1, 0x67, 0x8e, 0x55, 0x87, 0x9b, 0x18, 0x56, 0x52,
+  0x09, 0xe6, 0x23, 0xb9, 0xc9, 0xc9, 0xf5, 0xfc, 0x69, 0x1d, 0xcd, 0xa2,
+  0x91, 0xe3, 0x50, 0xa2, 0x79, 0x64, 0x03, 0x2f, 0xfd, 0x38, 0xec, 0x71,
+  0xdb, 0xed, 0xa7, 0xbc, 0x45, 0x22, 0x7f, 0x15, 0x91, 0x04, 0x3c, 0xe9,
+  0x2c, 0x2a, 0x55, 0x13, 0x62, 0x58, 0x33, 0x63, 0x3a, 0x4d, 0x67, 0xa7,
+  0x96, 0x47, 0x96, 0xb2, 0xa6, 0x3c, 0xb2, 0x36, 0xc9, 0xd3, 0x18, 0xd8,
+  0xea, 0xc6, 0x51, 0x2d, 0xaa, 0xd5, 0x6d, 0xa4, 0xa9, 0xac, 0x32, 0xc5,
+  0x0c, 0xf2, 0x54, 0x29, 0x4f, 0x3a, 0x6d, 0x19, 0xc7, 0x51, 0xff, 0x00,
+  0x7d, 0xf4, 0xf3, 0x83, 0xea, 0xa5, 0xb0, 0x42, 0x25, 0xa4, 0x8a, 0x9a,
+  0x82, 0x49, 0xa6, 0x65, 0x4a, 0x95, 0x8c, 0x39, 0x8e, 0x23, 0xec, 0x48,
+  0xdc, 0x91, 0xb7, 0xb6, 0x96, 0x4c, 0x4c, 0x15, 0x12, 0x7c, 0xc3, 0x6f,
+  0x29, 0x57, 0xe5, 0x4d, 0xd8, 0x92, 0x3b, 0x0d, 0x77, 0x71, 0xa9, 0x69,
+  0x53, 0xe4, 0x60, 0xa6, 0x8e, 0x06, 0x95, 0x46, 0x65, 0x78, 0xc6, 0xeb,
+  0xd3, 0x3e, 0xd8, 0x07, 0x19, 0xf5, 0x3a, 0x00, 0x66, 0x83, 0xab, 0x6a,
+  0xea, 0xe6, 0x49, 0xab, 0x2e, 0x17, 0x96, 0xf0, 0x6a, 0x7c, 0xd1, 0x45,
+  0x1b, 0x79, 0x80, 0x3b, 0x82, 0xde, 0xff, 0x00, 0x6d, 0x2d, 0x86, 0x4a,
+  0x68, 0x22, 0x96, 0x78, 0xe1, 0x79, 0xcb, 0x00, 0xaa, 0xd2, 0x80, 0x47,
+  0x36, 0x3b, 0x69, 0xa5, 0x45, 0xbe, 0x8a, 0x92, 0xdc, 0xf5, 0x4c, 0xaf,
+  0x20, 0x50, 0xab, 0x17, 0x3a, 0xed, 0x81, 0xdc, 0x8f, 0x43, 0xdb, 0x50,
+  0x53, 0x1f, 0x98, 0xa8, 0x35, 0x95, 0xe2, 0x38, 0x29, 0x97, 0xc8, 0x39,
+  0x13, 0x00, 0x11, 0xd8, 0x0f, 0xc6, 0xa0, 0x6a, 0x07, 0x34, 0x90, 0x23,
+  0x50, 0xc3, 0x0b, 0xf2, 0xa3, 0xc8, 0x39, 0x9f, 0x19, 0x00, 0x8f, 0x4f,
+  0xfb, 0xf4, 0xd1, 0x31, 0x40, 0xb0, 0xc8, 0x20, 0xf1, 0x02, 0x43, 0x93,
+  0xcc, 0x54, 0xee, 0xc3, 0x4b, 0x6b, 0xeb, 0x5a, 0x79, 0x84, 0x31, 0x07,
+  0x48, 0xf9, 0x89, 0x0b, 0xcc, 0x73, 0x8f, 0xf2, 0xd4, 0xad, 0x1c, 0xd1,
+  0x22, 0x91, 0x84, 0xc9, 0xca, 0x03, 0x92, 0x70, 0x46, 0x7a, 0xe7, 0x50,
+  0x60, 0x65, 0x53, 0xc7, 0x0a, 0x88, 0xd2, 0x00, 0x0f, 0x31, 0x06, 0x59,
+  0x18, 0x1e, 0x6f, 0x4c, 0x7a, 0x68, 0x1a, 0xaa, 0xd6, 0xe5, 0x68, 0x95,
+  0x23, 0x04, 0x0c, 0x73, 0x05, 0xc8, 0xd7, 0x35, 0xd2, 0xb3, 0xc7, 0x12,
+  0x31, 0xf3, 0x31, 0x00, 0x9e, 0x60, 0x77, 0xc7, 0xf7, 0xd0, 0x29, 0x04,
+  0x22, 0xb2, 0x40, 0xc2, 0x52, 0x63, 0xe8, 0x5b, 0x61, 0x9d, 0x2c, 0x84,
+  0x90, 0x55, 0x2a, 0x23, 0x09, 0xa7, 0x63, 0xd8, 0xaa, 0x46, 0x30, 0x75,
+  0x0c, 0x73, 0xc5, 0x1c, 0x92, 0xba, 0x29, 0x54, 0x39, 0x61, 0x9f, 0x5d,
+  0x14, 0x65, 0xa5, 0xa6, 0x4e, 0x6a, 0x94, 0x66, 0x69, 0x73, 0xc9, 0xe5,
+  0xc6, 0x4f, 0xa0, 0xd4, 0x74, 0x34, 0x93, 0x5c, 0xaa, 0x9e, 0x38, 0x41,
+  0x41, 0x18, 0x0c, 0xf1, 0xb0, 0xc1, 0x00, 0xf6, 0xd5, 0x49, 0xa4, 0xad,
+  0x82, 0xe7, 0x1c, 0x6a, 0xe4, 0xcf, 0xd1, 0xd5, 0x49, 0x55, 0x12, 0x32,
+  0xe5, 0xb3, 0x91, 0x8e, 0x83, 0x6d, 0x3b, 0xe1, 0xde, 0x1c, 0xbc, 0x5c,
+  0xe0, 0x6a, 0xb5, 0x10, 0xd2, 0x53, 0x09, 0x39, 0x3c, 0x6a, 0x89, 0x02,
+  0x26, 0x7d, 0x89, 0xdd, 0xbe, 0xc0, 0x1d, 0x3d, 0xb0, 0x70, 0xd5, 0xca,
+  0xd2, 0xf4, 0xb7, 0xb6, 0xb3, 0x25, 0x4d, 0x1c, 0x45, 0x64, 0xe5, 0x91,
+  0x03, 0xa4, 0x9e, 0xc4, 0x67, 0x45, 0xdf, 0xae, 0x54, 0x1c, 0x45, 0xc6,
+  0x12, 0xd5, 0xc4, 0xb0, 0x5a, 0xa9, 0x9c, 0x89, 0x24, 0x49, 0x5f, 0x96,
+  0x35, 0x7c, 0x00, 0xd8, 0x18, 0xeb, 0xfe, 0x9a, 0xcd, 0x93, 0x54, 0xaa,
+  0xa1, 0xd9, 0xcf, 0xcb, 0xac, 0x57, 0x50, 0xe4, 0x9a, 0x5f, 0x86, 0x16,
+  0xf3, 0xe1, 0x4d, 0x72, 0xba, 0x99, 0xd1, 0x94, 0xb0, 0x92, 0x05, 0xf2,
+  0x6d, 0xd4, 0x02, 0x7a, 0x77, 0xed, 0xa6, 0x74, 0x1f, 0x0d, 0x78, 0x7d,
+  0xee, 0x34, 0xd5, 0x74, 0xf7, 0x4b, 0x8d, 0x55, 0x34, 0x88, 0x3f, 0x92,
+  0xfb, 0x3b, 0x82, 0x32, 0x14, 0x1c, 0xec, 0x0e, 0xdb, 0xe3, 0x56, 0xfe,
+  0x16, 0xbf, 0x70, 0xb5, 0x25, 0xa5, 0xe9, 0x2b, 0x6a, 0xad, 0xd3, 0xc3,
+  0x12, 0x2a, 0x8f, 0x02, 0x42, 0x43, 0x9e, 0xcd, 0x82, 0x3e, 0xbd, 0xce,
+  0xfe, 0xc3, 0x57, 0xbb, 0x05, 0x77, 0x0a, 0x47, 0x6d, 0x94, 0xda, 0xea,
+  0xe9, 0xa0, 0xf0, 0x51, 0x25, 0xa9, 0x91, 0x9b, 0x1e, 0x18, 0x60, 0x70,
+  0x0b, 0x7e, 0x0e, 0xda, 0xe6, 0xfc, 0x3a, 0xb9, 0xbb, 0x79, 0x69, 0x19,
+  0xbe, 0x7c, 0x8f, 0xfb, 0xcc, 0xf6, 0x86, 0xeb, 0x5d, 0xc1, 0x96, 0xd6,
+  0xb2, 0xd1, 0x5a, 0x85, 0xa2, 0x16, 0x91, 0x8b, 0x18, 0xe2, 0xcb, 0x36,
+  0x7f, 0xab, 0x9f, 0xd7, 0x6d, 0x36, 0xb4, 0x71, 0xdc, 0xb4, 0xb6, 0xf5,
+  0x86, 0xae, 0xe3, 0x1a, 0x73, 0x1c, 0xc1, 0x2b, 0xb7, 0x9a, 0x45, 0x3d,
+  0x9b, 0xdc, 0x7f, 0x96, 0x9d, 0xdf, 0x6f, 0x56, 0x2b, 0xa5, 0xba, 0xa2,
+  0x95, 0x6a, 0xad, 0xd3, 0xa7, 0x86, 0x79, 0xa5, 0x9a, 0x50, 0x30, 0x7d,
+  0x37, 0x1f, 0xbe, 0xb1, 0x7b, 0x8d, 0xb2, 0xed, 0x2c, 0x32, 0x7c, 0x9c,
+  0x74, 0xf7, 0x5a, 0x26, 0xcb, 0x2c, 0x51, 0x37, 0x34, 0x91, 0x2e, 0x3a,
+  0xff, 0x00, 0xd7, 0x57, 0x9b, 0x0e, 0x5d, 0xb4, 0xa7, 0x7f, 0xf6, 0x23,
+  0x24, 0xa7, 0xea, 0x56, 0x6b, 0xd7, 0x3e, 0x2d, 0x9e, 0xa2, 0xdf, 0xe0,
+  0x0a, 0xc8, 0xda, 0x26, 0x05, 0x64, 0xca, 0x87, 0x2f, 0xfa, 0xf4, 0xd5,
+  0x2a, 0xed, 0x0c, 0x33, 0x54, 0x43, 0x83, 0xf2, 0xf0, 0x31, 0x1e, 0x33,
+  0x67, 0x65, 0x4e, 0xbf, 0xae, 0x91, 0x70, 0xec, 0xb1, 0x41, 0xc2, 0x38,
+  0x86, 0x36, 0x9e, 0x56, 0x25, 0xe3, 0x32, 0x3f, 0xd0, 0x17, 0x66, 0x5c,
+  0xe3, 0x1d, 0xc6, 0xdd, 0x76, 0xd2, 0xda, 0xaa, 0x9a, 0x8b, 0xbd, 0x05,
+  0x44, 0xe6, 0xb2, 0x8a, 0x0a, 0x78, 0x17, 0x95, 0x95, 0xe7, 0x0a, 0x5b,
+  0xff, 0x00, 0x88, 0xfd, 0xb5, 0xcc, 0x78, 0x35, 0x19, 0x66, 0xb7, 0xc9,
+  0xb4, 0x26, 0xa6, 0xfb, 0x1b, 0xde, 0x78, 0xe2, 0x82, 0x0b, 0xc8, 0x86,
+  0x82, 0x88, 0x55, 0x51, 0x53, 0xa2, 0xa6, 0x0c, 0xe4, 0x07, 0x20, 0x63,
+  0x9b, 0x38, 0xce, 0xfa, 0xd1, 0x3e, 0x1c, 0x71, 0xfd, 0x8a, 0xf0, 0x82,
+  0xdb, 0x4d, 0x4b, 0xfc, 0x3e, 0xbf, 0x97, 0x22, 0x26, 0x3c, 0xdc, 0xe4,
+  0x76, 0x56, 0xdb, 0x3a, 0xc7, 0xed, 0x2d, 0xc2, 0xd4, 0x09, 0x29, 0x96,
+  0xd8, 0xd7, 0x9a, 0x9c, 0x8d, 0x84, 0xf8, 0xa7, 0x55, 0xc7, 0xa8, 0x1b,
+  0x9d, 0xff, 0x00, 0xbe, 0xb4, 0xbe, 0x09, 0x3c, 0x33, 0x74, 0x86, 0x2a,
+  0x9a, 0x6b, 0x5d, 0x1d, 0x2d, 0x64, 0x78, 0x25, 0x15, 0x07, 0x3a, 0x9f,
+  0x5c, 0xeb, 0xa7, 0x87, 0x0c, 0x31, 0x4a, 0xe3, 0x15, 0x63, 0x21, 0x2d,
+  0xa2, 0x7e, 0x28, 0x8e, 0xe5, 0xc5, 0x1c, 0x5f, 0x6e, 0xa6, 0xb5, 0xd3,
+  0x93, 0x53, 0x6d, 0xb7, 0xc4, 0x31, 0x33, 0x72, 0xc6, 0x11, 0x54, 0x67,
+  0x27, 0x7d, 0x89, 0x23, 0x57, 0x2e, 0x20, 0xe2, 0x0b, 0x77, 0x0f, 0x70,
+  0xfd, 0x3d, 0x0c, 0xf5, 0x46, 0x09, 0x2a, 0x19, 0x11, 0xe4, 0x84, 0x11,
+  0xcb, 0xd8, 0xe0, 0x7a, 0x76, 0xfb, 0x0d, 0x0d, 0x5d, 0x2d, 0x55, 0x15,
+  0xae, 0x29, 0x2d, 0xf0, 0x4e, 0x9e, 0x2c, 0x71, 0x89, 0x66, 0xa7, 0x5e,
+  0x69, 0x47, 0x97, 0xb0, 0xd5, 0x16, 0xe1, 0x79, 0xe1, 0x0b, 0x4d, 0xfa,
+  0x14, 0xe2, 0x7b, 0xb4, 0xb5, 0xb2, 0x73, 0xf3, 0xd4, 0x52, 0xcf, 0x91,
+  0x27, 0x7c, 0x0f, 0x2f, 0xbf, 0x6f, 0xdb, 0x5d, 0x79, 0x79, 0xb3, 0xa7,
+  0x2f, 0x25, 0x66, 0x3d, 0x78, 0x8e, 0x4a, 0x5e, 0x21, 0xae, 0x81, 0xd5,
+  0xd7, 0xc3, 0x99, 0x94, 0x12, 0x36, 0x23, 0x27, 0x1f, 0xb0, 0xd7, 0x70,
+  0x03, 0xcb, 0x93, 0xdf, 0xb6, 0xb5, 0xcf, 0x8b, 0x5c, 0x05, 0x1d, 0xea,
+  0x55, 0xe2, 0xce, 0x0f, 0x6a, 0x6a, 0x9a, 0x49, 0x23, 0x5f, 0x16, 0x92,
+  0x39, 0x4f, 0x88, 0x08, 0x00, 0x64, 0x29, 0xea, 0x71, 0x81, 0x81, 0xbe,
+  0xda, 0xad, 0xf0, 0xd7, 0xc2, 0xbe, 0x2d, 0xbc, 0xf8, 0x73, 0x4d, 0x6e,
+  0x9a, 0xdb, 0x42, 0xcc, 0xb9, 0x9a, 0xa5, 0x08, 0x23, 0x7d, 0xf0, 0xbd,
+  0x4e, 0xde, 0xb8, 0x1a, 0x4a, 0x95, 0xba, 0x39, 0xd2, 0xc5, 0x26, 0xf8,
+  0x14, 0x70, 0x05, 0x82, 0xe1, 0xc4, 0x5c, 0x45, 0x1d, 0x2d, 0x15, 0x0c,
+  0xd5, 0x29, 0x09, 0x12, 0x4d, 0xc8, 0x36, 0x54, 0xf5, 0x3f, 0x73, 0xad,
+  0xd6, 0x9e, 0xd8, 0x96, 0x79, 0xde, 0xe5, 0x55, 0x49, 0x1c, 0xb2, 0x52,
+  0xa7, 0x96, 0x09, 0xd7, 0x99, 0x79, 0x8f, 0x42, 0x46, 0x7e, 0xfa, 0xbb,
+  0x70, 0x57, 0x08, 0xd9, 0x78, 0x2e, 0xcb, 0x15, 0x1d, 0xba, 0x27, 0x79,
+  0x1c, 0x8f, 0x1a, 0xa9, 0x90, 0x19, 0x25, 0x6f, 0x56, 0xf6, 0xf6, 0xed,
+  0xaa, 0xef, 0x1f, 0xde, 0x2d, 0xe2, 0xad, 0xa9, 0xe0, 0x90, 0x97, 0x4d,
+  0xa5, 0x0a, 0x36, 0x2c, 0x3a, 0xfe, 0xfa, 0x1c, 0xf3, 0x96, 0x3c, 0x6e,
+  0x9d, 0x36, 0x1c, 0xf1, 0xa8, 0x46, 0xd9, 0x99, 0x71, 0x6d, 0x25, 0xba,
+  0xe5, 0x57, 0x25, 0x7d, 0xca, 0x95, 0x00, 0x5c, 0xb3, 0x38, 0x24, 0x01,
+  0xeb, 0xb0, 0xd6, 0x7f, 0x76, 0x97, 0x87, 0xaa, 0xea, 0x45, 0x1d, 0x9e,
+  0x92, 0x6e, 0x42, 0x30, 0xf3, 0x4a, 0xc5, 0x53, 0xdc, 0x81, 0xe9, 0xad,
+  0x1f, 0x8c, 0x2d, 0xb3, 0xdd, 0x2c, 0x2e, 0xd4, 0xde, 0x43, 0x34, 0x80,
+  0x04, 0xc1, 0x62, 0xc3, 0x7c, 0xf4, 0xe9, 0xf9, 0xd6, 0x37, 0xc4, 0x2e,
+  0x96, 0xfb, 0x83, 0xdb, 0x23, 0xe4, 0x11, 0xc6, 0xc1, 0x26, 0x90, 0x36,
+  0x72, 0xdd, 0xf1, 0xfa, 0x63, 0xef, 0x9d, 0x63, 0xd2, 0xc3, 0x2c, 0xe1,
+  0xbf, 0x23, 0x62, 0x60, 0x7c, 0xb9, 0xd9, 0x28, 0x00, 0xf0, 0x9a, 0xa6,
+  0x6e, 0x40, 0x0a, 0x99, 0xd1, 0x0a, 0xa9, 0x1e, 0xed, 0x9d, 0x05, 0x1f,
+  0x0d, 0xd3, 0x47, 0x08, 0x8e, 0x98, 0xb4, 0x91, 0x1c, 0xee, 0xe7, 0x25,
+  0x94, 0xee, 0x0e, 0x75, 0x71, 0x86, 0x5a, 0x3a, 0x7b, 0x4b, 0x45, 0x30,
+  0x24, 0x39, 0x00, 0xc7, 0x8e, 0xa3, 0x1a, 0xa3, 0x52, 0xde, 0xa4, 0xa7,
+  0xbb, 0x56, 0x52, 0xc4, 0x85, 0x69, 0x62, 0x97, 0x08, 0x8c, 0x73, 0x81,
+  0xed, 0xae, 0x94, 0x61, 0x51, 0xa1, 0x84, 0xc6, 0x2a, 0xdb, 0x74, 0x52,
+  0x34, 0x55, 0x06, 0x58, 0x93, 0x2a, 0xb1, 0x3f, 0x55, 0x3e, 0xc7, 0x55,
+  0xcb, 0x8d, 0xce, 0xa2, 0x49, 0xd6, 0x26, 0x91, 0xd4, 0xc9, 0x83, 0x82,
+  0x7d, 0x75, 0x76, 0x8c, 0xd0, 0x5c, 0x84, 0x80, 0xb7, 0x84, 0x1c, 0x61,
+  0xb0, 0x39, 0x89, 0x3f, 0x6d, 0x4b, 0x6c, 0xf8, 0x71, 0x6b, 0xae, 0xf8,
+  0x8d, 0x4f, 0xc2, 0xf4, 0x57, 0x89, 0xbc, 0x27, 0x1e, 0x2c, 0xd5, 0x95,
+  0x09, 0x83, 0x12, 0x84, 0x2e, 0xe3, 0x04, 0xf5, 0x18, 0xc6, 0x33, 0xd7,
+  0xbe, 0x8d, 0x85, 0x13, 0x3e, 0x93, 0x0a, 0x0f, 0x88, 0x76, 0x03, 0xbf,
+  0x7d, 0x4f, 0x02, 0x2b, 0xc0, 0xac, 0x98, 0xc1, 0x03, 0x5c, 0xdd, 0xed,
+  0xd3, 0xd4, 0x5c, 0xea, 0x29, 0x52, 0x4f, 0xf7, 0x78, 0xa6, 0x60, 0x24,
+  0x3b, 0xe4, 0x02, 0x40, 0xfb, 0xed, 0xa9, 0xa1, 0x85, 0x29, 0x63, 0x31,
+  0xa9, 0x2e, 0xa0, 0xec, 0x71, 0x8d, 0x0d, 0x12, 0x71, 0x0a, 0x4a, 0x41,
+  0x25, 0x30, 0x63, 0x2c, 0x6c, 0xe8, 0xbb, 0x28, 0x3d, 0x73, 0xd0, 0x7d,
+  0xf4, 0xce, 0xdf, 0x5d, 0x4f, 0x68, 0x00, 0x13, 0x3c, 0x15, 0x41, 0xbc,
+  0xcc, 0x4e, 0xc0, 0xe0, 0xe3, 0x3e, 0xde, 0xda, 0x06, 0xd9, 0x70, 0xf0,
+  0x23, 0x92, 0x15, 0xa7, 0x89, 0xe2, 0x95, 0xd7, 0xc4, 0x56, 0x1b, 0x9e,
+  0x52, 0x0e, 0x41, 0xed, 0xd3, 0x4d, 0x2f, 0x37, 0x1a, 0x4b, 0x8f, 0x2b,
+  0x55, 0xc4, 0xa5, 0xd1, 0x3c, 0x35, 0x7c, 0x79, 0xf9, 0x47, 0x40, 0x4f,
+  0x7c, 0x0d, 0x25, 0xc7, 0xfd, 0xcb, 0x82, 0x51, 0x6d, 0xb5, 0xd6, 0x9b,
+  0xb7, 0x10, 0xdb, 0x2e, 0xd0, 0xc4, 0xaf, 0x52, 0x41, 0x8a, 0xa0, 0x83,
+  0xb3, 0xe1, 0x00, 0xc9, 0x1e, 0x9d, 0x0e, 0xa0, 0x98, 0xbd, 0x0d, 0xa6,
+  0xe9, 0x49, 0x09, 0x65, 0x9e, 0xdf, 0x5a, 0x8f, 0x4e, 0x73, 0x95, 0x72,
+  0xe7, 0x2a, 0x07, 0xa6, 0xdd, 0x74, 0xb7, 0x83, 0xee, 0x1e, 0x35, 0x3c,
+  0xdf, 0x22, 0x16, 0x39, 0xed, 0xa8, 0x65, 0x0a, 0xc3, 0x66, 0x0a, 0x30,
+  0x0f, 0xef, 0xa3, 0x2e, 0xf2, 0xc7, 0x4f, 0x75, 0xaf, 0x28, 0xea, 0x62,
+  0x8e, 0x5a, 0x5a, 0xa6, 0x03, 0xe9, 0x72, 0x46, 0x3f, 0x38, 0xc8, 0xc1,
+  0xd7, 0x47, 0x0f, 0xd0, 0xeb, 0x61, 0xfa, 0x20, 0x5a, 0xf5, 0x32, 0xf1,
+  0x2d, 0xae, 0xac, 0x4c, 0x4b, 0xc8, 0x65, 0x89, 0x8c, 0x87, 0x02, 0x26,
+  0x0c, 0x7f, 0x4c, 0xf6, 0xd7, 0xeb, 0x51, 0x92, 0x3b, 0xad, 0x7d, 0x2c,
+  0xb4, 0xc0, 0x4b, 0x1f, 0x33, 0xa2, 0x73, 0x64, 0xb1, 0x27, 0xaf, 0xe3,
+  0x44, 0x5c, 0x26, 0xb6, 0x8b, 0x64, 0x74, 0xef, 0x1c, 0x32, 0x4b, 0x0c,
+  0xb2, 0x31, 0x95, 0x81, 0x39, 0x2e, 0x49, 0x05, 0xbe, 0xe3, 0x03, 0xbe,
+  0x87, 0xbc, 0xcf, 0x53, 0x55, 0x73, 0xb5, 0x5c, 0xa8, 0xd3, 0xc2, 0xae,
+  0xa8, 0x85, 0x4c, 0xa1, 0x4e, 0x39, 0x59, 0x47, 0x9b, 0x56, 0x37, 0x78,
+  0x3a, 0x49, 0x4c, 0xd5, 0x69, 0x55, 0x31, 0x12, 0xf9, 0xc2, 0xb8, 0x71,
+  0xf4, 0x8f, 0x61, 0xe9, 0xef, 0xdf, 0x44, 0x5e, 0xd6, 0x1b, 0x55, 0xfe,
+  0x3a, 0xb1, 0x00, 0x9a, 0x9e, 0x78, 0x73, 0x4e, 0x84, 0xf9, 0x47, 0x62,
+  0x71, 0xae, 0x78, 0xba, 0x2a, 0x2a, 0xc8, 0xed, 0xd5, 0xc9, 0x34, 0x69,
+  0x55, 0x53, 0x2f, 0x2c, 0xab, 0xd0, 0x64, 0x1f, 0xaf, 0x1e, 0x9b, 0x6f,
+  0xf7, 0xd0, 0xf7, 0x46, 0x79, 0xe5, 0x89, 0x6a, 0x66, 0x1c, 0xf4, 0x8a,
+  0xc8, 0x54, 0x0d, 0x86, 0x48, 0x23, 0x07, 0xdf, 0xae, 0x80, 0xb4, 0x75,
+  0x4b, 0xce, 0xed, 0x8a, 0xfa, 0xc9, 0x8b, 0xb6, 0x5a, 0x34, 0xce, 0x54,
+  0x2f, 0x6d, 0xb5, 0x30, 0x64, 0xab, 0xb7, 0x24, 0x40, 0x78, 0x8c, 0x93,
+  0x34, 0x9b, 0x0f, 0xa7, 0xae, 0x73, 0xfa, 0xea, 0x0a, 0x68, 0x96, 0x48,
+  0x92, 0x44, 0x99, 0x54, 0x3f, 0xfc, 0x42, 0xc7, 0x04, 0x2e, 0x40, 0xdb,
+  0xdb, 0x5f, 0x60, 0xad, 0x6a, 0x39, 0xe4, 0xf9, 0x44, 0x0f, 0x02, 0xc5,
+  0xcc, 0x18, 0xaf, 0x28, 0xf3, 0x13, 0xe6, 0x03, 0xbf, 0x7d, 0x40, 0x8f,
+  0xb1, 0x4a, 0xa6, 0x65, 0x54, 0x81, 0x23, 0x89, 0x37, 0x77, 0xc7, 0x99,
+  0xbd, 0x4e, 0xbe, 0x32, 0x40, 0x0c, 0x8c, 0xbc, 0xc5, 0x7e, 0xac, 0x0e,
+  0xa7, 0x3d, 0xc9, 0xed, 0xa1, 0x67, 0x50, 0x70, 0xb1, 0x33, 0x3c, 0x60,
+  0x82, 0x09, 0xed, 0xae, 0xe2, 0x6c, 0x4e, 0x59, 0xc0, 0x0f, 0xb6, 0x0f,
+  0x6c, 0xfa, 0xe8, 0x4b, 0x25, 0x74, 0x75, 0x91, 0x11, 0x5b, 0x9d, 0xd7,
+  0x0c, 0xac, 0xdd, 0x7d, 0xb1, 0xa8, 0xf3, 0x5f, 0x5d, 0x70, 0x5a, 0x58,
+  0x55, 0xe5, 0xab, 0x76, 0x21, 0x63, 0x5d, 0xce, 0x74, 0x3d, 0x65, 0x4b,
+  0x53, 0xd5, 0xf8, 0xce, 0xa6, 0x47, 0xe5, 0xd8, 0x83, 0xb6, 0x7d, 0xf5,
+  0xf7, 0x86, 0xae, 0x95, 0x14, 0xd7, 0x46, 0x9d, 0x27, 0x6a, 0x4a, 0xb7,
+  0x23, 0xe5, 0xe4, 0x0e, 0x31, 0xcd, 0x9d, 0xc6, 0x71, 0xb1, 0x3a, 0x10,
+  0x33, 0xe7, 0x8c, 0x29, 0x7b, 0x2f, 0x7c, 0x39, 0xc0, 0x4c, 0x1a, 0xdb,
+  0xc4, 0x86, 0xe5, 0x4d, 0x70, 0x73, 0x3a, 0xac, 0x90, 0x8d, 0xfc, 0x3e,
+  0xdb, 0x83, 0xd0, 0xab, 0x63, 0xf4, 0xd2, 0xa4, 0x8e, 0x6a, 0xaf, 0x88,
+  0x57, 0x08, 0x3a, 0xcb, 0x55, 0x2b, 0x73, 0x12, 0x37, 0xc8, 0x03, 0x1a,
+  0xe2, 0x5b, 0xa5, 0x55, 0x35, 0x5d, 0x75, 0xc3, 0x15, 0x14, 0xb7, 0x29,
+  0x4f, 0x37, 0x82, 0xbb, 0x01, 0x9d, 0xd8, 0xfa, 0x0d, 0xfb, 0x63, 0x5f,
+  0x78, 0x3f, 0x88, 0x3e, 0x43, 0x88, 0x23, 0xe2, 0x23, 0x49, 0x1d, 0x5c,
+  0xa0, 0xb1, 0x71, 0x2f, 0x46, 0xe6, 0x03, 0x39, 0x03, 0xa1, 0xdb, 0x3a,
+  0x46, 0x59, 0x5b, 0x38, 0xd9, 0x72, 0xca, 0x6f, 0x93, 0x42, 0xac, 0x92,
+  0xba, 0xcd, 0x65, 0x9e, 0xd6, 0x64, 0x91, 0x59, 0xa0, 0x1e, 0x33, 0x74,
+  0xcf, 0x72, 0x3d, 0xfa, 0x6b, 0x2c, 0xb9, 0x55, 0x86, 0xa8, 0xf1, 0xa2,
+  0x8d, 0xa3, 0x47, 0xc3, 0x60, 0x9c, 0x63, 0x3d, 0x75, 0xa9, 0xf1, 0x6f,
+  0x19, 0xd9, 0xea, 0xed, 0x50, 0xd4, 0xd9, 0x96, 0xad, 0x6b, 0x6a, 0x0e,
+  0x25, 0x8e, 0xa1, 0xb9, 0xd6, 0x9f, 0xae, 0x79, 0x4e, 0x37, 0x27, 0xb1,
+  0xd6, 0x43, 0x7f, 0xa8, 0xa5, 0x15, 0x8a, 0xa3, 0x69, 0x79, 0xb0, 0xd8,
+  0x1b, 0x03, 0xdb, 0x3f, 0x7f, 0x5d, 0x2a, 0x9d, 0xee, 0x62, 0xb6, 0x96,
+  0xba, 0xbb, 0x6b, 0x52, 0xaa, 0x2b, 0xc7, 0x24, 0x53, 0x90, 0x09, 0x46,
+  0xe8, 0x41, 0x00, 0x86, 0xcf, 0x7c, 0xe7, 0x57, 0x7a, 0x4e, 0x1f, 0xb9,
+  0x57, 0xf0, 0x4d, 0x24, 0x56, 0xc0, 0x90, 0xab, 0xb2, 0xb4, 0xb0, 0xf4,
+  0x69, 0x64, 0xc9, 0xc3, 0x13, 0xfd, 0x5b, 0x74, 0xf4, 0x1a, 0x4b, 0xc4,
+  0x75, 0x90, 0x49, 0x6e, 0xb7, 0x45, 0xf2, 0x75, 0x91, 0x5c, 0x69, 0xd7,
+  0x13, 0x89, 0x36, 0x55, 0x42, 0xbe, 0x51, 0xef, 0xb6, 0x0f, 0xd8, 0x8d,
+  0x1f, 0x65, 0xe2, 0x2a, 0xd9, 0x6a, 0x22, 0xad, 0x7a, 0xd6, 0x2b, 0x00,
+  0x08, 0xc8, 0x48, 0x20, 0xa0, 0xec, 0x06, 0xda, 0xe6, 0xad, 0xc9, 0xbb,
+  0x42, 0xd2, 0x57, 0xc8, 0xa9, 0xad, 0x97, 0x84, 0xbb, 0xc1, 0x6e, 0xf9,
+  0x59, 0x3e, 0x6a, 0xa1, 0x7f, 0x92, 0x24, 0x1c, 0xbc, 0xde, 0xfa, 0x60,
+  0x9c, 0x15, 0xc6, 0xd4, 0xb5, 0x22, 0xba, 0x8e, 0x23, 0x0c, 0xd1, 0xe5,
+  0x87, 0xcb, 0x4c, 0x39, 0x87, 0xb6, 0x36, 0xdb, 0x45, 0x7c, 0x53, 0xb8,
+  0x51, 0x56, 0xd3, 0x43, 0x74, 0xb7, 0xd5, 0xab, 0xba, 0x1e, 0x5e, 0x50,
+  0x71, 0x2a, 0x12, 0xa3, 0xbf, 0xa6, 0x47, 0xe3, 0xf7, 0xd4, 0xfc, 0x01,
+  0xf1, 0x17, 0xf8, 0x75, 0x9a, 0x9e, 0xdf, 0x7a, 0x54, 0x92, 0x30, 0x4b,
+  0x19, 0x17, 0xeb, 0x52, 0x77, 0xdf, 0xd7, 0x3a, 0x67, 0xd5, 0x59, 0x36,
+  0xc7, 0xf4, 0x0b, 0xc7, 0x75, 0x33, 0x7f, 0xe8, 0x1b, 0x7c, 0x0b, 0x48,
+  0xb6, 0xea, 0x88, 0x1b, 0x9e, 0xb6, 0x34, 0x3b, 0x9c, 0x82, 0x01, 0xc7,
+  0xf7, 0xfb, 0x8d, 0x67, 0x96, 0x88, 0x8b, 0xba, 0x21, 0x84, 0x4a, 0x59,
+  0xb1, 0x82, 0x76, 0x24, 0xed, 0xad, 0x42, 0xb6, 0xb6, 0xd3, 0xc5, 0x6d,
+  0x55, 0x47, 0x14, 0xae, 0x6a, 0x6b, 0x26, 0x39, 0x2a, 0x0b, 0x10, 0xa3,
+  0xa0, 0xfc, 0x0c, 0x0d, 0x41, 0x27, 0x0a, 0xd3, 0x5a, 0x28, 0x8d, 0x1d,
+  0x24, 0x86, 0x3a, 0x92, 0xb9, 0xf1, 0x25, 0x05, 0x5b, 0x20, 0x74, 0xdf,
+  0xa0, 0xed, 0xa4, 0xe4, 0xd5, 0x42, 0x0d, 0x2f, 0x61, 0x49, 0xf0, 0x33,
+  0x36, 0xeb, 0x3a, 0xdb, 0x95, 0xad, 0x51, 0x0a, 0x0a, 0xe9, 0x11, 0x01,
+  0xf1, 0x10, 0x18, 0xf3, 0x8d, 0xf6, 0x18, 0xc8, 0x27, 0xd7, 0x54, 0xcb,
+  0x5d, 0xee, 0xe5, 0x1f, 0x15, 0xa8, 0x48, 0x29, 0x62, 0x11, 0x31, 0x59,
+  0x84, 0x3e, 0x50, 0x18, 0x67, 0x24, 0x2f, 0xa6, 0xd8, 0xeb, 0xdf, 0x42,
+  0x53, 0xf1, 0x15, 0x42, 0xdc, 0xe9, 0x6d, 0xd7, 0x98, 0xde, 0xa2, 0x88,
+  0xcb, 0xe1, 0x1e, 0x71, 0xba, 0x12, 0x71, 0xb1, 0xd1, 0x9c, 0x55, 0xc2,
+  0x15, 0x10, 0xc5, 0x51, 0x78, 0x86, 0xa1, 0x63, 0x59, 0x6a, 0x3c, 0x2a,
+  0x68, 0xc3, 0x79, 0xe4, 0x52, 0x7a, 0xff, 0x00, 0x6f, 0xd3, 0x4f, 0x96,
+  0x6d, 0xd2, 0xda, 0xd5, 0x58, 0x26, 0xa4, 0xb7, 0x1a, 0x99, 0xa9, 0x4d,
+  0xb1, 0xdc, 0xa8, 0x68, 0xc7, 0x20, 0x04, 0x0c, 0x8d, 0x86, 0xdf, 0x8d,
+  0x53, 0xf8, 0xcb, 0xe1, 0x95, 0x0d, 0xe0, 0x1a, 0xd9, 0xaa, 0x62, 0x82,
+  0x45, 0x89, 0x9e, 0x01, 0xcb, 0xcc, 0xe1, 0x80, 0x52, 0x03, 0xb0, 0xce,
+  0x17, 0xd7, 0xb0, 0x3a, 0xb2, 0xf0, 0x35, 0xb1, 0xae, 0xb7, 0x8a, 0xfa,
+  0x5a, 0xfb, 0x83, 0x47, 0x4f, 0xcc, 0x7e, 0x5d, 0x42, 0x85, 0x20, 0xe7,
+  0xfe, 0x63, 0xbf, 0xe3, 0x56, 0x1a, 0xab, 0x5d, 0x65, 0xbe, 0xad, 0x05,
+  0x6d, 0x23, 0x4f, 0x40, 0xaa, 0x73, 0x32, 0xb0, 0xe4, 0x60, 0x08, 0xc0,
+  0x65, 0x1d, 0x88, 0xdf, 0x1e, 0xda, 0xdd, 0x2c, 0x92, 0x8b, 0xb8, 0xfa,
+  0x1f, 0x14, 0xe2, 0xdb, 0x64, 0x1f, 0x02, 0x6d, 0xf5, 0x94, 0xb6, 0x39,
+  0xe2, 0x92, 0x9a, 0x96, 0x8a, 0xa6, 0x96, 0x51, 0x0b, 0x2c, 0x1b, 0xc1,
+  0x56, 0xa1, 0x47, 0xf3, 0x8b, 0xff, 0x00, 0x5b, 0x13, 0x91, 0xb6, 0x02,
+  0xf4, 0xc1, 0xd6, 0x93, 0x1f, 0x2c, 0xf3, 0x2c, 0x09, 0x51, 0x0a, 0xc9,
+  0x0e, 0x0c, 0x91, 0x23, 0x73, 0x11, 0x9d, 0xc1, 0x3d, 0x3a, 0xe9, 0x2d,
+  0x3a, 0x45, 0x05, 0xbe, 0x3a, 0xaa, 0x78, 0x21, 0x8e, 0x49, 0x10, 0x78,
+  0x66, 0x30, 0x04, 0x7e, 0x1e, 0x41, 0xd8, 0x7f, 0x49, 0xff, 0x00, 0x4d,
+  0x35, 0x88, 0x40, 0x8c, 0x95, 0x2a, 0x86, 0x42, 0x00, 0x0e, 0xfc, 0xb8,
+  0x61, 0x8e, 0x85, 0xbd, 0x86, 0xff, 0x00, 0xae, 0xab, 0x16, 0x69, 0x4a,
+  0x5e, 0x46, 0xb5, 0x2e, 0x06, 0x53, 0xc9, 0xe1, 0xc6, 0x0b, 0xc6, 0xce,
+  0x73, 0x8e, 0x55, 0x19, 0x24, 0x74, 0xce, 0xab, 0x75, 0xfc, 0x15, 0x6e,
+  0xa9, 0xa9, 0x96, 0x7a, 0x87, 0x91, 0xfc, 0x46, 0x27, 0x94, 0x01, 0xdf,
+  0xaf, 0x6d, 0x58, 0x62, 0x95, 0x5e, 0x36, 0xa8, 0xf1, 0xd5, 0xd4, 0x8f,
+  0x21, 0x1b, 0x00, 0x3e, 0xfa, 0x1f, 0x9a, 0x69, 0xf2, 0x2a, 0x13, 0x95,
+  0x41, 0xdc, 0xab, 0xe4, 0x1f, 0x6e, 0x9f, 0xbf, 0xb6, 0xb4, 0x67, 0xc3,
+  0x8b, 0x2a, 0x4a, 0x6a, 0xca, 0xc8, 0x93, 0x5c, 0x95, 0x39, 0xf8, 0x3e,
+  0x3a, 0x4b, 0x6d, 0xc9, 0xa0, 0x91, 0x9e, 0xa4, 0xd3, 0xca, 0xb6, 0xf5,
+  0x6d, 0x96, 0x1f, 0x29, 0x23, 0x1f, 0xf3, 0x6d, 0x9c, 0xeb, 0xc7, 0xdc,
+  0x43, 0x62, 0xab, 0xe7, 0xa8, 0x84, 0x41, 0x21, 0x97, 0x99, 0x94, 0xaf,
+  0x2e, 0xfc, 0xc3, 0xb7, 0xed, 0xaf, 0x77, 0xca, 0x95, 0x02, 0xa9, 0xa7,
+  0x82, 0x68, 0xc4, 0x0c, 0x9e, 0x60, 0xc3, 0x3e, 0x60, 0x46, 0xff, 0x00,
+  0xa6, 0x75, 0x87, 0xfc, 0x49, 0xe3, 0xa8, 0x24, 0xbb, 0x56, 0xc7, 0x45,
+  0x47, 0x4d, 0x1c, 0x48, 0x8e, 0xa2, 0x52, 0x3c, 0xf2, 0x49, 0xd3, 0x9b,
+  0x1e, 0xdd, 0x89, 0xd6, 0x6d, 0x54, 0xfe, 0x24, 0x9c, 0x7f, 0xe0, 0xcd,
+  0x9f, 0x6a, 0x4a, 0xcf, 0x2f, 0x5b, 0xae, 0x97, 0x3a, 0x54, 0xf9, 0x67,
+  0x93, 0x23, 0x3c, 0xbc, 0x8e, 0x33, 0xbf, 0xa6, 0xb8, 0xa5, 0xa5, 0x34,
+  0xb3, 0xbc, 0x8a, 0x9f, 0xcd, 0x99, 0xc8, 0x63, 0x9f, 0xa0, 0x13, 0xd7,
+  0xfe, 0x9a, 0xb8, 0x52, 0x59, 0xd2, 0xb6, 0xbc, 0xd7, 0x54, 0xc2, 0x4c,
+  0x4b, 0xbc, 0xac, 0xc7, 0xeb, 0x7e, 0xd8, 0x1f, 0xae, 0x84, 0xe2, 0x16,
+  0x4a, 0x6a, 0xb4, 0x0b, 0x4c, 0x73, 0xca, 0x0f, 0x9b, 0xa3, 0x7b, 0xea,
+  0xe1, 0x97, 0x7c, 0xb6, 0xc4, 0x5c, 0x64, 0x7c, 0x9e, 0xd6, 0x28, 0xea,
+  0xed, 0x95, 0x14, 0x22, 0x49, 0x69, 0x84, 0x45, 0xdc, 0x63, 0x3c, 0xc5,
+  0x4f, 0x31, 0x20, 0x7e, 0x40, 0xfc, 0xeb, 0xef, 0x1b, 0x5e, 0x45, 0xf7,
+  0x88, 0xab, 0x6f, 0x53, 0x40, 0xb4, 0xf3, 0xd5, 0xc6, 0xbc, 0xc0, 0x28,
+  0x5e, 0x76, 0x00, 0x02, 0xc5, 0x47, 0x4c, 0xe0, 0x6d, 0xed, 0xab, 0x67,
+  0xc2, 0xeb, 0xa4, 0x94, 0xa6, 0xe7, 0xc4, 0x35, 0x53, 0x28, 0x92, 0x9a,
+  0x94, 0xd3, 0xd3, 0xd3, 0x2c, 0x63, 0x05, 0x1b, 0x63, 0xe6, 0x3b, 0x2f,
+  0xb7, 0xb9, 0xce, 0xb3, 0xc7, 0xb5, 0xde, 0xe4, 0xab, 0x68, 0x24, 0xa8,
+  0xf1, 0xa9, 0x0c, 0xd9, 0x4e, 0x67, 0x1f, 0x56, 0xfe, 0xbe, 0x99, 0x23,
+  0x4e, 0x8c, 0xd3, 0x93, 0x8b, 0xf4, 0x35, 0x31, 0xaf, 0xc9, 0x5d, 0x29,
+  0x78, 0x3f, 0xe6, 0x40, 0xa4, 0x92, 0x8a, 0x49, 0x15, 0x32, 0x79, 0x0b,
+  0xc6, 0xcc, 0x33, 0x90, 0x33, 0xcc, 0x3f, 0xb6, 0xab, 0xd5, 0xd0, 0x3c,
+  0x10, 0x09, 0x26, 0x60, 0x99, 0x19, 0x03, 0xae, 0xfa, 0x79, 0x6a, 0x92,
+  0xa2, 0xd7, 0x72, 0x6a, 0x1a, 0xc5, 0x3c, 0x92, 0x31, 0xe5, 0xcf, 0x4c,
+  0xeb, 0xe7, 0x19, 0xa0, 0xae, 0x14, 0xb4, 0xf4, 0xa8, 0x8a, 0xc6, 0x4e,
+  0x56, 0x23, 0xaf, 0xa6, 0x95, 0x1c, 0x8f, 0xe4, 0x49, 0xf4, 0x0c, 0xa6,
+  0x55, 0x69, 0x26, 0x67, 0x5e, 0x63, 0xf4, 0xab, 0x6d, 0xf6, 0xd3, 0xfa,
+  0x51, 0x1a, 0x2f, 0x89, 0x50, 0x39, 0xc3, 0x79, 0x95, 0x71, 0xd4, 0x1d,
+  0x7e, 0xaa, 0xe1, 0x69, 0x6d, 0xf4, 0x80, 0xcb, 0x22, 0x78, 0xc1, 0xfc,
+  0xb8, 0x18, 0xcf, 0x5d, 0x08, 0xbe, 0x24, 0x8e, 0x90, 0xbc, 0x6c, 0xb2,
+  0x0d, 0x97, 0x1d, 0x3f, 0x5d, 0x33, 0xe4, 0x53, 0x57, 0x12, 0xdf, 0x28,
+  0xb4, 0xf0, 0xf4, 0x94, 0x13, 0x19, 0x3c, 0x68, 0xca, 0x96, 0x25, 0x51,
+  0x14, 0xec, 0x17, 0x07, 0xaf, 0xae, 0x74, 0x75, 0x6d, 0x03, 0x57, 0x45,
+  0x5b, 0x54, 0x58, 0xe2, 0xa6, 0x89, 0x5c, 0x05, 0x5e, 0x9c, 0x88, 0x39,
+  0xb3, 0xe9, 0xb9, 0x1a, 0x4b, 0x65, 0x49, 0x61, 0xaa, 0xa3, 0x6e, 0x61,
+  0xcf, 0x14, 0xca, 0x18, 0x0e, 0x99, 0x27, 0xd7, 0x57, 0x35, 0xc4, 0x13,
+  0x5d, 0x28, 0xe7, 0x40, 0x3c, 0x0a, 0x79, 0xd4, 0x64, 0xe3, 0x98, 0x92,
+  0xb8, 0xfb, 0x75, 0x3a, 0x76, 0x9f, 0xa6, 0x6d, 0xd1, 0xcf, 0x72, 0x6b,
+  0xf4, 0x53, 0x78, 0x96, 0x70, 0xb6, 0x1a, 0x48, 0x51, 0xb9, 0x52, 0xa9,
+  0xe3, 0x9c, 0xc6, 0x06, 0xd9, 0x20, 0xab, 0x7e, 0xe3, 0x4c, 0xa8, 0xf0,
+  0xb5, 0x16, 0xe7, 0xa6, 0x01, 0x3c, 0x02, 0x32, 0xec, 0x70, 0x3a, 0x64,
+  0x8f, 0xdb, 0x4b, 0x67, 0x0c, 0x28, 0x78, 0x6e, 0x29, 0xd5, 0xe4, 0x09,
+  0x3d, 0x44, 0xc5, 0x33, 0xb2, 0xa0, 0x61, 0x8c, 0x1f, 0xc6, 0x3b, 0x68,
+  0xc9, 0xe6, 0x49, 0x29, 0x93, 0xe5, 0x61, 0x68, 0x64, 0x9e, 0x62, 0xdc,
+  0x85, 0x89, 0xc6, 0x4e, 0x4e, 0xfd, 0xc6, 0x35, 0xa0, 0xd7, 0x0e, 0xc1,
+  0x69, 0x61, 0x96, 0xe5, 0x7b, 0x86, 0x9a, 0x47, 0x1f, 0x2e, 0xb2, 0x12,
+  0xa4, 0x0d, 0x94, 0x13, 0x9d, 0xb4, 0x5f, 0x11, 0xd2, 0x53, 0xc5, 0x7d,
+  0x16, 0xda, 0x66, 0x73, 0x1f, 0x22, 0xb4, 0x92, 0x36, 0xf8, 0xdb, 0x6f,
+  0xfc, 0x6a, 0x5b, 0x4d, 0x5a, 0xd0, 0x71, 0x07, 0x8a, 0xcd, 0x94, 0x73,
+  0xe4, 0x21, 0x76, 0x39, 0xdc, 0x0c, 0x6a, 0x6b, 0xd2, 0x54, 0x41, 0x5a,
+  0x2a, 0x4c, 0x7c, 0xa6, 0xb0, 0x99, 0x39, 0xc3, 0x67, 0x94, 0xff, 0x00,
+  0xe3, 0x3b, 0x68, 0x46, 0x24, 0x2c, 0x8a, 0x8e, 0x59, 0x88, 0x39, 0x64,
+  0xe4, 0x63, 0xc8, 0xca, 0x7e, 0x9c, 0x76, 0xd7, 0x10, 0x3a, 0xa8, 0x9a,
+  0x22, 0x87, 0x2c, 0xc0, 0x47, 0x83, 0xb0, 0xc6, 0x76, 0xf7, 0x1d, 0x74,
+  0x6b, 0xf8, 0x2d, 0x0a, 0xd1, 0xcb, 0x2a, 0x81, 0x36, 0x4a, 0xc8, 0xc3,
+  0x02, 0x3f, 0x71, 0xe8, 0x4e, 0x82, 0xf9, 0x79, 0x10, 0xc9, 0x07, 0x3a,
+  0x48, 0xc8, 0xde, 0x46, 0x56, 0xce, 0xdd, 0xb5, 0x44, 0x44, 0x82, 0x28,
+  0xd5, 0x9d, 0x64, 0x8f, 0xcf, 0x9c, 0x82, 0x3a, 0x69, 0x6d, 0x73, 0xc9,
+  0x33, 0x98, 0xd5, 0xb0, 0xca, 0x4e, 0xfe, 0x9b, 0xed, 0xfb, 0x68, 0xdb,
+  0xa8, 0x9e, 0x9c, 0xe2, 0x56, 0x1c, 0xdd, 0x48, 0xce, 0x96, 0x54, 0x4a,
+  0x42, 0xc4, 0x85, 0x0f, 0x34, 0xad, 0x93, 0x9d, 0x86, 0x35, 0x0b, 0x25,
+  0x96, 0x70, 0x5d, 0x28, 0x9a, 0x97, 0xc3, 0x66, 0x65, 0x65, 0x98, 0x92,
+  0x72, 0x3e, 0xda, 0x02, 0xa6, 0x08, 0xed, 0xf5, 0xb2, 0x4b, 0x5c, 0xa8,
+  0xc0, 0xf9, 0x57, 0x0b, 0x80, 0x17, 0xfe, 0x5f, 0x4d, 0x18, 0x55, 0x16,
+  0x55, 0x45, 0x05, 0x50, 0xae, 0x0e, 0x0e, 0xea, 0x73, 0xd7, 0x45, 0x9b,
+  0x19, 0xbb, 0x55, 0xa4, 0xd3, 0xcb, 0x27, 0xf0, 0xda, 0x75, 0xe6, 0xcb,
+  0xff, 0x00, 0xee, 0x11, 0xd8, 0x69, 0x51, 0x9b, 0x94, 0xdc, 0x59, 0xc8,
+  0xc9, 0xfe, 0xa3, 0x62, 0xf1, 0x25, 0x7d, 0x7d, 0x4c, 0x13, 0xd1, 0xc9,
+  0x57, 0x94, 0x01, 0x15, 0x49, 0xe7, 0x3c, 0xaa, 0x31, 0x81, 0xd3, 0x6d,
+  0xb1, 0xab, 0xbd, 0x8a, 0xd9, 0x67, 0xb8, 0x45, 0x14, 0x0b, 0x77, 0x36,
+  0xea, 0xc7, 0x20, 0x3d, 0x25, 0x64, 0x4c, 0xa4, 0xb9, 0xea, 0x73, 0xd3,
+  0x1a, 0xad, 0xcb, 0x73, 0x92, 0x9d, 0xdc, 0xdb, 0xff, 0x00, 0xdd, 0x83,
+  0x80, 0x14, 0xa8, 0xf3, 0x22, 0x0e, 0x8a, 0x0f, 0x6e, 0xbf, 0x9d, 0x7e,
+  0xa7, 0x79, 0x2b, 0x2b, 0x60, 0x85, 0xe6, 0xe7, 0xfe, 0x50, 0x2c, 0xcc,
+  0x77, 0x2e, 0xcc, 0xa3, 0x7f, 0x5f, 0xdb, 0xa6, 0xb3, 0xe4, 0xed, 0xc8,
+  0x43, 0x34, 0x6e, 0x20, 0xe0, 0x9b, 0xcd, 0x92, 0x9a, 0x8e, 0x68, 0x0d,
+  0x3d, 0x5c, 0x53, 0xb3, 0x2a, 0x3a, 0x36, 0xcb, 0x82, 0x37, 0x39, 0xe8,
+  0x7d, 0xbd, 0x06, 0x97, 0xd1, 0x59, 0xb8, 0x21, 0xaa, 0xa3, 0xfe, 0x2d,
+  0x78, 0xaa, 0x17, 0x29, 0x58, 0x44, 0xf2, 0xd3, 0xd3, 0x8f, 0x06, 0x39,
+  0x0b, 0x64, 0x9c, 0x9e, 0xa0, 0x0f, 0x4d, 0xbb, 0xe7, 0x7d, 0x36, 0xe3,
+  0x98, 0x6d, 0x16, 0x1e, 0x0f, 0xb4, 0xc3, 0x6e, 0xbc, 0x9a, 0x9b, 0x88,
+  0xcb, 0xd4, 0x88, 0x2b, 0x4c, 0x91, 0xc6, 0x40, 0xc3, 0x02, 0x9b, 0x80,
+  0x49, 0x23, 0x70, 0x7d, 0x46, 0xfa, 0xa5, 0xd0, 0xcb, 0x35, 0x1f, 0x0a,
+  0xd5, 0xf1, 0x19, 0xa6, 0xa5, 0x25, 0x26, 0x14, 0x50, 0x16, 0x07, 0x31,
+  0xc8, 0xe0, 0xb7, 0x30, 0x19, 0xdc, 0x80, 0xac, 0x37, 0xdb, 0x71, 0xa1,
+  0x4e, 0xda, 0x41, 0x17, 0x9a, 0x9b, 0x1f, 0x10, 0xf0, 0xf5, 0x75, 0x5d,
+  0x3b, 0xdc, 0x29, 0x65, 0xa2, 0x58, 0x0c, 0xef, 0x24, 0xd3, 0xa9, 0x32,
+  0x8c, 0x80, 0x15, 0x41, 0xdf, 0x9b, 0x71, 0xb0, 0xed, 0x9d, 0x01, 0x0d,
+  0x86, 0xdd, 0x7c, 0x09, 0x4f, 0x6f, 0xba, 0xc1, 0x43, 0x79, 0x6f, 0x39,
+  0xa7, 0xa8, 0xa8, 0x01, 0x1f, 0x62, 0x72, 0x18, 0xec, 0x35, 0x8e, 0x54,
+  0xdc, 0x6a, 0x65, 0xac, 0x53, 0x56, 0xcf, 0x50, 0x39, 0xc1, 0x2a, 0x64,
+  0x6c, 0xbf, 0xa0, 0xce, 0x75, 0xa0, 0xf0, 0xa5, 0xc7, 0x87, 0x63, 0xe2,
+  0x2a, 0x1b, 0x3d, 0xda, 0x2a, 0xc8, 0x9a, 0x66, 0x22, 0xa2, 0xa1, 0x9f,
+  0x9c, 0xc5, 0xe5, 0x25, 0x79, 0x32, 0x3e, 0x9c, 0x80, 0x33, 0xef, 0xa3,
+  0x7a, 0x7e, 0x77, 0x5f, 0xa0, 0x06, 0x75, 0xf3, 0x9f, 0xe1, 0xe2, 0x9d,
+  0x92, 0x9e, 0x27, 0xa3, 0x8b, 0x96, 0x49, 0xd4, 0x61, 0x64, 0x3d, 0x4e,
+  0x4f, 0xf5, 0x1f, 0x4f, 0xb6, 0xa1, 0xa8, 0xe1, 0x4b, 0xe9, 0x34, 0x72,
+  0x4d, 0x4b, 0x3c, 0x26, 0xa9, 0x99, 0x51, 0x66, 0x1c, 0xac, 0x40, 0xc7,
+  0x9b, 0x97, 0xa8, 0x19, 0x23, 0x7f, 0xbe, 0x99, 0xf0, 0x2f, 0x0f, 0x1e,
+  0x26, 0xe3, 0x43, 0x40, 0x2a, 0x9e, 0x9e, 0x3a, 0x58, 0x9e, 0xa3, 0xc6,
+  0x76, 0x0d, 0xba, 0x83, 0xca, 0x77, 0xdb, 0x39, 0xc7, 0x5e, 0xc4, 0xe9,
+  0x25, 0xff, 0x00, 0x8c, 0x38, 0x8a, 0xe5, 0x75, 0x79, 0x2b, 0xef, 0x73,
+  0xd4, 0x54, 0xc1, 0x21, 0x11, 0xb2, 0xbe, 0x02, 0x80, 0x71, 0xb6, 0x3f,
+  0xcb, 0x58, 0x96, 0x18, 0xf3, 0x40, 0x51, 0xa1, 0xda, 0xb8, 0x66, 0xdd,
+  0xc3, 0xd6, 0x88, 0xea, 0x6b, 0x0b, 0xc9, 0x73, 0x38, 0x6e, 0x68, 0xd8,
+  0xe2, 0x36, 0xc6, 0xd8, 0x00, 0x8d, 0xf7, 0xd0, 0x95, 0x97, 0x5a, 0xfa,
+  0xee, 0x78, 0xc5, 0xda, 0x49, 0x5d, 0x5b, 0x1e, 0x15, 0x46, 0xdc, 0xd8,
+  0xf4, 0x3a, 0x93, 0xe1, 0x2f, 0xc4, 0x1a, 0x48, 0xee, 0xf4, 0xf4, 0x7c,
+  0x5d, 0x04, 0x55, 0x49, 0x2b, 0x11, 0x15, 0x7c, 0x99, 0x2f, 0x19, 0x6e,
+  0xcf, 0x9c, 0xf3, 0x2f, 0xbf, 0x6d, 0x5d, 0xea, 0xbe, 0x1e, 0x56, 0x9b,
+  0xb2, 0x5f, 0x38, 0x76, 0xa2, 0x95, 0xff, 0x00, 0xdf, 0xa4, 0x22, 0x19,
+  0x10, 0x05, 0xe5, 0x0c, 0x70, 0x41, 0x07, 0x07, 0xa7, 0x4c, 0x74, 0x3e,
+  0xda, 0x46, 0x5d, 0x23, 0x6e, 0xd1, 0x7f, 0x13, 0x7d, 0x18, 0xe2, 0xdb,
+  0xa7, 0xaa, 0xe2, 0x78, 0x3c, 0x59, 0x4c, 0x30, 0x49, 0x2f, 0x34, 0xaa,
+  0xbe, 0xa3, 0x39, 0x1f, 0xae, 0xae, 0x15, 0x74, 0xf4, 0x44, 0x81, 0x2b,
+  0xca, 0xd0, 0xe0, 0x8e, 0x5e, 0x6e, 0xa5, 0xba, 0x9f, 0xbe, 0xb4, 0xb4,
+  0xf8, 0x71, 0x47, 0x53, 0x09, 0x17, 0x49, 0x07, 0xce, 0xb3, 0x16, 0x9a,
+  0xaa, 0x12, 0x54, 0x6e, 0x09, 0x01, 0x50, 0x92, 0x01, 0x1b, 0x7d, 0xc6,
+  0x75, 0x8c, 0xdf, 0x66, 0xfe, 0x1f, 0x7a, 0xaa, 0xb3, 0xf8, 0xce, 0xe6,
+  0x09, 0x0a, 0xf3, 0xba, 0x72, 0xe4, 0x82, 0x46, 0xc3, 0x27, 0x6d, 0x6b,
+  0xc3, 0x8a, 0x4b, 0xec, 0xca, 0x78, 0xe8, 0xd9, 0xf8, 0x53, 0x86, 0xe8,
+  0xff, 0x00, 0x88, 0x53, 0xf1, 0x03, 0xd7, 0xc8, 0xa5, 0x11, 0x79, 0x60,
+  0x31, 0x82, 0x55, 0xb9, 0x40, 0x2c, 0x09, 0x27, 0xfb, 0x6a, 0xd9, 0x56,
+  0x22, 0x92, 0x05, 0x85, 0x2b, 0x0a, 0xcd, 0xe5, 0x7f, 0x13, 0x3e, 0x63,
+  0x83, 0xf4, 0x91, 0xd3, 0xee, 0x74, 0x8e, 0x9a, 0xa2, 0xa6, 0x9e, 0xc5,
+  0x48, 0xf4, 0xc3, 0xc7, 0x0d, 0x4e, 0xbc, 0xf2, 0x0c, 0x01, 0x18, 0x00,
+  0x0e, 0x53, 0x9e, 0x9d, 0xc6, 0xdd, 0x71, 0xa0, 0x66, 0xad, 0x09, 0x4d,
+  0x05, 0x5d, 0x12, 0x24, 0x22, 0x49, 0x3c, 0x09, 0xd2, 0x38, 0x4f, 0x21,
+  0xc6, 0xfd, 0xce, 0x4f, 0x4f, 0x6d, 0x56, 0x4c, 0x8a, 0x32, 0x69, 0x9b,
+  0x1f, 0x6e, 0x8b, 0x4d, 0x3d, 0x42, 0xc1, 0x4d, 0x3c, 0x35, 0x46, 0x26,
+  0x75, 0x5c, 0xa8, 0x24, 0x30, 0x39, 0xe8, 0xb8, 0x1f, 0xb6, 0xab, 0x17,
+  0xbe, 0x20, 0x7b, 0x45, 0x4a, 0xf3, 0xd1, 0x54, 0x07, 0x48, 0x8b, 0x98,
+  0xc9, 0x18, 0xf0, 0xc9, 0xdc, 0x92, 0x76, 0xfc, 0x13, 0xaa, 0x97, 0x12,
+  0x71, 0x7c, 0x54, 0x97, 0xda, 0x85, 0x9a, 0xb5, 0x60, 0xa6, 0x8c, 0x73,
+  0x49, 0x84, 0xc0, 0x5d, 0x8e, 0x10, 0x2f, 0xa9, 0xdb, 0x7f, 0x6d, 0x71,
+  0x6a, 0xe2, 0x2a, 0xdb, 0xdf, 0x0c, 0xca, 0x05, 0xae, 0x25, 0x5d, 0xf0,
+  0x6b, 0x1b, 0x06, 0x55, 0x3d, 0x0a, 0x9d, 0xb9, 0x57, 0x1d, 0x4f, 0xf7,
+  0xd2, 0xe3, 0x39, 0x49, 0x5a, 0x66, 0x57, 0x94, 0xbc, 0xf0, 0xb7, 0x13,
+  0x47, 0x74, 0x82, 0xa2, 0x6b, 0x64, 0x6f, 0xf2, 0x71, 0xc4, 0x64, 0xe5,
+  0x09, 0x80, 0xa4, 0xe0, 0xf4, 0x27, 0x7e, 0xfd, 0x3a, 0xeb, 0xb3, 0x72,
+  0xfe, 0x35, 0x04, 0x75, 0x14, 0x2b, 0x35, 0x25, 0x50, 0x3b, 0xcb, 0x2f,
+  0x91, 0xa6, 0x0b, 0xb6, 0x15, 0x8f, 0x4c, 0xee, 0x7a, 0x74, 0xd2, 0x0f,
+  0x87, 0x0f, 0x05, 0x3d, 0x9a, 0x68, 0x26, 0xa3, 0x99, 0xe5, 0xa7, 0x8d,
+  0xc7, 0x89, 0x1b, 0x64, 0x54, 0x31, 0xe9, 0xe1, 0xa6, 0xc4, 0xf4, 0x03,
+  0x27, 0x6d, 0x58, 0xe8, 0x6d, 0x51, 0xcd, 0x47, 0x47, 0x1d, 0x78, 0xf9,
+  0xa9, 0xa5, 0x0d, 0x24, 0xe2, 0x70, 0x57, 0x95, 0x1b, 0x7f, 0x32, 0x13,
+  0xb1, 0x04, 0x74, 0x1b, 0x6d, 0xab, 0x87, 0xc9, 0xe9, 0xd8, 0x71, 0x7b,
+  0xe3, 0x64, 0x7c, 0x6f, 0x73, 0xbc, 0x43, 0xc0, 0xd5, 0x32, 0xc5, 0x32,
+  0x41, 0x5b, 0x28, 0xe5, 0x89, 0x63, 0x42, 0x79, 0x54, 0x92, 0x33, 0x91,
+  0xed, 0xaf, 0x3d, 0xd6, 0xda, 0x2b, 0x11, 0xd8, 0xcf, 0x32, 0x2a, 0x91,
+  0x92, 0x73, 0xb8, 0xc9, 0xf4, 0xd7, 0xa2, 0xe8, 0xed, 0xa6, 0xe5, 0x43,
+  0x72, 0xb6, 0x4d, 0x54, 0xbe, 0x0e, 0x4a, 0x53, 0xf8, 0x52, 0xf3, 0xaa,
+  0x2f, 0x63, 0x8f, 0xf2, 0xdf, 0xa8, 0xd6, 0x5f, 0xf1, 0x13, 0x83, 0xef,
+  0x5c, 0x3f, 0x6c, 0x8e, 0xe5, 0x03, 0x53, 0xdc, 0x8f, 0x89, 0xc8, 0xc8,
+  0x33, 0x94, 0x63, 0xd0, 0x9c, 0xf5, 0xd0, 0x64, 0x59, 0x67, 0x97, 0x73,
+  0xe9, 0x01, 0x97, 0x1b, 0x6e, 0xd1, 0x4b, 0xbc, 0xda, 0xd7, 0x87, 0xed,
+  0x8b, 0x2c, 0xf2, 0xd3, 0xf3, 0xd4, 0x43, 0xce, 0xac, 0x47, 0x98, 0x03,
+  0xd0, 0x6a, 0x99, 0x62, 0xb4, 0x52, 0xdd, 0xab, 0xe6, 0xae, 0xb8, 0xd6,
+  0x47, 0x49, 0x6d, 0x80, 0x9f, 0x1a, 0x79, 0xb3, 0x86, 0x38, 0xd9, 0x54,
+  0x0d, 0xd8, 0x9d, 0x69, 0x09, 0xf0, 0xe6, 0xf1, 0x74, 0x64, 0xbd, 0x71,
+  0x75, 0xc5, 0x69, 0xa8, 0xe3, 0x52, 0x1d, 0x61, 0x1c, 0xe6, 0x35, 0x09,
+  0x95, 0xce, 0xf8, 0xc1, 0xd8, 0x63, 0xae, 0xb3, 0x0b, 0xf0, 0x47, 0xbc,
+  0x7c, 0x85, 0x28, 0x8d, 0xa9, 0xa9, 0xd8, 0x08, 0x80, 0x5f, 0x2f, 0xdf,
+  0x5a, 0xa3, 0x92, 0x2f, 0xe8, 0x02, 0x8d, 0x1f, 0x62, 0x95, 0x22, 0xb7,
+  0x4f, 0x0d, 0x37, 0x34, 0x71, 0x19, 0x0e, 0x41, 0x4e, 0x5f, 0x10, 0x03,
+  0xe5, 0x38, 0xfb, 0x68, 0x27, 0x2b, 0x5f, 0x6b, 0x92, 0x02, 0xd9, 0x31,
+  0x39, 0x6c, 0x7a, 0x64, 0x6c, 0x7f, 0xef, 0xd7, 0x5a, 0x65, 0xb6, 0x81,
+  0x38, 0x9a, 0xd3, 0xf3, 0x30, 0x2c, 0x86, 0xb6, 0xdb, 0x96, 0xac, 0x61,
+  0x1f, 0xf2, 0xcc, 0x1c, 0xbb, 0x60, 0x8c, 0xe0, 0xae, 0x0e, 0xd8, 0xdf,
+  0x39, 0xed, 0xac, 0xf6, 0x4a, 0x58, 0xa8, 0xaf, 0x95, 0x34, 0xb2, 0x11,
+  0x14, 0x55, 0x00, 0xf2, 0x73, 0x7a, 0xe7, 0xa7, 0xf7, 0xd3, 0x78, 0x9b,
+  0xb4, 0x86, 0x45, 0x96, 0xbf, 0x83, 0x97, 0x2b, 0x6d, 0x65, 0xc1, 0x2d,
+  0x97, 0xbb, 0x2d, 0x3d, 0xca, 0xaa, 0x1c, 0xad, 0x1b, 0xcb, 0x8f, 0x2a,
+  0xf4, 0x2b, 0xfe, 0x7a, 0xb8, 0xfc, 0x45, 0xe1, 0x7b, 0x14, 0xfc, 0x49,
+  0x4d, 0xc4, 0x36, 0xa8, 0xe2, 0x5f, 0x05, 0x0a, 0x49, 0x4f, 0x08, 0xc4,
+  0x71, 0x48, 0x36, 0xc8, 0xf5, 0xef, 0xac, 0xd3, 0xe1, 0xbc, 0x17, 0x48,
+  0x3e, 0x23, 0x5a, 0x45, 0xa5, 0x11, 0xaa, 0xfc, 0x7c, 0x44, 0x59, 0xb0,
+  0xbd, 0x08, 0xc9, 0x3e, 0x98, 0xdf, 0x5e, 0x8d, 0xa0, 0xb1, 0xd2, 0xc5,
+  0x05, 0x7c, 0x8f, 0xe0, 0xcb, 0xcf, 0x1c, 0xaf, 0x56, 0xd3, 0xb9, 0x52,
+  0xd2, 0x16, 0x2c, 0x70, 0xbd, 0x87, 0x5d, 0x61, 0xd5, 0x62, 0x6a, 0x54,
+  0x9f, 0x62, 0xe7, 0xc9, 0x91, 0x5f, 0xf8, 0x5b, 0x9f, 0xe1, 0xdd, 0x67,
+  0x10, 0xc9, 0xce, 0xcd, 0x1d, 0x42, 0x45, 0x14, 0x7b, 0x80, 0xa3, 0xa1,
+  0x63, 0xef, 0x9c, 0xe3, 0x1a, 0xca, 0xeb, 0xa5, 0x14, 0xf9, 0x96, 0x1d,
+  0xa4, 0x3e, 0x54, 0x3e, 0x9e, 0xfa, 0xf4, 0xdf, 0xc4, 0x2b, 0xd5, 0x8e,
+  0x4b, 0x6d, 0x07, 0x0f, 0xbd, 0x3d, 0x14, 0xb6, 0xf9, 0x62, 0xf1, 0x43,
+  0x42, 0x85, 0x63, 0x84, 0x93, 0x85, 0xc0, 0x19, 0x24, 0xe1, 0xb5, 0xe7,
+  0x2b, 0xe5, 0xa4, 0x43, 0x57, 0x5f, 0x2b, 0x11, 0x24, 0x14, 0x93, 0x18,
+  0xd0, 0xaf, 0x4d, 0xf2, 0x41, 0x07, 0xec, 0x3a, 0x69, 0xda, 0x75, 0xb3,
+  0xc4, 0x28, 0xb2, 0xb6, 0x6a, 0x6a, 0x14, 0xb1, 0x8a, 0x46, 0x0b, 0x19,
+  0x04, 0x0c, 0xff, 0x00, 0x56, 0x7a, 0xeb, 0x40, 0x59, 0xa5, 0x7b, 0x24,
+  0x95, 0x0f, 0xcc, 0xdc, 0xd4, 0x3e, 0x21, 0x23, 0x66, 0x2c, 0x48, 0xe6,
+  0xfc, 0x6a, 0x91, 0x80, 0xf1, 0x24, 0x81, 0x64, 0xf0, 0xd9, 0x8b, 0x06,
+  0x2b, 0x80, 0xd8, 0xeb, 0x8f, 0x5d, 0x5e, 0x29, 0xea, 0x05, 0x57, 0x0e,
+  0xc9, 0x3b, 0x05, 0x52, 0x68, 0x9e, 0x9d, 0x49, 0x6e, 0xfc, 0xe1, 0x87,
+  0xfd, 0xfb, 0x6b, 0xad, 0x86, 0x06, 0xfd, 0x23, 0x05, 0xb5, 0x54, 0xc9,
+  0x43, 0x71, 0xb4, 0x37, 0xca, 0xfc, 0xc2, 0xc1, 0x40, 0xf3, 0x00, 0x4e,
+  0xec, 0xae, 0x58, 0x30, 0x23, 0xed, 0xcc, 0x73, 0xed, 0xa5, 0xf4, 0x54,
+  0xeb, 0x27, 0x0b, 0xd4, 0x5c, 0xd2, 0x4f, 0xf7, 0xea, 0x7a, 0xc0, 0x4a,
+  0x2f, 0x55, 0x89, 0x80, 0x2b, 0xfd, 0xb4, 0x55, 0xb6, 0x79, 0x57, 0x88,
+  0xe2, 0xb6, 0x1e, 0x46, 0x67, 0xa1, 0x8e, 0x9a, 0x07, 0xe7, 0xdd, 0x1f,
+  0xc3, 0xe6, 0x0c, 0x3d, 0xb7, 0x6e, 0xfd, 0xf5, 0x37, 0x09, 0x23, 0x35,
+  0xaa, 0xfd, 0x6d, 0x9a, 0x37, 0x87, 0x34, 0xc9, 0x32, 0xf3, 0x8d, 0xa5,
+  0x74, 0x7c, 0x10, 0x0f, 0x7c, 0xe7, 0x44, 0xfb, 0x35, 0x3e, 0xc0, 0x6b,
+  0x8f, 0x35, 0xc2, 0x2a, 0xb0, 0xfc, 0xc6, 0x67, 0xe7, 0x56, 0xfe, 0xfb,
+  0x7e, 0x75, 0x63, 0xb9, 0x24, 0x4f, 0x05, 0x14, 0x53, 0x2e, 0x11, 0x23,
+  0xf1, 0x15, 0xd8, 0xe4, 0x85, 0xc1, 0x1b, 0x0f, 0x4e, 0x9a, 0xaf, 0xcd,
+  0x49, 0x32, 0x43, 0x4b, 0x05, 0x45, 0x30, 0xa7, 0x78, 0xdf, 0x9c, 0x96,
+  0xf2, 0xb1, 0x0d, 0x92, 0x3f, 0x1a, 0x71, 0x73, 0x0c, 0x6d, 0x74, 0x41,
+  0xb1, 0x20, 0x8d, 0x08, 0x2e, 0xa7, 0xb7, 0x61, 0xa1, 0x34, 0x44, 0x55,
+  0x58, 0x11, 0x62, 0x80, 0x2a, 0x00, 0xbc, 0xb9, 0xc9, 0xf5, 0xf5, 0xc7,
+  0xa6, 0xa2, 0xa7, 0x56, 0x69, 0x53, 0x1b, 0x76, 0x27, 0x53, 0x73, 0x24,
+  0xb4, 0x6a, 0xaf, 0x1a, 0x18, 0x8a, 0xf2, 0x63, 0x97, 0x24, 0x10, 0x71,
+  0x9d, 0x7e, 0x82, 0x1a, 0x98, 0x26, 0x6a, 0x49, 0x31, 0x21, 0xe4, 0x2c,
+  0x92, 0x8f, 0xa5, 0xd4, 0x77, 0x1a, 0xa2, 0x88, 0x2e, 0x93, 0x3f, 0x8e,
+  0xf1, 0xab, 0x73, 0x78, 0x60, 0x17, 0xdb, 0x76, 0x27, 0xb6, 0x96, 0xcd,
+  0x11, 0x59, 0x7c, 0x39, 0x06, 0x46, 0x39, 0xc1, 0xf4, 0x3e, 0xda, 0x77,
+  0x08, 0x58, 0xae, 0x2e, 0x93, 0xd3, 0x99, 0xa3, 0xc2, 0xbb, 0x0e, 0x6c,
+  0x13, 0xb6, 0x7a, 0xe9, 0x05, 0xd8, 0xf3, 0x54, 0x89, 0xa3, 0xe6, 0x08,
+  0xa4, 0x31, 0x07, 0xaf, 0x2e, 0x48, 0xc6, 0xa1, 0x66, 0x87, 0xf0, 0xb3,
+  0xe1, 0xed, 0x57, 0x1d, 0x5c, 0x18, 0xd2, 0xd5, 0x2d, 0x34, 0x74, 0x50,
+  0xc6, 0xd3, 0x4a, 0xc0, 0x9c, 0xf3, 0xb1, 0xd8, 0x7b, 0xe3, 0x27, 0xf1,
+  0xad, 0x6b, 0xfd, 0xa3, 0x2c, 0x14, 0x16, 0x5f, 0x87, 0xb6, 0x4a, 0x7a,
+  0x0a, 0x54, 0x8a, 0x2a, 0x49, 0x45, 0x3a, 0x30, 0xfa, 0xb0, 0x63, 0x27,
+  0x7f, 0x5c, 0xf2, 0xe7, 0x56, 0x1f, 0xf6, 0x75, 0xb5, 0x7f, 0x0c, 0xe0,
+  0x9a, 0x5a, 0xca, 0x6e, 0x59, 0x69, 0xeb, 0xe1, 0x13, 0xbb, 0xa9, 0xc9,
+  0x2f, 0xb8, 0x0a, 0x7e, 0xc0, 0x63, 0xf3, 0xa5, 0x3c, 0x65, 0xc0, 0x3c,
+  0x61, 0xc7, 0x7c, 0x41, 0x5b, 0x70, 0xbd, 0x56, 0x43, 0x41, 0x6c, 0x81,
+  0x5d, 0x2d, 0xb4, 0x60, 0x97, 0x7c, 0xff, 0x00, 0x4b, 0x30, 0x1b, 0x2e,
+  0x4f, 0x53, 0x92, 0x7d, 0xb4, 0xa8, 0xc7, 0x6c, 0x5c, 0xbd, 0xb3, 0x9b,
+  0x38, 0x2e, 0x68, 0xc0, 0xf8, 0x4f, 0x83, 0xae, 0xdc, 0x61, 0x70, 0x6a,
+  0x2b, 0x3d, 0x3a, 0x4b, 0x2a, 0xc6, 0xd2, 0x3b, 0x33, 0xf2, 0xaa, 0x28,
+  0xc0, 0x3c, 0xc7, 0xb1, 0xc9, 0x18, 0xfb, 0xea, 0x1b, 0xcf, 0x0e, 0xdc,
+  0x78, 0x7a, 0x7f, 0x91, 0xbb, 0xd1, 0xd4, 0x51, 0xd4, 0x15, 0x0c, 0x12,
+  0x45, 0xc7, 0x32, 0xee, 0x32, 0x3d, 0xb6, 0x3a, 0xf6, 0x17, 0xc3, 0xde,
+  0x18, 0xa4, 0xe1, 0x4e, 0x16, 0x86, 0xd3, 0x4d, 0x1a, 0x34, 0xe2, 0x3c,
+  0xcd, 0x37, 0x42, 0xed, 0xd7, 0xf4, 0xdf, 0x03, 0x59, 0x17, 0xfb, 0x4c,
+  0xd9, 0x2a, 0x9a, 0xef, 0x6f, 0xbe, 0x63, 0xfd, 0xdd, 0xe9, 0xc5, 0x3b,
+  0x80, 0x33, 0xc8, 0xe0, 0x92, 0x37, 0xf7, 0xe6, 0xfd, 0xb4, 0x9c, 0xb0,
+  0xdb, 0x14, 0xcc, 0xf9, 0x31, 0xd2, 0x30, 0x6a, 0x88, 0xfc, 0x4e, 0x58,
+  0x23, 0xfa, 0x9b, 0x73, 0xf6, 0xd3, 0x1b, 0xfd, 0xc2, 0x08, 0xbe, 0x16,
+  0x4b, 0x60, 0x68, 0xa4, 0x79, 0x0d, 0xcc, 0x56, 0x2b, 0x96, 0xd8, 0x2f,
+  0x86, 0x50, 0x29, 0xf7, 0xd6, 0x91, 0xc1, 0xdc, 0x22, 0xf7, 0xdf, 0x87,
+  0x15, 0xf1, 0x5b, 0xad, 0x1f, 0x3d, 0x75, 0xa9, 0xae, 0x44, 0x86, 0x53,
+  0x85, 0x58, 0x15, 0x14, 0x64, 0xb3, 0x1e, 0x80, 0x86, 0xe8, 0x3e, 0xf8,
+  0xdb, 0x55, 0xcb, 0x47, 0xc3, 0xeb, 0x97, 0x12, 0xde, 0xeb, 0x78, 0x66,
+  0x26, 0x8a, 0x29, 0xe0, 0x49, 0x8c, 0x85, 0xf7, 0x55, 0xe4, 0x38, 0x03,
+  0x3e, 0xe7, 0x03, 0x3e, 0xfa, 0x4e, 0x37, 0xe5, 0x60, 0x24, 0x62, 0xf6,
+  0xfc, 0xcf, 0x72, 0x46, 0xe5, 0x3c, 0xb0, 0x9c, 0xf5, 0xfc, 0x69, 0xb5,
+  0xa1, 0x26, 0x6e, 0x28, 0x49, 0x23, 0x38, 0xf0, 0xc6, 0x7f, 0x04, 0x63,
+  0xfc, 0xc6, 0xa3, 0xae, 0xb3, 0xd4, 0xf0, 0xed, 0xda, 0xb6, 0xd1, 0x72,
+  0xa7, 0x68, 0x6a, 0xe9, 0xe4, 0x2a, 0xc0, 0x8d, 0x9b, 0x7e, 0xa0, 0xfa,
+  0x77, 0x1a, 0xd0, 0x7e, 0x18, 0xfc, 0x3e, 0xba, 0xf1, 0x05, 0xc1, 0x27,
+  0x86, 0x9c, 0xac, 0x4e, 0x57, 0xce, 0x0e, 0x47, 0x2e, 0xdb, 0x93, 0xdb,
+  0xd7, 0x1a, 0xd1, 0x9b, 0x22, 0x8c, 0x2d, 0x91, 0xa2, 0xdb, 0xf0, 0xe9,
+  0x6a, 0x65, 0xa1, 0xe2, 0x69, 0x12, 0x37, 0x4a, 0xb7, 0xb7, 0x83, 0x1b,
+  0x03, 0x96, 0x74, 0x0c, 0x32, 0xa0, 0x6d, 0xd8, 0x75, 0xd6, 0x7d, 0x4b,
+  0xc3, 0x57, 0x66, 0xb5, 0xcd, 0x75, 0x4b, 0x75, 0x4c, 0x74, 0x71, 0xbf,
+  0xfc, 0x5f, 0x05, 0x82, 0x05, 0xed, 0xb9, 0x1e, 0xfa, 0xd6, 0xef, 0xe6,
+  0xdd, 0xc1, 0xd7, 0x81, 0x65, 0xb4, 0xb1, 0x92, 0xe2, 0x22, 0x06, 0x5a,
+  0x85, 0xcf, 0x90, 0x64, 0x6d, 0xef, 0x9c, 0x74, 0xd7, 0x1c, 0x4f, 0x54,
+  0x78, 0xae, 0xd8, 0x54, 0x54, 0x57, 0xc3, 0x3d, 0x1c, 0x3f, 0xfe, 0x3a,
+  0x4b, 0xfc, 0x83, 0x1a, 0x8f, 0xf0, 0x6c, 0x33, 0x9c, 0x6f, 0xae, 0x3e,
+  0x3d, 0x46, 0xce, 0x7a, 0xb6, 0x2a, 0x8c, 0x9e, 0xa5, 0xa7, 0xf0, 0xa9,
+  0xe2, 0x2f, 0xb5, 0x3e, 0x54, 0x0c, 0x0c, 0x82, 0x4e, 0xfb, 0xeb, 0xd2,
+  0x56, 0xbb, 0x85, 0xf3, 0xff, 0x00, 0x4f, 0x58, 0x55, 0xea, 0x26, 0x8e,
+  0x96, 0x6a, 0x28, 0x52, 0x61, 0x1a, 0x8f, 0x11, 0xb2, 0xa3, 0x05, 0x7e,
+  0xfa, 0xf3, 0x7a, 0xe6, 0x40, 0x91, 0x92, 0x10, 0xf8, 0xb9, 0x3e, 0xc3,
+  0x04, 0x1d, 0x7a, 0x37, 0xe1, 0xe7, 0x11, 0x40, 0x96, 0x98, 0xa2, 0xa6,
+  0x11, 0x2b, 0x2c, 0x31, 0xaa, 0x34, 0xa7, 0x03, 0xc3, 0x5d, 0xca, 0xfd,
+  0xfb, 0xea, 0x6b, 0x1c, 0x54, 0xa2, 0x9b, 0xa2, 0xf1, 0xe4, 0x49, 0xf2,
+  0x5a, 0x2a, 0xe9, 0x2a, 0xad, 0xf4, 0x4e, 0x63, 0x9a, 0x69, 0xa4, 0x46,
+  0xfe, 0x4b, 0x4a, 0xd9, 0x0a, 0x3f, 0xab, 0x9b, 0x03, 0x73, 0xdf, 0x18,
+  0xce, 0x47, 0x5d, 0x79, 0xeb, 0x8e, 0xef, 0xd5, 0xfc, 0x59, 0xc5, 0x4e,
+  0x22, 0xa7, 0x65, 0x8a, 0x91, 0x1a, 0x00, 0xef, 0x19, 0x8d, 0xf6, 0x62,
+  0x72, 0xc0, 0xf4, 0x27, 0xd3, 0xb6, 0xb6, 0x4e, 0x3c, 0xa2, 0xbe, 0x7f,
+  0xe9, 0xa8, 0xae, 0xb4, 0x33, 0x3f, 0x38, 0x98, 0x4c, 0xbe, 0x0e, 0x23,
+  0xe4, 0x42, 0x7a, 0xb2, 0x0c, 0xf3, 0x11, 0x91, 0xdf, 0x4c, 0x78, 0x22,
+  0xc1, 0x41, 0x15, 0x6d, 0x35, 0x6c, 0xa2, 0x3a, 0xeb, 0x93, 0xc2, 0x64,
+  0x9a, 0xa7, 0x1e, 0x45, 0x7c, 0x82, 0x0e, 0x0e, 0xe4, 0xef, 0xb1, 0xf4,
+  0x1a, 0x76, 0x15, 0x2c, 0x72, 0xb6, 0xbb, 0x34, 0xed, 0xba, 0x47, 0xff,
+  0xd9
+};
+
+void jpeg_get_video_info(VideoDecodeInfo *info)
+{
+    info->profile   = GST_VAAPI_PROFILE_JPEG_BASELINE;
+    info->width     = JPEG_CLIP_WIDTH;
+    info->height    = JPEG_CLIP_HEIGHT;
+    info->data      = jpeg_clip;
+    info->data_size = JPEG_CLIP_DATA_SIZE;
+}
diff --git a/tests/test-jpeg.h b/tests/test-jpeg.h
new file mode 100644 (file)
index 0000000..8fdbcfe
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  test-jpeg.h - JPEG test data
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+*/
+
+#ifndef TEST_JPEG_H
+#define TEST_JPEG_H
+
+#include <glib.h>
+#include "test-decode.h"
+
+void jpeg_get_video_info(VideoDecodeInfo *info);
+
+#endif /* TEST_JPEG_H */
diff --git a/tests/test-mpeg2.c b/tests/test-mpeg2.c
new file mode 100644 (file)
index 0000000..3e75143
--- /dev/null
@@ -0,0 +1,1649 @@
+/*
+ *  test-mpeg2.c - MPEG-2 test data
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+*/
+
+#include "test-mpeg2.h"
+
+#define MPEG2_CLIP_WIDTH          320
+#define MPEG2_CLIP_HEIGHT         240
+#define MPEG2_CLIP_DATA_SIZE    19311
+
+/* Data dump of a 320x240 MPEG-2 video clip (mpeg2.m2v), it has a single frame */
+static const guchar mpeg2_clip[MPEG2_CLIP_DATA_SIZE] = {
+    0x00, 0x00, 0x01, 0xb3, 0x14, 0x00, 0xf0, 0x12, 0x07, 0x53, 0x23, 0x80,
+    0x00, 0x00, 0x01, 0xb5, 0x14, 0x8a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+    0x01, 0xb5, 0x2b, 0x02, 0x02, 0x02, 0x05, 0x02, 0x07, 0x80, 0x00, 0x00,
+    0x01, 0xb8, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0f,
+    0xff, 0xf8, 0x00, 0x00, 0x01, 0xb5, 0x8f, 0xff, 0xf7, 0x5d, 0x80, 0x00,
+    0x00, 0x01, 0x01, 0x43, 0xf8, 0x90, 0x03, 0xee, 0x36, 0xd4, 0x92, 0x85,
+    0x86, 0x37, 0x48, 0x01, 0xb3, 0xf7, 0x9a, 0x1d, 0x5c, 0x38, 0xb1, 0x95,
+    0xb9, 0x42, 0x43, 0xb2, 0xc2, 0x51, 0x24, 0x31, 0xb2, 0xed, 0x20, 0x73,
+    0xd9, 0x08, 0xcc, 0x5b, 0xe2, 0x39, 0xbc, 0xdb, 0x12, 0xb7, 0x8c, 0x31,
+    0xbf, 0x6c, 0x00, 0xc3, 0xeb, 0xc3, 0xd0, 0x6c, 0x3e, 0x16, 0xde, 0xa8,
+    0x89, 0xf3, 0xc1, 0x17, 0xda, 0x5a, 0x4f, 0xca, 0xb0, 0x6b, 0x7c, 0x07,
+    0xbb, 0x6c, 0x95, 0x8f, 0x74, 0x35, 0xaa, 0x45, 0x65, 0xb4, 0x35, 0xbf,
+    0xd4, 0x22, 0xab, 0xfe, 0x80, 0x07, 0x7c, 0xed, 0x7a, 0x97, 0x2b, 0xaf,
+    0x2f, 0x72, 0x64, 0x81, 0x86, 0x0f, 0x6f, 0x9a, 0x7b, 0x02, 0x10, 0x07,
+    0x76, 0x2f, 0x01, 0x30, 0x01, 0x2d, 0x21, 0x37, 0x89, 0xbc, 0x74, 0x00,
+    0xf4, 0xc3, 0x6b, 0xa4, 0x1f, 0x65, 0xa7, 0xb6, 0xff, 0x6d, 0x9f, 0x6f,
+    0x6f, 0x77, 0xa8, 0x5b, 0xa7, 0x95, 0x90, 0x2e, 0x2b, 0x71, 0xec, 0x35,
+    0xf4, 0x96, 0x92, 0x33, 0xa9, 0x92, 0x48, 0xdf, 0xcf, 0x50, 0x39, 0x13,
+    0xd1, 0xbd, 0x25, 0x4f, 0xbe, 0x5b, 0x10, 0x25, 0x6e, 0x14, 0xdc, 0x5e,
+    0xe0, 0x7b, 0x7a, 0x3d, 0x04, 0x2f, 0xf2, 0xb8, 0x84, 0x38, 0xdd, 0x16,
+    0x94, 0xdb, 0x46, 0xfd, 0xdf, 0x3a, 0x00, 0x7a, 0xf9, 0x49, 0x45, 0xb7,
+    0x52, 0xe9, 0x03, 0x9a, 0x4a, 0x40, 0xf8, 0x14, 0xdc, 0xa7, 0x4d, 0xf7,
+    0xbc, 0x25, 0x04, 0xa0, 0x04, 0x2a, 0x81, 0x6d, 0xda, 0x36, 0x67, 0x1b,
+    0xb8, 0x48, 0x96, 0xb7, 0x49, 0xea, 0xd9, 0x1c, 0x8d, 0xf8, 0xfb, 0x80,
+    0x07, 0x50, 0x9c, 0x13, 0x43, 0xae, 0x94, 0x07, 0x36, 0xff, 0x8b, 0x00,
+    0x1c, 0x8a, 0x35, 0x00, 0x20, 0x49, 0x40, 0xdb, 0x74, 0x05, 0x82, 0x10,
+    0x03, 0xcd, 0x28, 0x29, 0x06, 0x56, 0xf1, 0x2f, 0xc0, 0x03, 0xd1, 0x22,
+    0x26, 0xd0, 0x08, 0x0a, 0x03, 0x4d, 0x27, 0x37, 0x5d, 0x2f, 0x36, 0xb7,
+    0xe9, 0xef, 0x7a, 0x00, 0xd0, 0x83, 0xe5, 0x14, 0x65, 0x8a, 0x62, 0xd9,
+    0xe2, 0x31, 0xb8, 0x3e, 0xef, 0x15, 0xbd, 0xdc, 0xb8, 0xf4, 0xa3, 0x4a,
+    0xb9, 0x36, 0x1c, 0xde, 0xe7, 0x41, 0x08, 0x01, 0xb8, 0x79, 0xe0, 0x11,
+    0x4a, 0xbe, 0x07, 0xca, 0xdf, 0x2d, 0xea, 0x5d, 0x11, 0x99, 0xb0, 0x2c,
+    0x3a, 0x6e, 0x41, 0xaa, 0x5b, 0x23, 0xf2, 0xb5, 0x5a, 0x41, 0xcd, 0xd8,
+    0x42, 0xad, 0xf7, 0x78, 0xc8, 0x2d, 0xdc, 0x51, 0x70, 0x72, 0xcc, 0xd8,
+    0xb4, 0x75, 0x85, 0x43, 0x94, 0x25, 0xbd, 0x5e, 0xf9, 0x3c, 0x49, 0xbc,
+    0xe5, 0xa3, 0x2b, 0xb8, 0x49, 0x0a, 0x26, 0xd2, 0xa7, 0xea, 0x8d, 0xfd,
+    0xb1, 0xf7, 0xdd, 0x22, 0x8b, 0xef, 0xce, 0x5a, 0x51, 0x66, 0x64, 0x33,
+    0x8a, 0x85, 0x53, 0xc0, 0x7b, 0x51, 0x22, 0x34, 0xe8, 0xd7, 0xd0, 0x09,
+    0x8f, 0x5a, 0x53, 0xb8, 0x54, 0x1b, 0x4b, 0x2c, 0xbb, 0xaa, 0x18, 0xd5,
+    0x69, 0x6d, 0xd2, 0xfa, 0xba, 0x5b, 0x7c, 0x67, 0xc9, 0x37, 0x51, 0x02,
+    0x37, 0x8a, 0x6a, 0xec, 0x2b, 0x03, 0x94, 0xe4, 0x1e, 0xad, 0xce, 0x96,
+    0x95, 0x84, 0x34, 0x5a, 0x38, 0x63, 0x58, 0x90, 0x44, 0x0e, 0xa1, 0x35,
+    0xf4, 0xa0, 0xf3, 0xe1, 0x55, 0x0a, 0x46, 0x12, 0x5b, 0x93, 0x2c, 0x0c,
+    0x95, 0x51, 0x62, 0x94, 0x34, 0x34, 0x2d, 0xaa, 0x36, 0x8d, 0xf3, 0xbb,
+    0x0e, 0xe3, 0x37, 0x54, 0x02, 0x32, 0x83, 0x29, 0xd0, 0xea, 0xce, 0x7e,
+    0x95, 0x3c, 0x26, 0x9a, 0xd0, 0xcb, 0x9c, 0xba, 0xa8, 0x49, 0x8e, 0x2d,
+    0x68, 0x4d, 0x65, 0xa9, 0xaa, 0x05, 0xb2, 0x8c, 0x37, 0xe9, 0x5e, 0xfc,
+    0x00, 0x7a, 0xe7, 0x4e, 0x1e, 0xa3, 0xe5, 0x9b, 0xb9, 0x42, 0x52, 0xc3,
+    0xe3, 0x3f, 0x3f, 0x39, 0x86, 0x59, 0xb8, 0x80, 0x2a, 0xa9, 0x65, 0x3d,
+    0xa9, 0xd4, 0xfb, 0xf4, 0xf9, 0x65, 0x1e, 0xa9, 0x62, 0x6c, 0x18, 0x30,
+    0xf8, 0xdb, 0x5f, 0xb7, 0x8e, 0xde, 0xe7, 0x1b, 0xe2, 0x84, 0xc0, 0x86,
+    0xe3, 0x71, 0x37, 0x0a, 0x0b, 0x29, 0xbc, 0xe4, 0x33, 0x31, 0xbd, 0x1c,
+    0xf3, 0x40, 0x1e, 0xee, 0x3b, 0x4c, 0x5f, 0xd0, 0x21, 0x00, 0x36, 0x96,
+    0x3c, 0x7b, 0x76, 0xbd, 0xe9, 0xb5, 0xfd, 0x74, 0x81, 0xb6, 0xba, 0xdc,
+    0x25, 0x14, 0xde, 0x6f, 0xda, 0x80, 0x1f, 0xa4, 0xf3, 0x08, 0x0b, 0x38,
+    0x68, 0x6b, 0x75, 0x48, 0xdc, 0x52, 0x27, 0x1e, 0xf6, 0xa8, 0x0a, 0xaf,
+    0x91, 0xb9, 0x68, 0x48, 0x67, 0x8b, 0x70, 0xf7, 0xc7, 0x96, 0x3a, 0x5f,
+    0x59, 0x22, 0x59, 0xe2, 0xdc, 0xd7, 0x0c, 0xb9, 0x40, 0x07, 0xad, 0xf0,
+    0x7e, 0x82, 0x74, 0x8c, 0x01, 0x6a, 0xe9, 0x63, 0x75, 0xcf, 0x59, 0x43,
+    0xa1, 0x92, 0x04, 0x37, 0x86, 0xe2, 0xa5, 0x74, 0x50, 0x90, 0x1c, 0x43,
+    0x3c, 0x6d, 0xf0, 0x18, 0xdb, 0xf6, 0xce, 0x24, 0x28, 0x29, 0xb9, 0xb4,
+    0xac, 0xc0, 0x29, 0xbd, 0x2d, 0xab, 0xb6, 0xa3, 0x6a, 0xdf, 0xa6, 0x8e,
+    0x73, 0xc5, 0xbb, 0x99, 0x90, 0x04, 0x66, 0x17, 0xea, 0xa7, 0xb7, 0xa5,
+    0xe4, 0xa7, 0x6e, 0x69, 0x41, 0xbf, 0x9a, 0x60, 0xf3, 0xe0, 0xc6, 0x41,
+    0x74, 0x02, 0xbe, 0x38, 0x7e, 0x50, 0x4a, 0xff, 0xd9, 0x2d, 0x0d, 0x29,
+    0x7c, 0x1b, 0xaa, 0x27, 0x5c, 0x00, 0xdb, 0xfa, 0x20, 0x5b, 0xe2, 0x52,
+    0xe5, 0x8f, 0x11, 0xa6, 0xd8, 0x58, 0x6a, 0x52, 0x15, 0x6d, 0x0b, 0xb5,
+    0x40, 0xb6, 0x4d, 0xf0, 0x35, 0xb3, 0x76, 0xfa, 0xfe, 0x4b, 0xd0, 0x08,
+    0x31, 0xb4, 0x40, 0x1a, 0xab, 0x62, 0x80, 0x84, 0x01, 0x35, 0xe0, 0x9b,
+    0xff, 0xb2, 0x12, 0x19, 0x53, 0x94, 0x96, 0xd2, 0xdd, 0xbb, 0x0a, 0x66,
+    0xd0, 0x1a, 0x36, 0x21, 0x40, 0x85, 0xff, 0x1b, 0x8f, 0x9e, 0xa6, 0x2a,
+    0xb7, 0x75, 0xe3, 0x09, 0x0d, 0xb4, 0x18, 0xd4, 0xdd, 0xaf, 0x0e, 0x70,
+    0xba, 0x4a, 0x56, 0xe5, 0x11, 0x4f, 0x95, 0x28, 0x0a, 0xa8, 0xc6, 0xf4,
+    0x77, 0xf3, 0x79, 0x52, 0x4b, 0x4a, 0x5a, 0xb7, 0x3e, 0x7e, 0x6d, 0x24,
+    0x23, 0x44, 0x2d, 0x5b, 0xc2, 0x2d, 0x76, 0x6d, 0xa4, 0x3a, 0xdd, 0x61,
+    0x30, 0x00, 0xfe, 0x61, 0x26, 0x46, 0xfa, 0x10, 0x03, 0xf2, 0x2e, 0x00,
+    0x16, 0xfd, 0xb1, 0xfe, 0xdb, 0x32, 0x95, 0xa5, 0x08, 0xaf, 0x9c, 0xc1,
+    0xc5, 0x28, 0x6b, 0x7a, 0x80, 0x02, 0xd1, 0x16, 0xfb, 0xbc, 0x56, 0xe0,
+    0x5e, 0x8f, 0x75, 0x0d, 0x81, 0xac, 0x13, 0x21, 0xa4, 0x8a, 0x48, 0x63,
+    0x62, 0x42, 0xe3, 0x7e, 0xc1, 0xe0, 0x0f, 0xf9, 0x00, 0x72, 0x28, 0x4d,
+    0x14, 0xfb, 0x92, 0x1d, 0x8e, 0xb6, 0xa6, 0x58, 0x5d, 0xf4, 0xac, 0x7e,
+    0x40, 0x15, 0x80, 0x19, 0x7b, 0x3d, 0xf3, 0x65, 0xc2, 0xa7, 0x2e, 0xc3,
+    0xee, 0xc5, 0x28, 0xe6, 0x4f, 0xf8, 0xbf, 0x6f, 0x97, 0x0b, 0xe3, 0xae,
+    0xf5, 0x4a, 0x2f, 0x69, 0x61, 0x63, 0x5b, 0xb6, 0x46, 0x00, 0x63, 0x74,
+    0x4a, 0xdc, 0xd7, 0xe5, 0x4c, 0x42, 0xdb, 0x1d, 0xe3, 0x7b, 0xa4, 0xd7,
+    0x8d, 0x28, 0x32, 0x35, 0x99, 0x75, 0x4b, 0x78, 0x64, 0x0c, 0x8d, 0xfc,
+    0xa0, 0x00, 0x9c, 0x59, 0x10, 0x89, 0x79, 0x77, 0xc8, 0xa7, 0x95, 0x0d,
+    0xc7, 0x96, 0x51, 0x87, 0xc5, 0xad, 0x84, 0x01, 0x1b, 0xaf, 0xdc, 0x40,
+    0xa1, 0x79, 0xce, 0x52, 0xe5, 0x93, 0x1e, 0x56, 0x55, 0x01, 0xec, 0xf5,
+    0x6f, 0xd0, 0xa4, 0x6f, 0xe8, 0x01, 0xef, 0xc4, 0xde, 0x49, 0xef, 0x5b,
+    0x36, 0x6c, 0x3a, 0xa5, 0x2e, 0x56, 0xee, 0xdd, 0x98, 0x62, 0x5a, 0x15,
+    0xb4, 0xb4, 0x6e, 0xfd, 0x44, 0x21, 0x96, 0x31, 0xba, 0x1f, 0x62, 0x20,
+    0x0f, 0x98, 0x00, 0x00, 0x01, 0x02, 0x43, 0xf8, 0x37, 0x13, 0x05, 0xdd,
+    0xbe, 0xa9, 0x4b, 0x6c, 0xa2, 0xbc, 0xc5, 0x6e, 0x6c, 0x21, 0x12, 0x23,
+    0x77, 0x3e, 0x68, 0x05, 0xa2, 0xdf, 0x8e, 0xcf, 0x02, 0xe1, 0x60, 0x73,
+    0x79, 0x09, 0x08, 0x0e, 0x74, 0x25, 0x49, 0x1b, 0xcc, 0x42, 0xca, 0x21,
+    0xb7, 0x90, 0xdf, 0x40, 0x10, 0xff, 0xe7, 0x1d, 0x2e, 0x92, 0x59, 0x94,
+    0x80, 0x94, 0xbf, 0x16, 0xe7, 0xdc, 0x34, 0xb6, 0xd7, 0xb0, 0xd9, 0x2d,
+    0x50, 0x81, 0xc5, 0x35, 0x0f, 0x6a, 0x6f, 0xd4, 0xea, 0xfd, 0x5e, 0xa0,
+    0x03, 0x0a, 0xad, 0xc9, 0xee, 0x5f, 0x8e, 0x78, 0xb2, 0xc0, 0xc0, 0xe2,
+    0xbd, 0x4a, 0x46, 0xd5, 0xed, 0x27, 0x2e, 0xe1, 0xea, 0x13, 0x76, 0xd1,
+    0xc1, 0x65, 0x90, 0x99, 0xb6, 0x00, 0x1a, 0x24, 0x9e, 0x12, 0x87, 0xc8,
+    0x14, 0x96, 0x10, 0xda, 0x60, 0x74, 0xd0, 0x2d, 0x85, 0x30, 0xaa, 0xdf,
+    0x15, 0xff, 0x9c, 0x02, 0xaa, 0x36, 0xdb, 0x2d, 0xdb, 0x9b, 0xa0, 0x10,
+    0xc4, 0x94, 0x87, 0x1b, 0x3e, 0x02, 0x17, 0xfc, 0x6b, 0x88, 0x70, 0xf4,
+    0x21, 0x37, 0x7c, 0x5c, 0x9c, 0xba, 0xda, 0xac, 0x13, 0x59, 0x1f, 0x1b,
+    0xca, 0x2b, 0x30, 0x5e, 0xe3, 0xa2, 0x78, 0xd0, 0xe2, 0x43, 0x7b, 0x87,
+    0x53, 0x70, 0xbc, 0xa1, 0xb0, 0xf8, 0x12, 0xde, 0x44, 0x01, 0xf8, 0xaa,
+    0x94, 0xf9, 0x43, 0x71, 0x51, 0xb4, 0x3f, 0x20, 0x9e, 0x6c, 0x49, 0x03,
+    0x75, 0x76, 0x86, 0x42, 0x96, 0x95, 0x2b, 0x5a, 0x07, 0xb6, 0xfc, 0x97,
+    0x8d, 0xfa, 0x7f, 0xa3, 0xcd, 0x91, 0xe6, 0x78, 0xc2, 0xc2, 0x5b, 0x77,
+    0x7b, 0x48, 0xf6, 0x3d, 0x03, 0x21, 0xbd, 0x62, 0x58, 0x16, 0xb1, 0xbc,
+    0xdc, 0xe7, 0xce, 0x77, 0x2b, 0xf4, 0x05, 0x7d, 0x29, 0x30, 0x69, 0xf2,
+    0x37, 0x55, 0xd8, 0x00, 0x73, 0x3b, 0x89, 0x02, 0xad, 0x2c, 0x84, 0x3d,
+    0xb0, 0x43, 0x25, 0x6c, 0x2c, 0x4a, 0xab, 0xe8, 0xde, 0x7d, 0xe3, 0x40,
+    0x1d, 0x3f, 0xb7, 0x89, 0x90, 0x35, 0x1d, 0x76, 0xa8, 0xd2, 0x6c, 0x2d,
+    0x28, 0x5b, 0x78, 0xb7, 0xf3, 0x7e, 0x57, 0xcc, 0x22, 0x49, 0xdd, 0x2a,
+    0xa0, 0xd2, 0x83, 0x29, 0x6d, 0xf6, 0x3d, 0xbe, 0x73, 0x1c, 0x80, 0x10,
+    0x45, 0x25, 0xa9, 0x5e, 0xad, 0xe0, 0xc5, 0xf2, 0x00, 0x70, 0x27, 0x84,
+    0xd8, 0xa7, 0xee, 0xee, 0x59, 0x9b, 0x83, 0x40, 0x79, 0x22, 0xb5, 0x38,
+    0x0c, 0xc5, 0x6e, 0x8c, 0xa0, 0x16, 0x87, 0x90, 0xa3, 0x6f, 0xed, 0x2f,
+    0x0f, 0xf3, 0x59, 0x20, 0x13, 0x0f, 0x2d, 0x4e, 0x0a, 0x30, 0x39, 0x84,
+    0xd3, 0x69, 0x8b, 0x92, 0x04, 0x17, 0x8e, 0x81, 0x1b, 0x15, 0x6e, 0x8e,
+    0x29, 0xb8, 0x9c, 0x39, 0x53, 0x12, 0x5a, 0x51, 0x65, 0x42, 0xa4, 0x2b,
+    0xd2, 0x9c, 0xdb, 0x38, 0x9e, 0x7a, 0x8b, 0x42, 0x4b, 0x2c, 0x30, 0xe4,
+    0x6e, 0x88, 0x53, 0x7a, 0x27, 0xc6, 0xf0, 0xe8, 0x21, 0x00, 0x45, 0x28,
+    0x92, 0xb5, 0x46, 0x1e, 0x7b, 0x64, 0x32, 0x6c, 0x9e, 0x31, 0x15, 0x15,
+    0xb7, 0xe1, 0x68, 0x52, 0x80, 0x8a, 0xd1, 0xcd, 0xa2, 0x6d, 0xe6, 0x3f,
+    0x65, 0xaa, 0x33, 0x0a, 0xc9, 0x12, 0x05, 0xa8, 0xd0, 0x86, 0x6c, 0x37,
+    0xc6, 0xd8, 0x85, 0x94, 0x07, 0x36, 0x7e, 0xad, 0xeb, 0x92, 0x45, 0x2d,
+    0xb6, 0x69, 0x99, 0xb8, 0x50, 0x16, 0xdc, 0x30, 0x43, 0x00, 0x77, 0x3a,
+    0x80, 0x0c, 0x59, 0x1c, 0xd9, 0xcf, 0xc6, 0xd6, 0xf4, 0x11, 0xb0, 0x00,
+    0xf4, 0x5e, 0x15, 0xe2, 0x91, 0x07, 0xb7, 0xad, 0xc9, 0x99, 0xed, 0x53,
+    0x03, 0x22, 0xea, 0xcb, 0x40, 0x44, 0x3c, 0x73, 0x78, 0x31, 0x91, 0xbd,
+    0x75, 0x04, 0x2f, 0xf7, 0xde, 0xc9, 0x20, 0x73, 0x61, 0x69, 0xcd, 0x82,
+    0x90, 0x7c, 0x90, 0x86, 0xdd, 0x32, 0x25, 0x75, 0xd9, 0x03, 0x10, 0xec,
+    0xb7, 0xc0, 0x73, 0x74, 0x76, 0x65, 0xce, 0x6c, 0xd0, 0x83, 0x65, 0x90,
+    0x34, 0x7b, 0x70, 0xdc, 0x1d, 0xe6, 0x70, 0x46, 0x4c, 0xe0, 0xaf, 0x1a,
+    0xdd, 0xcd, 0x04, 0x20, 0x08, 0xda, 0x62, 0x04, 0xaa, 0xcf, 0x45, 0x52,
+    0x4b, 0x68, 0x37, 0x21, 0x21, 0xb6, 0xda, 0x01, 0x52, 0xe1, 0x0a, 0x96,
+    0xdf, 0x21, 0x7c, 0x8f, 0xf5, 0x8d, 0x6f, 0x60, 0x85, 0xfe, 0x0e, 0x11,
+    0x08, 0x66, 0xd2, 0x11, 0x4b, 0x58, 0x6c, 0xa9, 0x55, 0xbd, 0x08, 0xb9,
+    0x48, 0xbd, 0xd3, 0x82, 0x90, 0xc8, 0x07, 0xb6, 0x81, 0xad, 0xe7, 0x37,
+    0xd0, 0xa5, 0x18, 0x07, 0x36, 0x5e, 0x4a, 0x76, 0x72, 0x42, 0xbe, 0x44,
+    0xb6, 0xd6, 0x8a, 0x8c, 0xbc, 0xda, 0xf7, 0x3a, 0xe6, 0x50, 0xbc, 0xa9,
+    0xe8, 0x74, 0xa4, 0xb6, 0x89, 0xf8, 0xad, 0x03, 0x5b, 0xa3, 0x98, 0x96,
+    0x69, 0x25, 0x5a, 0xc2, 0x3a, 0x8a, 0xc3, 0x70, 0xa1, 0xf1, 0x1e, 0x9b,
+    0x21, 0xc1, 0x95, 0xae, 0xae, 0x27, 0x79, 0x4b, 0x09, 0x11, 0xba, 0xe4,
+    0x6c, 0x00, 0xb3, 0xaf, 0x32, 0x6d, 0x1c, 0x41, 0xf3, 0x96, 0x58, 0x01,
+    0xfb, 0x73, 0x3a, 0xc4, 0x90, 0x96, 0x48, 0x60, 0xf9, 0x63, 0x7e, 0x28,
+    0x8b, 0x28, 0x9e, 0xa6, 0x1b, 0x03, 0x15, 0x64, 0x41, 0xad, 0xec, 0xbe,
+    0x5d, 0xaf, 0x15, 0x9a, 0xfc, 0x81, 0xb7, 0x0e, 0xa9, 0xea, 0xd9, 0xba,
+    0xcb, 0x61, 0xa5, 0xd0, 0xc5, 0x1c, 0xde, 0x87, 0xcf, 0x8f, 0xed, 0x11,
+    0x98, 0x2f, 0x29, 0x69, 0x70, 0x02, 0xb7, 0xe4, 0x85, 0xcf, 0x05, 0xa3,
+    0x1a, 0xf2, 0x17, 0x11, 0x93, 0x7d, 0xb0, 0x06, 0x7b, 0x99, 0xa4, 0x7e,
+    0xa9, 0x03, 0x99, 0x2a, 0x79, 0xc7, 0x3f, 0x52, 0xde, 0x29, 0x94, 0xa5,
+    0x8a, 0x4b, 0x8d, 0xe3, 0xdf, 0xf9, 0x6f, 0xba, 0x80, 0x3d, 0x15, 0xfe,
+    0x00, 0x7d, 0x9e, 0xfc, 0x7b, 0x91, 0x93, 0x62, 0xe9, 0x3f, 0x9c, 0xcf,
+    0x27, 0x07, 0xdb, 0x46, 0x16, 0x5a, 0xc6, 0xe2, 0x8b, 0xfb, 0xe8, 0x02,
+    0x37, 0x88, 0x77, 0xc4, 0x1c, 0x95, 0x64, 0xaf, 0xde, 0x6c, 0xf2, 0x85,
+    0x41, 0xc5, 0xb2, 0xb6, 0x57, 0xcb, 0x28, 0xf4, 0x89, 0x19, 0xd1, 0x96,
+    0x50, 0xa6, 0xfc, 0xf7, 0xfc, 0x53, 0xfd, 0xc8, 0xf9, 0x9c, 0x3e, 0x06,
+    0x27, 0x39, 0x78, 0xd4, 0x01, 0x5c, 0xa8, 0xa7, 0x0e, 0x6f, 0xd4, 0x42,
+    0x01, 0x0b, 0xfc, 0xfe, 0x04, 0xb8, 0x84, 0xf9, 0x6c, 0xf0, 0x2c, 0xa6,
+    0xc9, 0xfd, 0xdb, 0xfe, 0xfa, 0x72, 0xb6, 0x84, 0x38, 0xd4, 0x7f, 0xa8,
+    0xea, 0xda, 0x44, 0xe0, 0x01, 0x9f, 0xb8, 0xbd, 0x72, 0x86, 0x99, 0x52,
+    0x42, 0x14, 0x6e, 0xbd, 0x86, 0xee, 0x12, 0xe4, 0x6e, 0xbd, 0x86, 0xee,
+    0x12, 0xe4, 0x6e, 0x90, 0x07, 0xbe, 0xfd, 0xf3, 0xcc, 0x86, 0x3e, 0xd4,
+    0x92, 0x01, 0x87, 0x64, 0x5f, 0x16, 0xe9, 0x09, 0xef, 0x9d, 0x7d, 0xb6,
+    0xbf, 0x68, 0xd5, 0x6d, 0x6d, 0xe0, 0x80, 0x14, 0x68, 0x20, 0x80, 0xaf,
+    0xde, 0x73, 0xce, 0x50, 0xc9, 0xc4, 0x3b, 0x68, 0xcf, 0x46, 0xdd, 0x4b,
+    0x3d, 0xb5, 0x54, 0xdb, 0x1b, 0xe7, 0x00, 0x3d, 0xfa, 0x40, 0x07, 0x8f,
+    0xc7, 0x11, 0xf1, 0x5e, 0x55, 0x5a, 0xe7, 0x47, 0x47, 0xe4, 0x9e, 0x6a,
+    0x88, 0x10, 0xdf, 0x17, 0x11, 0xf1, 0x84, 0x6b, 0xd0, 0x05, 0x84, 0xe9,
+    0x3f, 0x44, 0xe9, 0x62, 0x5c, 0x1a, 0xdf, 0x4e, 0x00, 0x78, 0x00, 0xbb,
+    0xb1, 0x3d, 0x63, 0x9f, 0xc6, 0x3e, 0x9a, 0xb2, 0xed, 0x19, 0xb1, 0xb1,
+    0x00, 0x39, 0x00, 0x71, 0xf2, 0x00, 0xe0, 0x01, 0x97, 0x4e, 0xce, 0xf9,
+    0xcd, 0xc8, 0x31, 0xf6, 0xea, 0x24, 0x31, 0xa0, 0xe8, 0xdc, 0xd4, 0xac,
+    0x2e, 0xc6, 0x00, 0x00, 0x01, 0x03, 0x43, 0xf9, 0x6d, 0x84, 0xef, 0x3a,
+    0x09, 0x80, 0x07, 0x34, 0x90, 0xde, 0x07, 0x7f, 0x39, 0x63, 0x7b, 0xb7,
+    0x1b, 0xc6, 0xf3, 0x32, 0xc0, 0x8d, 0xe0, 0xbb, 0x14, 0x2a, 0x56, 0xf2,
+    0x02, 0xdc, 0x4f, 0xe5, 0xf3, 0x3c, 0x7c, 0xdc, 0x5a, 0x1c, 0x7a, 0x37,
+    0x04, 0xa6, 0x48, 0xad, 0xe3, 0xa1, 0x6d, 0xd7, 0x6d, 0x55, 0x38, 0x32,
+    0x35, 0x87, 0xed, 0x02, 0x9b, 0x47, 0x21, 0xeb, 0x93, 0xd6, 0x56, 0xae,
+    0x97, 0x24, 0x9b, 0xe2, 0x35, 0xb3, 0x83, 0x99, 0x46, 0xdd, 0xf0, 0x00,
+    0xec, 0x80, 0x58, 0x51, 0xb0, 0x0a, 0x56, 0x5f, 0x6b, 0x05, 0x70, 0x2b,
+    0x22, 0x00, 0x8f, 0x82, 0xc9, 0x76, 0xd2, 0x5b, 0x50, 0xe8, 0x64, 0x8b,
+    0x42, 0x5b, 0x15, 0x0e, 0xad, 0x9c, 0x39, 0xae, 0x0d, 0x6d, 0xf1, 0x73,
+    0x12, 0xdf, 0x4b, 0x0e, 0x09, 0x6f, 0x46, 0xec, 0x00, 0x3d, 0x8f, 0xe0,
+    0xa0, 0xb5, 0x59, 0xe0, 0xde, 0x6e, 0xfe, 0x4d, 0x00, 0x18, 0x37, 0xd0,
+    0x7b, 0x04, 0x2f, 0xf0, 0x7f, 0xb9, 0x94, 0x00, 0x68, 0x9e, 0xa9, 0x1b,
+    0x40, 0x1c, 0xc0, 0x3d, 0x90, 0xd6, 0xec, 0x10, 0x9c, 0xe9, 0x44, 0x35,
+    0x6e, 0x57, 0xb3, 0xed, 0xe7, 0x5d, 0xb1, 0xc0, 0x3d, 0x0e, 0xbd, 0x59,
+    0xe8, 0x85, 0xaf, 0x83, 0x72, 0xb7, 0x1d, 0x9d, 0xbb, 0xcb, 0x8a, 0x1a,
+    0x6c, 0x3f, 0x10, 0xf1, 0x8a, 0xb5, 0xae, 0x15, 0x8f, 0x17, 0xcf, 0x2f,
+    0x2c, 0x31, 0x66, 0x15, 0x1b, 0x48, 0x54, 0x29, 0xb7, 0x71, 0x75, 0xbe,
+    0xbb, 0x9f, 0xbd, 0x8a, 0x99, 0x29, 0xc3, 0x9f, 0x90, 0xaa, 0x36, 0x9d,
+    0x47, 0xb7, 0xb2, 0xe7, 0x1d, 0xf3, 0x1d, 0x90, 0xf3, 0xcd, 0xe6, 0x5b,
+    0x43, 0x46, 0x0d, 0x6f, 0x9a, 0x13, 0x76, 0x90, 0xed, 0xa1, 0xf6, 0xb7,
+    0xbe, 0x70, 0x21, 0x7f, 0xbb, 0xb9, 0x88, 0x01, 0x0b, 0x73, 0x6a, 0x24,
+    0x5a, 0xd3, 0x96, 0xe4, 0x02, 0x9b, 0xf4, 0xda, 0xe9, 0xb6, 0x94, 0x12,
+    0x73, 0x57, 0xef, 0xaf, 0x77, 0x16, 0xf1, 0x14, 0x70, 0x6b, 0x71, 0x30,
+    0x53, 0x88, 0x97, 0xb7, 0x76, 0x60, 0x23, 0xff, 0xea, 0xbe, 0x18, 0xea,
+    0x12, 0x10, 0xda, 0x7d, 0xb8, 0xc7, 0xce, 0x73, 0xb4, 0x87, 0x16, 0x1d,
+    0xb2, 0xaa, 0x90, 0xda, 0x5e, 0xe5, 0xd1, 0xad, 0x8e, 0x8e, 0xb7, 0xd5,
+    0xbe, 0x60, 0x03, 0x39, 0x82, 0x34, 0xce, 0xe4, 0x83, 0x9f, 0x46, 0x0f,
+    0x6f, 0x35, 0x7f, 0x2f, 0x97, 0x21, 0x45, 0x5f, 0x35, 0x81, 0xd6, 0x40,
+    0xea, 0x58, 0x69, 0x0d, 0xbd, 0xe0, 0x03, 0xae, 0x60, 0xb8, 0x6f, 0x0f,
+    0xd0, 0xdf, 0x2a, 0x5e, 0x6a, 0x87, 0x1a, 0x65, 0x3c, 0xe6, 0xe6, 0xff,
+    0xf2, 0x00, 0x38, 0xf6, 0xc1, 0x5d, 0x85, 0xd8, 0xfb, 0xa8, 0xe2, 0xd6,
+    0x07, 0x84, 0x1e, 0x18, 0xdb, 0xe4, 0x34, 0xbc, 0x6e, 0xb7, 0x42, 0x7e,
+    0xcb, 0x9e, 0x0d, 0xf8, 0xc9, 0x22, 0x65, 0x94, 0x2e, 0xd4, 0x58, 0xa7,
+    0x0d, 0x6b, 0xcd, 0x84, 0x67, 0xc7, 0xd9, 0x42, 0x0b, 0x2b, 0xd4, 0x63,
+    0x67, 0x72, 0x48, 0x89, 0x28, 0xd4, 0x76, 0xbe, 0x2d, 0x94, 0xaa, 0x7a,
+    0x8c, 0x6c, 0xb5, 0x05, 0x5c, 0x84, 0xa2, 0x90, 0x29, 0xb7, 0x6f, 0x4e,
+    0x0d, 0x6c, 0x4a, 0x6c, 0xc0, 0x29, 0xb9, 0x20, 0x13, 0x69, 0x22, 0x48,
+    0xdd, 0x42, 0x6e, 0xd8, 0x57, 0x8b, 0x74, 0x7f, 0xe6, 0x09, 0x23, 0x4e,
+    0x1c, 0xfb, 0x03, 0x3b, 0xf3, 0xb1, 0xc8, 0x4d, 0x1a, 0xd9, 0x4b, 0xe5,
+    0xb6, 0x46, 0xe1, 0x80, 0x84, 0x00, 0xc0, 0x7b, 0x7e, 0x78, 0x5e, 0x51,
+    0x7c, 0x45, 0x8d, 0xec, 0x3d, 0xf0, 0xcd, 0x7d, 0x28, 0x02, 0x35, 0x88,
+    0xdb, 0x3b, 0x7d, 0x13, 0x36, 0xf7, 0x02, 0x43, 0xf3, 0x35, 0x27, 0x85,
+    0x6f, 0x6e, 0x45, 0x80, 0x07, 0x0f, 0xe6, 0x96, 0x13, 0x82, 0x7c, 0xec,
+    0x40, 0x82, 0xc0, 0xe6, 0xe4, 0xea, 0xf9, 0x73, 0x94, 0x00, 0x67, 0x00,
+    0xa6, 0xc9, 0xda, 0x41, 0x7f, 0x06, 0x7a, 0xeb, 0x7f, 0x34, 0xf7, 0x94,
+    0x5f, 0x1c, 0x3c, 0x13, 0x3f, 0xe8, 0xa8, 0xde, 0xaf, 0xeb, 0x97, 0xfd,
+    0xd6, 0xed, 0xb4, 0x21, 0x6c, 0x24, 0xb7, 0x43, 0xee, 0xe9, 0x7b, 0xcc,
+    0xb4, 0x26, 0x79, 0xcb, 0x65, 0xf4, 0x1c, 0xd4, 0x80, 0x3a, 0xde, 0x54,
+    0x0c, 0x20, 0xe7, 0xc3, 0xae, 0xe4, 0xa0, 0x53, 0x73, 0x3b, 0x0c, 0x74,
+    0x9c, 0xca, 0x17, 0x6b, 0x57, 0x09, 0xf0, 0xe9, 0xe7, 0x3c, 0x6d, 0x6f,
+    0x88, 0x26, 0x82, 0x17, 0xfc, 0x6e, 0x4f, 0x04, 0xa5, 0x56, 0xe9, 0x1b,
+    0x37, 0x6c, 0xc6, 0xbc, 0x88, 0xfe, 0xc4, 0x4d, 0x7a, 0xc9, 0x50, 0x3a,
+    0xc9, 0x29, 0x9b, 0x14, 0x28, 0x60, 0x4b, 0x75, 0x3f, 0xbd, 0x3f, 0x9f,
+    0x39, 0xe6, 0x1b, 0x8a, 0xa7, 0x4b, 0x10, 0x65, 0x52, 0x82, 0xe0, 0xd6,
+    0xf4, 0x26, 0x51, 0x78, 0x1d, 0x5b, 0x95, 0x0d, 0x53, 0x2b, 0x7e, 0x2f,
+    0xe8, 0xf9, 0x9d, 0x47, 0xf6, 0x58, 0xe9, 0x30, 0xe2, 0xc3, 0xe1, 0x6d,
+    0xdc, 0x50, 0x03, 0xdb, 0xcc, 0x94, 0x00, 0x5d, 0xe0, 0x07, 0xb6, 0x2f,
+    0x97, 0xef, 0xc6, 0x3a, 0xc2, 0xc0, 0x99, 0xe7, 0x65, 0x89, 0x1b, 0x4e,
+    0x59, 0x1f, 0xe7, 0xae, 0xc0, 0x1e, 0x61, 0x92, 0x5f, 0x55, 0xaa, 0x51,
+    0xcc, 0xf6, 0x4e, 0x32, 0x56, 0x76, 0x99, 0x2b, 0x6e, 0xe8, 0x5c, 0xc9,
+    0xe2, 0xa8, 0x78, 0x4b, 0x76, 0x85, 0xf3, 0x34, 0x5c, 0x52, 0x8e, 0xa5,
+    0xed, 0x4a, 0x87, 0x9e, 0x3e, 0x90, 0x9b, 0xcf, 0xec, 0x57, 0x4b, 0x60,
+    0x5a, 0xc9, 0x69, 0x0c, 0x63, 0x7a, 0x01, 0x26, 0x88, 0xb9, 0x32, 0x82,
+    0x48, 0x02, 0x1b, 0x2c, 0xbe, 0x95, 0xb9, 0x2f, 0xe1, 0x4b, 0x6c, 0x4e,
+    0x03, 0xdb, 0xc7, 0xce, 0xcf, 0x67, 0xf1, 0x1f, 0x83, 0xca, 0xb6, 0x20,
+    0x06, 0xcd, 0xb8, 0xd9, 0xcb, 0x94, 0xb0, 0xa1, 0x88, 0xdc, 0xf9, 0x2c,
+    0x4a, 0xb6, 0x85, 0x14, 0x42, 0x6c, 0xbb, 0x0d, 0x48, 0xd6, 0x51, 0x8f,
+    0x21, 0x4a, 0xd4, 0x74, 0x6f, 0xdf, 0x89, 0x76, 0xf2, 0xe7, 0xcd, 0x32,
+    0xc4, 0x4b, 0x52, 0xca, 0x5c, 0x08, 0x2c, 0x6b, 0x76, 0x88, 0xa4, 0x41,
+    0x62, 0xed, 0x96, 0x71, 0xb0, 0xa4, 0x37, 0x2d, 0x91, 0x60, 0x69, 0x6d,
+    0xee, 0x00, 0x18, 0x6f, 0x20, 0x0d, 0x48, 0xff, 0xd7, 0x2c, 0xb5, 0x4b,
+    0x27, 0xf3, 0x91, 0xf3, 0x6a, 0x20, 0x04, 0xc5, 0x95, 0x10, 0x36, 0x0f,
+    0x6f, 0x4c, 0x00, 0xc0, 0x57, 0x3e, 0xc0, 0x16, 0xcd, 0xba, 0x30, 0xcc,
+    0x28, 0xed, 0xa7, 0xcf, 0x35, 0x94, 0xe0, 0xb6, 0x39, 0xdc, 0xb1, 0x25,
+    0x09, 0x42, 0xd1, 0x8d, 0x7c, 0x87, 0x20, 0x53, 0x7b, 0xc0, 0x1b, 0x5d,
+    0x00, 0x7f, 0xc3, 0xdf, 0xc6, 0xa1, 0x68, 0x61, 0x3c, 0xdb, 0x65, 0xf1,
+    0x2d, 0xbd, 0xc3, 0x7c, 0x6c, 0x01, 0xa0, 0x9e, 0xd3, 0x9d, 0xd9, 0xd8,
+    0xeb, 0x73, 0x5f, 0x76, 0xdd, 0x41, 0xe1, 0x6d, 0xcf, 0x00, 0x64, 0x44,
+    0xea, 0x6c, 0x36, 0xdb, 0x40, 0x95, 0x2e, 0x9b, 0x42, 0x5b, 0x32, 0x36,
+    0xba, 0x8b, 0x9b, 0x8e, 0xb4, 0x78, 0x6d, 0x87, 0x1e, 0xda, 0x08, 0xb3,
+    0x75, 0x64, 0x6f, 0xeb, 0x3f, 0xcf, 0x7e, 0x85, 0x77, 0x8f, 0xcd, 0x55,
+    0x87, 0x48, 0x75, 0x4a, 0x48, 0x6e, 0x00, 0xb0, 0x06, 0xe0, 0x07, 0xdc,
+    0xd2, 0x33, 0xa7, 0x38, 0x54, 0x92, 0x1b, 0xa9, 0x5c, 0xa5, 0x64, 0x31,
+    0x07, 0x37, 0x88, 0x00, 0x36, 0x20, 0x88, 0xa5, 0x8b, 0x90, 0xfc, 0xe2,
+    0xcb, 0x24, 0x55, 0x01, 0xec, 0x6e, 0x37, 0xcf, 0xcf, 0xf0, 0x55, 0x99,
+    0xf1, 0xe7, 0x4f, 0x77, 0x7b, 0x22, 0xc1, 0xab, 0x4f, 0x83, 0x23, 0x3f,
+    0x8e, 0x37, 0x5c, 0x81, 0xf0, 0xea, 0x95, 0x0b, 0xad, 0x5c, 0x65, 0x41,
+    0xad, 0xc0, 0x02, 0xe1, 0x53, 0xfc, 0x2a, 0x6b, 0xe8, 0x6d, 0xd7, 0x86,
+    0xa1, 0x4d, 0xdc, 0x23, 0x00, 0x3c, 0xe8, 0x01, 0xb8, 0x03, 0x8f, 0x3e,
+    0xfd, 0xf9, 0xda, 0x51, 0xb3, 0x99, 0xce, 0xd8, 0x71, 0x43, 0x46, 0x64,
+    0x6f, 0x82, 0x11, 0x25, 0x11, 0xb9, 0x74, 0x0f, 0x1d, 0x46, 0x37, 0xb1,
+    0x00, 0x68, 0x44, 0xa0, 0x0e, 0xc4, 0x60, 0x9f, 0x9e, 0xcc, 0x5b, 0x35,
+    0xff, 0x9d, 0xd4, 0x37, 0x00, 0xc2, 0x7e, 0x14, 0x38, 0xa3, 0xe8, 0x5b,
+    0x6f, 0xe4, 0x41, 0xb2, 0x46, 0x84, 0x8f, 0x49, 0x11, 0x80, 0x00, 0x00,
+    0x01, 0x04, 0x43, 0xf9, 0x8e, 0xd8, 0xe7, 0x69, 0x90, 0x2f, 0x79, 0x44,
+    0x6c, 0xf5, 0xf4, 0x47, 0x79, 0x4e, 0x1e, 0xb2, 0x59, 0x54, 0x21, 0x18,
+    0x3d, 0xd3, 0x49, 0x98, 0x1a, 0x07, 0x35, 0x22, 0x72, 0x71, 0xd1, 0x70,
+    0xe2, 0xd5, 0x75, 0x0a, 0x50, 0xd6, 0xf3, 0x52, 0xc6, 0xf1, 0xd1, 0xbc,
+    0xba, 0xa0, 0x16, 0x17, 0xea, 0x39, 0xb4, 0x7c, 0xd3, 0x0d, 0x92, 0x8f,
+    0x92, 0x27, 0x8b, 0x58, 0x28, 0x9f, 0xbc, 0xcd, 0xba, 0x52, 0x87, 0x5c,
+    0x52, 0xdb, 0x41, 0x13, 0xb9, 0xcc, 0x42, 0x74, 0xa3, 0xeb, 0x86, 0x6d,
+    0x55, 0x3a, 0xd6, 0x71, 0xf2, 0x2a, 0x33, 0xa3, 0x9b, 0xf2, 0xde, 0xee,
+    0xd7, 0x3e, 0x15, 0x95, 0x81, 0x1f, 0x8d, 0xe4, 0x44, 0xba, 0x14, 0x7c,
+    0xb2, 0xb7, 0xb1, 0x10, 0xab, 0x32, 0xdf, 0x09, 0x15, 0x5b, 0xb3, 0xda,
+    0xfd, 0x79, 0x12, 0xb9, 0x28, 0x45, 0x92, 0x42, 0x13, 0x72, 0xcb, 0x16,
+    0x12, 0x58, 0x54, 0x46, 0xfc, 0x88, 0x03, 0xf4, 0xb4, 0x9f, 0x54, 0x05,
+    0x51, 0x7c, 0x9d, 0xe2, 0xa8, 0x58, 0x59, 0x6c, 0xa2, 0x93, 0xda, 0x1b,
+    0xa8, 0x13, 0xb2, 0xc5, 0x6f, 0x47, 0x25, 0x15, 0xce, 0x5c, 0xa0, 0x94,
+    0x01, 0x19, 0x6d, 0x04, 0xbf, 0xfd, 0x56, 0xf1, 0xd0, 0x0c, 0x15, 0x6f,
+    0xa3, 0x77, 0x0f, 0x56, 0xd0, 0xe6, 0xe8, 0xb3, 0xcf, 0xac, 0xd4, 0xf5,
+    0x29, 0xba, 0x1b, 0xf8, 0x39, 0xb0, 0xcc, 0x9f, 0x3a, 0xe9, 0xa4, 0x26,
+    0xee, 0xbf, 0x3f, 0x09, 0x08, 0x6d, 0x34, 0xb9, 0x5a, 0x1b, 0xe4, 0xb7,
+    0x53, 0xd8, 0x10, 0xbf, 0xdf, 0x98, 0x4b, 0xd8, 0xb3, 0xc5, 0xa8, 0xef,
+    0x3c, 0xae, 0xc5, 0x08, 0x59, 0x49, 0x32, 0x8c, 0x6e, 0x74, 0x2e, 0xd2,
+    0x4b, 0x21, 0xac, 0x37, 0xf5, 0x69, 0xf9, 0x52, 0x5c, 0x88, 0x4b, 0x6c,
+    0x4f, 0xa0, 0x16, 0xf3, 0xe7, 0x68, 0x04, 0x1b, 0x8b, 0xe2, 0x91, 0x09,
+    0x0c, 0xb9, 0x00, 0x0d, 0xf0, 0x5c, 0x04, 0xcf, 0xfd, 0x5a, 0x49, 0x67,
+    0xe1, 0x31, 0xfc, 0x19, 0xb4, 0x30, 0xd7, 0x1b, 0x3d, 0x14, 0xef, 0x14,
+    0xac, 0xc6, 0x23, 0x41, 0xe0, 0x73, 0x7e, 0x53, 0x78, 0xdf, 0xb7, 0x3f,
+    0x1c, 0x73, 0x20, 0x6a, 0xe6, 0x72, 0x60, 0xe2, 0x62, 0xa5, 0xf5, 0x6d,
+    0xbf, 0x6c, 0x84, 0x7f, 0xad, 0x4e, 0x2c, 0x80, 0x4e, 0xf3, 0x32, 0xe6,
+    0xc3, 0xe9, 0x49, 0x06, 0xb6, 0x69, 0xc6, 0x4f, 0x8e, 0x04, 0x3d, 0xf3,
+    0x29, 0x36, 0x5e, 0x73, 0x7c, 0xcc, 0x96, 0x2a, 0x15, 0x51, 0x67, 0x85,
+    0x8d, 0x89, 0xfa, 0x7c, 0x84, 0x39, 0x80, 0x5b, 0x3b, 0x52, 0x54, 0x6f,
+    0x57, 0x69, 0xb9, 0xb6, 0x37, 0xf4, 0x70, 0x07, 0x22, 0xe7, 0xc7, 0xdb,
+    0x78, 0x7b, 0xc2, 0x73, 0x2c, 0xb1, 0x17, 0xf1, 0x1b, 0xe7, 0x3f, 0x7e,
+    0xb7, 0xfc, 0x47, 0x9e, 0x41, 0x17, 0x28, 0xed, 0x3a, 0xc6, 0xf7, 0xbf,
+    0xe7, 0x82, 0x0f, 0xf6, 0x4a, 0x2e, 0x00, 0x41, 0xba, 0xb7, 0x28, 0x5b,
+    0x7b, 0xad, 0xda, 0x4e, 0xb7, 0x25, 0x0c, 0xb5, 0x0a, 0x6e, 0x5c, 0x8b,
+    0xb2, 0xc6, 0xe1, 0xe3, 0x10, 0x5c, 0xb2, 0x04, 0x2b, 0x7f, 0x9e, 0x2d,
+    0xf3, 0xf3, 0x03, 0x87, 0x86, 0x96, 0xdd, 0x61, 0x38, 0xed, 0x77, 0xcc,
+    0x35, 0x60, 0xfb, 0x64, 0xa6, 0x0d, 0x1f, 0x69, 0x6d, 0x39, 0xb4, 0x01,
+    0xb0, 0x9f, 0xf7, 0x2f, 0xd0, 0x9d, 0x7f, 0x0a, 0xeb, 0x69, 0xe0, 0x4c,
+    0xa8, 0xdd, 0x27, 0x15, 0x9d, 0xed, 0x0b, 0x57, 0xea, 0x96, 0x03, 0x26,
+    0xd2, 0x2b, 0xa2, 0x90, 0xf6, 0x36, 0xf0, 0x0c, 0x4b, 0x00, 0x06, 0x72,
+    0xb7, 0xa6, 0x02, 0x17, 0xf8, 0x91, 0x63, 0xa4, 0x80, 0x3d, 0x37, 0xdf,
+    0x78, 0x33, 0x21, 0xe4, 0xd5, 0x2a, 0x20, 0x4b, 0x7d, 0x7b, 0xe6, 0x02,
+    0x0f, 0xf5, 0x80, 0x2c, 0xfe, 0x66, 0x89, 0xe2, 0x69, 0x59, 0x9b, 0xef,
+    0xed, 0xe7, 0x27, 0x91, 0xf6, 0x93, 0xf6, 0x54, 0xa0, 0x11, 0x4b, 0x5b,
+    0xe5, 0x30, 0x10, 0xbf, 0xea, 0xbe, 0xd8, 0x37, 0xf5, 0x62, 0x6d, 0xbe,
+    0x0d, 0xd8, 0xfa, 0x7f, 0xb8, 0x00, 0x77, 0xef, 0x9e, 0x69, 0x47, 0xa3,
+    0xb8, 0xf3, 0xc8, 0x32, 0x87, 0xe9, 0x52, 0x2b, 0x73, 0xce, 0x6e, 0x26,
+    0x45, 0x08, 0x2d, 0xb8, 0xf2, 0xa2, 0x23, 0x7e, 0xbf, 0x1f, 0x9b, 0x73,
+    0x53, 0x60, 0x4c, 0x29, 0x46, 0x52, 0xdb, 0xa4, 0x00, 0xa4, 0x8b, 0x9f,
+    0x7e, 0x05, 0x88, 0x9a, 0xe9, 0x46, 0x51, 0x5f, 0x4f, 0x73, 0x37, 0xcc,
+    0xf9, 0xfa, 0x85, 0xa9, 0xe3, 0x9b, 0xe7, 0x22, 0xe0, 0x01, 0xf6, 0x8a,
+    0x8f, 0xd0, 0x9b, 0x78, 0xc4, 0x2c, 0x04, 0x68, 0x53, 0x7b, 0x5a, 0xa4,
+    0x52, 0x0e, 0x4d, 0x30, 0x05, 0x7c, 0xae, 0x9e, 0x1d, 0x60, 0xd0, 0xb6,
+    0xf2, 0x72, 0x82, 0x17, 0xfd, 0x57, 0x5c, 0x81, 0xb7, 0x4c, 0x29, 0xb0,
+    0x85, 0xec, 0x2b, 0xc6, 0x46, 0xf3, 0x80, 0x14, 0xf0, 0xf0, 0x07, 0x3f,
+    0x4e, 0x7d, 0xb1, 0xd0, 0x27, 0x7a, 0x7e, 0x2b, 0xa5, 0x2e, 0x15, 0x29,
+    0xd5, 0xb2, 0xfc, 0x3e, 0x00, 0x3a, 0xf7, 0xbb, 0x64, 0x41, 0xdd, 0x3a,
+    0x2e, 0x21, 0xc7, 0x16, 0xaa, 0x17, 0x55, 0xbe, 0xac, 0x00, 0xab, 0xa7,
+    0x7c, 0x80, 0x57, 0xbd, 0xbf, 0x68, 0x11, 0xf9, 0xd0, 0xfc, 0x29, 0x00,
+    0x8a, 0x34, 0x92, 0xdf, 0x37, 0x00, 0x75, 0xed, 0xee, 0x00, 0xfb, 0xdb,
+    0x33, 0xa8, 0x47, 0xed, 0xf6, 0x2e, 0x87, 0x1d, 0x31, 0xce, 0x88, 0x54,
+    0x29, 0xbd, 0x47, 0x3e, 0x0b, 0x15, 0x33, 0x4c, 0x09, 0x2e, 0xa5, 0xbe,
+    0x2d, 0xbe, 0x6a, 0xc2, 0xd0, 0x25, 0xbf, 0x9b, 0x57, 0x66, 0xf0, 0x63,
+    0xb2, 0x05, 0x0f, 0x0b, 0x6d, 0x2f, 0x2e, 0xd0, 0x29, 0xb6, 0x88, 0xdd,
+    0xeb, 0x80, 0x09, 0xec, 0x2c, 0x07, 0xb6, 0x4f, 0x16, 0x8e, 0x12, 0x08,
+    0x3f, 0xd8, 0x00, 0xfb, 0x39, 0x4a, 0x3d, 0x60, 0x8e, 0x64, 0xd7, 0x14,
+    0xb0, 0xed, 0x2e, 0x5b, 0x43, 0x28, 0xe6, 0xdc, 0xc5, 0x80, 0x53, 0x4c,
+    0x94, 0xb4, 0x6f, 0x29, 0x1b, 0x9b, 0x7e, 0xa4, 0xe3, 0x32, 0xd4, 0x8b,
+    0x78, 0x8f, 0x4e, 0x4d, 0x01, 0xc2, 0x98, 0x6a, 0x0d, 0x2c, 0xf0, 0xc5,
+    0x6f, 0x68, 0x22, 0xf6, 0x23, 0xe9, 0x05, 0x5e, 0xf2, 0x8e, 0xab, 0xd6,
+    0xba, 0x2c, 0x0f, 0x85, 0x4b, 0x0a, 0x94, 0x28, 0x7b, 0x69, 0x00, 0x5e,
+    0x4f, 0x00, 0x6a, 0x00, 0xe3, 0xdb, 0xb1, 0x79, 0xb4, 0x73, 0x85, 0x93,
+    0xd7, 0x8e, 0x7b, 0x3f, 0x2a, 0x6c, 0x40, 0x1c, 0x51, 0x8d, 0xfa, 0x34,
+    0x01, 0x0f, 0xdf, 0x5f, 0x44, 0x89, 0xcc, 0x90, 0xbb, 0x43, 0xde, 0xf2,
+    0xc7, 0xdf, 0x5a, 0xd4, 0x2c, 0xae, 0x34, 0xbf, 0x06, 0xd9, 0xe5, 0xbb,
+    0x4b, 0x6f, 0xf2, 0x77, 0x29, 0xc4, 0x85, 0xb6, 0x7e, 0xe2, 0xd8, 0x8d,
+    0xfa, 0xc8, 0x00, 0x9c, 0x01, 0xc8, 0xbd, 0xd8, 0x1d, 0x1d, 0x90, 0x98,
+    0x12, 0xd9, 0x40, 0x08, 0x7f, 0xfa, 0x46, 0x11, 0x49, 0xe2, 0x64, 0x2a,
+    0x79, 0x98, 0xb4, 0xab, 0x4a, 0x8d, 0x98, 0x9e, 0x25, 0xb4, 0xf6, 0x5d,
+    0xba, 0x55, 0x3d, 0xbf, 0x9b, 0x80, 0x3b, 0xf8, 0x70, 0x02, 0xf2, 0x30,
+    0x03, 0xbb, 0xde, 0xad, 0xa5, 0x66, 0x80, 0x1e, 0x4e, 0x26, 0xbb, 0x50,
+    0xba, 0x7e, 0xd4, 0x48, 0x58, 0x4b, 0x79, 0xa2, 0x27, 0x0f, 0xf7, 0xeb,
+    0x48, 0xfd, 0x5a, 0x32, 0xc4, 0xeb, 0x72, 0x2c, 0x38, 0xed, 0xb5, 0x61,
+    0x0a, 0x37, 0xe9, 0x7f, 0x9d, 0xbf, 0x5f, 0xef, 0xb8, 0xbd, 0xf5, 0xed,
+    0xf6, 0xc8, 0x15, 0x87, 0x48, 0x14, 0xdf, 0x9f, 0x80, 0x1e, 0xf5, 0xa0,
+    0x05, 0x14, 0x8d, 0xec, 0x2c, 0xe2, 0xe3, 0xed, 0xc1, 0x0e, 0x79, 0x47,
+    0x13, 0x0b, 0xa9, 0xe0, 0x5a, 0xb4, 0x8b, 0xa4, 0xe3, 0x4e, 0x0a, 0x4b,
+    0x63, 0x3e, 0x7f, 0x0a, 0x4a, 0xa7, 0x37, 0xcd, 0xfb, 0xb9, 0xc2, 0xdd,
+    0xc6, 0xeb, 0xec, 0x1b, 0x92, 0x59, 0xfb, 0x39, 0xbe, 0x96, 0x00, 0xfc,
+    0x5e, 0x09, 0xf7, 0x13, 0x38, 0xe8, 0x6a, 0x68, 0x05, 0x44, 0xcc, 0x7d,
+    0x01, 0x5e, 0xd2, 0x8e, 0x1a, 0xad, 0xf3, 0x5f, 0xee, 0x7b, 0x7d, 0x44,
+    0x5d, 0x15, 0x62, 0x25, 0x9b, 0xa1, 0x86, 0x14, 0x6f, 0x89, 0x41, 0x25,
+    0x56, 0xfb, 0x57, 0xf0, 0x8b, 0x84, 0x5f, 0xbf, 0x7b, 0xc6, 0x8c, 0x47,
+    0x64, 0x87, 0x3a, 0x21, 0x54, 0x7d, 0x3d, 0xb8, 0x7b, 0x78, 0x05, 0xa4,
+    0xc9, 0xa1, 0x91, 0x1a, 0x1f, 0xa4, 0xfa, 0x52, 0xb7, 0xe4, 0x88, 0x00,
+    0x15, 0x0a, 0x16, 0x96, 0xac, 0x55, 0x7d, 0x7e, 0x99, 0x86, 0xd2, 0xce,
+    0xb0, 0x6d, 0x09, 0x6f, 0x19, 0xe7, 0x3d, 0xac, 0x8e, 0x7e, 0xd5, 0x36,
+    0x9f, 0x86, 0xd5, 0x0b, 0x6f, 0x60, 0x00, 0xe8, 0x8b, 0x08, 0xc8, 0xfd,
+    0x99, 0xa5, 0x96, 0xeb, 0x26, 0x45, 0x0b, 0xaa, 0x73, 0x7c, 0x9f, 0xda,
+    0xd0, 0x06, 0xdf, 0x42, 0x27, 0x62, 0xc0, 0x45, 0xe6, 0xfb, 0x56, 0x0c,
+    0x26, 0x4b, 0x0a, 0x2d, 0xa7, 0x93, 0x27, 0x42, 0x16, 0x0f, 0x53, 0x69,
+    0xd0, 0x69, 0xc5, 0xb7, 0x3d, 0xb2, 0x4c, 0x58, 0xdf, 0x24, 0x01, 0xf9,
+    0x3b, 0xa1, 0x04, 0x6e, 0xc4, 0xfc, 0x6a, 0x5b, 0x3c, 0xe3, 0xb7, 0x83,
+    0x43, 0xe0, 0x65, 0xb0, 0xab, 0x65, 0x46, 0xfd, 0x38, 0x00, 0x8c, 0x8a,
+    0x08, 0x3f, 0xcc, 0x00, 0xfc, 0x8e, 0xf0, 0x0b, 0x34, 0x11, 0xc0, 0x13,
+    0x8f, 0x20, 0x31, 0x0a, 0x53, 0xb4, 0x7e, 0x9f, 0xe8, 0xde, 0x0f, 0xfb,
+    0xcd, 0x00, 0x4a, 0x47, 0xd7, 0x79, 0x41, 0xf8, 0x01, 0x66, 0x49, 0x6e,
+    0xd3, 0xc0, 0x72, 0x19, 0x09, 0x2d, 0xef, 0xdd, 0x1d, 0x04, 0xbe, 0x19,
+    0x80, 0x2b, 0xc7, 0x07, 0x6a, 0x0e, 0x45, 0x43, 0x9b, 0xd6, 0xe3, 0x6f,
+    0x39, 0x15, 0x60, 0xca, 0x6c, 0xab, 0x47, 0x37, 0x6c, 0xa6, 0xd6, 0x00,
+    0x00, 0x01, 0x05, 0x43, 0xf9, 0x7d, 0x74, 0xbc, 0x58, 0xed, 0x01, 0x5e,
+    0xd0, 0x82, 0x99, 0x05, 0xde, 0x29, 0x32, 0x84, 0xea, 0x9f, 0x46, 0x37,
+    0x4e, 0x3e, 0x5b, 0x4c, 0xb6, 0x0e, 0x68, 0x2b, 0xdd, 0xc6, 0x95, 0x92,
+    0xc5, 0x4d, 0xf0, 0x6e, 0x02, 0x9b, 0xc7, 0xc5, 0xd3, 0xa3, 0x7c, 0xf1,
+    0x6e, 0xbb, 0x25, 0x90, 0x22, 0x69, 0xb2, 0x21, 0x46, 0xb3, 0x0b, 0xe7,
+    0x9a, 0xfd, 0x76, 0x5a, 0xa6, 0xcf, 0x38, 0x8e, 0x9b, 0xa7, 0x19, 0x50,
+    0xc8, 0xdd, 0x93, 0x43, 0x9e, 0x1e, 0xed, 0xb1, 0x66, 0x07, 0x2a, 0xa5,
+    0x6d, 0xbb, 0x45, 0xba, 0x7d, 0x44, 0xce, 0x3b, 0xd2, 0xe5, 0x9d, 0x47,
+    0xd7, 0x75, 0x77, 0x89, 0x15, 0x0f, 0x02, 0x75, 0xb9, 0x4d, 0x27, 0x45,
+    0x3d, 0xb7, 0x2e, 0xa8, 0x1c, 0xdf, 0x96, 0xda, 0x6d, 0x88, 0xde, 0xcd,
+    0xdc, 0x80, 0x1f, 0xf2, 0xfc, 0x92, 0x41, 0xf5, 0xf1, 0x02, 0xe0, 0xda,
+    0x84, 0x36, 0xf2, 0xdc, 0x97, 0xc7, 0x04, 0x8b, 0x1b, 0x03, 0x9d, 0x05,
+    0x7b, 0xf4, 0x6d, 0x9e, 0x18, 0x85, 0xb4, 0x5a, 0x38, 0x86, 0xdc, 0xd4,
+    0xa9, 0x1b, 0xeb, 0x67, 0x37, 0xfd, 0xd6, 0x3b, 0xb7, 0xe4, 0x2c, 0xcc,
+    0xd7, 0x98, 0x8f, 0xb2, 0x15, 0x0b, 0x44, 0x54, 0x6f, 0x1a, 0x08, 0x60,
+    0x0d, 0x55, 0xbb, 0x02, 0x2a, 0xe5, 0xf2, 0xf4, 0x36, 0xd4, 0x6e, 0x56,
+    0xc3, 0x1d, 0x29, 0x2f, 0x25, 0x6f, 0x42, 0x50, 0xea, 0xa4, 0x36, 0xd8,
+    0x7b, 0x7b, 0xc4, 0x82, 0x17, 0xfa, 0xd7, 0xe4, 0x40, 0xb4, 0x46, 0xb4,
+    0x8d, 0xd6, 0xf5, 0xa6, 0xbe, 0xd1, 0x85, 0x41, 0xed, 0xe8, 0x2a, 0xe5,
+    0xe7, 0x49, 0x76, 0xda, 0xde, 0x66, 0x54, 0x73, 0xac, 0xbe, 0x3a, 0x89,
+    0xe2, 0x39, 0xae, 0x87, 0x69, 0xed, 0x27, 0x37, 0xb4, 0x45, 0x00, 0x3e,
+    0x84, 0x5e, 0x57, 0x01, 0x20, 0x00, 0xf9, 0x99, 0x38, 0x9e, 0x0a, 0x5c,
+    0x21, 0x37, 0x9b, 0x81, 0xcd, 0xdb, 0xe9, 0xf3, 0xfd, 0xc7, 0x1e, 0x72,
+    0x51, 0xb2, 0x58, 0xdc, 0x22, 0x63, 0x72, 0x8d, 0xac, 0xce, 0x6f, 0xd2,
+    0x11, 0xb8, 0x04, 0x1f, 0xed, 0xc1, 0x1d, 0xca, 0x13, 0xe7, 0xbb, 0x56,
+    0x0c, 0x19, 0x31, 0xaf, 0xc5, 0x00, 0x74, 0xf2, 0x31, 0x88, 0x1b, 0x37,
+    0xbf, 0x3b, 0x76, 0x1e, 0x03, 0x88, 0x52, 0xa3, 0x72, 0xf9, 0x40, 0x07,
+    0x3b, 0xf1, 0x99, 0x60, 0x4c, 0x32, 0xdb, 0x28, 0x4a, 0xa9, 0x2e, 0x35,
+    0x9c, 0x60, 0x20, 0x80, 0x9f, 0x5e, 0xd2, 0xcf, 0x1e, 0x05, 0xc5, 0xf0,
+    0xbc, 0x92, 0x1b, 0x53, 0xdb, 0xaa, 0xad, 0x45, 0x21, 0xab, 0x7b, 0xf7,
+    0x99, 0xcf, 0x1b, 0x0c, 0xca, 0x39, 0x3d, 0xb5, 0xd3, 0x28, 0xca, 0x76,
+    0xd2, 0xe9, 0x66, 0x36, 0x57, 0x99, 0xf1, 0xcd, 0xbe, 0x55, 0x3f, 0x69,
+    0x66, 0xc1, 0xaa, 0x3e, 0x01, 0xcd, 0xe8, 0xfa, 0x7e, 0x80, 0x33, 0xc2,
+    0x7c, 0xf3, 0x0a, 0xe1, 0xd6, 0x63, 0xa8, 0x0a, 0xe4, 0xb6, 0x94, 0x10,
+    0x18, 0xd9, 0x79, 0xdb, 0xf4, 0xa2, 0x75, 0xf4, 0x2a, 0x7c, 0x9b, 0x84,
+    0x38, 0x8a, 0xda, 0x35, 0xe7, 0xe4, 0xca, 0x4a, 0x6f, 0x85, 0xd0, 0x21,
+    0x7f, 0xd3, 0xd7, 0x77, 0xc2, 0x18, 0xb7, 0xc2, 0xd6, 0xfa, 0xef, 0xd2,
+    0xcf, 0xf8, 0x8d, 0x45, 0x01, 0x14, 0xb2, 0xc8, 0x34, 0x63, 0x7c, 0x75,
+    0x17, 0x72, 0x12, 0xa2, 0x92, 0x0e, 0x6e, 0x8d, 0x90, 0x5f, 0x3a, 0xed,
+    0x30, 0x2a, 0x3e, 0x36, 0x1a, 0x1d, 0x1b, 0x7e, 0x40, 0xc7, 0x56, 0xfa,
+    0x46, 0xee, 0xd8, 0x08, 0x20, 0x27, 0x40, 0x1c, 0x79, 0x4a, 0x17, 0xd6,
+    0x3e, 0xda, 0x17, 0x36, 0x55, 0xa1, 0x4d, 0xec, 0x85, 0xcd, 0xf7, 0x17,
+    0xbc, 0x10, 0x2d, 0x2f, 0x6d, 0x0f, 0xc7, 0x9a, 0xf1, 0x87, 0x06, 0x50,
+    0x96, 0xf0, 0xfd, 0x02, 0x10, 0x06, 0x8a, 0xe8, 0x41, 0x0b, 0x63, 0xf7,
+    0x3c, 0x26, 0xd6, 0xf7, 0x3f, 0xcd, 0x84, 0x7d, 0x12, 0x84, 0x3b, 0x57,
+    0xc4, 0x7f, 0xab, 0x71, 0x4c, 0x00, 0xab, 0x76, 0x5f, 0x57, 0xa5, 0xcf,
+    0x16, 0xe4, 0xb8, 0x40, 0xd7, 0x80, 0x0c, 0x6a, 0xb7, 0xe7, 0xb5, 0xd5,
+    0xd7, 0x8e, 0x28, 0xc4, 0x57, 0xc9, 0x4e, 0xb4, 0xba, 0x5d, 0x6f, 0xa0,
+    0xe6, 0x0b, 0xff, 0x8a, 0x17, 0x79, 0xf2, 0x59, 0x2c, 0x37, 0x3a, 0xe6,
+    0xba, 0x18, 0x7c, 0x2e, 0x01, 0xed, 0xe5, 0xba, 0xe4, 0x00, 0xe3, 0xa1,
+    0x7d, 0x3e, 0xd8, 0x3c, 0xed, 0xb2, 0x85, 0x18, 0x5b, 0x7a, 0x3c, 0x73,
+    0xc1, 0x03, 0xf3, 0x39, 0xe2, 0xd9, 0x88, 0x71, 0x3b, 0xbe, 0x3c, 0xe9,
+    0x67, 0xc0, 0xe2, 0xe0, 0x14, 0xd9, 0x77, 0x41, 0x08, 0x01, 0xab, 0xe2,
+    0x10, 0x9b, 0x91, 0xe0, 0x67, 0x89, 0x72, 0xb7, 0xe4, 0x7e, 0x3a, 0x00,
+    0xb3, 0x5d, 0x85, 0xd9, 0x6c, 0x52, 0x8b, 0xbe, 0xb0, 0x08, 0x6e, 0x98,
+    0x03, 0xed, 0x78, 0x03, 0xf1, 0x66, 0x3b, 0x8c, 0x83, 0x97, 0x30, 0x9a,
+    0x5a, 0x40, 0xe9, 0x6c, 0x3e, 0x86, 0xb7, 0xe9, 0x10, 0x40, 0xfd, 0x40,
+    0x07, 0x3d, 0xf0, 0x00, 0xf3, 0x8f, 0x61, 0x5a, 0xec, 0x85, 0xf2, 0xff,
+    0x24, 0x29, 0xc6, 0x87, 0x7e, 0x83, 0x24, 0x6d, 0x60, 0x04, 0xa0, 0x0e,
+    0x7d, 0xfa, 0x17, 0xb8, 0xf9, 0xe5, 0x92, 0x4c, 0x97, 0xcd, 0xf9, 0x13,
+    0x6d, 0x32, 0x1c, 0xdd, 0x9f, 0x27, 0xad, 0x50, 0xb6, 0xea, 0x16, 0x7c,
+    0xb5, 0x5b, 0xfc, 0xda, 0x00, 0xf3, 0xe3, 0xbe, 0x39, 0xf2, 0xe1, 0xef,
+    0xe4, 0xb5, 0xcc, 0x78, 0x01, 0xf3, 0x88, 0x3b, 0xe5, 0x09, 0xf2, 0x42,
+    0xac, 0x4b, 0x54, 0x7d, 0xad, 0xd4, 0xe2, 0xec, 0x15, 0xb8, 0x64, 0x08,
+    0xb9, 0xb4, 0xf1, 0x9e, 0x10, 0x2d, 0xbe, 0xb6, 0x00, 0x8f, 0xa8, 0x00,
+    0xc0, 0x01, 0x16, 0xef, 0x3c, 0xf2, 0x85, 0xf9, 0x63, 0xc4, 0x8b, 0x72,
+    0x53, 0x43, 0xcb, 0x5c, 0x52, 0x4b, 0x6e, 0x04, 0x0f, 0xd3, 0x00, 0xb3,
+    0x28, 0xbe, 0xdf, 0x75, 0xf2, 0x1d, 0x15, 0x6c, 0x8d, 0xbb, 0xe5, 0xba,
+    0xb7, 0xd6, 0x42, 0x98, 0xee, 0x79, 0x6c, 0xb6, 0x37, 0xf8, 0xdd, 0xd8,
+    0x00, 0x26, 0x5a, 0x09, 0x80, 0x06, 0xe9, 0x67, 0xab, 0x7d, 0x14, 0x10,
+    0x3f, 0x38, 0x8c, 0x08, 0x3f, 0xae, 0x00, 0xf3, 0x04, 0x08, 0x23, 0xf0,
+    0x84, 0xd3, 0x3e, 0x5f, 0xb2, 0x10, 0x38, 0x42, 0x7d, 0x85, 0x86, 0xb8,
+    0x6b, 0x7e, 0xaa, 0x00, 0x27, 0x00, 0x7e, 0x2c, 0x01, 0xc8, 0x03, 0xb7,
+    0x82, 0x10, 0x03, 0x3f, 0x6a, 0x4c, 0xeb, 0xae, 0xa9, 0x50, 0xcb, 0x4d,
+    0xda, 0x81, 0x2d, 0xed, 0xb0, 0x3a, 0xd5, 0x6e, 0x9d, 0x2e, 0xb6, 0xda,
+    0x5d, 0xa8, 0xde, 0x62, 0x28, 0x9e, 0x48, 0xbf, 0x71, 0x62, 0xc4, 0xf7,
+    0xa0, 0x3d, 0xde, 0x5e, 0xfb, 0x74, 0x74, 0x85, 0x0e, 0x92, 0x23, 0x74,
+    0xdb, 0x2e, 0x16, 0xc7, 0x22, 0x36, 0xcd, 0xab, 0x61, 0xd3, 0xcb, 0x69,
+    0x21, 0xa7, 0x54, 0x83, 0xd5, 0x95, 0xb1, 0xe0, 0x21, 0x00, 0x35, 0xd6,
+    0xc0, 0xe8, 0x00, 0x6f, 0x65, 0x9e, 0xb9, 0x24, 0x66, 0xc3, 0x70, 0x53,
+    0xa8, 0x03, 0x0f, 0x7f, 0xaf, 0x5b, 0x1c, 0x5c, 0x57, 0xd2, 0x03, 0xec,
+    0x93, 0x24, 0x2e, 0xa8, 0xe3, 0x83, 0x1b, 0xe6, 0xe6, 0x91, 0x1e, 0x44,
+    0xfb, 0x80, 0x5a, 0xf1, 0x24, 0xd7, 0x16, 0xfa, 0xf9, 0x03, 0x89, 0x96,
+    0x19, 0xb3, 0x03, 0x0a, 0x19, 0x1b, 0xed, 0x0a, 0x1d, 0x69, 0x21, 0xbf,
+    0x18, 0xbd, 0xc0, 0x06, 0x8f, 0xf8, 0x7c, 0xa1, 0xab, 0x3e, 0x28, 0xa4,
+    0x04, 0xb0, 0x03, 0x31, 0x47, 0x8e, 0x6f, 0x2e, 0x50, 0x03, 0xea, 0x92,
+    0x78, 0xd2, 0xc9, 0x4d, 0xc9, 0x00, 0xc6, 0xa3, 0x7e, 0x9b, 0xfe, 0x2b,
+    0x3b, 0xeb, 0x8b, 0xbd, 0xc1, 0xd7, 0x31, 0xcf, 0xd8, 0x62, 0x15, 0x2a,
+    0x1c, 0x7b, 0x75, 0xb2, 0x76, 0x45, 0x17, 0xed, 0xbf, 0xee, 0x2e, 0x96,
+    0x99, 0x8f, 0xd2, 0xe2, 0x42, 0xc7, 0x0d, 0x6e, 0x01, 0x13, 0x1c, 0x00,
+    0xa4, 0x4f, 0xb7, 0x6e, 0xd8, 0x38, 0x02, 0x9d, 0xe1, 0x66, 0xd3, 0xd5,
+    0x20, 0xd6, 0xfa, 0x8c, 0x17, 0x80, 0x0f, 0x38, 0x9f, 0x8c, 0xa9, 0x15,
+    0x4d, 0xc9, 0x25, 0x1a, 0x31, 0x54, 0xa6, 0xf3, 0x9e, 0x9c, 0xcd, 0x58,
+    0xa3, 0x91, 0x51, 0x28, 0x5b, 0x72, 0xd2, 0xe5, 0x95, 0xbc, 0x00, 0x0e,
+    0x7e, 0xef, 0x23, 0x47, 0xe3, 0xf5, 0xce, 0x2a, 0x13, 0xc3, 0xd5, 0x14,
+    0x04, 0x45, 0x29, 0x29, 0xbe, 0x72, 0x00, 0xf7, 0x0d, 0x17, 0xed, 0xc7,
+    0x7c, 0x00, 0xaa, 0x4e, 0x35, 0xea, 0xf2, 0xc7, 0x42, 0xa9, 0x47, 0x9e,
+    0xde, 0xf3, 0x3a, 0x7f, 0x3b, 0xcb, 0xd3, 0x06, 0x5c, 0x26, 0x96, 0xa3,
+    0x0b, 0x43, 0xda, 0xae, 0xa7, 0xbf, 0x31, 0x34, 0xc4, 0x1b, 0x38, 0xbc,
+    0x42, 0xae, 0xd0, 0xc5, 0x6e, 0xbd, 0xbb, 0xb2, 0xe1, 0xb4, 0x34, 0xc4,
+    0x56, 0xa5, 0xa8, 0x8a, 0xdf, 0x40, 0x8d, 0x39, 0xfe, 0xf1, 0xcc, 0x94,
+    0x68, 0x79, 0x99, 0xdd, 0x8e, 0x8a, 0x5a, 0xab, 0xa8, 0xd5, 0x29, 0xb9,
+    0xc0, 0x0e, 0x05, 0x80, 0x19, 0x73, 0x3a, 0x31, 0x00, 0x25, 0x8f, 0xda,
+    0x4c, 0x94, 0x38, 0xed, 0xf5, 0x6e, 0x48, 0x8e, 0x9f, 0xf1, 0xcb, 0xb7,
+    0xad, 0xb4, 0x05, 0x7c, 0xc2, 0x60, 0xdf, 0x06, 0xf9, 0x71, 0xa0, 0x02,
+    0x6d, 0x15, 0xaf, 0xb2, 0x0c, 0x86, 0xf1, 0xb2, 0xdf, 0x46, 0xc7, 0xb7,
+    0x9a, 0x2c, 0xcb, 0xe9, 0x30, 0xa8, 0xa0, 0x53, 0x25, 0x31, 0xf5, 0x51,
+    0x80, 0x00, 0x00, 0x01, 0x06, 0x43, 0xf8, 0xce, 0x95, 0xb6, 0x28, 0x43,
+    0x6a, 0xca, 0xf1, 0x3b, 0x30, 0xc4, 0x1c, 0x79, 0x7e, 0x81, 0x8d, 0x9b,
+    0x67, 0x9f, 0x09, 0x81, 0x4d, 0xd8, 0x13, 0x08, 0x2e, 0x3f, 0xc5, 0x5b,
+    0xc6, 0x45, 0x6f, 0x08, 0x73, 0x68, 0x2b, 0x2b, 0xa4, 0xcc, 0xf1, 0xa3,
+    0x47, 0x35, 0x3d, 0x3a, 0x3b, 0xad, 0x4b, 0x24, 0x1b, 0x55, 0xb6, 0x5d,
+    0x00, 0xb2, 0xda, 0xb0, 0x31, 0x25, 0x2d, 0xb9, 0xe4, 0xdc, 0x6c, 0x49,
+    0x92, 0x44, 0x65, 0x92, 0x45, 0xad, 0xf7, 0xb4, 0x10, 0xbf, 0xc8, 0x67,
+    0xa3, 0x07, 0xf6, 0x40, 0x10, 0x23, 0x97, 0x58, 0x1b, 0x23, 0xbc, 0xd6,
+    0xc0, 0x08, 0xd1, 0xba, 0xcf, 0x04, 0x2f, 0xf1, 0x36, 0x12, 0x9b, 0xc0,
+    0x7b, 0x60, 0x21, 0x80, 0x53, 0xa0, 0x5a, 0x3b, 0x32, 0x97, 0xe1, 0x4b,
+    0x6e, 0x95, 0x58, 0x50, 0x00, 0xd5, 0xac, 0xf6, 0xf6, 0x91, 0x64, 0x23,
+    0x76, 0x9b, 0x9e, 0x2a, 0x8a, 0xd5, 0xa8, 0x01, 0xee, 0x3b, 0x24, 0xf5,
+    0xa7, 0x85, 0x37, 0xab, 0xea, 0xdc, 0x76, 0xba, 0xa8, 0x4c, 0xaa, 0x93,
+    0xc4, 0x63, 0x78, 0xc4, 0xbb, 0xce, 0x52, 0x87, 0x52, 0xa4, 0x54, 0x09,
+    0x6d, 0x00, 0x4a, 0xe5, 0xf5, 0x46, 0xb1, 0xad, 0xfa, 0xd8, 0x1c, 0x68,
+    0x16, 0xde, 0x33, 0x01, 0x08, 0x02, 0xbb, 0x76, 0x6a, 0xf8, 0xe4, 0x01,
+    0xf3, 0x7a, 0x23, 0x29, 0x3b, 0x81, 0x66, 0xba, 0x86, 0xce, 0x5c, 0x74,
+    0x3c, 0xf0, 0xc6, 0xf9, 0xe7, 0x40, 0x84, 0x00, 0xce, 0x10, 0x58, 0x5e,
+    0xcd, 0xc5, 0xa3, 0x8b, 0x4a, 0x31, 0x87, 0x01, 0x8c, 0x9b, 0x48, 0x4d,
+    0x67, 0xc6, 0xfa, 0xc7, 0x48, 0xd5, 0xd2, 0xa4, 0x6d, 0x52, 0x99, 0x24,
+    0xbe, 0xa8, 0x8d, 0xd7, 0x12, 0xe7, 0xff, 0x5c, 0xee, 0x2e, 0x69, 0xf7,
+    0xc9, 0x7c, 0xff, 0x63, 0x0a, 0x1e, 0xc9, 0x93, 0x75, 0x22, 0x7c, 0xd7,
+    0x1e, 0x80, 0x12, 0x4b, 0xbc, 0xdd, 0xa7, 0x7e, 0x8e, 0x28, 0xf3, 0xca,
+    0x6c, 0xef, 0xbe, 0x77, 0x99, 0x28, 0x51, 0x93, 0x64, 0x90, 0x05, 0x45,
+    0x97, 0x02, 0x9b, 0xb0, 0x4e, 0x00, 0x34, 0x73, 0xfc, 0x94, 0xe5, 0xa8,
+    0xe0, 0x17, 0xb5, 0x0e, 0x5b, 0x2b, 0xec, 0xa7, 0x9d, 0x31, 0xdd, 0x87,
+    0xc3, 0xc7, 0xea, 0x7a, 0xb6, 0xa7, 0xab, 0x7a, 0x64, 0xd3, 0x63, 0x79,
+    0x72, 0x80, 0x1b, 0xde, 0x72, 0xcc, 0x87, 0xad, 0xcd, 0xe5, 0x66, 0x05,
+    0xdc, 0x90, 0x86, 0xde, 0x9d, 0xdb, 0x7d, 0x85, 0x09, 0x36, 0x4a, 0x04,
+    0xdc, 0xe7, 0x79, 0x76, 0xda, 0x79, 0xfa, 0xf2, 0xe7, 0xa2, 0xb7, 0x0b,
+    0x8b, 0x7e, 0xbb, 0x5d, 0xda, 0x2c, 0xa6, 0xe4, 0x20, 0x3d, 0xe5, 0x24,
+    0x2e, 0xaa, 0x01, 0x07, 0x8c, 0x69, 0xa8, 0x2f, 0x45, 0x53, 0x29, 0xd4,
+    0x3a, 0x8a, 0x7b, 0xc8, 0x45, 0x07, 0xd0, 0xa2, 0x9b, 0x43, 0x9a, 0x69,
+    0x73, 0x1b, 0xaa, 0x55, 0x8a, 0x80, 0x11, 0x28, 0x0b, 0x9b, 0x4c, 0x03,
+    0x2f, 0x88, 0x9e, 0x38, 0x57, 0x83, 0x63, 0xdf, 0xca, 0xc2, 0x5d, 0x95,
+    0xba, 0xbc, 0x82, 0x10, 0x05, 0x3e, 0x44, 0x00, 0x87, 0x2e, 0x7a, 0x29,
+    0x71, 0xa1, 0xbb, 0x9b, 0xc9, 0xd8, 0x7d, 0xc7, 0xe5, 0x08, 0xbe, 0x52,
+    0xca, 0xdc, 0xc8, 0xbf, 0x4b, 0xef, 0x89, 0x06, 0xd2, 0xa7, 0x2b, 0x14,
+    0x24, 0xa8, 0xde, 0xc7, 0x6c, 0x8e, 0x15, 0x24, 0x2c, 0x27, 0x05, 0x80,
+    0x0c, 0x4e, 0x6c, 0x1d, 0xed, 0xe7, 0x8f, 0x3c, 0x81, 0x0b, 0xc4, 0xb4,
+    0x0a, 0x56, 0x4d, 0x34, 0x3a, 0x56, 0xfc, 0x87, 0xe3, 0xdd, 0x4c, 0xe6,
+    0xc3, 0xf3, 0x0d, 0xb8, 0x90, 0xb2, 0x91, 0x5b, 0xef, 0x8e, 0x78, 0xa0,
+    0x40, 0xfd, 0x31, 0x60, 0x0f, 0x3b, 0xd7, 0x28, 0x0f, 0x77, 0x97, 0x72,
+    0x36, 0x96, 0x57, 0x92, 0xb7, 0xc6, 0x5d, 0xef, 0x99, 0xaf, 0x7f, 0x0f,
+    0x2c, 0xbc, 0xfc, 0x29, 0xdb, 0x49, 0xa5, 0xb5, 0x5e, 0xd9, 0x9f, 0xf2,
+    0x38, 0x8e, 0x39, 0xb2, 0x06, 0x3b, 0x9e, 0x66, 0x68, 0xe0, 0xd1, 0xa1,
+    0x2c, 0x17, 0xb5, 0xbc, 0xb1, 0xb2, 0x37, 0xfd, 0x08, 0xfb, 0x71, 0xdb,
+    0xf7, 0xe0, 0x5c, 0xb1, 0x01, 0x14, 0x01, 0x39, 0x2e, 0x59, 0x65, 0xf1,
+    0x66, 0xff, 0x60, 0xb7, 0x67, 0xc7, 0xbd, 0xcc, 0x4a, 0x08, 0x80, 0x09,
+    0xb6, 0x24, 0xb5, 0x42, 0x46, 0xb7, 0xce, 0x00, 0x09, 0xb6, 0x80, 0x2d,
+    0x00, 0x75, 0xef, 0xaf, 0xa1, 0x86, 0x88, 0x73, 0xec, 0x4a, 0x14, 0x3a,
+    0x84, 0x37, 0xd0, 0xfd, 0xb2, 0xf6, 0xee, 0x6c, 0x4a, 0x02, 0xad, 0x2b,
+    0x14, 0x20, 0x73, 0x74, 0x94, 0x03, 0x46, 0xec, 0x0c, 0x6f, 0xd4, 0xdd,
+    0x27, 0xda, 0x6b, 0x3e, 0x53, 0x35, 0xb0, 0xe0, 0x05, 0x36, 0xb5, 0xd2,
+    0x93, 0xa5, 0x24, 0xb5, 0xc6, 0x51, 0xbb, 0x9d, 0x5b, 0x0e, 0x01, 0x89,
+    0x09, 0x2d, 0x44, 0x86, 0x56, 0xa7, 0x0a, 0x67, 0x19, 0x37, 0xbc, 0x9a,
+    0xd7, 0x4a, 0x5b, 0x62, 0x9f, 0x9c, 0x6d, 0x54, 0x3a, 0x56, 0x6c, 0xdb,
+    0xe2, 0xf0, 0x08, 0x40, 0x13, 0x15, 0xab, 0x00, 0x9f, 0x61, 0x25, 0xb3,
+    0x00, 0xe0, 0x9c, 0x84, 0xb6, 0xdc, 0xab, 0x76, 0x40, 0xa5, 0xcb, 0xb2,
+    0x10, 0x9a, 0x20, 0x75, 0xb0, 0x94, 0xc1, 0xd6, 0xb7, 0xdb, 0x77, 0xe6,
+    0x21, 0x2d, 0xbe, 0x20, 0x00, 0xaf, 0x8a, 0x00, 0x4d, 0x04, 0x7d, 0x39,
+    0x9b, 0x0e, 0xaa, 0xf7, 0x3a, 0xf9, 0x58, 0x30, 0x3a, 0x6d, 0x54, 0x29,
+    0xbe, 0x99, 0xf0, 0xf7, 0x7b, 0xb8, 0xde, 0x70, 0xa2, 0x8b, 0x2e, 0x85,
+    0x37, 0x75, 0xcf, 0xa4, 0x0d, 0xd7, 0x4a, 0x19, 0x6c, 0x8b, 0x15, 0xb8,
+    0xee, 0xa7, 0xb7, 0x20, 0x03, 0xe6, 0xc2, 0xd4, 0xe2, 0xd6, 0xff, 0x23,
+    0x73, 0x2a, 0x9f, 0xe0, 0xb1, 0xbe, 0x90, 0x2b, 0x8d, 0xe7, 0xad, 0xdd,
+    0xcd, 0xa0, 0x2a, 0xda, 0xb1, 0x02, 0x0a, 0xa7, 0x04, 0x2d, 0x6f, 0xa4,
+    0x80, 0x21, 0xfb, 0x80, 0x58, 0x29, 0xce, 0xaf, 0xc8, 0x54, 0x36, 0xad,
+    0x1a, 0xdb, 0x88, 0xbf, 0x5d, 0x12, 0x00, 0xf7, 0x67, 0x31, 0x3f, 0x59,
+    0x32, 0x01, 0x03, 0x6b, 0x72, 0x89, 0x70, 0x05, 0xbc, 0xc4, 0xf5, 0x87,
+    0xb6, 0x3c, 0xcf, 0x3d, 0x84, 0xb8, 0xdf, 0x24, 0x01, 0xcf, 0x1b, 0xf5,
+    0xeb, 0x70, 0x8d, 0xe7, 0x40, 0x05, 0x35, 0x2c, 0xaf, 0x74, 0x3a, 0x24,
+    0xb4, 0x7b, 0x79, 0x72, 0x2f, 0x00, 0x06, 0x9f, 0x51, 0x46, 0xe3, 0xa5,
+    0x28, 0x39, 0x1d, 0x6b, 0xed, 0x52, 0xcf, 0x48, 0x5c, 0x6f, 0x42, 0x00,
+    0xfa, 0x8a, 0xfe, 0x77, 0x66, 0x73, 0x65, 0x96, 0x13, 0x24, 0xab, 0x4b,
+    0x1f, 0x03, 0x0f, 0x6f, 0x2a, 0x08, 0x00, 0x5b, 0xf5, 0xe3, 0x91, 0x35,
+    0xfd, 0x7b, 0x29, 0xd2, 0xe5, 0xda, 0x04, 0x15, 0x9b, 0x2c, 0x0c, 0x28,
+    0x63, 0x77, 0x5a, 0x95, 0x6b, 0x69, 0xb4, 0x38, 0xda, 0x4b, 0x6f, 0x18,
+    0x03, 0x97, 0x67, 0xc8, 0x97, 0x71, 0xc7, 0xb2, 0x1c, 0x5c, 0x73, 0x89,
+    0xa8, 0x34, 0xb6, 0xf9, 0x29, 0x1f, 0x8e, 0x40, 0x1d, 0x5f, 0xa3, 0xed,
+    0xc3, 0xae, 0x5d, 0x9c, 0x3b, 0x26, 0xc8, 0x7c, 0x3c, 0xc2, 0xdb, 0xe8,
+    0x40, 0x05, 0x9e, 0xfd, 0x88, 0xfe, 0x40, 0x0a, 0xf3, 0xe2, 0x55, 0xe2,
+    0x93, 0xb8, 0xe2, 0x07, 0xbd, 0xf3, 0x4c, 0x45, 0xa1, 0x0d, 0xe7, 0x6f,
+    0x45, 0x4e, 0x84, 0x6c, 0x15, 0xaf, 0x7e, 0x57, 0x64, 0x44, 0xd8, 0xf9,
+    0xa5, 0x6e, 0x5f, 0x52, 0xdb, 0x93, 0x97, 0x5f, 0x28, 0x96, 0xc1, 0x95,
+    0x62, 0x2b, 0x48, 0xb8, 0x1c, 0x55, 0x60, 0x00, 0x00, 0x01, 0x07, 0x43,
+    0xf9, 0xef, 0xbc, 0xbd, 0xf1, 0x2e, 0xf8, 0x28, 0xda, 0x7b, 0x6b, 0xe9,
+    0xf8, 0x44, 0xed, 0xfc, 0xf3, 0xe1, 0x2d, 0x92, 0x40, 0xa6, 0xf6, 0xa0,
+    0x0f, 0xc5, 0x69, 0x17, 0xdb, 0x08, 0xe2, 0x62, 0x0d, 0x41, 0x5b, 0xd5,
+    0x93, 0x9b, 0x03, 0xaf, 0xe7, 0x16, 0x20, 0x4b, 0x5c, 0x08, 0x1f, 0x9e,
+    0x44, 0xe0, 0x01, 0x87, 0xff, 0xdf, 0xe2, 0x0a, 0xdb, 0x0a, 0xf3, 0xdb,
+    0xc6, 0xba, 0xcd, 0x87, 0x00, 0x4f, 0xc0, 0x49, 0x54, 0xa0, 0xc6, 0xf2,
+    0xec, 0xb9, 0x6b, 0x78, 0xef, 0x94, 0x3e, 0x56, 0xfe, 0x39, 0x92, 0x3b,
+    0x12, 0x4f, 0x09, 0x1b, 0x66, 0x82, 0x17, 0xfc, 0xcd, 0x6c, 0xfc, 0xca,
+    0x55, 0xb0, 0x25, 0xbd, 0x28, 0x98, 0x4f, 0x17, 0xb4, 0xb0, 0xa7, 0xbb,
+    0x10, 0x30, 0xf5, 0xb2, 0xdf, 0x4a, 0xdc, 0x96, 0x1b, 0x91, 0xb0, 0xd8,
+    0xb1, 0xbb, 0xc4, 0x69, 0x3f, 0xe7, 0x93, 0x00, 0x06, 0x90, 0xb4, 0x08,
+    0x6f, 0x99, 0x4f, 0xd4, 0x21, 0x15, 0x00, 0xa8, 0xdf, 0x53, 0x13, 0x6b,
+    0xf2, 0xcc, 0x50, 0x11, 0x66, 0x2a, 0x8d, 0x3e, 0xc0, 0x29, 0xbe, 0x64,
+    0xf2, 0xab, 0xa9, 0x2a, 0xc6, 0xde, 0xc2, 0xca, 0x21, 0xab, 0x69, 0x43,
+    0xeb, 0x7e, 0xc0, 0x52, 0x91, 0xf6, 0xe9, 0x9a, 0x03, 0xca, 0x61, 0x55,
+    0xbd, 0x30, 0x9d, 0x04, 0x1f, 0xeb, 0x22, 0x0a, 0xa0, 0x15, 0x8e, 0x88,
+    0x64, 0x35, 0x40, 0x21, 0x30, 0xb0, 0xb2, 0x9b, 0xc2, 0xcf, 0xc9, 0xab,
+    0xe1, 0x36, 0xb7, 0xd3, 0xa3, 0x9e, 0x00, 0xff, 0xb7, 0xc3, 0xc3, 0x2c,
+    0x77, 0x2e, 0x31, 0x22, 0x9c, 0x66, 0x9f, 0xe2, 0xb2, 0x36, 0xce, 0x2b,
+    0x6c, 0x80, 0x03, 0x36, 0xb3, 0x9b, 0xbc, 0x8e, 0x47, 0xe9, 0xc0, 0x0f,
+    0x40, 0x1a, 0x64, 0xf6, 0x75, 0xa1, 0xe7, 0xf0, 0x2e, 0x5e, 0xf3, 0x4e,
+    0x54, 0xb1, 0x56, 0xa1, 0x47, 0x14, 0xad, 0xf1, 0xaf, 0xfb, 0xf8, 0x14,
+    0x67, 0x13, 0x75, 0x28, 0x09, 0x40, 0x0f, 0xbc, 0xaf, 0x39, 0x07, 0x15,
+    0x12, 0x4d, 0xa3, 0xcb, 0x18, 0xde, 0xfb, 0xe0, 0xc1, 0x5e, 0xd9, 0xd3,
+    0xf6, 0x86, 0x43, 0x70, 0xf1, 0x84, 0xc2, 0x9b, 0xca, 0xce, 0x5e, 0x00,
+    0xe8, 0x50, 0x8e, 0x44, 0xbf, 0x27, 0xea, 0x4a, 0x2f, 0xcf, 0xbc, 0x83,
+    0x40, 0x71, 0xc6, 0xc8, 0x64, 0xa0, 0x2a, 0x88, 0x5b, 0x72, 0x24, 0xb8,
+    0xe5, 0xf5, 0x91, 0xaa, 0x07, 0xc8, 0xdf, 0x8e, 0xe3, 0x2b, 0x85, 0xbe,
+    0xdc, 0x1e, 0x92, 0x6c, 0x83, 0x42, 0x80, 0xb6, 0xe8, 0x80, 0x34, 0xf8,
+    0x9d, 0xf2, 0xf5, 0xf3, 0x79, 0x6a, 0x6d, 0x2e, 0xad, 0x03, 0x9b, 0x97,
+    0x92, 0x7b, 0x3b, 0xaf, 0x30, 0x08, 0x67, 0x7e, 0x7b, 0x02, 0xe1, 0xb2,
+    0xd9, 0xe1, 0x1b, 0x36, 0x6c, 0xc9, 0x69, 0x41, 0x76, 0x92, 0x9b, 0xbe,
+    0xd6, 0xde, 0xd4, 0x8d, 0xfb, 0x2e, 0x1c, 0x00, 0x6e, 0x2b, 0xcb, 0xac,
+    0x41, 0xa9, 0xb1, 0xd6, 0xca, 0x36, 0xd2, 0xcf, 0x2d, 0x91, 0x2c, 0xd7,
+    0xa9, 0x61, 0x13, 0x99, 0x7d, 0x43, 0x1b, 0x86, 0x46, 0x80, 0x16, 0xf7,
+    0x75, 0x02, 0x2b, 0xf6, 0x44, 0x1f, 0x5b, 0xd4, 0x13, 0x45, 0x3e, 0xdc,
+    0x09, 0xb8, 0xaa, 0x10, 0x74, 0x89, 0x59, 0xb7, 0x58, 0x04, 0xea, 0xda,
+    0x77, 0x63, 0xf3, 0x26, 0xe8, 0x64, 0x27, 0xb9, 0xda, 0x50, 0xd3, 0xb6,
+    0xc3, 0xe0, 0x50, 0xd6, 0xeb, 0x79, 0x80, 0x1d, 0x80, 0x59, 0x2d, 0x1a,
+    0x51, 0x3e, 0x7c, 0x73, 0x74, 0x34, 0x3a, 0xba, 0xd4, 0xb0, 0x21, 0xb9,
+    0x50, 0xcf, 0x7b, 0xb5, 0x7c, 0x33, 0x6e, 0x6c, 0x01, 0x10, 0xdb, 0x60,
+    0x51, 0x8c, 0xee, 0xd2, 0x7c, 0xfb, 0x97, 0x00, 0x45, 0xe6, 0xe5, 0x38,
+    0x08, 0x54, 0x0e, 0x2c, 0x09, 0x6b, 0x6d, 0x87, 0x36, 0xd4, 0xbb, 0x57,
+    0xd6, 0x52, 0x9b, 0xaa, 0xe5, 0xe1, 0xc2, 0xf7, 0x02, 0xcc, 0xdd, 0x4b,
+    0x02, 0xcc, 0x1a, 0xdc, 0xf1, 0x33, 0x78, 0xdc, 0xcc, 0x41, 0xcf, 0x8f,
+    0xf2, 0xb0, 0xbf, 0x16, 0x5e, 0x26, 0x10, 0x66, 0x3f, 0x03, 0x0f, 0xb5,
+    0x4b, 0x2a, 0x9e, 0x31, 0xa5, 0xba, 0x1b, 0x7e, 0xb1, 0x61, 0x9a, 0x16,
+    0x08, 0x5f, 0xf0, 0xbb, 0x84, 0x34, 0x29, 0xb5, 0xd9, 0x05, 0xd7, 0x62,
+    0x06, 0xa1, 0x3a, 0xe4, 0x21, 0x2e, 0x36, 0x7e, 0xd1, 0xdc, 0x73, 0xc7,
+    0x3a, 0x80, 0x4d, 0xc5, 0x26, 0x69, 0xf4, 0xf3, 0xa5, 0x95, 0xb7, 0xe5,
+    0xbb, 0xc5, 0x72, 0x51, 0xa5, 0xc4, 0xee, 0xb8, 0x02, 0x23, 0x1e, 0x70,
+    0x5c, 0x66, 0xd0, 0xdf, 0x89, 0x16, 0x68, 0xaa, 0x21, 0x22, 0x84, 0x8a,
+    0xb8, 0x6a, 0x8f, 0x0c, 0x6a, 0xce, 0xd3, 0x0f, 0x1a, 0xb2, 0x2d, 0x6f,
+    0x4e, 0x2b, 0x34, 0x01, 0xe0, 0xb8, 0xe7, 0xb8, 0x22, 0xed, 0x76, 0xc2,
+    0xd4, 0x72, 0xcb, 0x03, 0x1b, 0xc5, 0x7c, 0x75, 0xce, 0xf4, 0x7e, 0xd0,
+    0xa2, 0xca, 0xa5, 0xc2, 0xa8, 0xe8, 0xca, 0xb7, 0x9b, 0x43, 0xae, 0x12,
+    0x1b, 0xfa, 0xe7, 0xfb, 0xb0, 0x41, 0xfc, 0xf2, 0x38, 0x03, 0xec, 0xe3,
+    0x6c, 0x1d, 0x2b, 0xf8, 0xaf, 0x2d, 0x42, 0x30, 0x94, 0xdf, 0xb3, 0x9d,
+    0xaa, 0xaa, 0xdf, 0xcf, 0x3d, 0x9b, 0xdb, 0xec, 0x8a, 0x02, 0x2d, 0x38,
+    0x7b, 0x7e, 0xb4, 0x00, 0x6d, 0x01, 0x07, 0xf6, 0x3f, 0x84, 0x77, 0xe0,
+    0x25, 0x00, 0x25, 0xec, 0xd9, 0x00, 0x47, 0x06, 0xb5, 0x40, 0xf6, 0xa8,
+    0x1e, 0xdf, 0xd9, 0x78, 0x03, 0x2d, 0xa1, 0xc5, 0x56, 0xe4, 0xe0, 0x19,
+    0xc4, 0x66, 0xe0, 0x0c, 0x5a, 0xdb, 0xb6, 0xed, 0xea, 0xe2, 0x99, 0x1b,
+    0x99, 0xc7, 0xe1, 0xb9, 0x62, 0x2c, 0x96, 0x49, 0xb6, 0x0d, 0x8b, 0x1b,
+    0x8f, 0xf6, 0xd0, 0x03, 0xcf, 0x77, 0xe4, 0x99, 0x4f, 0x9b, 0x2c, 0x59,
+    0xb2, 0xc0, 0xa6, 0x50, 0xaa, 0xd1, 0x2a, 0x37, 0xeb, 0x05, 0x02, 0x17,
+    0xfb, 0xa6, 0xcf, 0x41, 0xad, 0xea, 0x25, 0x36, 0x54, 0x6f, 0xce, 0xdf,
+    0xcf, 0x69, 0xae, 0x14, 0xe5, 0xc5, 0x39, 0xe2, 0xe0, 0xb7, 0x38, 0xd2,
+    0xbf, 0x15, 0x2c, 0xda, 0x75, 0xb0, 0x69, 0x71, 0xbe, 0xde, 0x20, 0x10,
+    0x80, 0x2f, 0xdd, 0xf3, 0xd6, 0x22, 0xb6, 0x3c, 0x5f, 0x37, 0x16, 0x42,
+    0x65, 0x29, 0xb8, 0x5b, 0x78, 0x09, 0x97, 0xa0, 0x4d, 0x00, 0x34, 0x6d,
+    0xbd, 0xc4, 0x14, 0x2f, 0x41, 0x30, 0x01, 0x26, 0x94, 0xde, 0x2c, 0x8d,
+    0xd0, 0x05, 0x62, 0x3d, 0x95, 0xda, 0x1b, 0x39, 0xe3, 0x69, 0x70, 0xe3,
+    0x8b, 0x29, 0xbd, 0x58, 0x80, 0x0a, 0x75, 0xcf, 0x2c, 0x26, 0x6b, 0x96,
+    0x90, 0x95, 0xa7, 0x8d, 0x97, 0x87, 0xca, 0x00, 0x34, 0x2f, 0xd1, 0x2b,
+    0x10, 0x99, 0x54, 0x84, 0xdf, 0x3c, 0x01, 0xb8, 0x9c, 0xf2, 0xae, 0x97,
+    0x1d, 0x16, 0xd7, 0xcc, 0x40, 0x1c, 0xc5, 0xba, 0x70, 0xf6, 0xf3, 0x7c,
+    0x7f, 0x2d, 0xf9, 0xf8, 0x13, 0x7d, 0xa5, 0x01, 0xe3, 0xf1, 0xe8, 0x56,
+    0x54, 0x45, 0x5c, 0x2d, 0x1a, 0xcf, 0x8d, 0x22, 0x00, 0x3a, 0xfb, 0xe5,
+    0x15, 0xd8, 0xbc, 0x2a, 0xcb, 0xaf, 0x4b, 0x32, 0xf0, 0xf8, 0x6c, 0x83,
+    0x4e, 0x1a, 0xde, 0x4c, 0x10, 0x00, 0xb0, 0x48, 0x01, 0xb0, 0x05, 0xb7,
+    0xdf, 0x38, 0xd8, 0xb5, 0x09, 0xd8, 0x4d, 0xba, 0x93, 0x15, 0x5b, 0xe7,
+    0xf3, 0xd9, 0xfc, 0x98, 0x6d, 0x90, 0x71, 0xc3, 0x4e, 0x18, 0x1a, 0x48,
+    0x6c, 0x77, 0x2d, 0x8a, 0xad, 0xfb, 0x80, 0x07, 0x4b, 0xc7, 0x66, 0xf0,
+    0xfc, 0x0c, 0xb3, 0x1e, 0x51, 0x44, 0x8a, 0xde, 0x64, 0x00, 0xb3, 0xdf,
+    0x8f, 0x61, 0x78, 0x6f, 0x1d, 0xe4, 0x2d, 0x2c, 0xd8, 0x53, 0xcc, 0x0e,
+    0xb5, 0xbe, 0x32, 0xff, 0x69, 0x40, 0x1e, 0x57, 0x3b, 0x1d, 0x4a, 0xbb,
+    0x26, 0xe3, 0xcf, 0xee, 0x87, 0xe2, 0x4a, 0x74, 0x30, 0xe4, 0x6e, 0x50,
+    0x00, 0x9f, 0x8c, 0x7a, 0x0a, 0xe9, 0xc3, 0x00, 0x2d, 0x7c, 0xc9, 0x6d,
+    0xfc, 0x5b, 0x2d, 0x92, 0x51, 0xaa, 0x53, 0x7d, 0x01, 0x93, 0x55, 0x20,
+    0x1b, 0x6e, 0xae, 0x64, 0xa4, 0xc8, 0xdf, 0xa6, 0xe0, 0x8b, 0xf6, 0x23,
+    0x7d, 0x3d, 0xba, 0xf6, 0x78, 0xbf, 0x25, 0xf2, 0xdd, 0xa8, 0xbb, 0xa3,
+    0x64, 0x5a, 0x52, 0xa4, 0x29, 0xa8, 0xfb, 0x00, 0x3b, 0x7e, 0x76, 0x41,
+    0xef, 0xd9, 0xcf, 0x92, 0xcf, 0x37, 0x87, 0x2f, 0x94, 0x87, 0x59, 0x14,
+    0x62, 0xb7, 0x91, 0x82, 0x7e, 0xae, 0xc3, 0x7e, 0x66, 0x4c, 0x2f, 0x05,
+    0x3a, 0x19, 0x34, 0xad, 0xa6, 0x94, 0x70, 0xc6, 0xf5, 0x60, 0x09, 0x67,
+    0x42, 0xdf, 0xb1, 0xdf, 0x3a, 0xa1, 0xd4, 0x6d, 0x44, 0x90, 0xba, 0x3c,
+    0x73, 0x59, 0x6d, 0xd0, 0x13, 0x5b, 0xec, 0xfb, 0x08, 0xe9, 0xd9, 0xdd,
+    0x10, 0x00, 0xf4, 0x5e, 0x5b, 0x2e, 0x3f, 0x45, 0xc0, 0x45, 0x00, 0x6d,
+    0xb4, 0xd2, 0x6a, 0x9e, 0x50, 0xf6, 0xf2, 0x1f, 0x40, 0x07, 0xe2, 0xfa,
+    0x4c, 0x00, 0x3e, 0x14, 0xe9, 0x25, 0x9e, 0xce, 0xc2, 0x91, 0xd0, 0x37,
+    0xd6, 0x8f, 0x6e, 0x6f, 0xf5, 0xf9, 0xcf, 0x0e, 0xf3, 0x88, 0x04, 0x3b,
+    0x9c, 0xd2, 0x61, 0xb1, 0x52, 0x98, 0xa5, 0x29, 0xfe, 0x8d, 0xb8, 0x00,
+    0x4e, 0xe7, 0x0b, 0xda, 0x65, 0x45, 0xb8, 0x1d, 0x0d, 0x54, 0x55, 0x21,
+    0x2b, 0x38, 0xc3, 0x00, 0x00, 0x00, 0x01, 0x08, 0x43, 0xf3, 0xc0, 0x0f,
+    0xbd, 0x85, 0x00, 0x3b, 0xfb, 0x8a, 0xeb, 0x9e, 0x5c, 0x74, 0x97, 0xca,
+    0x4d, 0xd3, 0x21, 0x32, 0x45, 0x52, 0xbd, 0x20, 0xe6, 0xfb, 0x10, 0x20,
+    0x01, 0x6b, 0xaf, 0xd7, 0xa9, 0xcf, 0xd1, 0xd7, 0x6f, 0xee, 0x72, 0x65,
+    0xdc, 0x86, 0x87, 0x4a, 0xa5, 0x15, 0xe2, 0xdf, 0x0a, 0x7d, 0xf3, 0xb2,
+    0x44, 0x1c, 0x51, 0x48, 0xde, 0x82, 0x6d, 0x7c, 0x6e, 0x51, 0xf5, 0xbc,
+    0xa2, 0xa5, 0x2d, 0xbe, 0x71, 0x1e, 0xdf, 0x61, 0x7d, 0x2a, 0xc3, 0xe6,
+    0xaf, 0x56, 0x13, 0xd6, 0x1d, 0xf9, 0x88, 0x77, 0x8c, 0x6d, 0x54, 0x0c,
+    0x20, 0x26, 0xff, 0xdd, 0x80, 0x02, 0xd2, 0x43, 0x6a, 0xd5, 0x73, 0xb5,
+    0xef, 0x50, 0xa9, 0x13, 0x50, 0x23, 0x56, 0x95, 0x42, 0x47, 0x35, 0xdf,
+    0x34, 0x50, 0x03, 0x7f, 0xb7, 0xd8, 0x4b, 0x9e, 0xa3, 0x2a, 0x89, 0xc0,
+    0xba, 0x55, 0xbb, 0x4a, 0x0b, 0x2d, 0xb9, 0x6d, 0x5b, 0x2b, 0x03, 0x29,
+    0x24, 0x0e, 0x6f, 0xd2, 0x80, 0x3b, 0x50, 0x05, 0x7f, 0xcf, 0x8d, 0xc3,
+    0x87, 0x76, 0xfd, 0x93, 0x89, 0x60, 0x23, 0xff, 0xed, 0xfd, 0x46, 0xf8,
+    0x80, 0xb3, 0x40, 0x1e, 0x09, 0xf8, 0xb4, 0x2e, 0x68, 0x8d, 0x14, 0xfb,
+    0x01, 0x28, 0x01, 0x75, 0xc4, 0x86, 0xfd, 0xa9, 0xbd, 0xf9, 0x80, 0x3b,
+    0xef, 0x9b, 0x68, 0xeb, 0x7b, 0x73, 0xf7, 0x38, 0x48, 0x5a, 0x07, 0x5b,
+    0x0e, 0x38, 0x75, 0x6f, 0xca, 0x42, 0xaf, 0x3f, 0xce, 0xbf, 0xef, 0xb6,
+    0x86, 0x71, 0x2d, 0x11, 0xed, 0x31, 0xc3, 0x49, 0xae, 0xe1, 0x57, 0x42,
+    0x54, 0x63, 0x68, 0x4c, 0x90, 0x0b, 0x62, 0xd2, 0xdb, 0xf1, 0x6e, 0xa4,
+    0xfb, 0x25, 0x8d, 0xf7, 0xd7, 0x72, 0xf7, 0x38, 0x01, 0xef, 0x74, 0x5b,
+    0xb0, 0x65, 0xe0, 0x57, 0xcf, 0x7d, 0xee, 0x45, 0x3c, 0x08, 0x40, 0x08,
+    0x13, 0x1b, 0xe4, 0xc0, 0x0f, 0xd4, 0x01, 0x18, 0x03, 0xef, 0xa7, 0x28,
+    0x17, 0x5f, 0x6f, 0x19, 0x07, 0x1f, 0x29, 0x70, 0x2a, 0xa3, 0x7e, 0x94,
+    0x00, 0x5b, 0x98, 0x23, 0x9e, 0x70, 0x50, 0x9e, 0x60, 0xc0, 0xfe, 0x37,
+    0x62, 0x43, 0xec, 0x2c, 0x30, 0x2d, 0xbc, 0x1e, 0x85, 0x51, 0x06, 0x3f,
+    0x98, 0xa1, 0x97, 0xf4, 0xad, 0x89, 0x86, 0x1f, 0xea, 0x31, 0xbf, 0xcf,
+    0x40, 0x0f, 0xe6, 0x70, 0xfd, 0xb2, 0x51, 0xf4, 0xdb, 0x64, 0x8d, 0xc9,
+    0xf7, 0xec, 0x00, 0xf1, 0xd6, 0xed, 0x81, 0xb1, 0x68, 0xc8, 0xdd, 0xe1,
+    0x58, 0x00, 0x65, 0xe6, 0xf2, 0xf2, 0x9e, 0x4c, 0x96, 0xac, 0xf0, 0x6f,
+    0x9f, 0x09, 0x9d, 0x09, 0xf8, 0x5a, 0x90, 0x25, 0xda, 0x1d, 0x29, 0xf0,
+    0x6b, 0x75, 0x82, 0x1f, 0xfd, 0x4d, 0x84, 0x2a, 0xc2, 0x1a, 0xad, 0xe1,
+    0xf9, 0x2f, 0xb8, 0xf4, 0x0a, 0xd7, 0x64, 0x56, 0x5e, 0x6d, 0xcc, 0x7f,
+    0x25, 0x86, 0xcb, 0x76, 0x44, 0x90, 0x2a, 0x01, 0xed, 0xde, 0x7e, 0xa0,
+    0xb7, 0xdf, 0x4a, 0x38, 0x29, 0x98, 0x4d, 0x37, 0xad, 0x76, 0xcf, 0x16,
+    0xeb, 0x90, 0xb2, 0x9b, 0x5c, 0x1a, 0xdf, 0x8e, 0xe5, 0x5c, 0x6d, 0xa8,
+    0x14, 0xb2, 0x7a, 0xd2, 0xdb, 0xd6, 0xc7, 0xcf, 0x9a, 0x92, 0xd0, 0xbd,
+    0x76, 0xec, 0xd0, 0xa8, 0xb5, 0x4a, 0x0c, 0xaa, 0xd8, 0xbb, 0x80, 0x16,
+    0x53, 0x37, 0x65, 0x0b, 0xa3, 0x42, 0xda, 0x02, 0x1f, 0xfd, 0x66, 0x3e,
+    0x50, 0xab, 0x72, 0x12, 0x49, 0x05, 0xb6, 0xf9, 0xf9, 0x8d, 0xd7, 0x00,
+    0x29, 0x6f, 0x4c, 0xd2, 0x78, 0xb1, 0x49, 0x02, 0x56, 0xbf, 0x0a, 0xb0,
+    0x24, 0x63, 0x59, 0xde, 0xcf, 0x2b, 0x2b, 0xd4, 0x00, 0x53, 0x04, 0x41,
+    0x4e, 0xb6, 0x82, 0x3f, 0xfe, 0x64, 0xa0, 0x51, 0xed, 0x97, 0x6d, 0xcd,
+    0xdd, 0x93, 0x46, 0x95, 0x9c, 0x19, 0x36, 0x8d, 0xa5, 0x9a, 0x51, 0x61,
+    0x2d, 0xd8, 0xee, 0x00, 0x1e, 0xbb, 0xaa, 0xf7, 0x0f, 0xae, 0x97, 0x33,
+    0x5e, 0xf0, 0xc3, 0xd6, 0x15, 0x09, 0x2d, 0xd0, 0xdd, 0xc3, 0x9b, 0xaf,
+    0xac, 0xa4, 0x5c, 0xba, 0x96, 0x45, 0x59, 0xba, 0x31, 0xba, 0x1c, 0xbe,
+    0x6f, 0x9e, 0xdc, 0x00, 0x85, 0xdb, 0x0d, 0x42, 0x8e, 0x09, 0x6a, 0x74,
+    0x9f, 0xf2, 0xfc, 0xe5, 0xd6, 0x86, 0xa7, 0x46, 0x50, 0xf0, 0x11, 0x9e,
+    0x5b, 0x0a, 0xaf, 0xfb, 0xf5, 0x24, 0x09, 0x8f, 0xb2, 0x10, 0xe8, 0xca,
+    0xd0, 0xda, 0x9e, 0xd8, 0xc4, 0xf9, 0xef, 0xa4, 0x08, 0x5d, 0x29, 0x14,
+    0x2a, 0x36, 0xfb, 0x40, 0x2b, 0x17, 0xc7, 0x21, 0xe1, 0x16, 0x64, 0x73,
+    0xe0, 0x5e, 0xfe, 0xa0, 0x59, 0x4d, 0x57, 0x69, 0xf6, 0x13, 0x9c, 0x72,
+    0x81, 0x69, 0x13, 0x40, 0xea, 0xd4, 0x67, 0x37, 0xdb, 0x1e, 0xed, 0xd0,
+    0x4a, 0xff, 0x9c, 0xca, 0x58, 0x40, 0xef, 0x05, 0x6b, 0x64, 0xde, 0x8a,
+    0xbc, 0xc7, 0xd9, 0x14, 0x08, 0xdb, 0x9e, 0xf2, 0x4a, 0x30, 0x07, 0x33,
+    0x88, 0x96, 0x85, 0x37, 0x87, 0xc8, 0x68, 0x8f, 0x6c, 0x7e, 0x84, 0xdb,
+    0x68, 0x7a, 0x04, 0x23, 0x7d, 0x02, 0x82, 0x10, 0x03, 0x89, 0xf6, 0xc9,
+    0x94, 0x12, 0x3f, 0xf7, 0x1d, 0x39, 0x77, 0x8e, 0x19, 0xb2, 0x90, 0xdb,
+    0xe6, 0x8f, 0x90, 0x57, 0xd7, 0xae, 0x65, 0x0a, 0xc1, 0x56, 0x1a, 0xa7,
+    0x9f, 0x06, 0xc0, 0xb6, 0x88, 0x53, 0x71, 0xd0, 0x30, 0x53, 0x7e, 0xe9,
+    0xe9, 0xd1, 0x1c, 0x5e, 0x3b, 0xc7, 0x83, 0x16, 0xdf, 0x46, 0xf7, 0x9f,
+    0xc8, 0x08, 0x3f, 0x95, 0xcf, 0xf8, 0x4a, 0x50, 0x49, 0xff, 0xde, 0x2c,
+    0x80, 0x96, 0x00, 0x65, 0x12, 0x5b, 0xe0, 0x62, 0xac, 0x77, 0x9e, 0xdc,
+    0x83, 0x12, 0x4a, 0x54, 0xf0, 0x6f, 0xb7, 0x7b, 0xc0, 0x41, 0xfc, 0x40,
+    0x01, 0x16, 0x20, 0x04, 0x37, 0x99, 0x28, 0x59, 0x8b, 0x69, 0x29, 0xad,
+    0x4e, 0x24, 0xb6, 0x14, 0xba, 0xdf, 0xec, 0x25, 0x41, 0xbe, 0x8a, 0xde,
+    0x30, 0x01, 0xf3, 0xc1, 0x04, 0x06, 0x40, 0x1f, 0xfc, 0x8a, 0x77, 0x8d,
+    0xe1, 0xf5, 0x60, 0x08, 0xaa, 0x07, 0xc0, 0xa6, 0xf5, 0x90, 0xaa, 0x00,
+    0x2e, 0x6f, 0xcb, 0xe0, 0x0f, 0x90, 0x10, 0x00, 0xeb, 0x8e, 0x3e, 0xba,
+    0x09, 0x7f, 0xf7, 0x49, 0xce, 0xa3, 0x0e, 0xb4, 0x9b, 0xe3, 0x0e, 0x6d,
+    0x4e, 0xad, 0xbc, 0x29, 0x5b, 0xf0, 0x00, 0x0c, 0x3d, 0xba, 0x7f, 0xdb,
+    0x8c, 0xf8, 0xce, 0x20, 0xfd, 0xe7, 0x7c, 0xa6, 0x2d, 0x0d, 0x39, 0xac,
+    0xff, 0x0a, 0xe1, 0xfd, 0x57, 0xd7, 0xe4, 0x91, 0x77, 0x5f, 0xb9, 0x61,
+    0xb6, 0xda, 0x87, 0xa0, 0xe0, 0x96, 0xe0, 0x89, 0xf2, 0xe4, 0xd8, 0xb5,
+    0x00, 0x95, 0x1c, 0xad, 0xab, 0xce, 0x80, 0x3b, 0x00, 0x32, 0xc1, 0x5b,
+    0x2c, 0x04, 0x6f, 0xfa, 0x7f, 0x91, 0x98, 0x34, 0x9a, 0x6d, 0x89, 0x02,
+    0xdb, 0xcf, 0x44, 0x76, 0xda, 0x42, 0x46, 0xe5, 0xb0, 0x39, 0x5b, 0xfd,
+    0x1f, 0xf7, 0xea, 0x82, 0x07, 0xe7, 0xf1, 0x08, 0x9e, 0xd7, 0x06, 0x79,
+    0x79, 0xce, 0x57, 0xbc, 0x1c, 0x1d, 0x83, 0x2d, 0x6e, 0xf8, 0x03, 0x2e,
+    0x78, 0x00, 0x4d, 0xce, 0x6f, 0x9d, 0x0c, 0x80, 0x3d, 0x0b, 0x0c, 0x87,
+    0xb7, 0x8d, 0x04, 0x00, 0x2a, 0x73, 0xc0, 0x1b, 0x39, 0xef, 0xf9, 0x17,
+    0x69, 0x6b, 0x99, 0xca, 0xd3, 0x62, 0xd3, 0x6c, 0x50, 0x96, 0xf9, 0xd8,
+    0xae, 0x35, 0xdf, 0x13, 0x20, 0x8b, 0x85, 0xa6, 0x4c, 0x45, 0x8b, 0x36,
+    0xae, 0x97, 0x7c, 0x5b, 0x67, 0xd8, 0x6b, 0xf7, 0x69, 0x08, 0xa6, 0xea,
+    0xe4, 0xbb, 0xb6, 0xd0, 0x29, 0xbf, 0xa5, 0x80, 0x17, 0x7d, 0x4d, 0xf7,
+    0xbb, 0xf3, 0xc3, 0xb9, 0x8a, 0x86, 0xa0, 0xc9, 0x85, 0x17, 0x10, 0xf3,
+    0xc3, 0x15, 0xbc, 0x68, 0x03, 0x22, 0x37, 0x5d, 0x7b, 0x0a, 0x70, 0x05,
+    0xbe, 0xd6, 0x93, 0x79, 0x78, 0xdd, 0x32, 0x40, 0xf1, 0xc5, 0x2b, 0x64,
+    0x00, 0x71, 0xf6, 0xe6, 0x7b, 0xc5, 0x78, 0x9d, 0xb0, 0x9b, 0x77, 0x6a,
+    0xdd, 0x58, 0x92, 0x14, 0x10, 0x34, 0xb6, 0xe6, 0x00, 0x36, 0x23, 0x70,
+    0x66, 0x2d, 0xef, 0x6f, 0xed, 0xdc, 0x21, 0xd9, 0x0f, 0xa5, 0x86, 0xb2,
+    0x7e, 0xd7, 0xf3, 0xbb, 0xb7, 0xc5, 0xb7, 0x7d, 0x37, 0x6d, 0xad, 0xf5,
+    0xba, 0x00, 0x39, 0xde, 0x65, 0xdd, 0xe7, 0x30, 0x10, 0xc0, 0x18, 0x50,
+    0xa7, 0x18, 0x92, 0xe6, 0xed, 0x1a, 0xef, 0xd5, 0x8d, 0x90, 0x01, 0xe7,
+    0x64, 0x77, 0x89, 0xc5, 0xf6, 0x32, 0xd0, 0xff, 0x67, 0x47, 0x48, 0x90,
+    0x83, 0x4d, 0xd8, 0x4b, 0xad, 0xe6, 0xc5, 0x3a, 0x74, 0x22, 0x4e, 0x84,
+    0x70, 0x34, 0xd9, 0xc6, 0x7e, 0xf6, 0xd3, 0x82, 0x9a, 0xe7, 0xed, 0x79,
+    0x8f, 0x5e, 0x72, 0xa2, 0xb8, 0xcd, 0x28, 0x98, 0x1c, 0x3a, 0x94, 0x06,
+    0xdb, 0x48, 0xda, 0xd6, 0xfb, 0xa4, 0x4e, 0x05, 0x70, 0x46, 0xda, 0xef,
+    0x7a, 0xfc, 0x53, 0x04, 0xf2, 0xf9, 0x0e, 0x98, 0x52, 0x87, 0xc8, 0x3e,
+    0xd6, 0x6f, 0x60, 0x07, 0xa4, 0x71, 0x3d, 0xe6, 0xbf, 0x8c, 0x53, 0x03,
+    0xac, 0xb1, 0x46, 0x14, 0x54, 0x1d, 0x06, 0xb7, 0x20, 0x00, 0xf7, 0xa7,
+    0x77, 0xb1, 0xd3, 0x99, 0x8a, 0x82, 0xf4, 0x80, 0xbe, 0x72, 0xca, 0x38,
+    0xa3, 0xe1, 0xde, 0xad, 0x97, 0xd9, 0xe2, 0xfd, 0xf9, 0x90, 0xc9, 0x46,
+    0xa9, 0xb5, 0x10, 0xc8, 0x04, 0x1e, 0xa3, 0x98, 0xf1, 0x66, 0xdf, 0xa3,
+    0x00, 0x58, 0xef, 0x97, 0x59, 0xcf, 0xd7, 0xdd, 0xfb, 0x4e, 0x99, 0x6a,
+    0x80, 0xe3, 0x0f, 0x38, 0x61, 0x4d, 0xc0, 0xae, 0xeb, 0x32, 0xb8, 0x43,
+    0xa1, 0x45, 0x16, 0x91, 0x0b, 0x0a, 0x6c, 0xde, 0xcb, 0x4c, 0x20, 0x4c,
+    0x39, 0x74, 0xa8, 0x56, 0x8e, 0xf0, 0x02, 0xdb, 0xa7, 0xf1, 0x9c, 0xc7,
+    0x50, 0x0b, 0x7b, 0xda, 0x74, 0x2e, 0xa2, 0xc7, 0x43, 0xd9, 0xc6, 0x6d,
+    0xf9, 0xf3, 0x74, 0xcc, 0x36, 0x62, 0x8d, 0xa6, 0x1e, 0x8a, 0x58, 0x6b,
+    0x27, 0x79, 0x5f, 0x83, 0x69, 0xe1, 0x65, 0x56, 0xee, 0x7c, 0xba, 0x8b,
+    0xd9, 0x72, 0x00, 0x45, 0x98, 0x61, 0x67, 0x31, 0x7d, 0xe0, 0x57, 0xbd,
+    0x58, 0x13, 0xb0, 0xeb, 0x3d, 0x51, 0x15, 0x86, 0x55, 0x80, 0x00, 0x00,
+    0x01, 0x09, 0x43, 0xf1, 0xf9, 0x49, 0xf9, 0x85, 0x04, 0xad, 0x6e, 0xaf,
+    0x32, 0x6e, 0x16, 0xdf, 0x2a, 0x77, 0x52, 0x11, 0xf8, 0xb7, 0x60, 0xe5,
+    0x32, 0xc8, 0x58, 0xc2, 0xca, 0x4a, 0xa1, 0x2d, 0xf6, 0xba, 0x47, 0x22,
+    0x00, 0x2d, 0x00, 0x7d, 0xbb, 0xbc, 0xdd, 0x4b, 0x49, 0xdd, 0x88, 0xe6,
+    0x07, 0x2e, 0x07, 0xc3, 0xa5, 0x1a, 0x8d, 0xe5, 0xb8, 0xa6, 0xf3, 0x55,
+    0x5b, 0xc0, 0xf7, 0x49, 0xde, 0xf0, 0x42, 0x36, 0x4b, 0xe0, 0xb6, 0x2b,
+    0x6f, 0x73, 0xf4, 0x51, 0x1c, 0x01, 0xe7, 0xdb, 0x9a, 0x13, 0x7b, 0xf9,
+    0x15, 0x1c, 0x4f, 0x04, 0x80, 0x03, 0xdd, 0x2f, 0x8a, 0x15, 0x0e, 0xa7,
+    0xb7, 0xa8, 0x16, 0x45, 0xf6, 0xfa, 0x11, 0x4d, 0xf8, 0x82, 0xcc, 0x36,
+    0xe6, 0xbf, 0x2f, 0x95, 0x55, 0x86, 0x7e, 0xad, 0x3d, 0x4b, 0x90, 0x21,
+    0xba, 0x22, 0x7b, 0xa0, 0x0f, 0xbe, 0x9f, 0x77, 0x73, 0xc5, 0x8f, 0x7f,
+    0x2f, 0x7d, 0x9b, 0x1f, 0xb1, 0xfa, 0xfd, 0x44, 0x43, 0xca, 0x8e, 0x0b,
+    0x56, 0xe7, 0x75, 0xf2, 0xa3, 0x02, 0xab, 0x2d, 0x44, 0x6f, 0xd8, 0x73,
+    0xae, 0x23, 0x7f, 0x04, 0xee, 0x3e, 0x00, 0x0a, 0x5d, 0xcf, 0x4b, 0x38,
+    0xc9, 0x03, 0xc0, 0x4b, 0x0a, 0x43, 0x0a, 0xad, 0xf0, 0x40, 0x03, 0xb8,
+    0xe7, 0xf9, 0xfb, 0x58, 0x7a, 0x6d, 0xd9, 0x9b, 0x57, 0x07, 0x15, 0x8a,
+    0x6d, 0x0a, 0x46, 0xfd, 0x0f, 0xf4, 0x16, 0x00, 0x6b, 0xc7, 0xff, 0xb1,
+    0x51, 0xf2, 0x9f, 0x78, 0xcd, 0x00, 0xb7, 0x6e, 0x53, 0xa9, 0x34, 0x3e,
+    0x9b, 0x0e, 0x1b, 0x1b, 0xf2, 0x63, 0xe4, 0x11, 0x82, 0xa4, 0x80, 0x94,
+    0x00, 0x66, 0x52, 0x51, 0x25, 0x9e, 0x16, 0xab, 0x3d, 0x23, 0x48, 0x0e,
+    0x35, 0xbf, 0xae, 0x08, 0xfa, 0xb8, 0x10, 0x3f, 0x2c, 0x4e, 0x8b, 0xe3,
+    0xbb, 0x40, 0x8e, 0x3e, 0x38, 0xeb, 0x88, 0xf9, 0xb0, 0xf0, 0xf7, 0xed,
+    0xab, 0x14, 0x32, 0x14, 0xdf, 0x50, 0xf9, 0xf8, 0xc0, 0x02, 0x8e, 0x1c,
+    0xe8, 0xb0, 0x11, 0xff, 0xee, 0xdb, 0x69, 0x60, 0x3c, 0x58, 0x52, 0x12,
+    0x5b, 0xf2, 0xfe, 0x80, 0x53, 0x5b, 0xf4, 0x38, 0x03, 0xc7, 0xc0, 0x04,
+    0xff, 0xe1, 0x7f, 0xdf, 0xb4, 0xc8, 0x08, 0xc0, 0x0a, 0xb4, 0x0c, 0xa6,
+    0x07, 0x50, 0x1c, 0xd1, 0x88, 0x58, 0xd1, 0xb5, 0xb9, 0x75, 0x1d, 0xd3,
+    0xf5, 0x7c, 0x21, 0x49, 0x4e, 0x1f, 0x5b, 0x38, 0x5b, 0xae, 0xcf, 0x04,
+    0x3d, 0xbf, 0xce, 0x9f, 0x71, 0x0f, 0x00, 0x2e, 0xfb, 0xbb, 0x1d, 0x65,
+    0x01, 0xe6, 0xbc, 0x46, 0xbb, 0x60, 0xca, 0x58, 0x45, 0x25, 0xb7, 0xce,
+    0x3a, 0xe8, 0x02, 0xbe, 0xdc, 0x4f, 0x2c, 0x62, 0xc3, 0x15, 0xbf, 0x5c,
+    0x00, 0x30, 0x17, 0xa0, 0x80, 0x05, 0x59, 0xef, 0xff, 0x16, 0x22, 0x4f,
+    0xd7, 0x5c, 0x3d, 0xc8, 0x66, 0xd4, 0x27, 0x9d, 0x4d, 0x8b, 0x50, 0x68,
+    0xd6, 0xfc, 0xd0, 0xfa, 0xf1, 0x7f, 0x24, 0x67, 0x71, 0x21, 0xd9, 0x5e,
+    0x4f, 0xec, 0xc9, 0x93, 0x21, 0x74, 0x3c, 0x74, 0x6e, 0x82, 0x6f, 0x3b,
+    0xa8, 0x43, 0xad, 0xa2, 0x96, 0xb5, 0xbc, 0x8f, 0xeb, 0x1c, 0x22, 0x47,
+    0x64, 0xf5, 0x3e, 0xda, 0xa3, 0x4b, 0x6b, 0x08, 0xce, 0x00, 0x33, 0xf7,
+    0x9b, 0x25, 0x0c, 0xaf, 0x32, 0x19, 0x46, 0xb7, 0xa7, 0x42, 0x01, 0xaf,
+    0x7c, 0xb8, 0x03, 0xde, 0x79, 0x93, 0x80, 0xa2, 0xb2, 0x0c, 0x81, 0xa5,
+    0xd6, 0xc1, 0xf7, 0x37, 0x0a, 0x44, 0x3d, 0x4a, 0x87, 0x86, 0x00, 0xd5,
+    0x96, 0x4b, 0xae, 0x46, 0x4a, 0x52, 0xb7, 0xd0, 0xec, 0x5e, 0x11, 0xb8,
+    0x7e, 0xbf, 0xac, 0x2c, 0xad, 0xe7, 0x1f, 0x93, 0x8b, 0x76, 0xa3, 0x8f,
+    0x8a, 0x51, 0x94, 0xb4, 0x2b, 0x0f, 0x8d, 0xc0, 0xe6, 0x68, 0x19, 0xca,
+    0x9e, 0x25, 0x29, 0x29, 0xb0, 0xf1, 0x28, 0xa1, 0x6e, 0xb7, 0x72, 0x06,
+    0x45, 0x58, 0x9e, 0x10, 0x68, 0x4b, 0x52, 0x46, 0xcc, 0x7b, 0xb6, 0xe2,
+    0x50, 0xab, 0x0a, 0x02, 0xeb, 0x5d, 0x87, 0x2d, 0xf5, 0x6d, 0xcf, 0xa0,
+    0x5b, 0x7d, 0x61, 0x6b, 0xcd, 0xe2, 0xd9, 0x2f, 0x83, 0xf0, 0xaa, 0x10,
+    0x31, 0xb7, 0xe4, 0xc8, 0x47, 0x94, 0xde, 0x02, 0xb5, 0xfb, 0x2e, 0x5b,
+    0x16, 0x9d, 0xa0, 0x5b, 0x69, 0x23, 0x7e, 0x7b, 0x23, 0x75, 0xbb, 0x29,
+    0xd0, 0xbf, 0x7f, 0x3b, 0x4b, 0x0c, 0x30, 0xda, 0x7b, 0x61, 0xd9, 0x39,
+    0x14, 0x23, 0x70, 0xc8, 0x55, 0x31, 0xd4, 0xc7, 0x1c, 0x4c, 0x51, 0x81,
+    0x67, 0xb7, 0xa0, 0x32, 0xb7, 0xa2, 0x8a, 0x8d, 0xea, 0xf6, 0xcb, 0xe5,
+    0x78, 0xd8, 0xa7, 0xd2, 0xd5, 0xd2, 0x1c, 0x58, 0xe1, 0xed, 0xb7, 0x87,
+    0xf9, 0x11, 0x95, 0x50, 0x72, 0x6e, 0x17, 0xa3, 0x09, 0x88, 0x31, 0xb9,
+    0x76, 0x1b, 0xf3, 0x9b, 0x54, 0x05, 0x77, 0x8d, 0xc2, 0xe1, 0x30, 0x71,
+    0xfe, 0xad, 0xd2, 0x17, 0x40, 0x0e, 0x05, 0xbe, 0x97, 0x46, 0x9a, 0x6b,
+    0xb3, 0x32, 0x94, 0x04, 0x50, 0xf2, 0xef, 0x8c, 0x29, 0x93, 0x6e, 0xde,
+    0x5c, 0xc2, 0x7f, 0x34, 0x9d, 0x81, 0x92, 0x72, 0xfc, 0x9b, 0x47, 0x0d,
+    0x28, 0xf0, 0x98, 0xce, 0x45, 0x7c, 0xe8, 0x00, 0xfe, 0x1a, 0x19, 0x49,
+    0xce, 0xe4, 0xc4, 0xd8, 0x1b, 0x64, 0xcb, 0x4a, 0x0d, 0x62, 0xe7, 0xef,
+    0x59, 0xef, 0xbb, 0x25, 0x1c, 0x82, 0xf4, 0xc9, 0x29, 0xe3, 0x92, 0x92,
+    0x1b, 0x1c, 0x33, 0xe1, 0xfd, 0xdb, 0x40, 0x47, 0xe6, 0xe5, 0x51, 0x83,
+    0x0d, 0x18, 0x10, 0xd4, 0xd2, 0x73, 0x74, 0x08, 0x96, 0x71, 0x45, 0xe4,
+    0xd4, 0x1c, 0x4f, 0x3f, 0x21, 0xd7, 0xc5, 0xb1, 0xdd, 0xa0, 0x0e, 0xbe,
+    0x9d, 0x63, 0xed, 0x0d, 0xb3, 0xcf, 0x75, 0x29, 0xe3, 0xf7, 0x6c, 0xf4,
+    0xb5, 0x97, 0x94, 0xb9, 0x66, 0x1b, 0xe2, 0x05, 0x1c, 0xdd, 0x5e, 0x45,
+    0xc7, 0x6f, 0xe6, 0x4a, 0x59, 0x53, 0x75, 0x4c, 0x1e, 0x70, 0x4d, 0x61,
+    0xa6, 0x95, 0x1b, 0xf1, 0x9e, 0xf2, 0x89, 0x99, 0x32, 0xca, 0x39, 0x43,
+    0x4e, 0x6f, 0xd3, 0x1f, 0xde, 0xb4, 0x10, 0x3f, 0x2f, 0xee, 0xe2, 0x37,
+    0xb7, 0xbc, 0xa5, 0xe6, 0xf5, 0x9d, 0xfb, 0x6b, 0xf5, 0xf9, 0x4f, 0x85,
+    0xe5, 0x92, 0x2d, 0x09, 0x2d, 0xbe, 0x46, 0x6c, 0x9b, 0x23, 0xcb, 0x19,
+    0x85, 0x86, 0x96, 0x88, 0xa5, 0x37, 0xbf, 0xff, 0x3b, 0x8c, 0x00, 0x79,
+    0x77, 0xe3, 0xa1, 0x14, 0xf0, 0x0b, 0x45, 0xba, 0xd5, 0x79, 0xa6, 0xc9,
+    0x61, 0x45, 0xda, 0x07, 0xb6, 0x67, 0xa4, 0x6c, 0x39, 0x45, 0x8d, 0xfd,
+    0xc4, 0x00, 0xb0, 0x01, 0xf8, 0x8f, 0x6b, 0xcf, 0x9b, 0xaa, 0x5b, 0x16,
+    0x21, 0x52, 0x7e, 0xc6, 0xc1, 0x90, 0xf1, 0xad, 0xf9, 0x59, 0x1d, 0xf1,
+    0xf6, 0xf8, 0xf8, 0xf6, 0x99, 0x49, 0x86, 0xee, 0x75, 0xc6, 0x61, 0xb7,
+    0x2d, 0x5a, 0xbb, 0x0f, 0xda, 0x79, 0xf5, 0xbb, 0xc2, 0xa0, 0x92, 0x7e,
+    0xbf, 0x90, 0x0b, 0x61, 0x44, 0xed, 0x26, 0xe5, 0x91, 0xd9, 0x52, 0x69,
+    0x95, 0x0b, 0x2e, 0x84, 0x56, 0xc9, 0xd8, 0xae, 0x45, 0x2e, 0x0a, 0x7c,
+    0xb4, 0x9b, 0x15, 0x20, 0xfa, 0x6d, 0x2c, 0x28, 0xe6, 0xd2, 0x15, 0x1b,
+    0x4d, 0xa5, 0x14, 0xdf, 0x3f, 0x9f, 0x3d, 0x89, 0xba, 0x87, 0x41, 0xaa,
+    0x56, 0x0d, 0x56, 0xdf, 0x95, 0xf3, 0xdf, 0x2b, 0xf3, 0x68, 0xc7, 0x60,
+    0xc9, 0x4b, 0x38, 0xaa, 0x71, 0x4d, 0x9f, 0xa9, 0x39, 0xdc, 0x5c, 0x29,
+    0x7f, 0x57, 0x52, 0xdd, 0x42, 0x9b, 0xa5, 0x9d, 0x3f, 0x7e, 0x2c, 0xb7,
+    0x61, 0x41, 0xd0, 0xa8, 0x54, 0x54, 0x0d, 0x38, 0x29, 0xa1, 0xb5, 0xab,
+    0x4f, 0x6f, 0x3f, 0xd3, 0x89, 0xd7, 0x55, 0xe4, 0xed, 0xe7, 0x69, 0x35,
+    0x06, 0x59, 0x22, 0x97, 0x4b, 0xfd, 0xb2, 0x74, 0x21, 0xf2, 0x45, 0x7d,
+    0x50, 0xa3, 0xea, 0xa0, 0xf6, 0xe8, 0xfd, 0x44, 0x65, 0xe8, 0x07, 0x2f,
+    0x55, 0xa6, 0xae, 0x52, 0xb1, 0x0a, 0x46, 0xe1, 0x3d, 0xdc, 0x60, 0xbf,
+    0x38, 0x6c, 0x28, 0xf3, 0x0a, 0x85, 0x94, 0x3e, 0x56, 0x43, 0x19, 0xb7,
+    0xaa, 0xf3, 0x79, 0xcc, 0x9c, 0x61, 0x94, 0xab, 0x62, 0x0c, 0x0a, 0x6d,
+    0x80, 0x64, 0x59, 0x1b, 0x88, 0xe7, 0xec, 0x3c, 0x9d, 0x9c, 0xd7, 0xda,
+    0xba, 0x8a, 0x34, 0x6b, 0x73, 0x5d, 0xd9, 0x07, 0xbd, 0xbc, 0xb8, 0xa2,
+    0xee, 0x63, 0xae, 0x07, 0x5a, 0x85, 0x1e, 0x87, 0xd1, 0x8c, 0x80, 0x07,
+    0xd1, 0xde, 0xd3, 0x9c, 0x2c, 0xb5, 0x58, 0x34, 0xb2, 0xe4, 0x0a, 0x8c,
+    0xda, 0x63, 0x7d, 0xd1, 0x22, 0xc8, 0x9a, 0xec, 0xd3, 0x0d, 0x01, 0xc7,
+    0x2f, 0xe4, 0xe8, 0x1f, 0x28, 0xcd, 0x81, 0x03, 0x55, 0xba, 0x93, 0xfe,
+    0xff, 0x6b, 0xce, 0xcd, 0xef, 0x64, 0xd9, 0x8f, 0x9b, 0x2e, 0xdb, 0x38,
+    0xc3, 0xe2, 0x0e, 0x29, 0xb8, 0x3f, 0x7e, 0x48, 0xc2, 0x3b, 0xd9, 0xb2,
+    0xd3, 0xea, 0xef, 0x26, 0xe4, 0xae, 0x42, 0x8a, 0xa7, 0xdf, 0x02, 0x9b,
+    0x3f, 0x26, 0x7c, 0xf4, 0x23, 0x5e, 0x3a, 0x4e, 0x21, 0xa9, 0x6c, 0xb4,
+    0x62, 0x4a, 0x1a, 0xc0, 0xd6, 0x8c, 0x4b, 0x95, 0xbc, 0x4f, 0xde, 0x5c,
+    0xec, 0x82, 0xde, 0xe2, 0xe9, 0x8e, 0x9c, 0xad, 0xa9, 0x87, 0xd2, 0x1b,
+    0x5b, 0xee, 0x88, 0x92, 0xc8, 0x78, 0xd3, 0x88, 0x4d, 0xdf, 0x13, 0x3a,
+    0xff, 0x7c, 0xe5, 0x76, 0x65, 0x4a, 0x1e, 0x9e, 0x56, 0x22, 0xd0, 0x21,
+    0x07, 0x8f, 0x6f, 0x3b, 0xb6, 0x39, 0xef, 0xf2, 0x33, 0xc7, 0x24, 0xd4,
+    0x38, 0x2d, 0x93, 0x69, 0x2a, 0xca, 0xda, 0x71, 0x6c, 0x7b, 0xf5, 0x42,
+    0x92, 0x0f, 0x85, 0x46, 0xd9, 0xfc, 0xe7, 0x9f, 0x7e, 0x46, 0x0e, 0x48,
+    0x5d, 0x64, 0x7e, 0xdf, 0x9c, 0x97, 0x8d, 0x94, 0x62, 0x1b, 0x84, 0xb4,
+    0xa7, 0x05, 0x36, 0x98, 0xfb, 0xa2, 0x5d, 0x73, 0x85, 0xa3, 0x69, 0xea,
+    0x50, 0x71, 0xd5, 0x88, 0xcd, 0xb4, 0x23, 0x3a, 0xf1, 0x96, 0x1b, 0xb2,
+    0x04, 0x0e, 0x87, 0xfa, 0xb6, 0x67, 0xe4, 0xd7, 0x3a, 0x79, 0x50, 0xc3,
+    0x12, 0x97, 0xbe, 0x07, 0x33, 0xba, 0x51, 0x1d, 0x24, 0x7d, 0x1d, 0xaf,
+    0xd4, 0x2c, 0xe6, 0xe6, 0xcc, 0x9e, 0x7a, 0xb4, 0x26, 0xca, 0x7a, 0x50,
+    0x1e, 0xb3, 0x8d, 0x6c, 0x00, 0x00, 0x01, 0x0a, 0x43, 0xf9, 0x00, 0x03,
+    0xbf, 0xe0, 0xb1, 0x5c, 0x93, 0xba, 0x30, 0x72, 0x79, 0xf1, 0x4d, 0x53,
+    0xac, 0x3e, 0x58, 0x53, 0x6f, 0xf9, 0x99, 0xc9, 0x1e, 0xf5, 0x2c, 0x80,
+    0x4f, 0x96, 0xd8, 0xba, 0x81, 0x8a, 0x39, 0xbd, 0x28, 0x03, 0x87, 0xb8,
+    0x8c, 0x29, 0xd6, 0xe4, 0x09, 0xdf, 0x3b, 0xaf, 0xa5, 0xa1, 0xf1, 0x55,
+    0x21, 0xc3, 0x1b, 0xce, 0x08, 0xcf, 0x21, 0x4b, 0x2f, 0x8c, 0x6f, 0x1b,
+    0x70, 0x9e, 0x4f, 0x8e, 0x50, 0x9c, 0xb1, 0x15, 0xbc, 0x74, 0x1c, 0xde,
+    0xd0, 0xee, 0xf1, 0xd3, 0x20, 0x66, 0x61, 0x44, 0xda, 0x15, 0x21, 0x55,
+    0xbd, 0x68, 0x03, 0xc7, 0xf1, 0xd7, 0x98, 0xbd, 0x4a, 0x7d, 0x97, 0x97,
+    0xbe, 0xee, 0x97, 0x22, 0x42, 0xa8, 0xc8, 0x14, 0xde, 0x14, 0x9b, 0xce,
+    0xad, 0x6b, 0x76, 0x51, 0x69, 0x90, 0x28, 0xa3, 0xda, 0x21, 0x52, 0x52,
+    0x5b, 0x46, 0x1f, 0x15, 0xbf, 0xa0, 0x7b, 0x25, 0x11, 0xdf, 0x61, 0x20,
+    0x13, 0xfe, 0x22, 0x14, 0x58, 0x70, 0xd2, 0xdb, 0xca, 0xda, 0x01, 0x53,
+    0xdd, 0xb6, 0x20, 0xc2, 0xe7, 0x8b, 0x71, 0x04, 0x3a, 0x0a, 0xe6, 0x6e,
+    0xec, 0x0d, 0x59, 0x12, 0x4f, 0x14, 0xad, 0xba, 0x02, 0x17, 0xfd, 0x3b,
+    0x69, 0x2e, 0x92, 0x58, 0x2a, 0xd8, 0xa4, 0x26, 0xac, 0x2b, 0x15, 0xbf,
+    0xb6, 0x80, 0x3b, 0x00, 0x5f, 0xec, 0x00, 0x5f, 0xfc, 0x8f, 0xe2, 0x74,
+    0xa8, 0x4f, 0xc1, 0x62, 0x35, 0x61, 0x97, 0x13, 0x72, 0x9e, 0x10, 0xdf,
+    0x6e, 0x11, 0xff, 0xe7, 0xa0, 0x06, 0x6f, 0xe5, 0xeb, 0xa3, 0x39, 0x79,
+    0x97, 0x64, 0xa8, 0x9c, 0x5c, 0x59, 0x07, 0xb7, 0xe4, 0xfe, 0xf9, 0x00,
+    0x35, 0xf6, 0x9c, 0xf9, 0xa4, 0x2e, 0x90, 0x3a, 0x49, 0x3b, 0xe4, 0x71,
+    0x46, 0xd2, 0xa4, 0x3d, 0xbd, 0x0f, 0xfb, 0xed, 0x9f, 0x04, 0x70, 0x0a,
+    0xfe, 0x05, 0x6d, 0x2f, 0xf2, 0x41, 0x5f, 0xc6, 0x61, 0x84, 0x0c, 0xcf,
+    0xc2, 0x55, 0xb8, 0x78, 0x63, 0x67, 0xd3, 0xcc, 0xdf, 0x3b, 0x6a, 0x0f,
+    0x74, 0x58, 0x81, 0x6d, 0xae, 0x5b, 0xa5, 0xd5, 0x0a, 0x6f, 0x9e, 0x2b,
+    0x9a, 0x00, 0xf8, 0x8d, 0x9c, 0x65, 0x5b, 0x57, 0x79, 0x47, 0x48, 0x5d,
+    0x55, 0x1a, 0x4a, 0x6f, 0x00, 0x2d, 0x61, 0x91, 0x47, 0x42, 0xc7, 0x48,
+    0x51, 0xed, 0xea, 0xf5, 0xdc, 0x00, 0x3a, 0xec, 0x8a, 0x44, 0xec, 0x9f,
+    0x00, 0x05, 0x3d, 0x90, 0x33, 0xbe, 0x6e, 0x69, 0xf0, 0x38, 0xb3, 0x2a,
+    0x78, 0x94, 0xde, 0x0b, 0xfd, 0x40, 0x2d, 0xd7, 0xeb, 0x90, 0x35, 0x2e,
+    0xd5, 0x83, 0x08, 0x4d, 0x35, 0x76, 0x54, 0xb0, 0x30, 0x29, 0xb0, 0xb0,
+    0xb6, 0xfa, 0x36, 0xd7, 0xc8, 0xf9, 0x7d, 0x0a, 0xa0, 0x6d, 0xae, 0x27,
+    0x10, 0x04, 0xdc, 0x40, 0x85, 0xb1, 0x5b, 0x81, 0xd6, 0x00, 0x19, 0x59,
+    0x9a, 0xf0, 0x9b, 0x04, 0xcb, 0x81, 0x87, 0x05, 0xb6, 0x5f, 0xa7, 0x40,
+    0x16, 0x08, 0x13, 0xcc, 0x81, 0x31, 0x0c, 0x84, 0xba, 0xdb, 0x4b, 0xe6,
+    0xb2, 0x90, 0xd9, 0xd8, 0x39, 0xba, 0x78, 0x80, 0x07, 0xc2, 0x1d, 0x32,
+    0xbe, 0x06, 0xcd, 0x47, 0x86, 0x0c, 0x94, 0x69, 0xe1, 0x8d, 0xbb, 0xdc,
+    0xd0, 0x03, 0x9a, 0x40, 0x2a, 0xa5, 0x86, 0xe2, 0x26, 0xcf, 0x0d, 0x96,
+    0x51, 0xc1, 0x8d, 0x92, 0xd7, 0xfd, 0x76, 0x0a, 0xc7, 0x28, 0xcc, 0x0f,
+    0xe7, 0x22, 0x3e, 0x87, 0x43, 0xf4, 0x60, 0x62, 0x16, 0x5b, 0x6b, 0x22,
+    0x6d, 0xf6, 0x23, 0x47, 0x62, 0x5a, 0xb6, 0xd8, 0x2b, 0xa8, 0xe9, 0xb7,
+    0x76, 0x97, 0x4d, 0xd5, 0xb6, 0x90, 0xdb, 0x3f, 0xd4, 0x25, 0xb6, 0xd4,
+    0xb6, 0xef, 0x32, 0x47, 0x45, 0x2c, 0xa3, 0xb3, 0xbd, 0x2b, 0x68, 0x1f,
+    0x0a, 0x66, 0xe3, 0x00, 0x0f, 0xa1, 0x39, 0xf4, 0x6a, 0x20, 0x7e, 0x4a,
+    0xa8, 0x70, 0xd5, 0x0d, 0x6b, 0x26, 0x5f, 0xbb, 0xf3, 0x64, 0xa1, 0x8b,
+    0x5d, 0xbb, 0x2c, 0x08, 0x92, 0x17, 0xe0, 0xd4, 0xb9, 0xcb, 0xce, 0xf7,
+    0x14, 0x24, 0x81, 0x66, 0x42, 0x13, 0x77, 0x40, 0x32, 0xa0, 0x5b, 0x7a,
+    0x50, 0x0c, 0xcd, 0x24, 0xd6, 0xcb, 0xb5, 0x63, 0x9d, 0x28, 0x61, 0xb9,
+    0xdb, 0xb0, 0xc8, 0x83, 0x07, 0x1e, 0x16, 0xdd, 0xb7, 0xe0, 0x00, 0x92,
+    0xbd, 0xd2, 0x3a, 0xcf, 0xd0, 0x09, 0x2d, 0xa8, 0x7c, 0x58, 0x89, 0x14,
+    0x22, 0xa3, 0x73, 0xfb, 0xb7, 0xdc, 0x40, 0x99, 0x2d, 0x01, 0x54, 0x9a,
+    0x85, 0x1c, 0x37, 0x29, 0xc3, 0x4e, 0x6f, 0x57, 0xd7, 0x90, 0x8f, 0x81,
+    0x62, 0x5d, 0xcb, 0xac, 0x01, 0x27, 0x90, 0xbc, 0xa9, 0x03, 0xd6, 0x02,
+    0x27, 0xfe, 0x5b, 0x22, 0xf8, 0x28, 0xf6, 0xdd, 0xba, 0x23, 0x7c, 0xad,
+    0xef, 0x7d, 0x9e, 0x27, 0x8c, 0xb9, 0x07, 0xee, 0xd7, 0x73, 0xbc, 0xef,
+    0xe8, 0xe8, 0xa5, 0x7a, 0x37, 0x93, 0xd3, 0x45, 0x66, 0x27, 0x28, 0x19,
+    0x6e, 0x6f, 0x9c, 0x18, 0x32, 0xd6, 0xd9, 0x78, 0x82, 0x81, 0x0b, 0xfe,
+    0xab, 0xa0, 0xc2, 0xe5, 0x2a, 0xd2, 0x11, 0x5e, 0x25, 0xb6, 0x9c, 0xe5,
+    0xef, 0x15, 0xaa, 0xe7, 0x02, 0x40, 0x01, 0x9b, 0xbb, 0x5f, 0xa1, 0x45,
+    0x1c, 0x16, 0xc3, 0x4a, 0x23, 0x71, 0xdb, 0xbd, 0xbd, 0x79, 0x96, 0xd2,
+    0x63, 0xb2, 0x3e, 0x2c, 0xb2, 0xd3, 0x51, 0x26, 0xf8, 0xb7, 0x4c, 0x49,
+    0x31, 0xca, 0x65, 0x29, 0x10, 0xe4, 0xb1, 0x47, 0x35, 0x3f, 0x5e, 0x9f,
+    0xc9, 0x75, 0x21, 0x72, 0xfe, 0xa2, 0xae, 0x12, 0xa8, 0xc6, 0xeb, 0xba,
+    0xce, 0xc5, 0xde, 0x7a, 0xb4, 0x11, 0xbf, 0xf3, 0x75, 0xcf, 0x92, 0xcc,
+    0xc0, 0xe8, 0x54, 0xab, 0x0b, 0x69, 0x67, 0x0f, 0xad, 0xd1, 0x9d, 0xed,
+    0x17, 0x97, 0xbe, 0x86, 0xdc, 0x29, 0x4a, 0xbf, 0xaa, 0x36, 0x1c, 0x53,
+    0x59, 0xed, 0xf1, 0x1c, 0xf7, 0xef, 0x1d, 0xc9, 0x40, 0x73, 0xb7, 0x56,
+    0x3a, 0x64, 0x18, 0x16, 0x59, 0x61, 0x8d, 0x9c, 0x51, 0x05, 0xdd, 0x4a,
+    0x27, 0x98, 0x34, 0x3a, 0xf2, 0xa9, 0x91, 0x0a, 0x2b, 0x00, 0xb6, 0x5d,
+    0xef, 0x51, 0x5d, 0x62, 0x14, 0x4e, 0x92, 0xd2, 0xb1, 0xc7, 0xda, 0x58,
+    0xe5, 0x0c, 0x66, 0xca, 0x16, 0x73, 0x7d, 0x22, 0x27, 0x09, 0x9a, 0x27,
+    0xdf, 0x4d, 0x28, 0xb9, 0xba, 0xa8, 0x64, 0x2c, 0xe2, 0x8a, 0x88, 0x53,
+    0x5b, 0xf5, 0xe2, 0x68, 0x18, 0x15, 0x24, 0xfd, 0x43, 0x6e, 0xd4, 0x43,
+    0xb7, 0x16, 0x0e, 0x29, 0x5b, 0x17, 0x5b, 0x78, 0x78, 0x19, 0xe5, 0x3f,
+    0x75, 0xcb, 0xbb, 0x46, 0x28, 0xd8, 0x73, 0x65, 0x8e, 0x77, 0x22, 0xb7,
+    0x4d, 0x86, 0x0d, 0xbb, 0x6a, 0x98, 0x30, 0x60, 0x4b, 0x26, 0x1b, 0xb3,
+    0xe1, 0xfa, 0x2b, 0xf2, 0x26, 0xa9, 0x52, 0xec, 0xda, 0x76, 0x49, 0x10,
+    0x86, 0x31, 0xb4, 0xdf, 0x67, 0xfb, 0xbd, 0xf3, 0x5f, 0xaa, 0x52, 0x47,
+    0xd9, 0x09, 0x67, 0x34, 0xde, 0x54, 0x4c, 0xb7, 0x28, 0x4e, 0x43, 0xc0,
+    0x7c, 0xd6, 0x71, 0xa4, 0xe9, 0x76, 0xc8, 0xa7, 0x93, 0x6c, 0x98, 0xb4,
+    0xb1, 0xb0, 0x74, 0x69, 0x6d, 0x02, 0x5b, 0xbb, 0xd8, 0x52, 0x71, 0xaf,
+    0xbc, 0xc5, 0x50, 0xec, 0x94, 0xa8, 0x8a, 0x94, 0xb9, 0x3c, 0x5b, 0x95,
+    0xc8, 0xb7, 0x0a, 0x7d, 0x97, 0x31, 0x0e, 0xb2, 0x3a, 0xa9, 0x91, 0x4b,
+    0x29, 0x61, 0x5e, 0xac, 0xc4, 0xfa, 0x2a, 0x41, 0x83, 0x2e, 0x9a, 0x92,
+    0x0e, 0x1e, 0x48, 0x6d, 0xdf, 0x63, 0x5f, 0x7b, 0xe6, 0xeb, 0xf7, 0x4f,
+    0x9f, 0x89, 0x46, 0x42, 0x8b, 0x96, 0x8c, 0x60, 0xf6, 0x84, 0xb2, 0x9c,
+    0xde, 0x5d, 0xdd, 0xf9, 0x85, 0xad, 0x9f, 0xa8, 0xa7, 0x59, 0xfa, 0x0c,
+    0x1a, 0x16, 0xd7, 0xf3, 0xf3, 0xc7, 0x1c, 0xc9, 0x3a, 0xe0, 0x6d, 0xb5,
+    0xd8, 0xb0, 0xe0, 0xc4, 0x6a, 0xba, 0x92, 0x45, 0x3e, 0x9e, 0x62, 0x42,
+    0xfc, 0x4f, 0x6c, 0x1c, 0x3e, 0xf2, 0x65, 0x48, 0x75, 0x42, 0xe8, 0xd8,
+    0x54, 0x61, 0x8d, 0x39, 0xbf, 0x5b, 0xf3, 0xce, 0x77, 0xf0, 0x27, 0x20,
+    0x91, 0x68, 0x4c, 0xfc, 0xde, 0x52, 0x4e, 0x20, 0x66, 0x6c, 0x1b, 0x4a,
+    0xa7, 0xc1, 0x8d, 0xcf, 0x13, 0xa2, 0x80, 0x0f, 0xdd, 0x82, 0xe6, 0x17,
+    0x16, 0xe4, 0x18, 0x71, 0xa7, 0x28, 0x63, 0x73, 0x1d, 0x2b, 0x8a, 0x2c,
+    0xa3, 0xcd, 0x7c, 0x85, 0x2c, 0x6e, 0x87, 0xb3, 0x8d, 0xcd, 0xba, 0xa3,
+    0xe4, 0xa6, 0xe2, 0x50, 0xa6, 0x50, 0xa6, 0xdb, 0x75, 0x6d, 0x6e, 0xbf,
+    0xc7, 0x96, 0x3b, 0x83, 0x90, 0xa7, 0x22, 0x19, 0x31, 0x14, 0x6a, 0x35,
+    0x4e, 0xf3, 0x10, 0x29, 0xce, 0xb7, 0x6d, 0x3c, 0x3e, 0xf6, 0xb6, 0x0c,
+    0x19, 0x69, 0xed, 0x5e, 0xdc, 0x11, 0xc6, 0x24, 0x09, 0x99, 0x6a, 0x16,
+    0x16, 0x18, 0xda, 0x66, 0xaf, 0x9d, 0x36, 0x8d, 0x43, 0xc9, 0x8a, 0xc4,
+    0x65, 0x68, 0x68, 0x16, 0xdf, 0x2b, 0xa7, 0x4e, 0xaf, 0x4f, 0xb2, 0x53,
+    0x8a, 0xb6, 0xa5, 0xa4, 0x82, 0xe1, 0x2d, 0xac, 0xe3, 0xbc, 0xe3, 0x92,
+    0xe6, 0x28, 0x0f, 0x10, 0xe1, 0x9e, 0x8d, 0x83, 0xab, 0xae, 0x32, 0x49,
+    0x11, 0x20, 0xd0, 0x82, 0x9a, 0xcf, 0x8d, 0x7c, 0x73, 0x8d, 0xb6, 0xa8,
+    0x10, 0x7d, 0x01, 0xab, 0x07, 0x30, 0x7d, 0x6d, 0xe6, 0x6b, 0x9d, 0xb6,
+    0xbe, 0x8c, 0x08, 0x6a, 0x16, 0x72, 0xb2, 0x94, 0x04, 0x64, 0x85, 0xc0,
+    0x92, 0xda, 0xae, 0x5d, 0xc6, 0x62, 0x71, 0xa1, 0x36, 0x86, 0x36, 0x0c,
+    0xdd, 0xc9, 0x2b, 0xc2, 0xa0, 0x67, 0x84, 0x64, 0xc3, 0x00, 0x00, 0x00,
+    0x01, 0x0b, 0x43, 0xf9, 0x16, 0xdf, 0x37, 0xad, 0x9e, 0xa7, 0x46, 0xde,
+    0xf0, 0xfc, 0xc2, 0xef, 0x8b, 0x71, 0xd3, 0xcf, 0x16, 0x92, 0x8a, 0x6f,
+    0x57, 0xc8, 0x21, 0x7f, 0xc8, 0x16, 0xb5, 0xbc, 0xb8, 0x52, 0xda, 0x43,
+    0x6f, 0x16, 0x37, 0x5b, 0xd7, 0x0f, 0x0a, 0x1e, 0x1a, 0xd2, 0x53, 0x39,
+    0xa0, 0x5b, 0x6c, 0x9f, 0x8b, 0x72, 0x7a, 0xca, 0xdc, 0xa9, 0x25, 0xc9,
+    0x00, 0x20, 0x43, 0xa8, 0x09, 0x69, 0xed, 0x3a, 0x1f, 0x23, 0x4d, 0x2d,
+    0xbe, 0x59, 0x84, 0x04, 0x99, 0x40, 0x47, 0x0c, 0x85, 0x85, 0x97, 0x49,
+    0x2d, 0xda, 0x04, 0x3f, 0xfa, 0xb4, 0x92, 0xdc, 0x48, 0x08, 0x40, 0x0e,
+    0x4e, 0x2b, 0xd7, 0x6d, 0x25, 0x95, 0x09, 0x4d, 0xe9, 0x39, 0xcb, 0xc9,
+    0xb8, 0x43, 0xb1, 0xb1, 0xa3, 0x09, 0x0c, 0x8e, 0x46, 0xfa, 0x72, 0x10,
+    0x76, 0x66, 0xdf, 0x0d, 0xb2, 0x2b, 0x68, 0x00, 0x6c, 0x28, 0x00, 0xf9,
+    0xe4, 0x45, 0x35, 0x6a, 0x62, 0xd2, 0x21, 0x19, 0xe0, 0x66, 0x80, 0x47,
+    0x69, 0xc1, 0x2a, 0x8c, 0x45, 0xc8, 0x2f, 0x2e, 0x2d, 0x38, 0xa5, 0x1b,
+    0x83, 0x61, 0x55, 0xbd, 0x29, 0x17, 0xef, 0x84, 0x4f, 0x9b, 0xc3, 0xa0,
+    0xf8, 0x6b, 0x84, 0xf5, 0x5f, 0xd1, 0x6e, 0xf3, 0xa1, 0xf9, 0x64, 0x9b,
+    0x32, 0x14, 0x75, 0x52, 0xeb, 0x79, 0xf1, 0xe4, 0xe3, 0x0a, 0xa1, 0x54,
+    0xb2, 0x89, 0x5e, 0x8d, 0x56, 0x1a, 0xdf, 0x82, 0xed, 0xfb, 0xc7, 0x41,
+    0xe6, 0x58, 0x96, 0x1a, 0xae, 0x0b, 0x1c, 0x35, 0x0a, 0x18, 0xde, 0x64,
+    0x5f, 0x39, 0xc7, 0xbe, 0x47, 0x66, 0xc3, 0xe6, 0xd5, 0x88, 0x51, 0xd4,
+    0xf0, 0xca, 0xde, 0x88, 0x01, 0x87, 0xc7, 0x3d, 0x7f, 0x5d, 0xf3, 0xcf,
+    0x2f, 0xe4, 0x99, 0x4c, 0x78, 0xa7, 0x65, 0x80, 0x16, 0x66, 0x2d, 0x57,
+    0xa0, 0xca, 0x12, 0xdc, 0x3a, 0x2f, 0xa1, 0x1e, 0x5b, 0xcf, 0x57, 0x4e,
+    0xdd, 0x4d, 0x89, 0x2d, 0x91, 0x70, 0xfa, 0xb2, 0x54, 0xa7, 0x96, 0xdd,
+    0xb7, 0x12, 0x6c, 0x84, 0x30, 0x2d, 0xb7, 0xa5, 0x37, 0x9d, 0xf9, 0x78,
+    0xeb, 0x64, 0xa1, 0x1b, 0x29, 0x5a, 0x80, 0x2b, 0x6c, 0x93, 0xf3, 0xce,
+    0x61, 0x61, 0x85, 0xd9, 0x09, 0x2d, 0x8c, 0x57, 0x19, 0xf0, 0x29, 0xd3,
+    0x24, 0x1b, 0x4f, 0xda, 0xfd, 0xa3, 0x49, 0xb6, 0xd5, 0xad, 0xa3, 0x87,
+    0xe8, 0x9c, 0xe7, 0x78, 0x88, 0x00, 0x28, 0xce, 0x24, 0xbb, 0x54, 0xe1,
+    0xb4, 0xe2, 0x13, 0x2b, 0x16, 0xd6, 0x8a, 0xdd, 0xc4, 0x6e, 0x35, 0xd8,
+    0x9e, 0x7b, 0x46, 0xe9, 0xb8, 0xec, 0xc9, 0x2a, 0xad, 0xa8, 0x83, 0x6b,
+    0x74, 0xfe, 0x6b, 0x80, 0x1c, 0xfc, 0x58, 0xee, 0xdf, 0x06, 0xe6, 0x3f,
+    0x87, 0xf3, 0xc6, 0x44, 0x89, 0x29, 0x32, 0xa2, 0x4a, 0x59, 0xd5, 0x0f,
+    0x6f, 0x31, 0x27, 0x96, 0xee, 0xa0, 0x52, 0x17, 0x5b, 0x50, 0x73, 0xf7,
+    0x6e, 0x14, 0x03, 0xdd, 0x96, 0x14, 0x30, 0xea, 0xa3, 0x5b, 0x7d, 0xaa,
+    0x95, 0xb7, 0xa3, 0x5b, 0xe9, 0x7f, 0x8d, 0x14, 0x26, 0x9a, 0xbe, 0x30,
+    0xb9, 0x06, 0x96, 0xdb, 0xb6, 0x93, 0xba, 0xe9, 0xda, 0x09, 0x7f, 0xf5,
+    0xed, 0xa8, 0xa7, 0x0e, 0x56, 0xf2, 0x7b, 0x60, 0x81, 0x0e, 0x96, 0xd0,
+    0xd5, 0xbe, 0x28, 0xde, 0xfb, 0xea, 0xe7, 0x39, 0xe2, 0x78, 0x7e, 0x50,
+    0xd9, 0xbf, 0x33, 0x49, 0xf6, 0x1c, 0x7b, 0xd6, 0x5c, 0xb9, 0x4a, 0x0a,
+    0x66, 0xb7, 0x9d, 0x80, 0x53, 0x6d, 0x00, 0x29, 0xb2, 0xb6, 0xa2, 0xb9,
+    0x04, 0x1f, 0xec, 0x7e, 0xf6, 0xed, 0x51, 0xc8, 0xe2, 0xa2, 0x8d, 0x2e,
+    0xc5, 0x18, 0x59, 0xc9, 0x5b, 0xa5, 0x2c, 0xfb, 0x65, 0x9a, 0x19, 0x71,
+    0x08, 0xe9, 0x6d, 0x90, 0x27, 0x92, 0xe2, 0xb5, 0x1f, 0xde, 0x60, 0x91,
+    0x1d, 0x3d, 0xf7, 0x02, 0xc5, 0x74, 0x24, 0x53, 0xec, 0x38, 0xed, 0xa5,
+    0xfa, 0x36, 0xc9, 0xba, 0x47, 0xc7, 0xde, 0x94, 0x32, 0xf1, 0x82, 0x77,
+    0x9b, 0x14, 0x36, 0x06, 0x00, 0x8e, 0x37, 0x63, 0x7a, 0x0d, 0xf9, 0xde,
+    0x67, 0x1d, 0x5f, 0x82, 0xb6, 0x9c, 0x98, 0x4e, 0x7c, 0xd4, 0x2d, 0x50,
+    0xa3, 0x88, 0x6a, 0xdb, 0x78, 0xea, 0x77, 0xbf, 0x97, 0xbe, 0x81, 0x10,
+    0x3b, 0x6c, 0xbf, 0xb1, 0xdb, 0x06, 0x78, 0x04, 0xb4, 0x12, 0x08, 0x40,
+    0x0d, 0xb4, 0xd9, 0x60, 0x62, 0x3a, 0xd2, 0xd5, 0x61, 0xd4, 0xa2, 0x86,
+    0x9e, 0xdc, 0xec, 0xa0, 0x06, 0x9d, 0xf3, 0xa9, 0x06, 0xa8, 0x04, 0xb5,
+    0x7c, 0x07, 0xd3, 0xa0, 0x53, 0x03, 0x1a, 0x46, 0xb6, 0x08, 0xd3, 0x87,
+    0x88, 0xdb, 0x82, 0xf9, 0x90, 0xac, 0xfc, 0xae, 0x19, 0x9c, 0x13, 0x57,
+    0xc5, 0xba, 0x3b, 0x08, 0x3d, 0x42, 0x7c, 0x01, 0x56, 0x6c, 0x42, 0x9b,
+    0xe7, 0x46, 0x87, 0xd8, 0x90, 0x30, 0xca, 0x02, 0xe6, 0xfa, 0xc1, 0x16,
+    0xc0, 0x06, 0x64, 0x4e, 0xcd, 0x72, 0x14, 0xbb, 0xca, 0xae, 0x4d, 0x92,
+    0xa1, 0xe8, 0x96, 0xc0, 0xa6, 0x74, 0xa6, 0x9c, 0xab, 0x4a, 0x6f, 0x33,
+    0x9d, 0x39, 0xef, 0xa0, 0xeb, 0x42, 0xf6, 0x45, 0x1c, 0x77, 0xab, 0x76,
+    0x1d, 0xef, 0xe4, 0x56, 0x2a, 0x16, 0x93, 0x12, 0x48, 0x65, 0x2d, 0x46,
+    0x36, 0x5f, 0x90, 0x43, 0xff, 0x87, 0x59, 0xab, 0x12, 0xe4, 0x2a, 0x4d,
+    0x2e, 0x55, 0x85, 0x21, 0xda, 0x16, 0xd8, 0x1f, 0xbc, 0x13, 0x9d, 0x92,
+    0xec, 0x1b, 0x99, 0x72, 0x9d, 0x9a, 0x35, 0x4b, 0x3a, 0x05, 0x36, 0x67,
+    0x36, 0x97, 0x4a, 0x46, 0xfd, 0x07, 0x3e, 0xe0, 0x16, 0x3e, 0xf1, 0x26,
+    0x01, 0x2e, 0xf3, 0xa1, 0xd5, 0xd2, 0xc2, 0xce, 0xa3, 0x06, 0xfa, 0xb7,
+    0x0e, 0x0b, 0xe0, 0x4f, 0x59, 0x93, 0x62, 0x17, 0x67, 0x73, 0x26, 0x62,
+    0x6a, 0x06, 0x8d, 0xbe, 0x0c, 0x3b, 0xb8, 0x2f, 0x87, 0x64, 0xa3, 0x91,
+    0xdc, 0xcd, 0x54, 0x28, 0x79, 0x0d, 0x83, 0xde, 0x62, 0x47, 0xa5, 0x38,
+    0x9b, 0x2a, 0x98, 0x32, 0x9c, 0x8d, 0x11, 0xab, 0x46, 0xb6, 0xcf, 0xb2,
+    0x72, 0x86, 0x6c, 0xa5, 0xfe, 0xd1, 0x12, 0xc2, 0xa3, 0x40, 0x0b, 0x6e,
+    0x99, 0x71, 0x03, 0x26, 0x86, 0xa2, 0x56, 0x77, 0xdf, 0x37, 0xec, 0x5d,
+    0x1d, 0x24, 0x51, 0x8d, 0x8b, 0xaf, 0xc1, 0x69, 0x07, 0xaa, 0x0c, 0x18,
+    0xc4, 0x6a, 0xad, 0xd5, 0xe7, 0xc3, 0x8c, 0x7c, 0xcd, 0x2d, 0x69, 0x86,
+    0x0f, 0x3e, 0x14, 0xa8, 0x4b, 0x6d, 0xa2, 0x77, 0xce, 0xd8, 0xeb, 0xd8,
+    0x0f, 0x16, 0xd9, 0x2c, 0x88, 0x51, 0xed, 0xc2, 0x8f, 0x36, 0xc3, 0x10,
+    0x75, 0x56, 0xec, 0xe7, 0x2f, 0x17, 0x7c, 0xaa, 0x4a, 0x02, 0x22, 0xd1,
+    0x0f, 0x62, 0x14, 0xc5, 0x2e, 0x37, 0x7e, 0xc9, 0xc4, 0xb8, 0x90, 0x2f,
+    0xd4, 0x05, 0xed, 0x9c, 0xc3, 0x76, 0xd5, 0x08, 0x4b, 0x1b, 0xaa, 0xe9,
+    0xe5, 0x8b, 0x54, 0xa4, 0x6e, 0x7e, 0xd7, 0x64, 0x0e, 0x94, 0xe2, 0xcb,
+    0xa5, 0x14, 0x35, 0xa0, 0x61, 0x4d, 0xaa, 0x96, 0x5b, 0x6a, 0xb9, 0xb7,
+    0xf6, 0x19, 0x30, 0xb2, 0xea, 0xad, 0x6c, 0x5b, 0xcb, 0x8c, 0xcf, 0x2b,
+    0x14, 0xea, 0xa8, 0x5c, 0x52, 0xce, 0x6e, 0x98, 0xae, 0xd0, 0xdb, 0x2d,
+    0x19, 0x25, 0x42, 0xc8, 0x6d, 0xcc, 0xfc, 0xf5, 0x96, 0xee, 0xd1, 0xe3,
+    0x68, 0x53, 0x38, 0xd9, 0x9c, 0xde, 0xff, 0xc4, 0xe6, 0xc3, 0x68, 0x59,
+    0xed, 0x88, 0x57, 0x3b, 0x95, 0x77, 0x3c, 0x06, 0x23, 0x54, 0x25, 0xdc,
+    0xf2, 0xe5, 0xe7, 0x8e, 0x1f, 0x94, 0x39, 0xf2, 0x53, 0x9b, 0xe8, 0x00,
+    0x81, 0xfa, 0xa0, 0x0f, 0xbe, 0x40, 0x1e, 0xfd, 0xb8, 0x8e, 0x16, 0xe3,
+    0x4d, 0x97, 0xae, 0x05, 0xee, 0x43, 0x2c, 0x7e, 0x5b, 0x03, 0xe5, 0x38,
+    0x7b, 0x54, 0x65, 0x1b, 0xf9, 0xe9, 0x13, 0x1e, 0x91, 0x47, 0x14, 0x79,
+    0x74, 0xa6, 0x4b, 0xd5, 0xc1, 0x56, 0xaa, 0x84, 0x54, 0x59, 0x11, 0x61,
+    0x45, 0x0c, 0x6f, 0xba, 0x02, 0x07, 0xe7, 0x80, 0x59, 0x9f, 0xda, 0xe1,
+    0x19, 0x34, 0x38, 0xde, 0x5f, 0x61, 0x97, 0x65, 0xc8, 0x62, 0xda, 0x3c,
+    0xb4, 0x8d, 0xec, 0x7e, 0x08, 0xa4, 0x70, 0x06, 0xbf, 0xf8, 0xfa, 0xfe,
+    0xe8, 0x76, 0x4b, 0x86, 0xc8, 0x4c, 0xcc, 0x83, 0x1b, 0xcd, 0x22, 0x73,
+    0x1d, 0xcb, 0x9f, 0x96, 0x51, 0xd2, 0x37, 0x08, 0x87, 0x99, 0xb9, 0xb3,
+    0xd1, 0xbf, 0x92, 0x02, 0x07, 0xe6, 0x7d, 0xa0, 0x03, 0x3f, 0xe3, 0xf8,
+    0xf8, 0xf9, 0xca, 0x95, 0x1d, 0xe6, 0x85, 0xe3, 0x9f, 0x0b, 0x85, 0x50,
+    0xc5, 0x6f, 0xd0, 0x00, 0x05, 0x20, 0x0e, 0x44, 0xfd, 0x40, 0x1f, 0xf7,
+    0xaf, 0xeb, 0x40, 0x8e, 0xb8, 0xc2, 0xec, 0x31, 0x57, 0x74, 0x29, 0xbb,
+    0xe0, 0x0c, 0x39, 0xdf, 0x8e, 0xe5, 0xde, 0x10, 0x22, 0xc0, 0x2e, 0x36,
+    0x92, 0x25, 0xd1, 0x3f, 0x05, 0x50, 0x92, 0x88, 0x48, 0xd6, 0x20, 0x5f,
+    0x06, 0x39, 0xf7, 0x28, 0x4e, 0x36, 0x5c, 0x24, 0xc9, 0x6b, 0x00, 0x00,
+    0x00, 0x01, 0x0c, 0x43, 0xd4, 0x08, 0x1f, 0xa2, 0x01, 0x61, 0x14, 0x5e,
+    0x67, 0xf0, 0x4e, 0xcf, 0xd6, 0xf2, 0xfe, 0x71, 0x0c, 0xe2, 0x54, 0xda,
+    0xb6, 0x8c, 0x0a, 0xad, 0xd1, 0x00, 0x63, 0x8f, 0x22, 0x88, 0x22, 0xbb,
+    0xbb, 0x4e, 0x04, 0x50, 0x0f, 0xb9, 0x5f, 0x25, 0x0f, 0xfd, 0xf9, 0xe4,
+    0x28, 0x25, 0xbe, 0xad, 0xa2, 0xdc, 0x00, 0xd0, 0x00, 0x45, 0x9c, 0x50,
+    0xc0, 0xe8, 0x6e, 0xbe, 0xad, 0x32, 0xfe, 0xe5, 0x26, 0xc2, 0x86, 0x54,
+    0x63, 0xc8, 0x82, 0x7f, 0xc8, 0x03, 0xd0, 0xfb, 0x6f, 0xec, 0x10, 0x80,
+    0x2a, 0xbf, 0xcc, 0x02, 0x27, 0x75, 0x2c, 0x0d, 0x3d, 0xbc, 0x2a, 0x93,
+    0x65, 0x28, 0x02, 0x23, 0xdb, 0x8b, 0x74, 0xc2, 0xe9, 0x09, 0xbf, 0xc9,
+    0x70, 0x10, 0x80, 0x1e, 0x47, 0xa4, 0x0d, 0xab, 0x52, 0x0e, 0x3a, 0x8d,
+    0xa1, 0x6c, 0x2e, 0x2c, 0x59, 0xb4, 0x36, 0xda, 0x53, 0x0c, 0xfc, 0x57,
+    0x00, 0x0c, 0x24, 0x39, 0x9c, 0xb7, 0x8d, 0xf4, 0x2d, 0xb7, 0x85, 0xda,
+    0xdc, 0x0d, 0xf2, 0xb9, 0x03, 0x12, 0x42, 0x44, 0x6f, 0x75, 0xb2, 0xf6,
+    0xfe, 0xcd, 0x0a, 0x0f, 0x35, 0xbc, 0xe6, 0x97, 0x8a, 0x42, 0xa6, 0x52,
+    0x5a, 0x37, 0xd3, 0x04, 0xbf, 0xf3, 0x6b, 0xac, 0x0d, 0xf3, 0xdd, 0xd9,
+    0x26, 0x1e, 0x36, 0x5a, 0x54, 0x3c, 0x6b, 0x4c, 0x2e, 0xa1, 0x29, 0x59,
+    0x46, 0xf7, 0x7d, 0xbe, 0x35, 0xcf, 0xfe, 0xbb, 0x45, 0xe9, 0xd2, 0xeb,
+    0x89, 0xfc, 0xef, 0x7c, 0xbe, 0x58, 0x6c, 0xa9, 0xe7, 0x13, 0x33, 0x32,
+    0x18, 0x7c, 0x0b, 0x6f, 0x9d, 0x4e, 0x32, 0xe7, 0x19, 0x96, 0x0f, 0xb9,
+    0x0e, 0xa6, 0x42, 0xce, 0x5a, 0x5d, 0x6a, 0x28, 0x88, 0xe7, 0x4f, 0x2b,
+    0x90, 0x73, 0xed, 0x98, 0xaf, 0x53, 0xcb, 0x44, 0x08, 0x6b, 0x30, 0x38,
+    0x5e, 0x6c, 0x88, 0x02, 0xb9, 0x57, 0xd6, 0x37, 0x9c, 0x98, 0x61, 0x49,
+    0x46, 0xa6, 0x52, 0x99, 0x99, 0x23, 0x7d, 0x90, 0x05, 0x84, 0x52, 0x38,
+    0xaf, 0xa8, 0x94, 0xf6, 0x2c, 0x11, 0x00, 0x17, 0x08, 0x98, 0xe3, 0x66,
+    0xf2, 0x62, 0xc5, 0xf2, 0x0c, 0xa1, 0x4d, 0xf2, 0x27, 0x49, 0x38, 0x73,
+    0x8b, 0x1e, 0x54, 0x87, 0x81, 0x4d, 0xd1, 0xca, 0x00, 0x64, 0xe7, 0x29,
+    0x0a, 0x94, 0xdc, 0xc5, 0x9e, 0x51, 0xf5, 0x42, 0x0d, 0x75, 0x84, 0x30,
+    0xc6, 0xf4, 0xf2, 0x2e, 0x54, 0xf4, 0x56, 0xe9, 0x90, 0xaa, 0x49, 0x6c,
+    0x9e, 0xe0, 0x2d, 0xb3, 0xd4, 0x14, 0xf8, 0x00, 0x31, 0x88, 0xdd, 0xf2,
+    0x3b, 0xaf, 0x3a, 0x59, 0x0d, 0xb2, 0x55, 0xfa, 0x1b, 0x62, 0xd0, 0xb2,
+    0x43, 0x22, 0x64, 0x64, 0x39, 0xbe, 0x54, 0x4e, 0xf3, 0x11, 0x43, 0x0f,
+    0x48, 0xbe, 0xad, 0xa3, 0xad, 0xd1, 0x53, 0xf2, 0xa0, 0x53, 0x71, 0xac,
+    0x3a, 0xa8, 0x4a, 0x94, 0xdd, 0x17, 0xec, 0x58, 0x6a, 0x06, 0x29, 0x4a,
+    0x39, 0xa1, 0x4e, 0x8c, 0xe3, 0x68, 0xa0, 0x16, 0xf1, 0xc6, 0xcd, 0x09,
+    0x2e, 0x4a, 0xbe, 0xad, 0xfa, 0x64, 0x01, 0xb8, 0x9a, 0x00, 0xeb, 0xee,
+    0x00, 0xe7, 0x7d, 0xfc, 0xa4, 0x28, 0xcc, 0x00, 0x3d, 0x17, 0xc3, 0x9d,
+    0x07, 0x95, 0x84, 0xed, 0xb8, 0xb4, 0x07, 0x8b, 0x6b, 0x7e, 0x71, 0xdf,
+    0xcb, 0xf2, 0x10, 0x8a, 0x6f, 0xd3, 0x20, 0x0a, 0x14, 0x10, 0x40, 0x4c,
+    0x8f, 0xdd, 0xf3, 0xa0, 0x11, 0x73, 0xb9, 0xb0, 0x05, 0x4a, 0xb4, 0x34,
+    0x62, 0xb7, 0x36, 0x6c, 0xe3, 0x7c, 0xb2, 0xe0, 0x6a, 0xee, 0xc0, 0x86,
+    0x98, 0x5e, 0xe4, 0x25, 0xb7, 0xf2, 0x89, 0x08, 0x3e, 0xf4, 0x55, 0x40,
+    0x47, 0xff, 0xd8, 0x27, 0x5d, 0xce, 0x48, 0x08, 0xff, 0xfb, 0xf8, 0x99,
+    0xa5, 0x04, 0x94, 0x5b, 0x74, 0x2e, 0x80, 0x1f, 0x00, 0x1b, 0x23, 0xe5,
+    0x02, 0x64, 0x76, 0x76, 0xa5, 0x94, 0x4c, 0xcd, 0x2e, 0x12, 0x9b, 0x37,
+    0x34, 0x0c, 0x11, 0x4e, 0x0c, 0xbd, 0x0a, 0x17, 0x2e, 0x20, 0xdf, 0xd6,
+    0xe6, 0x6d, 0x01, 0x1d, 0x48, 0xdd, 0x4b, 0x00, 0x0f, 0x05, 0x0a, 0xe1,
+    0x36, 0x06, 0x42, 0x2c, 0x7c, 0xc0, 0xc1, 0x9e, 0x72, 0x16, 0x18, 0xde,
+    0xb0, 0xc6, 0xf6, 0xcf, 0x6f, 0xce, 0x7b, 0x26, 0x4d, 0x4d, 0x7d, 0x18,
+    0x55, 0x33, 0x65, 0xbb, 0x14, 0x08, 0x7d, 0xb5, 0xb8, 0xcb, 0x5d, 0xc7,
+    0x1b, 0x60, 0xec, 0x99, 0x2c, 0x0e, 0x1e, 0x03, 0x36, 0xeb, 0x48, 0xff,
+    0x62, 0x05, 0xb8, 0x58, 0xd4, 0x15, 0x3c, 0xb6, 0xd3, 0xa0, 0xd9, 0xa9,
+    0xe2, 0xad, 0x97, 0x90, 0x42, 0xff, 0x5d, 0xbc, 0x20, 0x5e, 0x24, 0x2e,
+    0xfa, 0x12, 0x98, 0x87, 0xb5, 0x53, 0x9b, 0x41, 0x22, 0xf4, 0x5f, 0x7c,
+    0xef, 0x96, 0xd8, 0x32, 0x4e, 0x9c, 0x62, 0x8d, 0xfd, 0xac, 0x29, 0xbd,
+    0x29, 0x19, 0xd3, 0xeb, 0xfd, 0xee, 0xd1, 0x7b, 0x75, 0x64, 0x7c, 0x5c,
+    0xd9, 0x92, 0x4a, 0xba, 0x9e, 0x70, 0x9a, 0x90, 0x39, 0xb8, 0x2b, 0x09,
+    0xf9, 0x64, 0x09, 0xb1, 0x70, 0xe1, 0xa7, 0x44, 0x3c, 0x21, 0xae, 0x74,
+    0xd7, 0x08, 0xce, 0x67, 0x36, 0xd4, 0x3b, 0x69, 0x91, 0xd2, 0x58, 0x7a,
+    0xc2, 0x83, 0x94, 0xb6, 0x89, 0x1b, 0x3a, 0x54, 0x56, 0xf4, 0xdc, 0xf6,
+    0x15, 0xaf, 0xa2, 0xb2, 0x40, 0x09, 0x6c, 0x31, 0x16, 0xa1, 0xc3, 0xce,
+    0x39, 0xb0, 0xe5, 0x79, 0x3d, 0xf5, 0xf2, 0x2f, 0xe9, 0x23, 0xa2, 0xa5,
+    0x3c, 0x29, 0xbb, 0x3c, 0xdd, 0x14, 0x2f, 0x71, 0x0b, 0x3b, 0x3c, 0xae,
+    0x38, 0xfa, 0x12, 0x35, 0x02, 0x5b, 0x3a, 0xce, 0xd3, 0x8e, 0x8b, 0x02,
+    0x43, 0xb0, 0x3e, 0x0f, 0x2a, 0xfa, 0xb4, 0xc8, 0x53, 0x6d, 0xb5, 0x6b,
+    0x6d, 0xce, 0xae, 0x5d, 0x18, 0x7c, 0x2d, 0x42, 0x9a, 0xfd, 0xd8, 0xfb,
+    0x37, 0x28, 0x4d, 0xa5, 0x9c, 0x15, 0xea, 0xdc, 0x8e, 0xb2, 0xe7, 0x50,
+    0xe8, 0x3e, 0x86, 0x8c, 0x21, 0x04, 0xb5, 0xb7, 0x11, 0xf0, 0xb1, 0xc7,
+    0x0f, 0x30, 0xf2, 0xda, 0x6b, 0x68, 0xde, 0xcc, 0xf3, 0x72, 0xee, 0xbe,
+    0x8e, 0xc2, 0xce, 0x90, 0x90, 0xdc, 0xd1, 0x40, 0x61, 0xd6, 0xdb, 0xb4,
+    0xe0, 0xc1, 0xc8, 0xcc, 0x08, 0x60, 0x0b, 0x99, 0xa3, 0x4e, 0xab, 0xa3,
+    0x1b, 0x1b, 0xdf, 0xe7, 0x61, 0xc0, 0x3c, 0x33, 0x2c, 0x09, 0x0d, 0x62,
+    0x56, 0x2b, 0x76, 0x75, 0x72, 0xda, 0x99, 0x96, 0x8d, 0xb6, 0x16, 0xd8,
+    0xf2, 0x9b, 0xce, 0x92, 0x0f, 0x6d, 0x8e, 0x7d, 0xc7, 0x9b, 0x32, 0x0d,
+    0x2f, 0x10, 0xb8, 0xa5, 0x9c, 0xce, 0x26, 0x00, 0x1f, 0xfb, 0x48, 0x81,
+    0xa6, 0xdc, 0xb9, 0xb3, 0xd4, 0xe6, 0x89, 0x52, 0x94, 0xd9, 0x66, 0xcc,
+    0x79, 0x4d, 0xd3, 0x99, 0x67, 0x05, 0xa4, 0x0b, 0x53, 0xdb, 0xd4, 0x80,
+    0x37, 0x14, 0xef, 0xaf, 0x5b, 0xc3, 0xbd, 0xf9, 0xca, 0x96, 0xbb, 0x1f,
+    0xbc, 0x2d, 0x93, 0x5d, 0x77, 0x28, 0x6a, 0x96, 0xde, 0x9f, 0xe4, 0x47,
+    0xbf, 0xfc, 0x01, 0x8f, 0x5f, 0x0e, 0x76, 0xaa, 0x19, 0x86, 0xbd, 0xff,
+    0xb1, 0xbe, 0x90, 0xb6, 0xc1, 0x05, 0xf1, 0xbf, 0x1f, 0x1c, 0x00, 0x56,
+    0xf9, 0x2e, 0x69, 0x3a, 0xf3, 0xd1, 0x99, 0xa5, 0x87, 0xa8, 0x79, 0x92,
+    0x16, 0x10, 0xdc, 0xbd, 0x07, 0x00, 0xe4, 0x84, 0xde, 0x68, 0x89, 0xe5,
+    0x57, 0x42, 0x9b, 0xe9, 0x80, 0x14, 0xfc, 0x8a, 0x77, 0x28, 0x2a, 0x3a,
+    0x87, 0x4f, 0x37, 0x17, 0x71, 0x12, 0x1b, 0x0e, 0xf5, 0x6e, 0xc8, 0x01,
+    0x3f, 0xce, 0x7c, 0x90, 0x26, 0xfb, 0x75, 0xfb, 0xf2, 0x79, 0x92, 0x9b,
+    0x13, 0xf0, 0xb6, 0x0f, 0x5b, 0x5b, 0xd9, 0x80, 0x3c, 0xff, 0xe7, 0xc9,
+    0x07, 0x7a, 0x9d, 0xc9, 0x40, 0x27, 0x2e, 0x66, 0xdb, 0x51, 0x74, 0xe1,
+    0xd5, 0x50, 0xe8, 0xad, 0xee, 0xfe, 0x3f, 0xa2, 0x9e, 0x2c, 0x5e, 0x76,
+    0xf7, 0xc0, 0x1e, 0x73, 0x39, 0xc7, 0xc8, 0x90, 0x38, 0x3a, 0xad, 0x44,
+    0x38, 0x31, 0xbc, 0xde, 0xc4, 0x0a, 0xb8, 0x55, 0x2c, 0x34, 0xe8, 0x8d,
+    0xca, 0xe7, 0x70, 0x88, 0x58, 0x5b, 0x7f, 0x34, 0x00, 0x78, 0x23, 0x90,
+    0x03, 0x5e, 0xfd, 0xe7, 0xce, 0x5a, 0x4d, 0xe6, 0xbf, 0x76, 0xed, 0xa6,
+    0x17, 0x87, 0x7a, 0x1c, 0xdd, 0xd0, 0x04, 0xd8, 0x29, 0xfb, 0x5f, 0xc6,
+    0xec, 0x85, 0x2f, 0x96, 0xd5, 0xf2, 0x0b, 0xc0, 0xc6, 0xbb, 0xe8, 0x47,
+    0x70, 0x03, 0xa2, 0x27, 0xba, 0xc1, 0x38, 0xaa, 0x66, 0x13, 0x95, 0x64,
+    0xb1, 0x69, 0x41, 0x10, 0xb6, 0xf8, 0xb7, 0xb8, 0x8a, 0x46, 0xaf, 0x93,
+    0xe3, 0x61, 0xf3, 0x97, 0x73, 0x1e, 0x67, 0x9c, 0x3a, 0xc5, 0x68, 0x7b,
+    0xb8, 0xe9, 0x54, 0xa1, 0xb4, 0x04, 0x4d, 0xcd, 0x33, 0x31, 0x16, 0x46,
+    0xfe, 0xd4, 0x00, 0xe9, 0xdc, 0x7c, 0x08, 0x7e, 0xe4, 0xbb, 0x52, 0x07,
+    0xea, 0x54, 0x92, 0x0d, 0x6f, 0x0f, 0x7b, 0xc7, 0x6f, 0x4e, 0xeb, 0x50,
+    0x11, 0xff, 0xef, 0x74, 0xcc, 0x43, 0xce, 0xaa, 0xdc, 0x91, 0x41, 0xc2,
+    0xc8, 0xb3, 0x71, 0x00, 0x8c, 0x9d, 0xed, 0xc9, 0x10, 0xea, 0x6a, 0xe4,
+    0x5a, 0x18, 0xdc, 0x20, 0x0a, 0x3a, 0xf6, 0x7f, 0x0e, 0xa2, 0x5c, 0x3b,
+    0x76, 0xcc, 0xab, 0x2c, 0x4a, 0x50, 0x6f, 0x83, 0x79, 0xfc, 0x8a, 0x9e,
+    0x4e, 0x8e, 0x74, 0xa1, 0x35, 0x5b, 0x33, 0x11, 0x12, 0x37, 0xd7, 0x00,
+    0x40, 0xff, 0x79, 0xa2, 0x1d, 0x5d, 0x5d, 0x2a, 0xd9, 0x5e, 0xe3, 0x0d,
+    0xa1, 0x6d, 0xf6, 0x00, 0x05, 0xdf, 0x34, 0x01, 0xb8, 0x03, 0xce, 0x6f,
+    0x7d, 0x82, 0x47, 0xfe, 0x38, 0xda, 0x62, 0x1f, 0x0b, 0x81, 0xad, 0xf0,
+    0xbe, 0xbe, 0xff, 0x22, 0x44, 0xed, 0xdf, 0x83, 0x16, 0xd8, 0xe7, 0x66,
+    0xa1, 0x86, 0xdf, 0xca, 0x25, 0x28, 0xf8, 0xdf, 0x5c, 0x9f, 0x5e, 0xff,
+    0xe2, 0xb7, 0xae, 0xf9, 0xe6, 0x8d, 0x2a, 0xd5, 0x36, 0x40, 0xc6, 0xf6,
+    0x36, 0xbf, 0x97, 0xc3, 0x6e, 0x96, 0x4a, 0x6d, 0xa0, 0x7d, 0x8a, 0x4a,
+    0x60, 0x00, 0x00, 0x01, 0x0d, 0x43, 0xf7, 0xdd, 0x8a, 0x78, 0x80, 0x06,
+    0xc0, 0x0d, 0x05, 0x73, 0x52, 0x25, 0x20, 0x02, 0x10, 0x03, 0xf7, 0x2b,
+    0x8d, 0x50, 0xea, 0x6d, 0xa5, 0x95, 0x43, 0x65, 0x6f, 0x4c, 0x00, 0xf8,
+    0x5b, 0x80, 0x1b, 0x77, 0xcf, 0xcd, 0xdc, 0xa3, 0xe7, 0x9f, 0x0b, 0x24,
+    0x3a, 0xfe, 0xa5, 0x29, 0x43, 0x1a, 0x10, 0x34, 0x89, 0xcd, 0xde, 0x5f,
+    0xc5, 0xa7, 0x77, 0x37, 0xc9, 0x21, 0x8a, 0x61, 0xc1, 0x2d, 0xf3, 0xe0,
+    0x07, 0xc0, 0x0d, 0x78, 0xe7, 0xe4, 0x88, 0xff, 0x6f, 0x68, 0x85, 0xf9,
+    0x3e, 0x6d, 0x96, 0x6e, 0x2a, 0x40, 0xe9, 0x21, 0x77, 0xc1, 0xbc, 0x34,
+    0xfc, 0x56, 0xe7, 0x96, 0x64, 0xb2, 0xac, 0xa5, 0x8e, 0x52, 0x82, 0x02,
+    0x5b, 0xf8, 0x7d, 0xcb, 0xe7, 0x95, 0x60, 0x62, 0x4b, 0x2c, 0x21, 0x56,
+    0xd9, 0x06, 0xd6, 0xfa, 0xb0, 0x02, 0x1c, 0x80, 0x09, 0x1c, 0x28, 0x89,
+    0xf5, 0x10, 0xf8, 0x1d, 0x67, 0x7c, 0xf6, 0xee, 0xa4, 0x35, 0xda, 0x5e,
+    0x54, 0x1c, 0xa3, 0x61, 0x4d, 0x98, 0x10, 0x3f, 0x4b, 0xf9, 0xa0, 0x0f,
+    0xfe, 0x33, 0x3d, 0x88, 0xf9, 0x46, 0x49, 0xdb, 0xf2, 0x24, 0xe3, 0x4b,
+    0xb8, 0xaa, 0xd9, 0xc2, 0xe2, 0x94, 0xde, 0x7b, 0xe1, 0xcd, 0xf1, 0x80,
+    0x1c, 0x8a, 0xec, 0x01, 0x0f, 0xf0, 0x43, 0xb5, 0xd8, 0x1b, 0x39, 0x9d,
+    0x87, 0x28, 0x0a, 0xa8, 0xdf, 0x46, 0xfb, 0x7f, 0x7e, 0x77, 0xfe, 0x40,
+    0x31, 0xf4, 0x63, 0xae, 0x3b, 0xf3, 0x77, 0xc1, 0x0a, 0x40, 0xb6, 0xfa,
+    0x37, 0xf7, 0xe7, 0xbf, 0xa8, 0x03, 0x71, 0x62, 0x44, 0xe8, 0x62, 0x6b,
+    0xd4, 0x39, 0x3f, 0x08, 0x98, 0x32, 0x48, 0xdf, 0x3f, 0xfe, 0x0b, 0x00,
+    0x10, 0x67, 0x57, 0x66, 0x0c, 0xa5, 0xe1, 0x65, 0x9e, 0xd3, 0x23, 0xba,
+    0xe5, 0xf6, 0xda, 0x02, 0x29, 0x0b, 0x6b, 0xdb, 0x31, 0xf4, 0xbf, 0x06,
+    0xfe, 0x5f, 0xdf, 0xbe, 0xfd, 0xb2, 0x75, 0xd6, 0xd4, 0x2d, 0x65, 0x88,
+    0x89, 0xe8, 0xde, 0x08, 0x00, 0xf5, 0xe2, 0x3d, 0x9c, 0xfe, 0x79, 0xc9,
+    0x13, 0xf0, 0xee, 0xe0, 0xea, 0x03, 0x56, 0xfa, 0x3f, 0xd5, 0xc0, 0x82,
+    0x02, 0x7e, 0xdc, 0x9a, 0x5c, 0x39, 0x49, 0xf9, 0x21, 0xdb, 0x25, 0x2e,
+    0x0d, 0x6f, 0x8d, 0x75, 0x67, 0x44, 0x0e, 0x6a, 0x84, 0x3d, 0x72, 0x98,
+    0x38, 0xe1, 0xc3, 0x5b, 0x93, 0x78, 0x82, 0x66, 0xbb, 0x89, 0x83, 0xe2,
+    0x5c, 0x6c, 0x2c, 0x34, 0xa8, 0xda, 0x11, 0x45, 0xe0, 0x87, 0x53, 0x2b,
+    0x8e, 0x53, 0x35, 0x15, 0x2a, 0x1c, 0x1a, 0x90, 0xe6, 0xa3, 0xfb, 0xb6,
+    0xed, 0xb6, 0x00, 0x46, 0x5d, 0x28, 0x28, 0x31, 0xbd, 0x8e, 0x77, 0x78,
+    0xa2, 0xf5, 0xd8, 0x17, 0x69, 0xcd, 0xe0, 0x3e, 0xd2, 0xfd, 0x51, 0x20,
+    0x5e, 0xcd, 0xca, 0xa8, 0x71, 0x68, 0xde, 0x97, 0xee, 0xb6, 0x92, 0x14,
+    0x5b, 0x76, 0xce, 0x9d, 0xc0, 0x9d, 0x57, 0x00, 0xaa, 0xa0, 0xd8, 0x31,
+    0xbc, 0xe0, 0xa9, 0x38, 0xe1, 0xda, 0x50, 0x48, 0xc8, 0xad, 0xf4, 0x0e,
+    0x45, 0xe6, 0xfd, 0x26, 0xc7, 0xe1, 0x55, 0x1e, 0xb5, 0xd9, 0xa1, 0xd4,
+    0x3c, 0x7c, 0x94, 0xa3, 0xda, 0x00, 0x27, 0xf9, 0xf6, 0xfa, 0x8a, 0x23,
+    0x77, 0x5f, 0x14, 0x11, 0x00, 0x13, 0xae, 0xc8, 0x84, 0x7e, 0xf8, 0x8e,
+    0x81, 0x1b, 0xc6, 0xae, 0xc8, 0x34, 0xa2, 0x8b, 0x6a, 0x44, 0x18, 0xda,
+    0x13, 0x65, 0x6f, 0xe6, 0xe0, 0x38, 0xdb, 0x23, 0x6d, 0xd2, 0xe0, 0x16,
+    0xd9, 0x3d, 0xdd, 0x08, 0x12, 0x3b, 0x68, 0x69, 0xb6, 0x8f, 0x2d, 0xb7,
+    0xda, 0xaf, 0xb4, 0xc0, 0x82, 0xc6, 0x34, 0x51, 0xa4, 0xa6, 0x34, 0xaa,
+    0xde, 0xde, 0xcc, 0x32, 0xcb, 0x35, 0x06, 0xd8, 0x55, 0x42, 0xd4, 0x7b,
+    0x75, 0xbe, 0x94, 0x02, 0xdf, 0x99, 0x5e, 0xfc, 0x0c, 0x8e, 0xda, 0x52,
+    0xd0, 0xc5, 0xb1, 0xb9, 0xe4, 0x68, 0xff, 0x97, 0xdd, 0x2c, 0xe5, 0x5d,
+    0xdf, 0x27, 0x2c, 0xc2, 0xce, 0x3e, 0xb6, 0xbe, 0xb9, 0xbe, 0xde, 0xd8,
+    0xee, 0x02, 0x6c, 0xc9, 0x0a, 0x83, 0x21, 0x50, 0x73, 0x73, 0xd3, 0x64,
+    0x96, 0x46, 0x76, 0xa5, 0x6f, 0xde, 0xdb, 0xa4, 0x7f, 0x8f, 0x67, 0x6d,
+    0xa3, 0xd2, 0xb8, 0x47, 0x75, 0xca, 0x02, 0x27, 0x48, 0x88, 0xdc, 0xdc,
+    0xc9, 0x74, 0x5a, 0x84, 0x7e, 0x04, 0xf6, 0x28, 0x5d, 0xc1, 0xb0, 0xe9,
+    0x69, 0x96, 0x84, 0x94, 0xc9, 0xec, 0x08, 0x5f, 0xe3, 0xc7, 0x3d, 0x6e,
+    0xd3, 0xca, 0xd0, 0x33, 0x1f, 0x80, 0x03, 0x57, 0x4d, 0x8a, 0x13, 0x2b,
+    0x55, 0x2c, 0xe3, 0x9e, 0xa9, 0x0f, 0x8d, 0xf6, 0xd5, 0x5a, 0xb4, 0xb9,
+    0xc3, 0xa9, 0xc1, 0x0d, 0xea, 0x48, 0x6a, 0x92, 0x5b, 0xd5, 0x81, 0xf3,
+    0x49, 0x2d, 0xd1, 0x51, 0xe0, 0x07, 0x06, 0xe2, 0x01, 0x08, 0x40, 0x17,
+    0x28, 0xf3, 0xb6, 0xad, 0x24, 0xb2, 0xc3, 0x48, 0xfe, 0x7a, 0x58, 0x0a,
+    0xdd, 0xd7, 0x25, 0x78, 0xe2, 0xab, 0x68, 0x11, 0xcb, 0xc5, 0x73, 0x56,
+    0x3c, 0xc5, 0x49, 0x1d, 0xdf, 0x6f, 0xdb, 0x03, 0x52, 0xdd, 0x90, 0xa9,
+    0x47, 0x4b, 0x5a, 0xb7, 0x61, 0x02, 0xfd, 0x1d, 0xde, 0x84, 0x95, 0x9b,
+    0xd6, 0x5b, 0x4a, 0x42, 0xd1, 0x17, 0xc5, 0xae, 0x94, 0xda, 0xc6, 0xeb,
+    0x9c, 0xc1, 0x74, 0x54, 0xcc, 0x2c, 0x62, 0xef, 0x12, 0xc2, 0xcf, 0x19,
+    0x46, 0x9e, 0x1a, 0xcb, 0x0d, 0xe3, 0xe4, 0x46, 0x98, 0x78, 0xe1, 0x4e,
+    0xb3, 0x74, 0x69, 0x34, 0xaa, 0xa8, 0xc7, 0x9e, 0x70, 0x89, 0x9e, 0xd3,
+    0x9b, 0x46, 0xd5, 0x82, 0x7a, 0xb9, 0xe6, 0x30, 0xe0, 0xca, 0xd8, 0xdc,
+    0x67, 0x0e, 0xce, 0x27, 0x8e, 0x45, 0x7f, 0xa2, 0xd2, 0x9a, 0x0e, 0x6a,
+    0x3e, 0x37, 0xae, 0x13, 0xb6, 0xdf, 0x2c, 0xc8, 0x33, 0xf1, 0x9b, 0x4b,
+    0xa1, 0x6c, 0x65, 0x33, 0x87, 0xc4, 0x81, 0x17, 0xb7, 0xe9, 0xe7, 0x0d,
+    0x90, 0x61, 0x25, 0xab, 0x7d, 0xcd, 0x49, 0x29, 0x43, 0x25, 0x3b, 0x0b,
+    0x83, 0x8f, 0x24, 0x35, 0x7c, 0x4d, 0xd7, 0xee, 0x94, 0x36, 0xc9, 0xae,
+    0x86, 0x95, 0x4b, 0xa5, 0x9e, 0x30, 0x35, 0x6b, 0x45, 0x6b, 0x6e, 0xe7,
+    0x5d, 0xd8, 0x03, 0x9b, 0x4e, 0x5b, 0xb2, 0xd3, 0x90, 0x86, 0xd5, 0xed,
+    0x91, 0x40, 0xea, 0xa3, 0x9b, 0x35, 0x48, 0x92, 0xc0, 0x82, 0xda, 0xf9,
+    0xf9, 0xd3, 0xc0, 0x22, 0xf5, 0x3d, 0x86, 0xb6, 0xe5, 0xc5, 0xb8, 0x68,
+    0x52, 0x1a, 0x74, 0x39, 0x97, 0x9e, 0x88, 0x3e, 0xd9, 0xbc, 0xc5, 0x29,
+    0x2e, 0x49, 0x4c, 0xcb, 0x42, 0x62, 0x95, 0x68, 0x53, 0x73, 0xfa, 0x97,
+    0x8e, 0xe4, 0xdf, 0x49, 0x14, 0x34, 0x31, 0xba, 0x3f, 0x4e, 0xb0, 0x01,
+    0xc8, 0x9c, 0x27, 0xe9, 0x65, 0x07, 0xf4, 0x56, 0x13, 0xa8, 0x0a, 0xdf,
+    0x43, 0x4e, 0x0b, 0x68, 0x1a, 0x53, 0x73, 0xf0, 0x06, 0x35, 0x6f, 0xa3,
+    0x7f, 0x47, 0x00, 0x5a, 0x01, 0x67, 0xdc, 0x8a, 0xef, 0x8d, 0x10, 0xf3,
+    0xa4, 0xb8, 0x41, 0x73, 0xe7, 0x98, 0xd3, 0xa6, 0x15, 0x61, 0x43, 0xea,
+    0xb7, 0x98, 0x12, 0xe0, 0x01, 0x0f, 0xb0, 0x8e, 0x5f, 0xe1, 0x38, 0x93,
+    0x09, 0x46, 0x36, 0x0f, 0x6c, 0x98, 0x47, 0xd8, 0xfd, 0xc1, 0xf6, 0xbb,
+    0x0c, 0x33, 0x4a, 0x1e, 0x32, 0x8e, 0x39, 0xbb, 0x80, 0x0f, 0x28, 0xb0,
+    0x06, 0x20, 0x0f, 0xf8, 0xe2, 0x71, 0xb0, 0x75, 0xd2, 0x75, 0xd7, 0x24,
+    0x0f, 0xa5, 0xc2, 0xa1, 0x51, 0xb9, 0xf2, 0xf9, 0x49, 0x29, 0x29, 0xbc,
+    0x5c, 0x86, 0x61, 0x4d, 0xfb, 0x01, 0x5c, 0x00, 0x19, 0x77, 0xdf, 0x29,
+    0x81, 0xa6, 0xb9, 0xf2, 0x4c, 0x5f, 0x16, 0xf9, 0x5c, 0x81, 0xdd, 0x6d,
+    0xf1, 0x5c, 0xca, 0x43, 0xb2, 0x29, 0x29, 0xbe, 0x9e, 0x00, 0xd8, 0x58,
+    0x20, 0x80, 0xb7, 0x06, 0x91, 0xc9, 0xd0, 0x67, 0x13, 0x6f, 0x16, 0x3a,
+    0xc2, 0x6d, 0x01, 0xc8, 0xf4, 0x28, 0x6b, 0x7c, 0xaf, 0x8b, 0x75, 0xdf,
+    0x17, 0x9c, 0x09, 0xb9, 0xcf, 0x95, 0x40, 0x11, 0x5d, 0xb0, 0xa8, 0xd8,
+    0xec, 0x3f, 0x00, 0x06, 0x4a, 0xd9, 0x50, 0xd6, 0xfd, 0x57, 0xbc, 0xde,
+    0xb9, 0xc7, 0xae, 0x06, 0x6c, 0x55, 0xcb, 0x02, 0x2c, 0x2d, 0xbe, 0x82,
+    0x00, 0xec, 0x50, 0x01, 0xd3, 0xbb, 0x27, 0x9a, 0x3e, 0xf6, 0xf1, 0x3b,
+    0xa1, 0xf9, 0x4a, 0xc3, 0xa2, 0xc9, 0x32, 0x14, 0x3d, 0xbc, 0xe7, 0xc6,
+    0xf3, 0xfe, 0x82, 0x9d, 0xcb, 0xdc, 0x59, 0x30, 0xcd, 0xdb, 0xae, 0x1e,
+    0x9e, 0x45, 0xc0, 0xf8, 0x30, 0x9a, 0xdd, 0xbf, 0xf6, 0x75, 0xf5, 0xbc,
+    0x0a, 0xe3, 0x32, 0x1d, 0x26, 0xdb, 0x15, 0xc8, 0x7a, 0xac, 0x1b, 0x42,
+    0x9b, 0xcc, 0xb8, 0xa7, 0x27, 0x80, 0x1e, 0xd9, 0x86, 0xc6, 0xf8, 0x7f,
+    0x5f, 0x8e, 0x5f, 0xc0, 0xa1, 0x3b, 0x47, 0x57, 0x6b, 0xb2, 0xec, 0x83,
+    0x8f, 0x80, 0x72, 0x36, 0xe0, 0x05, 0xe0, 0x0f, 0x2e, 0x91, 0xfc, 0x9e,
+    0xeb, 0x95, 0x51, 0xfb, 0x62, 0xdc, 0xcb, 0x69, 0x90, 0xbd, 0x18, 0xad,
+    0x8b, 0x8d, 0x70, 0x02, 0x69, 0xc7, 0x02, 0xdd, 0x40, 0x7b, 0x16, 0x2a,
+    0xc4, 0x32, 0x1e, 0x50, 0xc0, 0xa8, 0xde, 0xa8, 0x00, 0xab, 0x6f, 0xf7,
+    0xb1, 0x7d, 0x8a, 0x96, 0x8f, 0x86, 0xf3, 0xce, 0xe9, 0x65, 0x5a, 0x85,
+    0xd5, 0x28, 0x96, 0xda, 0xda, 0x9b, 0x61, 0x4c, 0xee, 0x96, 0xdf, 0x9d,
+    0xe8, 0xd0, 0x02, 0x87, 0x6a, 0xf7, 0x46, 0xae, 0xe8, 0xbd, 0xde, 0x70,
+    0xb1, 0x9e, 0x5f, 0xa8, 0xbe, 0x2d, 0xe3, 0xdf, 0x79, 0xfe, 0xce, 0x11,
+    0xc1, 0x92, 0xd7, 0xa2, 0x78, 0xa9, 0xde, 0x2d, 0xf4, 0x37, 0x89, 0x80,
+    0x82, 0x02, 0xbb, 0xce, 0xc7, 0x58, 0x4c, 0xb2, 0x3d, 0x33, 0x24, 0xa1,
+    0x11, 0x0a, 0x81, 0x4c, 0xbf, 0xdd, 0x84, 0x4f, 0x7e, 0xf4, 0x5b, 0xe2,
+    0x2c, 0xb8, 0x66, 0x6d, 0x86, 0x60, 0xf0, 0x89, 0x1b, 0x1e, 0x83, 0xae,
+    0x69, 0x0a, 0xb3, 0x85, 0x40, 0x2d, 0xbe, 0x98, 0xbe, 0xef, 0xc7, 0x2f,
+    0x9f, 0x3d, 0xdd, 0xd3, 0xb8, 0xd9, 0x29, 0x86, 0x5b, 0xb4, 0x7e, 0x53,
+    0x92, 0x28, 0xe6, 0xf2, 0xdf, 0x4e, 0x34, 0x01, 0xac, 0xf8, 0x9f, 0x99,
+    0xfb, 0xdd, 0xd4, 0x95, 0x6e, 0xd2, 0xc9, 0xa7, 0xa0, 0xd6, 0xe7, 0x11,
+    0x26, 0xfd, 0xc8, 0xc2, 0x05, 0xfb, 0x60, 0x6e, 0x65, 0x7e, 0x5b, 0xbb,
+    0x20, 0x61, 0x69, 0x5b, 0x38, 0x03, 0x17, 0x71, 0xf4, 0xf7, 0xdc, 0x0f,
+    0x87, 0xad, 0xce, 0x7a, 0x90, 0xd4, 0x0d, 0xc9, 0x62, 0xf8, 0xb7, 0x4f,
+    0x12, 0xb9, 0xd9, 0xb2, 0x84, 0xa4, 0x58, 0x42, 0x69, 0x18, 0x05, 0x30,
+    0x00, 0x00, 0x01, 0x0e, 0x43, 0xfa, 0xd0, 0x87, 0x4c, 0x11, 0xbc, 0xe4,
+    0x90, 0xb2, 0xea, 0x14, 0x60, 0x5b, 0x78, 0x70, 0x02, 0x7e, 0x7a, 0x00,
+    0x75, 0xd1, 0x02, 0xef, 0x35, 0x60, 0x22, 0x00, 0x26, 0x5b, 0x8f, 0xbb,
+    0x80, 0x60, 0xc3, 0x14, 0xc3, 0xe1, 0x61, 0x81, 0x8d, 0xed, 0x7e, 0xa0,
+    0x16, 0x00, 0x2d, 0x23, 0x5d, 0xe9, 0x2d, 0x2a, 0xae, 0x75, 0xa0, 0x66,
+    0xcb, 0x2a, 0x16, 0x59, 0x29, 0xbb, 0x82, 0x78, 0xe7, 0x3d, 0xf8, 0x00,
+    0xb2, 0x55, 0xab, 0x86, 0x3e, 0x1f, 0x1f, 0x4a, 0x91, 0x14, 0x69, 0x6d,
+    0xf3, 0x59, 0x24, 0xd3, 0x2d, 0x21, 0x9c, 0xde, 0x45, 0x95, 0xf5, 0x27,
+    0x82, 0xc6, 0xf5, 0x72, 0xed, 0x00, 0x2f, 0x79, 0x16, 0x41, 0x7c, 0xdf,
+    0xdd, 0xef, 0x34, 0xcb, 0x84, 0x13, 0x09, 0xee, 0x8b, 0x92, 0xcb, 0x5d,
+    0xe4, 0xa8, 0x72, 0xb7, 0xbf, 0xb5, 0xdb, 0xc4, 0x55, 0x83, 0x2e, 0xab,
+    0xd6, 0x50, 0x11, 0x01, 0xed, 0xc5, 0xb6, 0x80, 0x5b, 0x65, 0xb4, 0xb4,
+    0x59, 0x9b, 0x91, 0x14, 0x9b, 0x4b, 0xb4, 0xf2, 0xdb, 0xad, 0x9b, 0xb5,
+    0xf2, 0x05, 0x98, 0x52, 0x4b, 0xfa, 0x18, 0x59, 0xde, 0xad, 0xb3, 0xa7,
+    0x9a, 0x18, 0xa4, 0x86, 0xf4, 0x23, 0x7d, 0x0c, 0x5c, 0x2d, 0x03, 0x29,
+    0x71, 0x65, 0x18, 0x43, 0x6f, 0x2c, 0x00, 0xb7, 0xe7, 0xcb, 0x24, 0xcc,
+    0x71, 0x63, 0x4a, 0x1a, 0xde, 0x96, 0x48, 0xbb, 0x2e, 0x51, 0xb5, 0x21,
+    0x85, 0xca, 0x49, 0x6c, 0x79, 0x2e, 0xba, 0x47, 0x5b, 0x07, 0x87, 0xd8,
+    0x50, 0x61, 0x43, 0xeb, 0x68, 0xfe, 0x77, 0x87, 0x67, 0x94, 0xf0, 0xa7,
+    0xd4, 0xac, 0xae, 0xdc, 0x85, 0x4f, 0x56, 0xfc, 0x08, 0x03, 0x59, 0x00,
+    0x1e, 0x6f, 0xff, 0x79, 0xe2, 0x04, 0x08, 0x22, 0x67, 0x2b, 0x40, 0x4b,
+    0x69, 0xbc, 0xac, 0x41, 0xd0, 0x3e, 0xb7, 0xe3, 0x8f, 0xaf, 0x0f, 0x22,
+    0x66, 0x9a, 0x65, 0x83, 0x53, 0x2a, 0x12, 0x4a, 0x6f, 0xe8, 0x24, 0xc7,
+    0x67, 0x7e, 0x56, 0xed, 0x43, 0xab, 0xdc, 0x1c, 0xa4, 0x30, 0xe8, 0xdf,
+    0x9c, 0xc0, 0x14, 0x13, 0xc0, 0x16, 0x0a, 0xb7, 0x9e, 0xf6, 0xd1, 0xaa,
+    0x23, 0x2d, 0xd3, 0x0e, 0xb4, 0x38, 0x64, 0x81, 0x2d, 0xc8, 0xe8, 0x01,
+    0x66, 0xc9, 0x7c, 0x57, 0xc4, 0xf6, 0xe6, 0x52, 0x75, 0x02, 0xdb, 0xfc,
+    0xdb, 0xf0, 0x23, 0x05, 0xab, 0xd0, 0x32, 0x1c, 0x69, 0xde, 0x0c, 0x04,
+    0xd0, 0x0b, 0x5f, 0x35, 0x60, 0x0a, 0x83, 0xa1, 0x94, 0x2c, 0xb3, 0xa3,
+    0x7b, 0x5f, 0xae, 0xe8, 0x94, 0xe3, 0x16, 0x0d, 0x2e, 0x42, 0xd2, 0x86,
+    0x41, 0x8d, 0xc7, 0x71, 0x3f, 0xe3, 0xbe, 0x0d, 0xa5, 0x8c, 0x2a, 0xc9,
+    0x43, 0x1b, 0x47, 0x2d, 0xe3, 0x2d, 0x94, 0x30, 0x2d, 0xb3, 0x95, 0x4f,
+    0x6f, 0x73, 0xf3, 0x5f, 0xf7, 0x22, 0x0a, 0xee, 0x65, 0x3b, 0x03, 0xf9,
+    0x17, 0x7a, 0xd4, 0xa3, 0x13, 0x39, 0xb1, 0x55, 0x47, 0x16, 0xdc, 0xc1,
+    0x55, 0xff, 0x41, 0x1d, 0x70, 0x4f, 0x09, 0xd8, 0x28, 0x53, 0x9c, 0x48,
+    0x89, 0x14, 0x32, 0x37, 0xbb, 0x11, 0x1c, 0x00, 0xe5, 0xff, 0xfe, 0x32,
+    0x4a, 0x52, 0x9b, 0xc7, 0xdb, 0xda, 0x89, 0x36, 0xe0, 0xd3, 0x62, 0x55,
+    0xb3, 0x46, 0xa0, 0xda, 0x31, 0xbe, 0x6e, 0x47, 0xf6, 0x76, 0xe6, 0x6e,
+    0x65, 0xc3, 0x91, 0x75, 0x0d, 0x44, 0x08, 0x6d, 0x31, 0x34, 0xc2, 0xe0,
+    0x04, 0x55, 0xad, 0x47, 0x90, 0x9b, 0xed, 0x09, 0x15, 0x08, 0xdc, 0xfc,
+    0xd9, 0x9c, 0xf9, 0x97, 0x2c, 0xe7, 0xbc, 0x97, 0x75, 0xd1, 0xc9, 0x61,
+    0x6a, 0x85, 0xd6, 0xf2, 0xd5, 0x04, 0x0b, 0xa6, 0x37, 0xa5, 0x76, 0x52,
+    0x2f, 0x6e, 0x16, 0xe9, 0xe9, 0x4b, 0x40, 0xb6, 0xcc, 0x2d, 0x7e, 0xc4,
+    0x61, 0x4f, 0x7d, 0xa0, 0x93, 0xff, 0x85, 0x81, 0xca, 0x16, 0xd9, 0x3a,
+    0x1b, 0xb9, 0x64, 0x0a, 0xab, 0x63, 0x67, 0x90, 0xe6, 0xfc, 0xc3, 0xa5,
+    0x17, 0x12, 0x10, 0xd0, 0x90, 0xde, 0x84, 0xd3, 0x79, 0x0e, 0xc0, 0xb9,
+    0x46, 0x8c, 0x64, 0x00, 0x7f, 0x27, 0x5f, 0x3a, 0x57, 0x86, 0x8f, 0x6a,
+    0x37, 0x2e, 0xf5, 0x29, 0x41, 0x11, 0x10, 0xe2, 0x9b, 0x59, 0x67, 0x92,
+    0x56, 0xb3, 0xa2, 0x5f, 0x56, 0xfd, 0x4c, 0xda, 0x47, 0xf3, 0x87, 0x82,
+    0x38, 0x01, 0xc5, 0xcb, 0x76, 0x80, 0x8a, 0xc3, 0x7c, 0x22, 0xb6, 0xaf,
+    0x70, 0x42, 0x00, 0x8d, 0x7b, 0xac, 0x0a, 0x00, 0xa8, 0xce, 0xaa, 0x84,
+    0xa9, 0x97, 0xd0, 0xb8, 0xd9, 0xf4, 0x10, 0xbf, 0xc4, 0x02, 0xaa, 0x58,
+    0x24, 0xff, 0xde, 0x79, 0x96, 0x12, 0x92, 0xd2, 0x53, 0x77, 0x72, 0xd7,
+    0x60, 0x9b, 0x3d, 0x3d, 0xb7, 0x5e, 0x9e, 0x0f, 0xb8, 0x00, 0x30, 0x56,
+    0xe8, 0x80, 0x85, 0xff, 0x53, 0x40, 0xe6, 0xef, 0x80, 0x85, 0xff, 0x53,
+    0x40, 0xe2, 0x43, 0x7e, 0x50, 0xa0, 0x07, 0xd7, 0x39, 0xa8, 0x13, 0xa2,
+    0x6e, 0x3a, 0xf8, 0x99, 0x97, 0x03, 0x06, 0xd6, 0xeb, 0x60, 0x7e, 0xe3,
+    0xad, 0xa1, 0x92, 0x81, 0x9b, 0x20, 0x5d, 0xc5, 0x02, 0x9b, 0x9e, 0x5f,
+    0x1b, 0xd4, 0xce, 0x22, 0x17, 0x65, 0x00, 0x3d, 0xef, 0xe6, 0x49, 0x60,
+    0x65, 0xb2, 0x2f, 0x8a, 0x63, 0x5f, 0x96, 0xd0, 0xfb, 0x43, 0x0b, 0xee,
+    0xa6, 0x6a, 0x9c, 0x58, 0xd0, 0xd3, 0x9b, 0x73, 0x9b, 0xb0, 0xf0, 0x39,
+    0xbc, 0xe2, 0x4c, 0xfb, 0x91, 0x84, 0x57, 0x48, 0x11, 0x6d, 0xba, 0x1b,
+    0x43, 0xc3, 0xda, 0x77, 0x60, 0x89, 0xed, 0x74, 0xf0, 0x1e, 0xf5, 0xce,
+    0x07, 0x00, 0x89, 0x06, 0xd3, 0xbc, 0x1b, 0xa2, 0x21, 0x3f, 0xe2, 0x7a,
+    0x2b, 0xc3, 0x21, 0x72, 0x9c, 0xd5, 0xbf, 0x00, 0x2a, 0x13, 0xc6, 0xad,
+    0x18, 0xaa, 0x61, 0x84, 0x34, 0x28, 0x94, 0xd0, 0xda, 0xd2, 0xdb, 0xc7,
+    0xcc, 0x59, 0x72, 0x18, 0x30, 0x68, 0xca, 0x12, 0x8d, 0x5b, 0x83, 0xe6,
+    0xe8, 0xc0, 0xca, 0x64, 0x08, 0x2d, 0x15, 0xb6, 0xee, 0xe3, 0xb8, 0x20,
+    0xcd, 0xa1, 0x98, 0xb5, 0x03, 0x69, 0x34, 0x35, 0xb1, 0x3f, 0x26, 0xe4,
+    0xa5, 0x85, 0x5b, 0x28, 0x0d, 0x58, 0x60, 0x73, 0x76, 0x6a, 0x9b, 0x69,
+    0x09, 0xb9, 0x12, 0x63, 0x9d, 0x10, 0x87, 0x4e, 0xf5, 0x6d, 0x99, 0x27,
+    0xb3, 0xf2, 0xa3, 0x73, 0xe2, 0xe4, 0xcd, 0x84, 0x35, 0x91, 0x91, 0xf1,
+    0x83, 0x9b, 0xba, 0x47, 0xce, 0x31, 0xfe, 0x74, 0x74, 0x4b, 0xb2, 0x25,
+    0x38, 0x71, 0xea, 0xdc, 0xc5, 0xb3, 0xdc, 0x0c, 0x41, 0xf4, 0x3a, 0x48,
+    0x54, 0x3e, 0x9e, 0x36, 0xd6, 0xe9, 0x5a, 0x6c, 0x75, 0x50, 0x95, 0x83,
+    0x7d, 0x5b, 0x6f, 0xde, 0x9b, 0x1c, 0x20, 0x56, 0x40, 0x1e, 0x3d, 0xf8,
+    0xff, 0xcb, 0xa1, 0xde, 0x2a, 0xd9, 0xe4, 0x36, 0x65, 0x2f, 0xc2, 0xb7,
+    0x87, 0x03, 0x8c, 0x00, 0x18, 0x37, 0x85, 0xe2, 0xbc, 0xfa, 0xe9, 0xcf,
+    0xe3, 0x81, 0x98, 0x6d, 0x43, 0x31, 0x10, 0x79, 0x0d, 0xbe, 0x89, 0xf7,
+    0xf9, 0x23, 0x7b, 0x91, 0xb1, 0xef, 0xe6, 0x3e, 0x17, 0x45, 0x73, 0x9b,
+    0x09, 0xb2, 0x51, 0xd4, 0x61, 0x2d, 0xbc, 0x3f, 0xc7, 0x52, 0x2e, 0xee,
+    0x8f, 0xba, 0x56, 0x64, 0x91, 0x0a, 0x38, 0x07, 0xb6, 0xd5, 0x6d, 0xcf,
+    0x33, 0xe7, 0xdb, 0xdb, 0x65, 0x43, 0xae, 0x65, 0x0e, 0xdb, 0x6c, 0xa9,
+    0x4e, 0xd3, 0x8a, 0x28, 0x63, 0x73, 0x5a, 0x4e, 0x29, 0x42, 0x56, 0x36,
+    0x4d, 0xfb, 0xa0, 0x06, 0x3e, 0xd0, 0x8d, 0xf5, 0x76, 0xa7, 0x32, 0x95,
+    0x09, 0xd5, 0xee, 0xdc, 0x57, 0x80, 0xac, 0x34, 0x63, 0x0f, 0xf8, 0x03,
+    0x51, 0x1f, 0x3d, 0x3b, 0x9e, 0x74, 0x53, 0xec, 0x0f, 0x9c, 0x08, 0xde,
+    0x03, 0xc9, 0xf6, 0x16, 0xb1, 0x54, 0xa4, 0x3c, 0x39, 0x8e, 0x7c, 0x8a,
+    0x00, 0x45, 0xef, 0x1e, 0x47, 0xe2, 0xf1, 0x88, 0xee, 0x2e, 0x51, 0x77,
+    0x9f, 0x2c, 0x7e, 0x97, 0xb5, 0x35, 0x24, 0xb4, 0x60, 0xc5, 0x6f, 0x25,
+    0x9c, 0x5f, 0x62, 0x2f, 0xdf, 0xab, 0xe7, 0x64, 0x01, 0x26, 0x3c, 0x8d,
+    0x97, 0x5e, 0xe9, 0x56, 0xd3, 0x4c, 0xe4, 0xac, 0xa8, 0x3a, 0xdc, 0x56,
+    0x29, 0x65, 0x94, 0x34, 0x6c, 0x3d, 0xaa, 0x94, 0xdf, 0xb3, 0x13, 0xf0,
+    0x23, 0x3e, 0xb7, 0x9e, 0x33, 0xb7, 0x6a, 0x21, 0xaf, 0x14, 0xf7, 0x6f,
+    0x96, 0x18, 0xa7, 0x4b, 0x12, 0x01, 0x03, 0xaa, 0x36, 0x7f, 0xe8, 0x91,
+    0x0e, 0x11, 0x5c, 0x25, 0xfc, 0xb8, 0xeb, 0xc3, 0xf8, 0xce, 0xde, 0xee,
+    0x0a, 0xfc, 0xc3, 0xe5, 0x19, 0xad, 0xf1, 0x8e, 0x30, 0x02, 0xde, 0x05,
+    0x23, 0x8c, 0x81, 0x9b, 0x20, 0xc2, 0xbf, 0x43, 0xfc, 0x1b, 0xe9, 0x7f,
+    0x04, 0x57, 0x80, 0x3d, 0xeb, 0x81, 0x73, 0x45, 0x67, 0xea, 0x3a, 0x75,
+    0xbd, 0xcd, 0xcc, 0x85, 0x50, 0x31, 0xe5, 0x4b, 0x95, 0x8e, 0xec, 0xc4,
+    0x92, 0x40, 0x9b, 0x16, 0xb6, 0x74, 0x07, 0xed, 0xf4, 0x72, 0x3c, 0x50,
+    0xa5, 0xdb, 0x69, 0x5f, 0x9d, 0x97, 0x23, 0xf5, 0xcb, 0x16, 0x7e, 0xcb,
+    0xa8, 0x71, 0xcc, 0xa0, 0x0b, 0x7e, 0x1f, 0x2f, 0x4f, 0x8f, 0x83, 0xf2,
+    0xe3, 0xdd, 0xae, 0xcd, 0x94, 0xaa, 0x36, 0x0c, 0xb0, 0x7a, 0x37, 0x50,
+    0x8b, 0x9d, 0x00, 0x31, 0xea, 0x91, 0xb4, 0x5c, 0x95, 0x30, 0x3b, 0x3e,
+    0x9f, 0x57, 0xbb, 0x98, 0x5a, 0x2f, 0x95, 0x87, 0xa8, 0x4a, 0x58, 0x8d,
+    0xe5, 0x00, 0x1a, 0x11, 0xbd, 0xb0, 0x57, 0x5c, 0x4c, 0xeb, 0x21, 0x77,
+    0xcb, 0x80, 0xc8, 0x34, 0xb4, 0x1b, 0x5b, 0x91, 0xf5, 0x65, 0x52, 0x15,
+    0x29, 0x9d, 0xa5, 0xd6, 0xfe, 0xac, 0x47, 0x12, 0x08, 0x5f, 0xdc, 0xf3,
+    0x7c, 0x8a, 0xa9, 0xbc, 0x75, 0xb6, 0xa5, 0x8b, 0x68, 0xd0, 0xd4, 0x6e,
+    0x37, 0xb7, 0x02, 0x38, 0xe8, 0xcd, 0x74, 0x44, 0x9e, 0x5b, 0x14, 0xf8,
+    0xad, 0xe8, 0xc0, 0x15, 0x09, 0xe4, 0x00, 0xac, 0x56, 0x11, 0xc8, 0x95,
+    0xe7, 0x4a, 0x01, 0x63, 0x89, 0xcf, 0x7e, 0xb8, 0x11, 0x00, 0x10, 0x6c,
+    0x3c, 0xcc, 0x2f, 0xd5, 0xbd, 0x00, 0x01, 0x8f, 0xb7, 0x5e, 0xe2, 0xdd,
+    0xd0, 0x93, 0x76, 0xc0, 0x09, 0x97, 0x9e, 0x39, 0xf2, 0x7a, 0x96, 0xe0,
+    0x20, 0x30, 0x31, 0xb9, 0xc5, 0x87, 0x49, 0x2c, 0x09, 0x09, 0x8d, 0x3c,
+    0x93, 0x12, 0x84, 0xb7, 0xf2, 0x0f, 0x79, 0x3e, 0xb7, 0xe3, 0x1d, 0x64,
+    0x0d, 0xd5, 0x32, 0xf8, 0x58, 0xde, 0x97, 0xb1, 0x64, 0x07, 0x5a, 0xe9,
+    0x98, 0x12, 0x61, 0xb6, 0xd3, 0xdb, 0xea, 0xa0, 0x05, 0xe2, 0x63, 0xb3,
+    0xbb, 0xe7, 0x12, 0x19, 0x9a, 0xec, 0xc7, 0xe8, 0x18, 0x94, 0xfb, 0xe4,
+    0xe9, 0x4e, 0xba, 0x91, 0x42, 0x1b, 0xe0, 0xc2, 0x83, 0xa6, 0x6a, 0xe0,
+    0xfc, 0x0e, 0xdf, 0xd5, 0x3d, 0xbb, 0x37, 0xf2, 0x5e, 0x2b, 0x1b, 0x92,
+    0x6b, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x43, 0xfd, 0x0a, 0x00, 0xf4, 0x58,
+    0xaf, 0xbf, 0xbf, 0x02, 0x2d, 0x72, 0xa2, 0x9b, 0x98, 0xeb, 0x6b, 0xe4,
+    0xc3, 0x96, 0xc9, 0x0b, 0x46, 0xf4, 0x06, 0xf1, 0xd7, 0x0b, 0xa5, 0x14,
+    0x5c, 0xcb, 0xb2, 0x19, 0x4e, 0xa7, 0x97, 0x5b, 0x9b, 0xc3, 0x80, 0x0f,
+    0x9f, 0xab, 0x9a, 0xa3, 0x1d, 0xa9, 0x53, 0x2d, 0xc4, 0x52, 0xea, 0x14,
+    0xa3, 0x56, 0x37, 0x20, 0x52, 0xe7, 0x31, 0xcf, 0xd3, 0x51, 0x03, 0xf7,
+    0xbe, 0x13, 0x2e, 0xd0, 0xc2, 0xc7, 0x51, 0xed, 0xf2, 0x99, 0x52, 0xac,
+    0xf0, 0x2d, 0xb8, 0x60, 0xfb, 0x5b, 0xf5, 0x02, 0xaa, 0x6f, 0x36, 0x65,
+    0x88, 0x50, 0x74, 0x42, 0x86, 0x9c, 0x1a, 0x81, 0xad, 0xe4, 0x00, 0x1e,
+    0x4e, 0xfe, 0x3e, 0xf9, 0x32, 0x45, 0x29, 0x03, 0xae, 0xf9, 0x5d, 0x96,
+    0x18, 0x58, 0xf8, 0xbe, 0x0d, 0xe1, 0xc0, 0x17, 0x6f, 0x04, 0x6e, 0x78,
+    0x32, 0xe5, 0x5b, 0x53, 0x74, 0x53, 0xcb, 0xc9, 0xa1, 0xf4, 0x39, 0xf2,
+    0x17, 0x6c, 0x6d, 0x9f, 0x02, 0xbb, 0xcf, 0xa7, 0xd6, 0xc1, 0x7c, 0x82,
+    0x30, 0x02, 0x55, 0x0f, 0x0e, 0x85, 0x00, 0x90, 0xe5, 0xb6, 0x2f, 0x83,
+    0x67, 0x31, 0x66, 0x92, 0x55, 0xb9, 0xb0, 0x3a, 0x2b, 0x7f, 0x41, 0xff,
+    0x40, 0x03, 0xfe, 0x85, 0xf0, 0xf3, 0x28, 0x23, 0xff, 0xef, 0x0f, 0x0f,
+    0xd3, 0x62, 0x8f, 0xa1, 0xa5, 0xb0, 0x14, 0xb8, 0x2a, 0x71, 0xc8, 0x98,
+    0x01, 0x2e, 0x6c, 0xd5, 0x74, 0xe3, 0x30, 0xaf, 0x5b, 0x4e, 0x0d, 0x46,
+    0xe3, 0xf1, 0x7b, 0xff, 0xd2, 0x29, 0xb5, 0xd0, 0xb3, 0x37, 0xc9, 0xdb,
+    0xbc, 0xee, 0x39, 0xe5, 0xee, 0x01, 0x8b, 0x61, 0x34, 0x29, 0xbd, 0x0f,
+    0xdf, 0xbd, 0xd8, 0xb8, 0xea, 0x1d, 0x9f, 0x8c, 0xf3, 0xde, 0x7c, 0xa9,
+    0xa7, 0x87, 0x45, 0x2c, 0xc3, 0x94, 0x63, 0x6a, 0x64, 0xd5, 0xa8, 0xda,
+    0xa4, 0xdc, 0x02, 0xdb, 0xe3, 0xf5, 0xf0, 0xe0, 0x04, 0x80, 0x06, 0xaf,
+    0xaf, 0x50, 0x26, 0xf1, 0xbc, 0x4a, 0xe5, 0x85, 0x93, 0x6d, 0x54, 0x50,
+    0xb6, 0xfc, 0xff, 0xf5, 0xcc, 0xcb, 0x0c, 0x37, 0xc6, 0x4a, 0xdf, 0xa5,
+    0x48, 0xb9, 0xc5, 0x22, 0x7c, 0xf7, 0x95, 0x16, 0xc9, 0xb3, 0x31, 0x0d,
+    0xb4, 0xf3, 0xec, 0xb1, 0x56, 0x24, 0x29, 0x5b, 0xe4, 0x80, 0x0d, 0xfe,
+    0x01, 0x04, 0x06, 0x7f, 0xb3, 0x39, 0x15, 0xc8, 0xc0, 0xe2, 0x0b, 0x97,
+    0xcc, 0xb0, 0x20, 0x29, 0xb0, 0x32, 0x66, 0x3b, 0x25, 0x0a, 0x7b, 0x64,
+    0xf9, 0xe5, 0x24, 0x4f, 0x16, 0xfc, 0x30, 0xbd, 0xc0, 0x07, 0x9f, 0xfd,
+    0xe7, 0x3c, 0xd4, 0x6a, 0x49, 0x64, 0x32, 0x37, 0x91, 0x22, 0xf7, 0xc1,
+    0x17, 0x34, 0x40, 0x8e, 0xea, 0x17, 0x25, 0xe7, 0x16, 0xf3, 0xd6, 0x6c,
+    0x35, 0x3c, 0xae, 0x1e, 0xb0, 0xa3, 0x9b, 0xe9, 0xc0, 0x05, 0x70, 0x57,
+    0x0f, 0xdf, 0x8f, 0xe4, 0x01, 0xe6, 0x87, 0x1a, 0x5d, 0x94, 0xc9, 0xbe,
+    0x5b, 0x96, 0x5b, 0x2c, 0x6f, 0x94, 0x49, 0xf8, 0xf8, 0x9a, 0xa1, 0x73,
+    0x9c, 0x36, 0xda, 0x1a, 0x5c, 0x25, 0x37, 0x6e, 0x5a, 0x9f, 0x9a, 0x15,
+    0x56, 0x94, 0xcc, 0xfb, 0x1b, 0x0e, 0x96, 0x00, 0x5b, 0x4d, 0xc0, 0x15,
+    0xaa, 0x43, 0xc3, 0x21, 0xed, 0x88, 0xae, 0x05, 0x77, 0x00, 0x06, 0x7a,
+    0xaa, 0x48, 0x46, 0xfa, 0xaf, 0xbd, 0xd9, 0xfc, 0x12, 0x46, 0xd3, 0x34,
+    0x30, 0x0c, 0xf9, 0xfb, 0x66, 0xc0, 0xf3, 0xa6, 0x48, 0x6c, 0x94, 0xa3,
+    0xea, 0x37, 0xcd, 0x36, 0xf9, 0xbf, 0x05, 0xe5, 0x08, 0x84, 0x02, 0xb5,
+    0xb4, 0x96, 0xdc, 0xc8, 0xbe, 0x87, 0x10, 0xd9, 0xc3, 0x9b, 0xfa, 0x6f,
+    0xc0, 0xbf, 0x70, 0x02, 0x3f, 0x69, 0xbd, 0x08, 0xed, 0x41, 0x10, 0x01,
+    0x30, 0x51, 0xaa, 0x80, 0x91, 0xff, 0x92, 0xfe, 0xe0, 0xe5, 0xaa, 0xdb,
+    0x3f, 0xff, 0x34, 0x01, 0xf6, 0x91, 0x08, 0xc2, 0x62, 0x9f, 0x69, 0xbc,
+    0x71, 0xbf, 0x9d, 0x26, 0xd2, 0xad, 0x85, 0x41, 0xad, 0xe4, 0x3b, 0xf8,
+    0x04, 0x1f, 0xd9, 0x00, 0x12, 0x00, 0x5b, 0x68, 0x64, 0x36, 0x3c, 0xca,
+    0x38, 0x3f, 0xc8, 0xe4, 0xa5, 0xf8, 0x37, 0xe8, 0x2f, 0x91, 0x3b, 0xcf,
+    0xb8, 0xb8, 0x06, 0x60, 0xc7, 0x5e, 0xdd, 0xa8, 0x93, 0x53, 0x15, 0x23,
+    0xee, 0x20, 0xc2, 0x1b, 0x79, 0xef, 0x90, 0x52, 0x5d, 0xa0, 0x03, 0x46,
+    0xca, 0x95, 0x16, 0x7a, 0xb7, 0xf1, 0x30, 0x07, 0x74, 0x10, 0x40, 0x5c,
+    0x4f, 0xf7, 0xda, 0x20, 0xf5, 0xcf, 0x7e, 0x9c, 0x1f, 0x6c, 0x2a, 0x9b,
+    0x62, 0xac, 0x92, 0xa0, 0xc1, 0xed, 0xf2, 0x8e, 0x13, 0x8b, 0xb7, 0x6f,
+    0x81, 0x8b, 0x3c, 0x5b, 0xf4, 0xf9, 0x10, 0x48, 0x20, 0x80, 0xe7, 0xd3,
+    0x3e, 0x5d, 0x9c, 0xe9, 0x76, 0xde, 0x36, 0xbf, 0x4d, 0xab, 0x7c, 0xe9,
+    0x4b, 0x9a, 0x7a, 0xa5, 0x3d, 0x5b, 0xf3, 0x5f, 0xcc, 0x20, 0x76, 0xf7,
+    0x49, 0x7c, 0x26, 0x6d, 0x1f, 0x06, 0x6b, 0x75, 0x17, 0xde, 0x9b, 0xe8,
+    0x3e, 0x05, 0xb6, 0xaa, 0xa7, 0xb7, 0xc4, 0xe3, 0x83, 0x76, 0x65, 0x40,
+    0x08, 0xee, 0x2b, 0x7b, 0xf8, 0x08, 0x40, 0x15, 0xa2, 0xce, 0x90, 0xf0,
+    0x43, 0x00, 0x68, 0x14, 0x79, 0x3e, 0x58, 0x49, 0x6f, 0x17, 0x26, 0xf9,
+    0xe1, 0x6a, 0x3b, 0xf3, 0x6b, 0xac, 0xf0, 0xa0, 0x6d, 0xbd, 0xc6, 0x4b,
+    0xd0, 0x81, 0x32, 0x5a, 0x11, 0x1d, 0xc6, 0x85, 0x02, 0x27, 0xfd, 0x6a,
+    0xfa, 0x48, 0xde, 0xb5, 0x0f, 0x6f, 0x41, 0x49, 0xe0, 0x73, 0x74, 0x71,
+    0x9c, 0xce, 0xdd, 0xf8, 0xa1, 0x7e, 0xdb, 0xef, 0xc8, 0x4d, 0x59, 0xb3,
+    0x56, 0xc1, 0xc9, 0x2c, 0xad, 0x81, 0xe6, 0x68, 0xbf, 0x7f, 0x6d, 0x81,
+    0x59, 0xf3, 0x5d, 0xbc, 0x51, 0xc1, 0xc6, 0x58, 0x78, 0x49, 0x4c, 0xfd,
+    0x3a, 0xd1, 0x5c, 0x77, 0x65, 0x83, 0x03, 0xbf, 0x92, 0xcd, 0xb0, 0xf3,
+    0xf7, 0x39, 0x59, 0x00, 0x46, 0x5a, 0xb6, 0xbd, 0xc7, 0x89, 0xeb, 0xef,
+    0xca, 0xe5, 0x5a, 0x56, 0xe0, 0x87, 0x88, 0xc7, 0xe4, 0x3c, 0x02, 0x57,
+    0x6e, 0xfa, 0x16, 0xda, 0xb7, 0x54, 0x6f, 0x9b, 0x43, 0xde, 0x2a, 0xf8,
+    0xc3, 0x62, 0x14, 0x12, 0x91, 0xbd, 0x35, 0xda, 0x44, 0x30, 0xcd, 0xf4,
+    0xd7, 0xd2, 0xbd, 0x2a, 0x92, 0xdb, 0x83, 0xdc, 0xb9, 0x5d, 0x73, 0x9a,
+    0x3e, 0x58, 0xf7, 0xdd, 0x88, 0x4c, 0x38, 0xb1, 0x81, 0x55, 0xba, 0x76,
+    0x00, 0x1b, 0x07, 0x27, 0x8e, 0xf9, 0xd4, 0x1a, 0x73, 0x65, 0x5b, 0xa0,
+    0xf5, 0x6f, 0x90, 0x58, 0xa3, 0x0b, 0xf5, 0x83, 0x82, 0xd4, 0x84, 0xc7,
+    0x7f, 0x39, 0x0b, 0xf5, 0x80, 0x7c, 0x6b, 0xea, 0x67, 0x56, 0xcb, 0x68,
+    0x61, 0xb8, 0x97, 0x4a, 0x1c, 0xa3, 0xce, 0x68, 0xf7, 0x57, 0xd8, 0xf8,
+    0x81, 0xa9, 0x9a, 0x51, 0x0d, 0x19, 0x1c, 0xc1, 0xe8, 0xde, 0x19, 0x08,
+    0x19, 0x14, 0xb0, 0x98, 0x9b, 0xe8, 0x39, 0xb9, 0xcf, 0x2b, 0x70, 0x95,
+    0x28, 0xc0, 0xa0, 0xd6, 0xed, 0x2b, 0xde, 0xf9, 0x66, 0x21, 0xe0, 0x88,
+    0x00, 0x95, 0x54, 0x2a, 0x61, 0xed, 0xc0, 0x2b, 0x08, 0x13, 0x3d, 0x75,
+    0x2c, 0x24, 0xc6, 0x9a, 0xca, 0x14, 0x07, 0x37, 0xf6, 0x90, 0x02, 0x5f,
+    0x20, 0x02, 0xd0, 0x06, 0xd3, 0xd9, 0xdb, 0x68, 0x0f, 0x7b, 0x27, 0xf0,
+    0xfc, 0xe2, 0x4a, 0xb7, 0xf7, 0x76, 0x67, 0x85, 0xb1, 0xbd, 0x4f, 0x6f,
+    0xd0, 0x40, 0x03, 0x9e, 0x78, 0x9b, 0xba, 0xa3, 0x41, 0x0b, 0xfd, 0x67,
+    0x3a, 0x78, 0x4e, 0x6c, 0x5b, 0x7c, 0x63, 0x7d, 0x7b, 0xeb, 0x01, 0x07,
+    0xf9, 0x7f, 0xff, 0x57, 0xeb, 0xac, 0x02, 0x7c, 0xec, 0xde, 0x1f, 0x83,
+    0x0e, 0x5c, 0xd9, 0x24, 0x81, 0x8d, 0xf3, 0x90, 0x02, 0x3f, 0xf0, 0x81,
+    0x00, 0x0d, 0xb3, 0xe3, 0xec, 0xfe, 0x51, 0x4c, 0x7f, 0x3d, 0x75, 0x90,
+    0x9f, 0xce, 0xca, 0x86, 0x9b, 0x69, 0x85, 0xaa, 0x54, 0x34, 0x73, 0x46,
+    0xda, 0xba, 0x57, 0x81, 0x88, 0xde, 0x5e, 0xae, 0x2a, 0x92, 0x9b, 0xf8,
+    0x90, 0x02, 0x12, 0x33, 0xc0, 0x1d, 0x80, 0x36, 0x7c, 0x17, 0x2c, 0x1b,
+    0x25, 0xeb, 0x9b, 0x24, 0xfd, 0xc2, 0xb4, 0x6c, 0xc1, 0xcd, 0xc9, 0xfa,
+    0xf5, 0xbf, 0x04, 0x5e, 0x05, 0xf5, 0xcc, 0x3a, 0xa6, 0xe4, 0x78, 0x75,
+    0x18, 0x3e, 0x58, 0xdf, 0xba, 0x3e, 0x5f, 0x48, 0xbf, 0x7f, 0x71, 0x7d,
+    0xdd, 0x1b, 0x4b, 0xe7, 0x9b, 0xa6, 0x0c, 0xfd, 0x69, 0xd2, 0x05, 0x37,
+    0xe6, 0xbf, 0xee, 0x02, 0x08, 0x16, 0x0b, 0xff, 0x74, 0x81, 0x5b, 0xc0,
+    0xa3, 0x2f, 0x86, 0xdb, 0x6c, 0x21, 0xd6, 0xe7, 0xa8, 0xed, 0xb0, 0x96,
+    0x3d, 0xb0, 0xdf, 0xc5, 0xad, 0xfc, 0x61, 0xe0, 0x63, 0x32, 0x90, 0xed,
+    0x6d, 0x7e, 0xdb, 0xa0, 0x0c, 0x1d, 0xf7, 0x16, 0xb2, 0x06, 0x4f, 0xe8,
+    0x92, 0xb2, 0xd0, 0xc2, 0x07, 0x19, 0x8b, 0xeb, 0x5b, 0xec, 0x80, 0x0b,
+    0x5d, 0xef, 0xcf, 0xd8, 0x01, 0xcd, 0x17, 0x2a, 0x93, 0x60, 0x87, 0x11,
+    0xcc, 0xe9, 0xd6, 0xa7, 0xe2, 0xcd, 0x7f, 0x12, 0x52, 0x86, 0x8c, 0xd6,
+    0xf1, 0x20, 0x05, 0xa2, 0x27, 0xb8, 0x02, 0xa1, 0x64, 0x1d, 0xd3, 0x83,
+    0x93, 0xe0, 0x5e, 0xe5, 0xca, 0x34, 0x3b, 0x69, 0x25, 0x2b, 0x67, 0x3f,
+    0x25, 0x4f, 0x11, 0xed, 0x16, 0x0d, 0x24, 0x37, 0xf1, 0x28, 0x08, 0x5f,
+    0xef, 0x38, 0x8b, 0xe3, 0x2d, 0xa4, 0xa8, 0xdd, 0xdf, 0x28, 0x00, 0xee,
+    0x8a, 0xc0, 0x4c, 0x00, 0x3a, 0xa9, 0xea, 0xdc, 0xfe, 0xf1, 0xf4, 0x5e,
+    0x72, 0xe7, 0xca, 0x36, 0x57, 0x2e, 0x6c, 0xb0, 0x22, 0x95, 0x5b, 0xed,
+    0x40, 0x04, 0xa2, 0xa8, 0x01, 0x79, 0x1b, 0x31, 0xcf, 0x01, 0x13, 0xec,
+    0x48, 0xa3, 0x29, 0x6a, 0x32, 0xb6, 0x8e, 0xa4, 0x0d, 0x7d, 0x21, 0x58,
+    0xca, 0x94, 0x5b, 0x7b, 0xf9, 0x76, 0xfb, 0xc0, 0x06, 0x25, 0x06, 0x5b,
+    0x3e, 0x84, 0xe9, 0xc4, 0x18, 0x4d, 0x59, 0xab, 0x42, 0x92, 0x37, 0x80,
+    0x00, 0x77, 0xf0, 0x2f, 0x3d, 0xc5, 0xf5, 0xc3, 0xf8, 0xd8, 0xb2, 0xe4,
+    0x7b, 0xf2, 0x6a, 0x51, 0x95, 0x06, 0x5f, 0x16, 0xfa, 0xc7, 0xd3, 0xbd,
+    0xe0, 0x8b, 0xec, 0x27, 0xe6, 0x0e, 0x0e, 0xb9, 0xde, 0x57, 0x39, 0x69,
+    0x51, 0x2d, 0xa5, 0x14, 0xd8, 0xa5, 0xc0, 0x06, 0x40, 0x0f, 0x1f, 0xf1,
+    0x40, 0x2c, 0xc2, 0xd3, 0x2b, 0xb8, 0x7a, 0xe7, 0x9d, 0xbe, 0x7a, 0x36,
+    0x16, 0x43, 0xad, 0xe3, 0xf5, 0x7c, 0xf5, 0x66, 0xc0, 0xca, 0xb9, 0x02,
+    0xdb, 0x29, 0x4e, 0x46, 0xfe, 0x72, 0xe7, 0x4d, 0x00, 0xb3, 0x2c, 0xf0,
+    0xef, 0x61, 0xa0, 0x97, 0xff, 0xb6, 0x2a, 0x05, 0xb7, 0xea, 0x88, 0x21,
+    0xd8, 0x2b, 0xdb, 0x9e, 0x08, 0x0a, 0x02, 0x5d, 0xe6, 0xb8, 0xf9, 0x0a,
+    0xa5, 0x0c, 0x2c, 0x7b, 0x7e, 0x5a, 0x9a, 0x01, 0x5c, 0xe2, 0x60, 0x04,
+    0x22, 0xf7, 0x24, 0x21, 0xa4, 0x6f, 0xd3, 0xe0, 0x0f, 0x81, 0x0b, 0xfd,
+    0x33, 0x9b, 0x6b, 0xc6, 0xc4, 0x90, 0x99, 0x92, 0x87, 0x86, 0x5b, 0xb5,
+    0x59, 0x65, 0x20, 0x13, 0xac, 0xb0, 0x34, 0x3c, 0xf9, 0x5a, 0xf2, 0xcd,
+    0x4a, 0xad, 0xf4, 0x12, 0x7c, 0x11, 0x7b, 0xcb, 0x8e, 0xb2, 0x9a, 0xeb,
+    0x21, 0xa9, 0x12, 0x87, 0xe2, 0xee, 0xcb, 0x55, 0x15, 0x46, 0xb7, 0xe6,
+    0x71, 0x1e, 0xcf, 0xf8, 0x00, 0x71, 0xd7, 0xb6, 0x3d, 0x60, 0xd0, 0x42,
+    0x00, 0x69, 0x69, 0x48, 0x51, 0x61, 0xf6, 0xac, 0x85, 0x1e, 0x5b, 0x7d,
+    0xcf, 0xe4, 0x89, 0xc0, 0x03, 0x0e, 0xe3, 0x9f, 0xb2, 0x29, 0xab, 0xc0,
+    0x01, 0xec, 0x27, 0xe6, 0xeb, 0xcf, 0x44, 0xb0, 0xb8, 0x91, 0x1b, 0xd7,
+    0xfd, 0xfd, 0xde, 0x00, 0xdf, 0xe6, 0x13, 0xd7, 0xf5, 0x09, 0xde, 0x46,
+    0xd3, 0x2d, 0x2f, 0x7f, 0x6a, 0x64, 0x50, 0xe3, 0x8b, 0x6e, 0x9b, 0x2f,
+    0x2f, 0xc3, 0x28, 0x00, 0xd0, 0xf5, 0x6e, 0x8a, 0x54, 0x95, 0x58, 0x00,
+    0x00, 0x01, 0xb7
+};
+
+void mpeg2_get_video_info(VideoDecodeInfo *info)
+{
+    info->profile   = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
+    info->width     = MPEG2_CLIP_WIDTH;
+    info->height    = MPEG2_CLIP_HEIGHT;
+    info->data      = mpeg2_clip;
+    info->data_size = MPEG2_CLIP_DATA_SIZE;
+}
diff --git a/tests/test-mpeg2.h b/tests/test-mpeg2.h
new file mode 100644 (file)
index 0000000..c43154d
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  test-mpeg2.h - MPEG-2 test data
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+*/
+
+#ifndef TEST_MPEG2_H
+#define TEST_MPEG2_H
+
+#include <glib.h>
+#include "test-decode.h"
+
+void mpeg2_get_video_info(VideoDecodeInfo *info);
+
+#endif /* TEST_MPEG2_H */
diff --git a/tests/test-subpicture-data.c b/tests/test-subpicture-data.c
new file mode 100644 (file)
index 0000000..02f2188
--- /dev/null
@@ -0,0 +1,1430 @@
+/*
+ *  test-subpicture-data.c - subpicture data
+ *
+ *  Copyright (C) <2011> Intel Corporation
+ *  Copyright (C) <2011> Collabora Ltd.
+ *  Copyright (C) <2011> Thibault Saunier <thibault.saunier@collabora.com>
+ *
+ *  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
+ */
+
+#include "test-subpicture-data.h"
+
+#define SUBPICTURE_WIDTH           184
+#define SUBPICTURE_HEIGHT          38
+#define SUBPICTURE_DATA_SIZE     27968
+
+/* Raw RGBA data */
+static const guint32 text[] = {
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x09000000, 0x63000000, 0x08000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x44000000, 0x88000000, 0x88000000, 0x88000000, 0x88000000,
+  0x88000000, 0x88000000, 0x88000000, 0x88000000, 0x88000000,
+  0x44000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x44000000, 0x88000000, 0x44000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x44000000, 0x88000000,
+  0x44000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x69000000, 0xff0000b4, 0x65000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
+  0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0x80000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0x80000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x80000000, 0xff0000ff, 0x80000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6a000000,
+  0xff0000b6, 0x9c000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x3c000000, 0xbb000000,
+  0xff0000ff, 0xdd000000, 0xbb000000, 0xbb000000, 0xbb000000,
+  0xbb000000, 0xdd000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xc0000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x08000000, 0x61000000,
+  0x60000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xc0000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xc0000000, 0x00000000, 0x00000000,
+  0x00000000, 0x1f000000, 0x5c000000, 0x78000000, 0x60000000,
+  0x27000000, 0x00000000, 0x00000000, 0x44000000, 0xc4000000,
+  0xff0000ff, 0xe2000000, 0x88000000, 0x88000000, 0x88000000,
+  0x0f000000, 0x00000000, 0x00000000, 0x42000000, 0x78000000,
+  0x78000000, 0x41000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x1f000000, 0x5c000000, 0x78000000,
+  0x60000000, 0x27000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x1f000000, 0x5c000000, 0x78000000, 0x60000000,
+  0x27000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x42000000, 0x78000000, 0x78000000, 0x41000000,
+  0x00000000, 0x00000000, 0x00000000, 0x44000000, 0x88000000,
+  0x88000000, 0x45000000, 0x3d000000, 0x73000000, 0x6c000000,
+  0x37000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x44000000,
+  0xc4000000, 0xff0000ff, 0xe2000000, 0x88000000, 0x88000000,
+  0x88000000, 0x53000000, 0x88000000, 0x88000000, 0x44000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x41000000,
+  0x78000000, 0x78000000, 0x46000000, 0x01000000, 0x00000000,
+  0x00000000, 0x44000000, 0x88000000, 0x88000000, 0x49000000,
+  0x55000000, 0x78000000, 0x4a000000, 0x02000000, 0x02000000,
+  0x4f000000, 0x78000000, 0x4d000000, 0x01000000, 0x00000000,
+  0x00000000, 0x44000000, 0x88000000, 0x88000000, 0x45000000,
+  0x3e000000, 0x77000000, 0x78000000, 0x43000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x42000000, 0x78000000, 0x78000000, 0x41000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1f000000,
+  0x5c000000, 0x78000000, 0x60000000, 0x27000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x80000000, 0xff0000ff, 0xc0000000,
+  0x00000000, 0x00000000, 0x44000000, 0x88000000, 0x80000000,
+  0x77000000, 0x9e000000, 0x00000000, 0x00000000, 0x9000000a,
+  0xfd000076, 0xff0000b6, 0xff0000ef, 0xfe0000dc, 0xf50000a0,
+  0xc8000036, 0x35000000, 0x80000000, 0xff0000ff, 0xff0000ff,
+  0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff00009c, 0x1c000000,
+  0x10000000, 0xc900001f, 0xff0000ad, 0xff0000e7, 0xff0000e7,
+  0xff0000ad, 0xc900001f, 0x13000000, 0x00000000, 0x00000000,
+  0x9000000a, 0xfd000076, 0xff0000b6, 0xff0000ef, 0xfe0000dc,
+  0xf50000a0, 0xc8000036, 0x35000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x9000000a,
+  0xfd000076, 0xff0000b6, 0xff0000ef, 0xfe0000dc, 0xf50000a0,
+  0xc8000036, 0x35000000, 0x00000000, 0x10000000, 0xc900001f,
+  0xff0000ad, 0xff0000e7, 0xff0000e7, 0xff0000ad, 0xc900001f,
+  0x13000000, 0x00000000, 0x80000000, 0xff0000ff, 0xff0000ff,
+  0xee000011, 0xff0000a3, 0xff0000e5, 0xff0000ca, 0xfc000072,
+  0x94000010, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff00009c,
+  0x9b000000, 0xff0000ff, 0xff0000ff, 0x80000000, 0x00000000,
+  0x00000000, 0x10000000, 0xc900001f, 0xff0000ad, 0xfe0000e7,
+  0xff0000e7, 0xff0000af, 0xc600001f, 0x11000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xff0000ff, 0xf700001f, 0xff0000b6,
+  0xff0000eb, 0xf80000ac, 0xbb00001a, 0xc8000022, 0xff0000b3,
+  0xff0000e6, 0xf900008a, 0xad000017, 0x00000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xff0000ff, 0xf300001b, 0xff0000ad,
+  0xfe0000e3, 0xff0000e9, 0xff0000ad, 0xc100001d, 0x0f000000,
+  0x00000000, 0x00000000, 0x10000000, 0xc900001f, 0xff0000ad,
+  0xff0000e7, 0xff0000e7, 0xff0000ad, 0xc900001f, 0x13000000,
+  0x00000000, 0x00000000, 0x9000000a, 0xfd000076, 0xff0000b6,
+  0xff0000ef, 0xfe0000dc, 0xf50000a0, 0xc8000036, 0x35000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xe2000000, 0x88000000,
+  0x88000000, 0xc4000000, 0xff0000ff, 0x80000000, 0x00000000,
+  0x00000000, 0x00000000, 0x43000000, 0xff000078, 0xf8000096,
+  0xbe00002c, 0xb9000011, 0xe5000051, 0xfa0000cf, 0xff0000ff,
+  0x8d000000, 0x3c000000, 0xbb000000, 0xff0000ff, 0xdd000000,
+  0xbb000000, 0xbb000000, 0xbb000000, 0x57000000, 0xbc00001a,
+  0xff0000e4, 0xf5000098, 0xc8000033, 0xd1000033, 0xf900009a,
+  0xff0000e4, 0xbe00001a, 0x00000000, 0x43000000, 0xff000078,
+  0xf8000096, 0xbe00002c, 0xb9000011, 0xe5000051, 0xfa0000cf,
+  0xff0000ff, 0x8d000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x43000000, 0xff000078, 0xf8000096,
+  0xbe00002c, 0xb9000011, 0xe5000051, 0xfa0000cf, 0xff0000ff,
+  0x8d000000, 0x00000000, 0xbc00001a, 0xff0000e4, 0xf5000098,
+  0xc8000033, 0xd1000033, 0xf900009a, 0xff0000e4, 0xbe00001a,
+  0x00000000, 0x3c000000, 0xbb000000, 0xff0000ff, 0xff0000b1,
+  0xea000077, 0xbd00001d, 0xda000042, 0xfd0000bc, 0xfa000074,
+  0x36000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x3c000000, 0xbb000000, 0xff0000ff,
+  0xdd000000, 0xbb000000, 0xbb000000, 0xbb000000, 0x81000000,
+  0xbb000000, 0xff0000ff, 0xc0000000, 0x00000000, 0x00000000,
+  0xb700001a, 0xff0000e6, 0xf500008e, 0xc9000031, 0xd000002c,
+  0xf8000087, 0xff0000dd, 0xb1000014, 0x00000000, 0x3c000000,
+  0xbb000000, 0xff0000ff, 0xff0000a9, 0xd4000054, 0xc5000024,
+  0xfc0000a8, 0xfa0000b4, 0xff0000a7, 0xd5000054, 0xc4000024,
+  0xfc0000aa, 0xfc000088, 0x3e000000, 0x00000000, 0x3c000000,
+  0xbb000000, 0xff0000ff, 0xff0000cf, 0xf2000087, 0xc600002d,
+  0xd1000033, 0xf900009a, 0xff0000e1, 0xb6000017, 0x00000000,
+  0x00000000, 0xbc00001a, 0xff0000e4, 0xf5000098, 0xc8000033,
+  0xd1000033, 0xf900009a, 0xff0000e4, 0xbe00001a, 0x00000000,
+  0x43000000, 0xff000078, 0xf8000096, 0xbe00002c, 0xb9000011,
+  0xe5000051, 0xfa0000cf, 0xff0000ff, 0x8d000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
+  0xff0000ff, 0xff0000ff, 0xc0000000, 0x00000000, 0x00000000,
+  0x00000000, 0x75000000, 0xfe0000e4, 0xc5000025, 0x4c000000,
+  0x16000000, 0x09000000, 0xcd000040, 0xff0000ff, 0xc0000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x00000000, 0x00000000, 0x2e000000, 0xff00009c, 0xf8000092,
+  0x7e000000, 0x4c000000, 0x1a000000, 0x30000000, 0xfa000096,
+  0xff00009b, 0x37000000, 0x75000000, 0xfe0000e4, 0xc5000025,
+  0x4c000000, 0x16000000, 0x09000000, 0xcd000040, 0xff0000ff,
+  0xc0000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x75000000, 0xfe0000e4, 0xc5000025, 0x4c000000,
+  0x16000000, 0x09000000, 0xcd000040, 0xff0000ff, 0xc0000000,
+  0x2e000000, 0xff00009c, 0xf8000092, 0x7e000000, 0x4c000000,
+  0x1a000000, 0x30000000, 0xfa000096, 0xff00009b, 0x37000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xf5000078, 0x5e000000,
+  0x3c000000, 0x0f000000, 0xcd00004b, 0xfe0000c1, 0x89000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x80000000, 0xff0000ff, 0xc0000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xc0000000, 0x00000000, 0x2e000000, 0xff00009b,
+  0xf900009e, 0x82000000, 0x47000000, 0x19000000, 0x25000000,
+  0xf700008e, 0xfe000086, 0x25000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xee000060, 0x56000000, 0x2a000000, 0xb9000036,
+  0xff0000ff, 0xe9000060, 0x55000000, 0x2a000000, 0xba000038,
+  0xff0000ca, 0x91000000, 0x00000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xf7000084, 0x70000000, 0x44000000, 0x17000000,
+  0x30000000, 0xfb000096, 0xff000098, 0x32000000, 0x2e000000,
+  0xff00009c, 0xf8000092, 0x7e000000, 0x4c000000, 0x1a000000,
+  0x30000000, 0xfa000096, 0xff00009b, 0x37000000, 0x75000000,
+  0xfe0000e4, 0xc5000025, 0x4c000000, 0x16000000, 0x09000000,
+  0xcd000040, 0xff0000ff, 0xc0000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xdd000000, 0xbb000000, 0xbb000000, 0xdd000000,
+  0xff0000ff, 0xc0000000, 0x00000000, 0x00000000, 0x00000000,
+  0x49000000, 0xf70000a8, 0xfb0000cb, 0xea000055, 0x82000005,
+  0x48000000, 0x44000000, 0x88000000, 0x9e000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xc0000000, 0x00000000, 0x00000000,
+  0x00000000, 0x5d000000, 0xff0000da, 0xd0000049, 0x49000000,
+  0x00000000, 0x00000000, 0x00000000, 0xbe00004b, 0xfe0000d9,
+  0x96000000, 0x49000000, 0xf70000a8, 0xfb0000cb, 0xea000055,
+  0x82000005, 0x48000000, 0x44000000, 0x88000000, 0x9e000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x49000000, 0xf70000a8, 0xfb0000cb, 0xea000055, 0x82000005,
+  0x48000000, 0x44000000, 0x88000000, 0x9e000000, 0x5d000000,
+  0xff0000da, 0xd0000049, 0x49000000, 0x00000000, 0x00000000,
+  0x00000000, 0xbe00004b, 0xfe0000d9, 0x96000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xd1000028, 0x3c000000, 0x00000000,
+  0x00000000, 0x90000011, 0xff0000fc, 0xaf000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xc0000000, 0x00000000, 0x5d000000, 0xff0000da, 0xeb000034,
+  0xad000000, 0x88000000, 0x88000000, 0x88000000, 0xde00002f,
+  0xff0000cb, 0x7b000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xcd000020, 0x30000000, 0x00000000, 0x84000005, 0xff0000ff,
+  0xcd000020, 0x30000000, 0x00000000, 0x85000006, 0xff0000fc,
+  0xb1000000, 0x00000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xd300002c, 0x42000000, 0x00000000, 0x00000000, 0x00000000,
+  0xbe00004b, 0xfe0000d8, 0x95000000, 0x5d000000, 0xff0000da,
+  0xd0000049, 0x49000000, 0x00000000, 0x00000000, 0x00000000,
+  0xbe00004b, 0xfe0000d9, 0x96000000, 0x49000000, 0xf70000a8,
+  0xfb0000cb, 0xea000055, 0x82000005, 0x48000000, 0x44000000,
+  0x88000000, 0x9e000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xc0000000, 0x00000000, 0x00000000, 0x3c000000, 0x77000000,
+  0x9e000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x8f000007, 0xf900007e, 0xfc0000dd, 0xff0000f2, 0xfb0000c2,
+  0xf200005c, 0x72000001, 0x00000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xc0000000, 0x00000000, 0x00000000, 0x00000000,
+  0x78000000, 0xff0000f6, 0xc0000012, 0x25000000, 0x00000000,
+  0x00000000, 0x00000000, 0x92000013, 0xff0000f6, 0xb4000000,
+  0x00000000, 0x8f000007, 0xf900007e, 0xfc0000dd, 0xff0000f2,
+  0xfb0000c2, 0xf200005c, 0x72000001, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x8f000007, 0xf900007e, 0xfc0000dd, 0xff0000f2, 0xfb0000c2,
+  0xf200005c, 0x72000001, 0x00000000, 0x78000000, 0xff0000f6,
+  0xc0000012, 0x25000000, 0x00000000, 0x00000000, 0x00000000,
+  0x92000013, 0xff0000f6, 0xb4000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xc0000000, 0x14000000, 0x00000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xbf000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xc0000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x80000000, 0xff0000ff, 0xc0000000,
+  0x00000000, 0x7a000000, 0xff0000f6, 0xff0000ff, 0xff0000ff,
+  0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ee,
+  0xa8000000, 0x00000000, 0x80000000, 0xff0000ff, 0xc0000000,
+  0x10000000, 0x00000000, 0x80000000, 0xff0000ff, 0xc0000000,
+  0x10000000, 0x00000000, 0x80000000, 0xff0000ff, 0xbf000000,
+  0x00000000, 0x00000000, 0x80000000, 0xff0000ff, 0xc0000000,
+  0x16000000, 0x00000000, 0x00000000, 0x00000000, 0x92000013,
+  0xff0000f6, 0xb3000000, 0x78000000, 0xff0000f6, 0xc0000012,
+  0x25000000, 0x00000000, 0x00000000, 0x00000000, 0x92000013,
+  0xff0000f6, 0xb4000000, 0x00000000, 0x8f000007, 0xf900007e,
+  0xfc0000dd, 0xff0000f2, 0xfb0000c2, 0xf200005c, 0x72000001,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x80000000, 0xff0000ff, 0xc0000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x44000000,
+  0x88000000, 0x44000000, 0x00000000, 0x44000000, 0x88000000,
+  0x65000000, 0x84000000, 0xc8000014, 0xf4000059, 0xfc0000cc,
+  0xfb000098, 0x40000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xc0000000, 0x00000000, 0x00000000, 0x00000000, 0x5d000000,
+  0xff0000da, 0xdc00004a, 0x09000000, 0x00000000, 0x00000000,
+  0x00000000, 0xbe00004b, 0xfe0000d9, 0xb1000000, 0x44000000,
+  0x88000000, 0x65000000, 0x84000000, 0xc8000014, 0xf4000059,
+  0xfc0000cc, 0xfb000098, 0x40000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x44000000, 0x88000000,
+  0x65000000, 0x84000000, 0xc8000014, 0xf4000059, 0xfc0000cc,
+  0xfb000098, 0x40000000, 0x5d000000, 0xff0000da, 0xdc00004a,
+  0x09000000, 0x00000000, 0x00000000, 0x00000000, 0xbe00004b,
+  0xfe0000d9, 0xb1000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xc0000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xc0000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xc0000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x69000000, 0xff0000d9, 0xe8000028, 0xbb000000, 0xbb000000,
+  0xbb000000, 0xbb000000, 0xda000000, 0xff000000, 0xc1000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xd6000036, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0xbe00004b, 0xfe0000d8,
+  0xb1000000, 0x5d000000, 0xff0000da, 0xdc00004a, 0x09000000,
+  0x00000000, 0x00000000, 0x00000000, 0xbe00004b, 0xfe0000d9,
+  0xb1000000, 0x44000000, 0x88000000, 0x65000000, 0x84000000,
+  0xc8000014, 0xf4000059, 0xfc0000cc, 0xfb000098, 0x40000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0x80000000, 0x00000000, 0x80000000, 0xff0000ff, 0xba00003a,
+  0x00000000, 0x00000000, 0x0b000000, 0xc1000027, 0xff0000e2,
+  0x9d000000, 0x00000000, 0x7f000000, 0xff0000fd, 0xc0000002,
+  0x00000000, 0x43000000, 0x88000000, 0x71000000, 0xff00009b,
+  0xfb000095, 0x39000000, 0x00000000, 0x00000000, 0x18000000,
+  0xf9000096, 0xff00009b, 0x85000000, 0x80000000, 0xff0000ff,
+  0xba00003a, 0x00000000, 0x00000000, 0x0b000000, 0xc1000027,
+  0xff0000e2, 0x9d000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x80000000, 0xff0000ff, 0xba00003a,
+  0x00000000, 0x00000000, 0x0b000000, 0xc1000027, 0xff0000e2,
+  0x9d000000, 0x2b000000, 0xff00009b, 0xfb000095, 0x39000000,
+  0x00000000, 0x00000000, 0x18000000, 0xf9000096, 0xff00009b,
+  0x85000000, 0x00000000, 0x80000000, 0xff0000ff, 0xc0000000,
+  0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xc0000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x7f000000, 0xff0000fd,
+  0xc0000002, 0x00000000, 0x43000000, 0x88000000, 0x46000000,
+  0x80000000, 0xff0000ff, 0xc0000000, 0x00000000, 0x2b000000,
+  0xff000097, 0xf4000080, 0x1b000000, 0x00000000, 0x00000000,
+  0x08000000, 0xe0000059, 0xff0000b5, 0x55000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xc0000000, 0x00000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xc0000000, 0x00000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xc0000000, 0x00000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xf9000089, 0x28000000, 0x00000000,
+  0x00000000, 0x18000000, 0xf9000096, 0xff000097, 0x83000000,
+  0x2b000000, 0xff00009b, 0xfb000095, 0x39000000, 0x00000000,
+  0x00000000, 0x18000000, 0xf9000096, 0xff00009b, 0x85000000,
+  0x80000000, 0xff0000ff, 0xba00003a, 0x00000000, 0x00000000,
+  0x0b000000, 0xc1000027, 0xff0000e2, 0x9d000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x44000000,
+  0xc4000000, 0xff0000ff, 0xe2000000, 0x88000000, 0x88000000,
+  0x88000000, 0x88000000, 0xc4000000, 0xff0000ff, 0xc0000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xfc0000c5, 0xcf00004a,
+  0x91000010, 0xab00002c, 0xfa00009d, 0xff000074, 0x95000000,
+  0x00000000, 0x66000000, 0xff0000c1, 0xee000050, 0x8e00000d,
+  0xe400005a, 0xfe0000c7, 0x66000000, 0xb800001a, 0xff0000e4,
+  0xf8000099, 0xac000033, 0xac000033, 0xf5000099, 0xff0000e4,
+  0xcc00001a, 0x4e000000, 0x80000000, 0xff0000ff, 0xfc0000c5,
+  0xcf00004a, 0x91000010, 0xab00002c, 0xfa00009d, 0xff000074,
+  0x95000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xfc0000c5, 0xcf00004a,
+  0x91000010, 0xab00002c, 0xfa00009d, 0xff000074, 0x95000000,
+  0x00000000, 0xb800001a, 0xff0000e4, 0xf8000099, 0xac000033,
+  0xac000033, 0xf5000099, 0xff0000e4, 0xcc00001a, 0x4e000000,
+  0x44000000, 0xc4000000, 0xff0000ff, 0xe2000000, 0x44000000,
+  0x00000000, 0x44000000, 0xc4000000, 0xff0000ff, 0xe2000000,
+  0x44000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x66000000, 0xff0000c1, 0xee000050,
+  0x8e00000d, 0xe400005a, 0xfe0000c7, 0xaa000000, 0xc4000000,
+  0xff0000ff, 0xe2000000, 0x44000000, 0x00000000, 0xad000015,
+  0xff0000d3, 0xf200007f, 0xaa00002d, 0x9d00001d, 0xe6000061,
+  0xff0000e9, 0xe9000025, 0x60000000, 0x44000000, 0xc4000000,
+  0xff0000ff, 0xe2000000, 0x44000000, 0x44000000, 0xc4000000,
+  0xff0000ff, 0xe2000000, 0x44000000, 0x44000000, 0xc4000000,
+  0xff0000ff, 0xe2000000, 0x44000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xff0000bc, 0xf5000088, 0xa900002d, 0xac000033,
+  0xf5000099, 0xff0000e1, 0xc9000017, 0x4c000000, 0x00000000,
+  0xb800001a, 0xff0000e4, 0xf8000099, 0xac000033, 0xac000033,
+  0xf5000099, 0xff0000e4, 0xcc00001a, 0x4e000000, 0x80000000,
+  0xff0000ff, 0xfc0000c5, 0xcf00004a, 0x91000010, 0xab00002c,
+  0xfa00009d, 0xff000074, 0x95000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff,
+  0xff0000ff, 0xff0000ff, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x36000000, 0xd300003b, 0xfb0000aa, 0xff0000e1, 0xff0000f0,
+  0xff0000b6, 0xfc000076, 0xae000008, 0x3a000000, 0x00000000,
+  0x15000000, 0xee000046, 0xff0000bd, 0xff0000ef, 0xfd0000be,
+  0xeb00003f, 0x6f000000, 0x13000000, 0xcd00001f, 0xff0000ae,
+  0xff0000e8, 0xff0000e8, 0xff0000ae, 0xd900001f, 0x7d000000,
+  0x0d000000, 0x36000000, 0xd300003b, 0xfb0000aa, 0xff0000e1,
+  0xff0000f0, 0xff0000b6, 0xfc000076, 0xae000008, 0x3a000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x36000000, 0xd300003b, 0xfb0000aa, 0xff0000e1, 0xff0000f0,
+  0xff0000b6, 0xfc000076, 0xae000008, 0x3a000000, 0x00000000,
+  0x13000000, 0xcd00001f, 0xff0000ae, 0xff0000e8, 0xff0000e8,
+  0xff0000ae, 0xd900001f, 0x7d000000, 0x0d000000, 0x80000000,
+  0xff0000ff, 0xff0000ff, 0xff0000ff, 0x80000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0x80000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x15000000, 0xee000046, 0xff0000bd, 0xff0000ef,
+  0xfd0000be, 0xeb00003f, 0xbc000000, 0xff0000ff, 0xff0000ff,
+  0xff0000ff, 0x80000000, 0x00000000, 0x0e000000, 0xc0000018,
+  0xff0000a4, 0xff0000e1, 0xff0000e5, 0xfc00009b, 0xec000042,
+  0x8d000000, 0x13000000, 0x80000000, 0xff0000ff, 0xff0000ff,
+  0xff0000ff, 0x80000000, 0x80000000, 0xff0000ff, 0xff0000ff,
+  0xff0000ff, 0x80000000, 0x80000000, 0xff0000ff, 0xff0000ff,
+  0xff0000ff, 0x80000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xf8000012, 0xff0000a6, 0xff0000e2, 0xff0000e9, 0xff0000ad,
+  0xd100001d, 0x78000000, 0x0c000000, 0x00000000, 0x13000000,
+  0xcd00001f, 0xff0000ae, 0xff0000e8, 0xff0000e8, 0xff0000ae,
+  0xd900001f, 0x7d000000, 0x0d000000, 0x36000000, 0xd300003b,
+  0xfb0000aa, 0xff0000e1, 0xff0000f0, 0xff0000b6, 0xfc000076,
+  0xae000008, 0x3a000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x3c000000, 0x77000000, 0xbb000000,
+  0xbb000000, 0xbb000000, 0xbb000000, 0xbb000000, 0xbb000000,
+  0xbb000000, 0xbb000000, 0x9e000000, 0x00000000, 0x00000000,
+  0x00000000, 0x4a000000, 0x96000000, 0xb2000000, 0xa8000000,
+  0x6e000000, 0x3b000000, 0x04000000, 0x00000000, 0x00000000,
+  0x0f000000, 0x78000000, 0xaa000000, 0xaa000000, 0x68000000,
+  0x20000000, 0x00000000, 0x00000000, 0x47000000, 0xa5000000,
+  0xb4000000, 0x94000000, 0x57000000, 0x10000000, 0x00000000,
+  0x00000000, 0x00000000, 0x4a000000, 0x96000000, 0xb2000000,
+  0xa8000000, 0x6e000000, 0x3b000000, 0x04000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x4a000000, 0x96000000, 0xb2000000, 0xa8000000,
+  0x6e000000, 0x3b000000, 0x04000000, 0x00000000, 0x00000000,
+  0x00000000, 0x47000000, 0xa5000000, 0xb4000000, 0x94000000,
+  0x57000000, 0x10000000, 0x00000000, 0x3c000000, 0x77000000,
+  0xbb000000, 0xbb000000, 0x9e000000, 0x00000000, 0x3c000000,
+  0x77000000, 0xbb000000, 0xbb000000, 0x9e000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x0f000000, 0x78000000, 0xaa000000, 0xaa000000,
+  0x68000000, 0x54000000, 0x77000000, 0xbb000000, 0xbb000000,
+  0x9e000000, 0x00000000, 0x00000000, 0x00000000, 0x3b000000,
+  0x9f000000, 0xb0000000, 0x9e000000, 0x51000000, 0x21000000,
+  0x00000000, 0x3c000000, 0x77000000, 0xbb000000, 0xbb000000,
+  0x9e000000, 0x3c000000, 0x77000000, 0xbb000000, 0xbb000000,
+  0x9e000000, 0x3c000000, 0x77000000, 0xbb000000, 0xbb000000,
+  0x9e000000, 0x00000000, 0x80000000, 0xff0000ff, 0xc0000000,
+  0x43000000, 0x9d000000, 0xb3000000, 0x95000000, 0x57000000,
+  0x0f000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x47000000, 0xa5000000, 0xb4000000, 0x94000000, 0x57000000,
+  0x10000000, 0x00000000, 0x00000000, 0x00000000, 0x4a000000,
+  0x96000000, 0xb2000000, 0xa8000000, 0x6e000000, 0x3b000000,
+  0x04000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x44000000, 0xc4000000, 0xff0000ff, 0xe2000000, 0x44000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xff0000ff, 0xff0000ff, 0x80000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x3c000000, 0x77000000,
+  0xbb000000, 0xbb000000, 0x9e000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x09000000, 0x63000000, 0x08000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x44000000, 0x88000000, 0x44000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x44000000,
+  0x88000000, 0x88000000, 0x44000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x69000000, 0xff0000b4, 0x65000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x44000000, 0x88000000, 0x88000000,
+  0x44000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x44000000,
+  0x88000000, 0x88000000, 0x44000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0x80000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xff0000ff, 0x80000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x6a000000, 0xff0000b6, 0x9c000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xff0000ff, 0x80000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xff0000ff, 0x80000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xc0000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x3c000000, 0xbb000000, 0xff0000ff,
+  0xc0000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x08000000,
+  0x61000000, 0x60000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x3c000000, 0xbb000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x3c000000, 0xbb000000, 0xff0000ff,
+  0xc0000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x44000000, 0xc4000000,
+  0xff0000ff, 0xe2000000, 0x88000000, 0x88000000, 0x88000000,
+  0x0f000000, 0x00000000, 0x00000000, 0x41000000, 0x78000000,
+  0x78000000, 0x46000000, 0x01000000, 0x00000000, 0x00000000,
+  0x44000000, 0x88000000, 0x88000000, 0x45000000, 0x3d000000,
+  0x73000000, 0x6c000000, 0x37000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x41000000,
+  0x78000000, 0x78000000, 0x46000000, 0x01000000, 0x00000000,
+  0x00000000, 0x00000000, 0x80000000, 0xff0000ff, 0xc0000000,
+  0x38000000, 0x6e000000, 0x79000000, 0x43000000, 0x00000000,
+  0x00000000, 0x00000000, 0x44000000, 0x88000000, 0x88000000,
+  0x44000000, 0x38000000, 0x75000000, 0x86000000, 0x88000000,
+  0x44000000, 0x00000000, 0x00000000, 0x42000000, 0x78000000,
+  0x78000000, 0x41000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x1f000000, 0x5c000000, 0x78000000,
+  0x60000000, 0x27000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x42000000, 0x78000000, 0x78000000,
+  0x41000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x1f000000, 0x5c000000, 0x78000000, 0x60000000,
+  0x27000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x1f000000, 0x5c000000, 0x78000000, 0x60000000, 0x27000000,
+  0x00000000, 0x00000000, 0x44000000, 0x88000000, 0x88000000,
+  0x44000000, 0x00000000, 0x44000000, 0x88000000, 0x88000000,
+  0x45000000, 0x3d000000, 0x73000000, 0x6c000000, 0x37000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x43000000, 0x79000000, 0x6f000000, 0x38000000,
+  0x80000000, 0xff0000ff, 0xc0000000, 0x00000000, 0x44000000,
+  0x88000000, 0x88000000, 0x44000000, 0x00000000, 0x00000000,
+  0x44000000, 0x88000000, 0x88000000, 0x44000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x43000000, 0x79000000,
+  0x6f000000, 0x38000000, 0x80000000, 0xff0000ff, 0xc0000000,
+  0x00000000, 0x00000000, 0x00000000, 0x02000000, 0x46000000,
+  0x76000000, 0x65000000, 0x27000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x80000000, 0xff0000ff, 0xff0000ff,
+  0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff00009c, 0x1c000000,
+  0x10000000, 0xc900001f, 0xff0000ad, 0xfe0000e7, 0xff0000e7,
+  0xff0000af, 0xc600001f, 0x11000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xff0000ff, 0xee000011, 0xff0000a3, 0xff0000e5,
+  0xff0000ca, 0xfc000072, 0x94000010, 0x00000000, 0x00000000,
+  0x00000000, 0x10000000, 0xc900001f, 0xff0000ad, 0xfe0000e7,
+  0xff0000e7, 0xff0000af, 0xc600001f, 0x11000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xf7000011, 0xff0000a2,
+  0xfe0000e0, 0xff0000e9, 0xff0000ad, 0xc100001d, 0x0f000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xff0000ff, 0xef000014,
+  0xff0000a3, 0xff0000dd, 0xff0000ff, 0xff0000ff, 0x80000000,
+  0x10000000, 0xc900001f, 0xff0000ad, 0xff0000e7, 0xff0000e7,
+  0xff0000ad, 0xc900001f, 0x13000000, 0x00000000, 0x00000000,
+  0x9000000a, 0xfd000076, 0xff0000b6, 0xff0000ef, 0xfe0000dc,
+  0xf50000a0, 0xc8000036, 0x35000000, 0x00000000, 0x10000000,
+  0xc900001f, 0xff0000ad, 0xff0000e7, 0xff0000e7, 0xff0000ad,
+  0xc900001f, 0x13000000, 0x00000000, 0x00000000, 0x9000000a,
+  0xfd000076, 0xff0000b6, 0xff0000ef, 0xfe0000dc, 0xf50000a0,
+  0xc8000036, 0x35000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x9000000a, 0xfd000076,
+  0xff0000b6, 0xff0000ef, 0xfe0000dc, 0xf50000a0, 0xc8000036,
+  0x35000000, 0x80000000, 0xff0000ff, 0xff0000ff, 0x80000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xff0000ff, 0xee000011,
+  0xff0000a3, 0xff0000e5, 0xff0000ca, 0xfc000072, 0x94000010,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x10000000, 0xc900001e,
+  0xff0000ad, 0xff0000e9, 0xfe0000e0, 0xff0000a2, 0xed000011,
+  0xff0000ff, 0xc0000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xff0000ff, 0x80000000, 0x00000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xff0000ff, 0x80000000, 0x00000000, 0x00000000,
+  0x10000000, 0xc900001e, 0xff0000ad, 0xff0000e9, 0xfe0000e0,
+  0xff0000a2, 0xed000011, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x00000000, 0x36000000, 0xdd000045, 0xff0000bf, 0xff0000ef,
+  0xff0000b9, 0xfc000063, 0x7e00000b, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x3c000000, 0xbb000000, 0xff0000ff, 0xdd000000,
+  0xbb000000, 0xbb000000, 0xbb000000, 0x57000000, 0xb700001a,
+  0xff0000e6, 0xf500008e, 0xc9000031, 0xd000002c, 0xf8000087,
+  0xff0000dd, 0xb1000014, 0x00000000, 0x3c000000, 0xbb000000,
+  0xff0000ff, 0xff0000b1, 0xea000077, 0xbd00001d, 0xda000042,
+  0xfd0000bc, 0xfa000074, 0x36000000, 0x00000000, 0x00000000,
+  0xb700001a, 0xff0000e6, 0xf500008e, 0xc9000031, 0xd000002c,
+  0xf8000087, 0xff0000dd, 0xb1000014, 0x00000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xff0000bd, 0xf200008c, 0xc500002f,
+  0xd1000033, 0xf900009a, 0xff0000e1, 0xb6000017, 0x00000000,
+  0x3c000000, 0xbb000000, 0xff0000ff, 0xff0000b8, 0xe0000067,
+  0xb8000015, 0xf000005c, 0xff0000ff, 0xc0000000, 0xbc00001a,
+  0xff0000e4, 0xf5000098, 0xc8000033, 0xd1000033, 0xf900009a,
+  0xff0000e4, 0xbe00001a, 0x00000000, 0x43000000, 0xff000078,
+  0xf8000096, 0xbe00002c, 0xb9000011, 0xe5000051, 0xfa0000cf,
+  0xff0000ff, 0x8d000000, 0x00000000, 0xbc00001a, 0xff0000e4,
+  0xf5000098, 0xc8000033, 0xd1000033, 0xf900009a, 0xff0000e4,
+  0xbe00001a, 0x00000000, 0x43000000, 0xff000078, 0xf8000096,
+  0xbe00002c, 0xb9000011, 0xe5000051, 0xfa0000cf, 0xff0000ff,
+  0x8d000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x43000000, 0xff000078, 0xf8000096, 0xbe00002c,
+  0xb9000011, 0xe5000051, 0xfa0000cf, 0xff0000ff, 0x8d000000,
+  0x3c000000, 0xbb000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x3c000000, 0xbb000000, 0xff0000ff, 0xff0000b1, 0xea000077,
+  0xbd00001d, 0xda000042, 0xfd0000bc, 0xfa000074, 0x36000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0xb7000019, 0xff0000e2, 0xf5000098,
+  0xc8000033, 0xd100002f, 0xf800008c, 0xff0000bc, 0xff0000ff,
+  0xc0000000, 0x00000000, 0x3c000000, 0xbb000000, 0xff0000ff,
+  0xc0000000, 0x00000000, 0x00000000, 0x3c000000, 0xbb000000,
+  0xff0000ff, 0xc0000000, 0x00000000, 0x00000000, 0xb7000019,
+  0xff0000e2, 0xf5000098, 0xc8000033, 0xd100002f, 0xf800008c,
+  0xff0000bc, 0xff0000ff, 0xc0000000, 0x00000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xf2000076, 0xbe000014, 0xd7000031,
+  0xfe0000b1, 0xff00008e, 0x33000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x00000000, 0x00000000, 0x2e000000, 0xff00009b, 0xf900009e,
+  0x82000000, 0x47000000, 0x19000000, 0x25000000, 0xf700008e,
+  0xfe000086, 0x25000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xf5000078, 0x5e000000, 0x3c000000, 0x0f000000, 0xcd00004b,
+  0xfe0000c1, 0x89000000, 0x00000000, 0x2e000000, 0xff00009b,
+  0xf900009e, 0x82000000, 0x47000000, 0x19000000, 0x25000000,
+  0xf700008e, 0xfe000086, 0x25000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xf900008a, 0x68000000, 0x46000000, 0x18000000,
+  0x30000000, 0xfb000096, 0xff000098, 0x32000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xf0000068, 0x5d000000, 0x34000000,
+  0x42000000, 0x90000000, 0xb4000000, 0xff00009c, 0xf8000092,
+  0x7e000000, 0x4c000000, 0x1a000000, 0x30000000, 0xfa000096,
+  0xff00009b, 0x37000000, 0x75000000, 0xfe0000e4, 0xc5000025,
+  0x4c000000, 0x16000000, 0x09000000, 0xcd000040, 0xff0000ff,
+  0xc0000000, 0x2e000000, 0xff00009c, 0xf8000092, 0x7e000000,
+  0x4c000000, 0x1a000000, 0x30000000, 0xfa000096, 0xff00009b,
+  0x37000000, 0x75000000, 0xfe0000e4, 0xc5000025, 0x4c000000,
+  0x16000000, 0x09000000, 0xcd000040, 0xff0000ff, 0xc0000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x75000000, 0xfe0000e4, 0xc5000025, 0x4c000000, 0x16000000,
+  0x09000000, 0xcd000040, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xc0000000, 0x00000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xf5000078, 0x5e000000, 0x3c000000,
+  0x0f000000, 0xcd00004b, 0xfe0000c1, 0x89000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x2a000000, 0xff00009a, 0xf9000092, 0x7d000000, 0x4c000000,
+  0x1a000000, 0x26000000, 0xf600008b, 0xff0000ff, 0xc0000000,
+  0x00000000, 0x00000000, 0x80000000, 0xff0000ff, 0xc0000000,
+  0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xc0000000, 0x00000000, 0x2a000000, 0xff00009a, 0xf9000092,
+  0x7d000000, 0x4c000000, 0x1a000000, 0x26000000, 0xf600008b,
+  0xff0000ff, 0xc0000000, 0x00000000, 0x00000000, 0x3c000000,
+  0x77000000, 0x9b000000, 0x3b000000, 0x0a000000, 0xaf000027,
+  0xff0000e4, 0x8f000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xc0000000, 0x00000000, 0x00000000,
+  0x00000000, 0x5d000000, 0xff0000da, 0xeb000034, 0xad000000,
+  0x88000000, 0x88000000, 0x88000000, 0xde00002f, 0xff0000cb,
+  0x7b000000, 0x00000000, 0x80000000, 0xff0000ff, 0xd1000028,
+  0x3c000000, 0x00000000, 0x00000000, 0x90000011, 0xff0000fc,
+  0xaf000000, 0x00000000, 0x5d000000, 0xff0000da, 0xeb000034,
+  0xad000000, 0x88000000, 0x88000000, 0x88000000, 0xde00002f,
+  0xff0000cb, 0x7b000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xd7000036, 0x45000000, 0x00000000, 0x00000000, 0x00000000,
+  0xbe00004b, 0xfe0000d8, 0x95000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xcb000019, 0x34000000, 0x00000000, 0x00000000,
+  0x00000000, 0x5d000000, 0xff0000da, 0xd0000049, 0x49000000,
+  0x00000000, 0x00000000, 0x00000000, 0xbe00004b, 0xfe0000d9,
+  0x96000000, 0x49000000, 0xf70000a8, 0xfb0000cb, 0xea000055,
+  0x82000005, 0x48000000, 0x44000000, 0x88000000, 0x9e000000,
+  0x5d000000, 0xff0000da, 0xd0000049, 0x49000000, 0x00000000,
+  0x00000000, 0x00000000, 0xbe00004b, 0xfe0000d9, 0x96000000,
+  0x49000000, 0xf70000a8, 0xfb0000cb, 0xea000055, 0x82000005,
+  0x48000000, 0x44000000, 0x88000000, 0x9e000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x49000000,
+  0xf70000a8, 0xfb0000cb, 0xea000055, 0x82000005, 0x48000000,
+  0x44000000, 0x88000000, 0x9e000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xc0000000, 0x00000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xd1000028, 0x3c000000, 0x00000000, 0x00000000,
+  0x90000011, 0xff0000fc, 0xaf000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5b000000,
+  0xff0000da, 0xd0000049, 0x49000000, 0x00000000, 0x00000000,
+  0x00000000, 0xb0000037, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x00000000, 0x00000000, 0x80000000, 0xff0000ff, 0xc0000000,
+  0x00000000, 0x5b000000, 0xff0000da, 0xd0000049, 0x49000000,
+  0x00000000, 0x00000000, 0x00000000, 0xb0000037, 0xff0000ff,
+  0xc0000000, 0x00000000, 0x00000000, 0x00000000, 0x2d000000,
+  0x60000000, 0x81000000, 0x88000000, 0xc4000000, 0xff0000f6,
+  0xb3000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xc0000000, 0x00000000, 0x00000000, 0x00000000,
+  0x7a000000, 0xff0000f6, 0xff0000ff, 0xff0000ff, 0xff0000ff,
+  0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ee, 0xa8000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xc0000000, 0x14000000,
+  0x00000000, 0x00000000, 0x80000000, 0xff0000ff, 0xbf000000,
+  0x00000000, 0x7a000000, 0xff0000f6, 0xff0000ff, 0xff0000ff,
+  0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xff0000ee,
+  0xa8000000, 0x00000000, 0x80000000, 0xff0000ff, 0xc0000001,
+  0x1b000000, 0x00000000, 0x00000000, 0x00000000, 0x92000013,
+  0xff0000f6, 0xb3000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xc0000000, 0x0d000000, 0x00000000, 0x00000000, 0x00000000,
+  0x78000000, 0xff0000f6, 0xc0000012, 0x25000000, 0x00000000,
+  0x00000000, 0x00000000, 0x92000013, 0xff0000f6, 0xb4000000,
+  0x00000000, 0x8f000007, 0xf900007e, 0xfc0000dd, 0xff0000f2,
+  0xfb0000c2, 0xf200005c, 0x72000001, 0x00000000, 0x78000000,
+  0xff0000f6, 0xc0000012, 0x25000000, 0x00000000, 0x00000000,
+  0x00000000, 0x92000013, 0xff0000f6, 0xb4000000, 0x00000000,
+  0x8f000007, 0xf900007e, 0xfc0000dd, 0xff0000f2, 0xfb0000c2,
+  0xf200005c, 0x72000001, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8f000007,
+  0xf900007e, 0xfc0000dd, 0xff0000f2, 0xfb0000c2, 0xf200005c,
+  0x72000001, 0x00000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xc0000000, 0x00000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xc0000000, 0x14000000, 0x00000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xbf000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x78000000, 0xff0000f6,
+  0xc0000012, 0x25000000, 0x00000000, 0x00000000, 0x00000000,
+  0x80000001, 0xff0000ff, 0xc0000000, 0x00000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xc0000000, 0x00000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x78000000, 0xff0000f6, 0xc0000012, 0x25000000, 0x00000000,
+  0x00000000, 0x00000000, 0x80000001, 0xff0000ff, 0xc0000000,
+  0x00000000, 0x01000000, 0xa1000010, 0xfe00007f, 0xfe0000c1,
+  0xff0000f9, 0xff0000ff, 0xff0000ff, 0xff0000ff, 0xbd000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xc0000000, 0x00000000, 0x00000000, 0x00000000, 0x69000000,
+  0xff0000d9, 0xe8000028, 0xbb000000, 0xbb000000, 0xbb000000,
+  0xbb000000, 0xda000000, 0xff000000, 0xc1000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xc0000000, 0x00000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x69000000, 0xff0000d9, 0xe8000028, 0xbb000000, 0xbb000000,
+  0xbb000000, 0xbb000000, 0xda000000, 0xff000000, 0xc1000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xd300002b, 0x01000000,
+  0x00000000, 0x00000000, 0x00000000, 0xbe00004b, 0xfe0000d8,
+  0xb1000000, 0x00000000, 0x80000000, 0xff0000ff, 0xc0000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x5d000000,
+  0xff0000da, 0xdc00004a, 0x09000000, 0x00000000, 0x00000000,
+  0x00000000, 0xbe00004b, 0xfe0000d9, 0xb1000000, 0x44000000,
+  0x88000000, 0x65000000, 0x84000000, 0xc8000014, 0xf4000059,
+  0xfc0000cc, 0xfb000098, 0x40000000, 0x5d000000, 0xff0000da,
+  0xdc00004a, 0x09000000, 0x00000000, 0x00000000, 0x00000000,
+  0xbe00004b, 0xfe0000d9, 0xb1000000, 0x44000000, 0x88000000,
+  0x65000000, 0x84000000, 0xc8000014, 0xf4000059, 0xfc0000cc,
+  0xfb000098, 0x40000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x44000000, 0x88000000, 0x65000000,
+  0x84000000, 0xc8000014, 0xf4000059, 0xfc0000cc, 0xfb000098,
+  0x40000000, 0x00000000, 0x80000000, 0xff0000ff, 0xc0000000,
+  0x00000000, 0x00000000, 0x80000000, 0xff0000ff, 0xc0000000,
+  0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xc0000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x5b000000, 0xff0000da, 0xdc000049,
+  0x09000000, 0x00000000, 0x00000000, 0x00000000, 0xa700002c,
+  0xff0000ff, 0xc0000000, 0x00000000, 0x00000000, 0x7e000000,
+  0xff0000fc, 0xc7000011, 0x00000000, 0x00000000, 0x00000000,
+  0xa500002a, 0xff0000ff, 0xc0000000, 0x00000000, 0x5b000000,
+  0xff0000da, 0xdc000049, 0x09000000, 0x00000000, 0x00000000,
+  0x00000000, 0xa700002c, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x48000000, 0xff000083, 0xfb0000a8, 0xc7000038, 0xb500000a,
+  0xba000000, 0xdd000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x7f000000, 0xff0000fd, 0xc0000002,
+  0x00000000, 0x43000000, 0x88000000, 0x71000000, 0xff000097,
+  0xf4000080, 0x1b000000, 0x00000000, 0x00000000, 0x08000000,
+  0xe0000059, 0xff0000b5, 0x55000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xc0000000, 0x00000000, 0x00000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xc0000000, 0x00000000, 0x2b000000,
+  0xff000097, 0xf4000080, 0x1b000000, 0x00000000, 0x00000000,
+  0x08000000, 0xe0000059, 0xff0000b5, 0x55000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xf7000083, 0x1f000000, 0x00000000,
+  0x00000000, 0x18000000, 0xf9000096, 0xff000097, 0x83000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x2b000000, 0xff00009b,
+  0xfb000095, 0x39000000, 0x00000000, 0x00000000, 0x18000000,
+  0xf9000096, 0xff00009b, 0x85000000, 0x80000000, 0xff0000ff,
+  0xba00003a, 0x00000000, 0x00000000, 0x0b000000, 0xc1000027,
+  0xff0000e2, 0x9d000000, 0x2b000000, 0xff00009b, 0xfb000095,
+  0x39000000, 0x00000000, 0x00000000, 0x18000000, 0xf9000096,
+  0xff00009b, 0x85000000, 0x80000000, 0xff0000ff, 0xba00003a,
+  0x00000000, 0x00000000, 0x0b000000, 0xc1000027, 0xff0000e2,
+  0x9d000000, 0x00000000, 0x44000000, 0x88000000, 0x45000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xba00003a, 0x00000000,
+  0x00000000, 0x0b000000, 0xc1000027, 0xff0000e2, 0x9d000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x00000000, 0x80000000, 0xff0000ff, 0xc0000000, 0x00000000,
+  0x00000000, 0x00000000, 0x80000000, 0xff0000ff, 0xc0000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x2a000000, 0xff000099, 0xfb000092, 0x38000000,
+  0x00000000, 0x00000000, 0x0b000000, 0xf0000084, 0xff0000ff,
+  0xc0000000, 0x00000000, 0x00000000, 0x67000000, 0xfe0000c2,
+  0xdf000048, 0x09000000, 0x00000000, 0x07000000, 0xec00007a,
+  0xff0000ff, 0xc0000000, 0x00000000, 0x2a000000, 0xff000099,
+  0xfb000092, 0x38000000, 0x00000000, 0x00000000, 0x0b000000,
+  0xf0000084, 0xff0000ff, 0xc0000000, 0x00000000, 0x76000000,
+  0xff0000e1, 0xbd000026, 0x54000000, 0x1c000000, 0x05000000,
+  0x98000015, 0xff0000ff, 0xc0000000, 0x00000000, 0x00000000,
+  0x44000000, 0x88000000, 0x88000000, 0x44000000, 0x00000000,
+  0x00000000, 0x66000000, 0xff0000c1, 0xee000050, 0x8e00000d,
+  0xe400005a, 0xfe0000c7, 0x66000000, 0xad000015, 0xff0000d3,
+  0xf200007f, 0xaa00002d, 0x9d00001d, 0xe6000061, 0xff0000e9,
+  0xe9000025, 0x60000000, 0x44000000, 0xc4000000, 0xff0000ff,
+  0xe2000000, 0x44000000, 0x00000000, 0x44000000, 0xc4000000,
+  0xff0000ff, 0xe2000000, 0x44000000, 0x00000000, 0xad000015,
+  0xff0000d3, 0xf200007f, 0xaa00002d, 0x9d00001d, 0xe6000061,
+  0xff0000e9, 0xe9000025, 0x60000000, 0x44000000, 0xc4000000,
+  0xff0000ff, 0xff0000cc, 0xf3000083, 0xa900002b, 0xac000033,
+  0xf5000099, 0xff0000e1, 0xc9000017, 0x4c000000, 0x44000000,
+  0xc4000000, 0xff0000ff, 0xe2000000, 0x88000000, 0x44000000,
+  0x00000000, 0x00000000, 0x00000000, 0xb800001a, 0xff0000e4,
+  0xf8000099, 0xac000033, 0xac000033, 0xf5000099, 0xff0000e4,
+  0xcc00001a, 0x4e000000, 0x80000000, 0xff0000ff, 0xfc0000c5,
+  0xcf00004a, 0x91000010, 0xab00002c, 0xfa00009d, 0xff000074,
+  0x95000000, 0x00000000, 0xb800001a, 0xff0000e4, 0xf8000099,
+  0xac000033, 0xac000033, 0xf5000099, 0xff0000e4, 0xcc00001a,
+  0x4e000000, 0x80000000, 0xff0000ff, 0xfc0000c5, 0xcf00004a,
+  0x91000010, 0xab00002c, 0xfa00009d, 0xff000074, 0x95000000,
+  0x00000000, 0x8e000009, 0xff0000e8, 0x72000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x80000000, 0xff0000ff, 0xfc0000c5, 0xcf00004a, 0x91000010,
+  0xab00002c, 0xfa00009d, 0xff000074, 0x95000000, 0x44000000,
+  0xc4000000, 0xff0000ff, 0xe2000000, 0x44000000, 0x44000000,
+  0xc4000000, 0xff0000ff, 0xe2000000, 0x44000000, 0x00000000,
+  0x44000000, 0xc4000000, 0xff0000ff, 0xe2000000, 0x44000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0xb8000019, 0xff0000e2, 0xf7000097, 0xab000032,
+  0xa900002b, 0xef000083, 0xff0000cc, 0xff0000ff, 0xe2000000,
+  0x44000000, 0x00000000, 0x30000000, 0xf9000076, 0xfd0000ba,
+  0xc4000041, 0x9c00001c, 0xe9000076, 0xff0000b0, 0xff0000ff,
+  0xe2000000, 0x44000000, 0x00000000, 0xb8000019, 0xff0000e2,
+  0xf7000097, 0xab000032, 0xa900002b, 0xef000083, 0xff0000cc,
+  0xff0000ff, 0xe2000000, 0x44000000, 0x47000000, 0xfd000086,
+  0xfd0000af, 0xbd000038, 0x8f00000e, 0xc000003c, 0xfe0000b5,
+  0xff0000ff, 0xe2000000, 0x44000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xff0000ff, 0x80000000, 0x00000000, 0x00000000,
+  0x15000000, 0xee000046, 0xff0000bd, 0xff0000ef, 0xfd0000be,
+  0xeb00003f, 0x6f000000, 0x0e000000, 0xc0000018, 0xff0000a4,
+  0xff0000e1, 0xff0000e5, 0xfc00009b, 0xec000042, 0x8d000000,
+  0x13000000, 0x80000000, 0xff0000ff, 0xff0000ff, 0xff0000ff,
+  0x80000000, 0x00000000, 0x80000000, 0xff0000ff, 0xff0000ff,
+  0xff0000ff, 0x80000000, 0x00000000, 0x0e000000, 0xc0000018,
+  0xff0000a4, 0xff0000e1, 0xff0000e5, 0xfc00009b, 0xec000042,
+  0x8d000000, 0x13000000, 0x80000000, 0xff0000ff, 0xff0000ff,
+  0xfa00001a, 0xff0000ad, 0xff0000e4, 0xff0000e9, 0xff0000ad,
+  0xd100001d, 0x78000000, 0x0c000000, 0x80000000, 0xff0000ff,
+  0xff0000ff, 0xff0000ff, 0xff0000ff, 0x80000000, 0x00000000,
+  0x00000000, 0x00000000, 0x13000000, 0xcd00001f, 0xff0000ae,
+  0xff0000e8, 0xff0000e8, 0xff0000ae, 0xd900001f, 0x7d000000,
+  0x0d000000, 0x36000000, 0xd300003b, 0xfb0000aa, 0xff0000e1,
+  0xff0000f0, 0xff0000b6, 0xfc000076, 0xae000008, 0x3a000000,
+  0x00000000, 0x13000000, 0xcd00001f, 0xff0000ae, 0xff0000e8,
+  0xff0000e8, 0xff0000ae, 0xd900001f, 0x7d000000, 0x0d000000,
+  0x36000000, 0xd300003b, 0xfb0000aa, 0xff0000e1, 0xff0000f0,
+  0xff0000b6, 0xfc000076, 0xae000008, 0x3a000000, 0x00000000,
+  0xba00002b, 0xff0000ba, 0x9f000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x36000000,
+  0xd300003b, 0xfb0000aa, 0xff0000e1, 0xff0000f0, 0xff0000b6,
+  0xfc000076, 0xae000008, 0x3a000000, 0x80000000, 0xff0000ff,
+  0xff0000ff, 0xff0000ff, 0x80000000, 0x80000000, 0xff0000ff,
+  0xff0000ff, 0xff0000ff, 0x80000000, 0x00000000, 0x80000000,
+  0xff0000ff, 0xff0000ff, 0xff0000ff, 0x80000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x0f000000, 0xc300001e, 0xff0000ae, 0xff0000e9, 0xfe0000e5,
+  0xff0000ae, 0xf600001a, 0xff0000ff, 0xff0000ff, 0x80000000,
+  0x00000000, 0x00000000, 0x96000011, 0xfd000075, 0xff0000cc,
+  0xff0000e6, 0xff0000a4, 0xf2000011, 0xff0000ff, 0xff0000ff,
+  0x80000000, 0x00000000, 0x0f000000, 0xc300001e, 0xff0000ae,
+  0xff0000e9, 0xfe0000e5, 0xff0000ae, 0xf600001a, 0xff0000ff,
+  0xff0000ff, 0x80000000, 0x00000000, 0x9b000011, 0xfc000082,
+  0xff0000cb, 0xff0000f2, 0xff0000ca, 0xfe000048, 0xff0000ff,
+  0xff0000ff, 0x80000000, 0x00000000, 0x80000000, 0xff0000ff,
+  0xff0000ff, 0xc0000000, 0x00000000, 0x00000000, 0x00000000,
+  0x0f000000, 0x78000000, 0xaa000000, 0xaa000000, 0x68000000,
+  0x20000000, 0x00000000, 0x00000000, 0x3b000000, 0x9f000000,
+  0xb0000000, 0x9e000000, 0x51000000, 0x21000000, 0x00000000,
+  0x3c000000, 0x77000000, 0xbb000000, 0xbb000000, 0x9e000000,
+  0x00000000, 0x3c000000, 0x77000000, 0xbb000000, 0xbb000000,
+  0x9e000000, 0x00000000, 0x00000000, 0x00000000, 0x3b000000,
+  0x9f000000, 0xb0000000, 0x9e000000, 0x51000000, 0x21000000,
+  0x00000000, 0x3c000000, 0x77000000, 0xbb000000, 0x9e000000,
+  0x47000000, 0xa5000000, 0xb3000000, 0x95000000, 0x57000000,
+  0x0f000000, 0x00000000, 0x3c000000, 0x77000000, 0xbb000000,
+  0xbb000000, 0xbb000000, 0x9e000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x47000000, 0xa5000000,
+  0xb4000000, 0x94000000, 0x57000000, 0x10000000, 0x00000000,
+  0x00000000, 0x00000000, 0x4a000000, 0x96000000, 0xb2000000,
+  0xa8000000, 0x6e000000, 0x3b000000, 0x04000000, 0x00000000,
+  0x00000000, 0x00000000, 0x47000000, 0xa5000000, 0xb4000000,
+  0x94000000, 0x57000000, 0x10000000, 0x00000000, 0x00000000,
+  0x00000000, 0x4a000000, 0x96000000, 0xb2000000, 0xa8000000,
+  0x6e000000, 0x3b000000, 0x04000000, 0x13000000, 0xf600007d,
+  0xf900006e, 0x66000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x4a000000, 0x96000000, 0xb2000000, 0xa8000000, 0x6e000000,
+  0x3b000000, 0x04000000, 0x3c000000, 0x77000000, 0xbb000000,
+  0xbb000000, 0x9e000000, 0x3c000000, 0x77000000, 0xbb000000,
+  0xbb000000, 0x9e000000, 0x00000000, 0x3c000000, 0x77000000,
+  0xbb000000, 0xbb000000, 0x9e000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x47000000, 0xa5000000, 0xb5000000, 0x94000000,
+  0x7f000000, 0x7e000000, 0xbb000000, 0x9e000000, 0x00000000,
+  0x00000000, 0x00000000, 0x3d000000, 0x8d000000, 0xaa000000,
+  0x93000000, 0x7b000000, 0x7c000000, 0xbb000000, 0x9e000000,
+  0x00000000, 0x00000000, 0x00000000, 0x47000000, 0xa5000000,
+  0xb5000000, 0x94000000, 0x7f000000, 0x7e000000, 0xbb000000,
+  0x9e000000, 0x00000000, 0x00000000, 0x35000000, 0x8d000000,
+  0xaa000000, 0xa1000000, 0x8e000000, 0x8a000000, 0xbb000000,
+  0x9e000000, 0x00000000, 0x3c000000, 0x77000000, 0xbb000000,
+  0x9e000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x6d000000, 0xff000097, 0x9c000002,
+  0x37000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x06000000, 0x79000000, 0x4d000000, 0x01000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
+
+void subpicture_get_info(VideoSubpictureInfo *info)
+{
+  info->width = SUBPICTURE_WIDTH;
+  info->height = SUBPICTURE_HEIGHT;
+  info->data = text;
+  info->data_size = SUBPICTURE_DATA_SIZE;
+}
diff --git a/tests/test-subpicture-data.h b/tests/test-subpicture-data.h
new file mode 100644 (file)
index 0000000..cc37988
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *  test-subpicture-data.h - subpicture data
+ *
+ *  Copyright (C) <2011> Intel Corporation
+ *  Copyright (C) <2011> Collabora Ltd.
+ *  Copyright (C) <2011> Thibault Saunier <thibault.saunier@collabora.com>
+ *
+ *  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
+ */
+
+#ifndef TEST_SUBPICTURE_DATA
+#define TEST_SUBPICTURE_DATA
+
+#include <glib.h>
+#include "test-decode.h"
+
+typedef struct _VideoSubpictureInfo VideoSubpictureInfo;
+
+struct _VideoSubpictureInfo {
+    guint               width;
+    guint               height;
+    const guint32      *data;
+    guint               data_size;
+};
+
+void subpicture_get_info(VideoSubpictureInfo *info);
+
+#endif /* TEST_SUBPICTURE_DATA*/
diff --git a/tests/test-subpicture.c b/tests/test-subpicture.c
new file mode 100644 (file)
index 0000000..7a65fe3
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ *  test-subpicture.c - Test GstVaapiSubpicture
+ *
+ *  Copyright (C) <2011> Intel Corporation
+ *  Copyright (C) <2011> Collabora Ltd.
+ *  Copyright (C) <2011> Thibault Saunier <thibault.saunier@collabora.com>
+ *
+ *  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
+ */
+
+#include "config.h"
+#include <string.h>
+#include <gst/vaapi/gstvaapidecoder.h>
+#include <gst/vaapi/gstvaapidecoder_mpeg2.h>
+#include <gst/vaapi/gstvaapisurface.h>
+#include "output.h"
+#include "test-mpeg2.h"
+#include "test-subpicture-data.h"
+
+typedef void (*GetVideoInfoFunc)(VideoDecodeInfo *info);
+
+typedef struct _CodecDefs CodecDefs;
+struct _CodecDefs {
+    const gchar        *codec_str;
+    GetVideoInfoFunc    get_video_info;
+};
+
+static const CodecDefs g_codec_defs[] = {
+#define INIT_FUNCS(CODEC) { #CODEC, CODEC##_get_video_info }
+    INIT_FUNCS(mpeg2),
+#undef INIT_FUNCS
+    { NULL, }
+};
+
+static const CodecDefs *
+get_codec_defs(const gchar *codec_str)
+{
+    const CodecDefs *c;
+    for (c = g_codec_defs; c->codec_str; c++)
+        if (strcmp(codec_str, c->codec_str) == 0)
+            return c;
+    return NULL;
+}
+
+static inline void pause(void)
+{
+    g_print("Press any key to continue...\n");
+    getchar();
+}
+
+static gchar *g_codec_str;
+
+static GOptionEntry g_options[] = {
+    { "codec", 'c',
+      0,
+      G_OPTION_ARG_STRING, &g_codec_str,
+      "codec to test", NULL },
+    { NULL, }
+};
+
+static void
+upload_image (guint8 *dst, const guint32 *src, guint size)
+{
+    guint i;
+
+    for (i = 0; i < size; i += 4) {
+        dst[i    ] = *src >> 24;
+        dst[i + 1] = *src >> 16;
+        dst[i + 2] = *src >> 8;
+        dst[i + 3] = *src++;
+    }
+}
+
+int
+main(int argc, char *argv[])
+{
+    GstVaapiDisplay      *display;
+    GstVaapiWindow       *window;
+    GstVaapiDecoder      *decoder = NULL;
+    GstCaps              *decoder_caps;
+    GstStructure         *structure;
+    GstVaapiDecoderStatus status;
+    const CodecDefs      *codec;
+    GstBuffer            *buffer;
+    GstVaapiSurfaceProxy *proxy;
+    GstVaapiSurface      *surface;
+    VideoDecodeInfo       info;
+    VideoSubpictureInfo   subinfo;
+    GstVaapiImage        *subtitle_image;
+    GstVaapiSubpicture   *subpicture;
+    GstCaps              *argbcaps;
+    GstVaapiRectangle     sub_rect;
+    guint                 surf_width, surf_height;
+
+    static const guint win_width  = 640;
+    static const guint win_height = 480;
+
+    if (!video_output_init(&argc, argv, g_options))
+        g_error("failed to initialize video output subsystem");
+
+    if (!g_codec_str)
+        g_codec_str = g_strdup("mpeg2");
+
+    g_print("Test %s decode\n", g_codec_str);
+    codec = get_codec_defs(g_codec_str);
+    if (!codec)
+        g_error("no %s codec data found", g_codec_str);
+
+    display = video_output_create_display(NULL);
+    if (!display)
+        g_error("could not create VA display");
+
+    window = video_output_create_window(display, win_width, win_height);
+    if (!window)
+        g_error("could not create window");
+
+    codec->get_video_info(&info);
+    decoder_caps = gst_vaapi_profile_get_caps(info.profile);
+    if (!decoder_caps)
+        g_error("could not create decoder caps");
+
+    structure = gst_caps_get_structure(decoder_caps, 0);
+    if (info.width > 0 && info.height > 0)
+        gst_structure_set(
+            structure,
+            "width",  G_TYPE_INT, info.width,
+            "height", G_TYPE_INT, info.height,
+            NULL
+        );
+
+    decoder = gst_vaapi_decoder_mpeg2_new(display, decoder_caps);
+    if (!decoder)
+        g_error("could not create video decoder");
+    gst_caps_unref(decoder_caps);
+
+    buffer = gst_buffer_new();
+    if (!buffer)
+        g_error("could not create encoded data buffer");
+    gst_buffer_set_data(buffer, (guchar *)info.data, info.data_size);
+
+    if (!gst_vaapi_decoder_put_buffer(decoder, buffer))
+        g_error("could not send video data to the decoder");
+    gst_buffer_unref(buffer);
+
+    if (!gst_vaapi_decoder_put_buffer(decoder, NULL))
+        g_error("could not send EOS to the decoder");
+
+    proxy = gst_vaapi_decoder_get_surface(decoder, &status);
+    if (!proxy)
+        g_error("could not get decoded surface (decoder status %d)", status);
+
+    surface = gst_vaapi_surface_proxy_get_surface(proxy);
+    if (!surface)
+        g_error("could not get underlying surface");
+
+    gst_vaapi_surface_get_size(surface, &surf_width, &surf_height);
+    printf("surface size %dx%d\n", surf_width, surf_height);
+
+    subpicture_get_info (&subinfo);
+
+    /* Adding subpicture */
+    argbcaps = gst_caps_new_simple ("video/x-raw-rgb",
+              "endianness", G_TYPE_INT, G_BIG_ENDIAN,
+              "bpp", G_TYPE_INT, 32,
+              "red_mask", G_TYPE_INT, 0xff000000,
+              "green_mask", G_TYPE_INT, 0x00ff0000,
+              "blue_mask", G_TYPE_INT, 0x0000ff00,
+              "alpha_mask", G_TYPE_INT, 0x000000ff,
+              "width", G_TYPE_INT,  subinfo.width,
+              "height", G_TYPE_INT, subinfo.height,
+               NULL);
+
+    buffer = gst_buffer_new_and_alloc (subinfo.data_size);
+    upload_image (GST_BUFFER_DATA (buffer), subinfo.data, subinfo.data_size);
+    gst_buffer_set_caps (buffer, argbcaps);
+
+    subtitle_image = gst_vaapi_image_new (display,
+      GST_VAAPI_IMAGE_RGBA, subinfo.width, subinfo.height);
+
+    if (!gst_vaapi_image_update_from_buffer (subtitle_image, buffer, NULL))
+        g_error ("could not update VA image with subtitle data");
+
+    subpicture = gst_vaapi_subpicture_new (subtitle_image);
+
+    /* We position it as a subtitle, centered at the bottom. */
+    sub_rect.x = (surf_width - subinfo.width) / 2;
+    sub_rect.y = surf_height - subinfo.height - 10;
+    sub_rect.height = subinfo.height;
+    sub_rect.width = subinfo.width;
+
+    if (!gst_vaapi_surface_associate_subpicture (
+         surface,
+         subpicture,
+         NULL,
+         &sub_rect))
+        g_error("could not associate subpicture");
+
+    gst_vaapi_window_show(window);
+
+    if (!gst_vaapi_window_put_surface(window,
+                                      GST_VAAPI_SURFACE_PROXY_SURFACE(proxy),
+                                      NULL,
+                                      NULL,
+                                      GST_VAAPI_PICTURE_STRUCTURE_FRAME))
+        g_error("could not render surface");
+
+    pause();
+
+    gst_buffer_unref(buffer);
+    g_object_unref(proxy);
+    g_object_unref(decoder);
+    g_object_unref(window);
+    g_object_unref(display);
+    g_free(g_codec_str);
+    video_output_exit();
+    return 0;
+}
diff --git a/tests/test-surfaces.c b/tests/test-surfaces.c
new file mode 100644 (file)
index 0000000..c236e5e
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ *  test-surfaces.c - Test GstVaapiSurface and GstVaapiSurfacePool
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include <gst/vaapi/gstvaapisurface.h>
+#include <gst/vaapi/gstvaapisurfacepool.h>
+#include "output.h"
+
+#define MAX_SURFACES 4
+
+static void
+gst_vaapi_object_destroy_cb(gpointer object, gpointer user_data)
+{
+    g_print("destroying GstVaapiObject %p\n", object);
+}
+
+int
+main(int argc, char *argv[])
+{
+    GstVaapiDisplay    *display;
+    GstVaapiSurface    *surface;
+    GstVaapiID          surface_id;
+    GstVaapiSurface    *surfaces[MAX_SURFACES];
+    GstVaapiVideoPool  *pool;
+    GstCaps            *caps;
+    gint                i;
+
+    static const GstVaapiChromaType chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
+    static const guint              width       = 320;
+    static const guint              height      = 240;
+
+    if (!video_output_init(&argc, argv, NULL))
+        g_error("failed to initialize video output subsystem");
+
+    display = video_output_create_display(NULL);
+    if (!display)
+        g_error("could not create Gst/VA display");
+
+    surface = gst_vaapi_surface_new(display, chroma_type, width, height);
+    if (!surface)
+        g_error("could not create Gst/VA surface");
+
+    /* This also tests for the GstVaapiParamSpecID */
+    g_object_get(G_OBJECT(surface), "id", &surface_id, NULL);
+    if (surface_id != gst_vaapi_surface_get_id(surface))
+        g_error("could not retrieve the native surface ID");
+    g_print("created surface %" GST_VAAPI_ID_FORMAT "\n",
+            GST_VAAPI_ID_ARGS(surface_id));
+
+    g_object_unref(surface);
+
+    caps = gst_caps_new_simple(
+        GST_VAAPI_SURFACE_CAPS_NAME,
+        "type", G_TYPE_STRING, "vaapi",
+        "width", G_TYPE_INT, width,
+        "height", G_TYPE_INT, height,
+        NULL
+    );
+    if (!caps)
+        g_error("cound not create Gst/VA surface caps");
+
+    pool = gst_vaapi_surface_pool_new(display, caps);
+    if (!pool)
+        g_error("could not create Gst/VA surface pool");
+
+    for (i = 0; i < MAX_SURFACES; i++) {
+        surface = gst_vaapi_video_pool_get_object(pool);
+        if (!surface)
+            g_error("could not allocate Gst/VA surface from pool");
+        g_print("created surface %" GST_VAAPI_ID_FORMAT " from pool\n",
+                GST_VAAPI_ID_ARGS(gst_vaapi_surface_get_id(surface)));
+        surfaces[i] = surface;
+    }
+
+    /* Check the pool doesn't return the last free'd surface */
+    surface = g_object_ref(surfaces[1]);
+
+    for (i = 0; i < 2; i++)
+        gst_vaapi_video_pool_put_object(pool, surfaces[i]);
+
+    for (i = 0; i < 2; i++) {
+        surfaces[i] = gst_vaapi_video_pool_get_object(pool);
+        if (!surfaces[i])
+            g_error("could not re-allocate Gst/VA surface%d from pool", i);
+        g_print("created surface %" GST_VAAPI_ID_FORMAT " from pool (realloc)\n",
+                GST_VAAPI_ID_ARGS(gst_vaapi_surface_get_id(surfaces[i])));
+    }
+
+    if (surface == surfaces[0])
+        g_error("Gst/VA pool doesn't queue free surfaces");
+
+    for (i = MAX_SURFACES - 1; i >= 0; i--) {
+        if (!surfaces[i])
+            continue;
+        gst_vaapi_video_pool_put_object(pool, surfaces[i]);
+        surfaces[i] = NULL;
+    }
+
+    g_signal_connect(
+        G_OBJECT(surface),
+        "destroy",
+        G_CALLBACK(gst_vaapi_object_destroy_cb), NULL
+    );
+
+    /* Unref in random order to check objects are correctly refcounted */
+    g_print("unref display\n");
+    g_object_unref(display);
+    gst_caps_unref(caps);
+    g_print("unref pool\n");
+    g_object_unref(pool);
+    g_print("unref surface\n");
+    g_object_unref(surface);
+    video_output_exit();
+    return 0;
+}
diff --git a/tests/test-textures.c b/tests/test-textures.c
new file mode 100644 (file)
index 0000000..7bf40fd
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ *  test-textures.c - Test GstVaapiTexture
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+*/
+
+#include <gst/vaapi/gstvaapidisplay_glx.h>
+#include <gst/vaapi/gstvaapiwindow_glx.h>
+#include <gst/vaapi/gstvaapisurface.h>
+#include <gst/vaapi/gstvaapiimage.h>
+#include <gst/vaapi/gstvaapitexture.h>
+#include "image.h"
+
+static inline void pause(void)
+{
+    g_print("Press any key to continue...\n");
+    getchar();
+}
+
+static inline guint gl_get_current_texture_2d(void)
+{
+    GLint texture;
+    glGetIntegerv(GL_TEXTURE_BINDING_2D, &texture);
+    return (guint)texture;
+}
+
+int
+main(int argc, char *argv[])
+{
+    GstVaapiDisplay    *display;
+    GstVaapiWindow     *window;
+    GstVaapiWindowGLX  *glx_window;
+    GstVaapiSurface    *surface;
+    GstVaapiImage      *image;
+    GstVaapiTexture    *textures[2];
+    GstVaapiTexture    *texture;
+    GLuint              texture_id;
+    GstVaapiRectangle   src_rect;
+    GstVaapiRectangle   dst_rect;
+    guint               flags = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
+
+    static const GstVaapiChromaType chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
+    static const guint              width       = 320;
+    static const guint              height      = 240;
+    static const guint              win_width   = 640;
+    static const guint              win_height  = 480;
+
+    gst_init(&argc, &argv);
+
+    display = gst_vaapi_display_glx_new(NULL);
+    if (!display)
+        g_error("could not create VA display");
+
+    surface = gst_vaapi_surface_new(display, chroma_type, width, height);
+    if (!surface)
+        g_error("could not create VA surface");
+
+    image = image_generate(display, GST_VAAPI_IMAGE_NV12, width, height);
+    if (!image)
+        g_error("could not create VA image");
+    if (!image_upload(image, surface))
+        g_error("could not upload VA image to surface");
+
+    window = gst_vaapi_window_glx_new(display, win_width, win_height);
+    if (!window)
+        g_error("could not create window");
+    glx_window = GST_VAAPI_WINDOW_GLX(window);
+
+    gst_vaapi_window_show(window);
+
+    if (!gst_vaapi_window_glx_make_current(glx_window))
+        g_error("coult not bind GL context");
+
+    g_print("#\n");
+    g_print("# Create texture with gst_vaapi_texture_new()\n");
+    g_print("#\n");
+    {
+        texture = gst_vaapi_texture_new(
+            display,
+            GL_TEXTURE_2D,
+            GL_RGBA,
+            width,
+            height
+        );
+        if (!texture)
+            g_error("could not create VA texture");
+
+        textures[0] = texture;
+        texture_id  = gst_vaapi_texture_get_id(texture);
+
+        if (!gst_vaapi_texture_put_surface(texture, surface, flags))
+            g_error("could not transfer VA surface to texture");
+
+        if (!gst_vaapi_window_glx_put_texture(glx_window, texture, NULL, NULL))
+            g_error("could not render texture into the window");
+    }
+
+    g_print("#\n");
+    g_print("# Create texture with gst_vaapi_texture_new_with_texture()\n");
+    g_print("#\n");
+    {
+        const GLenum target = GL_TEXTURE_2D;
+        const GLenum format = GL_BGRA;
+
+        glEnable(target);
+        glGenTextures(1, &texture_id);
+        glBindTexture(target, texture_id);
+        glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+        glTexImage2D(
+            target,
+            0,
+            GL_RGBA8,
+            width, height,
+            0,
+            format,
+            GL_UNSIGNED_BYTE,
+            NULL
+        );
+        glDisable(target);
+
+        texture = gst_vaapi_texture_new_with_texture(
+            display,
+            texture_id,
+            target,
+            format
+        );
+        if (!texture)
+            g_error("could not create VA texture");
+
+        if (texture_id != gst_vaapi_texture_get_id(texture))
+            g_error("invalid texture id");
+
+        if (gl_get_current_texture_2d() != texture_id)
+            g_error("gst_vaapi_texture_new_with_texture() altered texture bindings");
+
+        textures[1] = texture;
+
+        if (!gst_vaapi_texture_put_surface(texture, surface, flags))
+            g_error("could not transfer VA surface to texture");
+
+        if (gl_get_current_texture_2d() != texture_id)
+            g_error("gst_vaapi_texture_put_surface() altered texture bindings");
+
+        src_rect.x      = 0;
+        src_rect.y      = 0;
+        src_rect.width  = width;
+        src_rect.height = height;
+
+        dst_rect.x      = win_width/2;
+        dst_rect.y      = win_height/2;
+        dst_rect.width  = win_width/2;
+        dst_rect.height = win_height/2;
+
+        if (!gst_vaapi_window_glx_put_texture(glx_window, texture, 
+                                              &src_rect, &dst_rect))
+            g_error("could not render texture into the window");
+
+        if (gl_get_current_texture_2d() != texture_id)
+            g_error("gst_vaapi_window_glx_put_texture() altered texture bindings");
+    }
+
+    gst_vaapi_window_glx_swap_buffers(glx_window);
+    pause();
+
+    g_object_unref(textures[0]);
+    g_object_unref(textures[1]);
+    glDeleteTextures(1, &texture_id);
+
+    g_object_unref(window);
+    g_object_unref(display);
+    gst_deinit();
+    return 0;
+}
diff --git a/tests/test-vc1.c b/tests/test-vc1.c
new file mode 100644 (file)
index 0000000..60170f1
--- /dev/null
@@ -0,0 +1,1778 @@
+/*
+ *  test-vc1.c - VC-1 test data
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+*/
+
+#include "test-vc1.h"
+
+#define VC1_CLIP_WIDTH            293
+#define VC1_CLIP_HEIGHT           240
+#define VC1_CLIP_DATA_SIZE      20864
+
+/* Data dump of a 320x240 VC-1 video clip (vc1.raw), it has a single frame */
+static const guchar vc1_clip[VC1_CLIP_DATA_SIZE] = {
+    0x00, 0x00, 0x01, 0x0f, 0xca, 0x00, 0x09, 0xf0, 0x77, 0x0a, 0x09, 0x20,
+    0x1d, 0xff, 0x0a, 0x0b, 0x80, 0x84, 0x80, 0x00, 0x00, 0x01, 0x0e, 0x4c,
+    0x10, 0x80, 0x00, 0x00, 0x01, 0x0d, 0xc1, 0xd8, 0xd4, 0x47, 0xd0, 0xaa,
+    0xc4, 0x45, 0xaa, 0xb8, 0x01, 0xdf, 0x4c, 0xc1, 0x3a, 0xfa, 0x13, 0x67,
+    0x6a, 0xed, 0x2c, 0x67, 0xbc, 0xef, 0xdc, 0x69, 0x99, 0xf8, 0x53, 0x97,
+    0x01, 0xdc, 0xbe, 0xd8, 0x3b, 0xa2, 0x96, 0xe8, 0xa1, 0x94, 0x02, 0x57,
+    0x82, 0x82, 0xd6, 0x14, 0xc7, 0x61, 0x5a, 0x00, 0x22, 0x81, 0x73, 0x33,
+    0x20, 0x00, 0xa0, 0x09, 0xc0, 0x50, 0xfa, 0x06, 0xce, 0x35, 0x91, 0x8d,
+    0x19, 0x0f, 0x07, 0x1e, 0x84, 0x5b, 0x3a, 0x29, 0x03, 0xad, 0x8f, 0x8a,
+    0xd2, 0x22, 0xf0, 0xfc, 0x28, 0xd2, 0x95, 0x4a, 0xfe, 0x74, 0x4b, 0x23,
+    0xe7, 0xd4, 0x12, 0x1f, 0x37, 0x01, 0x88, 0xf8, 0xa4, 0x09, 0x76, 0x51,
+    0xae, 0xf4, 0x23, 0x6d, 0x29, 0x8c, 0x54, 0xaa, 0x2c, 0x68, 0x10, 0x7e,
+    0x71, 0xbf, 0x10, 0xb4, 0x77, 0x97, 0x8b, 0xa1, 0x54, 0xd1, 0xda, 0xb5,
+    0x5f, 0x61, 0xf0, 0x64, 0x64, 0x29, 0x25, 0x7d, 0x42, 0xe0, 0xff, 0x2a,
+    0x83, 0x29, 0x61, 0xfc, 0xee, 0xe5, 0x11, 0x04, 0xc0, 0x43, 0xc0, 0xc4,
+    0x0e, 0x18, 0x43, 0xb6, 0x08, 0x55, 0xa0, 0x22, 0xf4, 0x58, 0x01, 0xc6,
+    0x43, 0x0d, 0xba, 0x04, 0x3e, 0x8e, 0x5f, 0xc1, 0x11, 0x56, 0xef, 0xd7,
+    0x78, 0xe2, 0xd2, 0xdb, 0x84, 0x16, 0x76, 0xc6, 0x92, 0x15, 0xf6, 0xc2,
+    0x76, 0x2f, 0xd2, 0xef, 0x46, 0x02, 0x60, 0x24, 0xda, 0x16, 0x48, 0x95,
+    0xc4, 0x87, 0x81, 0xa7, 0xdd, 0xd7, 0x77, 0x56, 0xb7, 0xb5, 0x28, 0x9d,
+    0x6b, 0x7b, 0xd6, 0x8b, 0x80, 0x42, 0x28, 0xb0, 0x28, 0x82, 0x50, 0x04,
+    0x65, 0x1a, 0xc3, 0x79, 0x74, 0x6c, 0x3e, 0x9e, 0x69, 0x0e, 0xc1, 0xed,
+    0x8d, 0xe9, 0xf0, 0xf4, 0xf8, 0xde, 0xc1, 0x62, 0x1d, 0x1f, 0x4a, 0x5d,
+    0x02, 0x11, 0xfa, 0xd8, 0x10, 0xb8, 0xa0, 0xc5, 0xf5, 0x85, 0xd1, 0x19,
+    0x14, 0x06, 0x21, 0x5b, 0xa5, 0x37, 0xcd, 0xf2, 0xbc, 0x3b, 0x7f, 0xe3,
+    0x1c, 0x62, 0x51, 0x4b, 0x09, 0x2e, 0x48, 0x1f, 0x4e, 0x19, 0xe4, 0x90,
+    0x22, 0x81, 0xf4, 0xf7, 0x16, 0x4f, 0xe5, 0x97, 0x12, 0x9b, 0x92, 0x6e,
+    0xcc, 0x61, 0xd6, 0x4a, 0x59, 0x66, 0x7d, 0xc2, 0x1d, 0x33, 0x7e, 0x62,
+    0x29, 0x81, 0x80, 0xb7, 0xa4, 0xcb, 0xc4, 0xc3, 0x9b, 0x1d, 0x2b, 0x00,
+    0xc9, 0x78, 0x82, 0xef, 0xd7, 0xa5, 0xad, 0x08, 0x18, 0x7c, 0x97, 0x61,
+    0x3e, 0xaf, 0x4e, 0x21, 0xd6, 0x5a, 0x35, 0xd6, 0xf9, 0xdf, 0x89, 0xe9,
+    0x09, 0x99, 0x3e, 0x53, 0x81, 0x80, 0x21, 0xd9, 0x44, 0x7f, 0xb9, 0xe7,
+    0x7d, 0x1d, 0xa6, 0xd4, 0xb6, 0x60, 0x71, 0xa3, 0x87, 0x13, 0x40, 0x7a,
+    0x50, 0xac, 0x02, 0x87, 0xe3, 0x7a, 0xab, 0xce, 0x11, 0xed, 0x51, 0x97,
+    0xc5, 0xf0, 0x33, 0xf5, 0x3b, 0x7e, 0x05, 0xda, 0x4d, 0x29, 0x23, 0xa7,
+    0xca, 0x43, 0x0e, 0x72, 0xf0, 0x96, 0xe9, 0x95, 0x4a, 0x32, 0xb0, 0xc4,
+    0xe5, 0x65, 0x73, 0xc3, 0x30, 0xea, 0xfb, 0x93, 0x04, 0x64, 0x48, 0x48,
+    0x20, 0x1a, 0x8c, 0xde, 0xb0, 0x24, 0x7d, 0xd6, 0xe9, 0x5b, 0xb9, 0x0b,
+    0x18, 0xb9, 0xc4, 0x4a, 0x81, 0xaa, 0xfb, 0x6b, 0x2f, 0xe6, 0x77, 0x00,
+    0x17, 0xa8, 0x1f, 0x7f, 0x8b, 0xcd, 0xaf, 0xb5, 0xc1, 0x26, 0x99, 0x3f,
+    0x74, 0xd9, 0x69, 0x4c, 0x4c, 0xe5, 0x8a, 0x51, 0x3b, 0x47, 0x18, 0x33,
+    0x1a, 0xc5, 0xc3, 0xe1, 0xeb, 0xc7, 0x80, 0xa4, 0xb3, 0x5f, 0x22, 0x64,
+    0xcc, 0x97, 0xcb, 0xdb, 0xe5, 0xc9, 0x09, 0x89, 0x65, 0xfd, 0x61, 0x76,
+    0xc3, 0xf7, 0xfe, 0x7d, 0xe1, 0x70, 0x07, 0x9a, 0x17, 0x95, 0x08, 0x4d,
+    0xec, 0xfb, 0x38, 0x61, 0x06, 0x1e, 0x96, 0x91, 0x19, 0x42, 0x88, 0xf1,
+    0x45, 0x04, 0x69, 0x63, 0x1c, 0x99, 0xf8, 0x26, 0xf4, 0xfc, 0xf0, 0xeb,
+    0x48, 0x06, 0x9d, 0xef, 0x46, 0x72, 0x41, 0xa9, 0xa5, 0xb8, 0x4a, 0xf0,
+    0xd3, 0x82, 0x65, 0x88, 0x98, 0x40, 0x97, 0x4a, 0x95, 0x10, 0x52, 0xca,
+    0x47, 0xec, 0x14, 0x75, 0x86, 0xd5, 0x7d, 0xf7, 0xda, 0xa5, 0x09, 0xc6,
+    0x50, 0x02, 0x8f, 0xd7, 0x51, 0x42, 0x43, 0x60, 0x27, 0x67, 0xa0, 0xd6,
+    0xd8, 0xcf, 0x58, 0xc5, 0x13, 0x27, 0xa2, 0x4e, 0x4f, 0xc3, 0xc2, 0x50,
+    0xcb, 0x8d, 0x00, 0x53, 0x87, 0x5a, 0x6b, 0x4d, 0xb4, 0x07, 0x0b, 0x40,
+    0xb3, 0xba, 0xc3, 0x14, 0xb8, 0x75, 0xda, 0x84, 0x50, 0x96, 0x12, 0xc6,
+    0xd1, 0x00, 0xa5, 0xa3, 0x4c, 0x11, 0x45, 0x02, 0xc7, 0x2f, 0xe2, 0x8f,
+    0xb7, 0xe9, 0xff, 0xe2, 0x48, 0x8b, 0x28, 0x1c, 0x38, 0x8c, 0x41, 0xc9,
+    0xd0, 0xfa, 0x13, 0x4f, 0xfd, 0x6b, 0x72, 0xa5, 0x0e, 0xd7, 0x2f, 0x2b,
+    0xee, 0x37, 0xe6, 0xb0, 0x41, 0x4d, 0x45, 0x83, 0x88, 0x6d, 0x14, 0x6d,
+    0xa6, 0xb1, 0x59, 0x7d, 0x7e, 0xa7, 0x8d, 0x48, 0xc3, 0x4c, 0x80, 0x91,
+    0xf0, 0x4d, 0xfc, 0xaf, 0xe6, 0xae, 0x9a, 0x24, 0xca, 0x73, 0xc4, 0x13,
+    0xf8, 0x28, 0xd2, 0xbf, 0xdf, 0xc4, 0xd0, 0x4e, 0xf4, 0x3e, 0x2c, 0x60,
+    0x6a, 0xd4, 0x6e, 0x44, 0x8a, 0xae, 0x09, 0x37, 0xb1, 0x98, 0xaf, 0x69,
+    0xf0, 0xee, 0x6f, 0x0a, 0x55, 0x6d, 0x12, 0x7c, 0xf0, 0x08, 0x78, 0xd2,
+    0x98, 0x7c, 0xdf, 0xd7, 0xa0, 0x0d, 0xf3, 0x52, 0x65, 0xf6, 0xb9, 0xfe,
+    0xf3, 0x73, 0x4c, 0xe2, 0x3a, 0x27, 0x64, 0x00, 0x28, 0x54, 0x2d, 0x4a,
+    0x59, 0x42, 0x43, 0xea, 0x26, 0xeb, 0x13, 0x2a, 0x5a, 0x9a, 0x35, 0xe9,
+    0xe3, 0xe0, 0x3d, 0x84, 0xf0, 0x12, 0xbe, 0x84, 0x3f, 0x1c, 0xe6, 0x06,
+    0xab, 0x30, 0x0d, 0xa3, 0xba, 0xe4, 0x24, 0xe0, 0x6f, 0x5c, 0xab, 0x43,
+    0x9a, 0xf6, 0xf4, 0xd9, 0x74, 0x7e, 0x2c, 0x63, 0xf3, 0xd2, 0x17, 0x0b,
+    0x57, 0xda, 0x1d, 0xd0, 0x47, 0x52, 0xc7, 0xc9, 0xb8, 0x14, 0x12, 0x23,
+    0xc1, 0x23, 0x9b, 0x78, 0x51, 0x81, 0x7b, 0x66, 0x48, 0xbb, 0xc8, 0x7a,
+    0x67, 0x84, 0x0a, 0xff, 0x82, 0xe9, 0x7e, 0xea, 0x5f, 0x5b, 0x94, 0xd6,
+    0x24, 0x48, 0x3b, 0xa6, 0x25, 0x29, 0xd1, 0x92, 0x12, 0x9a, 0x5f, 0x84,
+    0x3e, 0xb4, 0xe4, 0x3f, 0x15, 0xad, 0xe9, 0xec, 0xbc, 0x10, 0x7d, 0xc9,
+    0xcd, 0xeb, 0x71, 0xd3, 0x79, 0x1a, 0xc2, 0xf5, 0x0d, 0x31, 0xac, 0x6a,
+    0xac, 0xbc, 0x7f, 0x67, 0x43, 0x78, 0xc5, 0x23, 0x97, 0x56, 0x88, 0x3c,
+    0xb0, 0x8e, 0x2c, 0x8a, 0x2b, 0x63, 0xfe, 0xb2, 0xaa, 0xb1, 0x71, 0x72,
+    0x74, 0x41, 0xc3, 0x78, 0x0c, 0x5f, 0x92, 0x8d, 0x64, 0xe0, 0xf8, 0xde,
+    0x09, 0x8f, 0xcd, 0x39, 0x45, 0x5a, 0x5d, 0x12, 0x6b, 0x26, 0xad, 0xfe,
+    0xc0, 0x51, 0x1e, 0x00, 0xe9, 0x36, 0xf1, 0xb6, 0x74, 0x7b, 0x67, 0x6e,
+    0xe2, 0xe4, 0xf4, 0x8e, 0x40, 0x87, 0xc6, 0x14, 0xcc, 0xa8, 0x25, 0x37,
+    0x72, 0x0c, 0xc0, 0xf4, 0xff, 0xf4, 0x7d, 0xdc, 0xa8, 0xda, 0x68, 0xa5,
+    0xbf, 0x04, 0xa3, 0x2c, 0x9f, 0xc7, 0x0a, 0x7c, 0x37, 0x86, 0xe7, 0x76,
+    0x4e, 0x50, 0x79, 0xa5, 0xd1, 0x5f, 0x2e, 0x6f, 0x9a, 0x5c, 0x75, 0x73,
+    0xd3, 0x7a, 0x10, 0x69, 0x45, 0xf1, 0x99, 0xca, 0x04, 0x24, 0x0a, 0x76,
+    0xf5, 0xb9, 0xf7, 0xca, 0xf3, 0xfe, 0xde, 0x28, 0x70, 0x47, 0x3c, 0x35,
+    0x17, 0x70, 0x21, 0x42, 0x32, 0x81, 0xfb, 0x3d, 0xc8, 0xf0, 0x35, 0xfe,
+    0xe7, 0xee, 0x1b, 0x1e, 0xdd, 0xce, 0x19, 0xa2, 0x95, 0x95, 0x43, 0x2f,
+    0xb2, 0x26, 0xcc, 0xbb, 0xb7, 0x8b, 0x8b, 0xff, 0x1c, 0xeb, 0x82, 0xa9,
+    0x4f, 0x25, 0x58, 0xfa, 0x41, 0x22, 0x4a, 0xcb, 0x38, 0xc4, 0xff, 0x12,
+    0x0d, 0xf7, 0x3b, 0xed, 0x0c, 0x7e, 0x29, 0xd3, 0x19, 0xe2, 0x2c, 0xff,
+    0x8e, 0xbf, 0xe1, 0x1b, 0xc9, 0x6f, 0xac, 0x51, 0x97, 0x49, 0x68, 0x4d,
+    0x20, 0x27, 0x3f, 0x11, 0xfe, 0x1e, 0x7f, 0xef, 0xda, 0x76, 0xba, 0xba,
+    0xf2, 0xdb, 0x60, 0x36, 0x9a, 0xa3, 0x28, 0x89, 0xc8, 0x64, 0xb0, 0x90,
+    0x79, 0xcb, 0x9d, 0x45, 0xcc, 0xdd, 0x6d, 0xf0, 0xd5, 0xb5, 0x8a, 0x64,
+    0x51, 0x96, 0xcb, 0x12, 0x70, 0x0a, 0xca, 0x69, 0x34, 0x20, 0x43, 0x31,
+    0x3c, 0xba, 0xb2, 0x80, 0xe1, 0xb2, 0x65, 0x79, 0x6f, 0x4e, 0x6e, 0x92,
+    0x4b, 0xbf, 0x80, 0x2a, 0xb7, 0x97, 0x7f, 0xc9, 0xf5, 0xbc, 0xef, 0x1e,
+    0x7f, 0xc9, 0xb6, 0x3d, 0x86, 0x4c, 0x89, 0x62, 0xac, 0x2b, 0xd0, 0x26,
+    0x9d, 0xab, 0xeb, 0xfb, 0x5d, 0x4b, 0x6c, 0xe5, 0x58, 0x29, 0xb3, 0x4a,
+    0x09, 0xed, 0x17, 0xf1, 0x00, 0xbb, 0x5c, 0x17, 0xc4, 0x56, 0x3b, 0xfc,
+    0x13, 0x08, 0xc5, 0xcf, 0xc4, 0x14, 0x5f, 0xe2, 0xf8, 0xa5, 0xe2, 0xde,
+    0x2f, 0x85, 0xde, 0xf7, 0xf7, 0x4d, 0xcd, 0x7b, 0xf2, 0xb6, 0x8b, 0x72,
+    0x03, 0x6b, 0x2c, 0x7f, 0xde, 0x40, 0xf4, 0x76, 0x52, 0x2b, 0x61, 0x2d,
+    0x72, 0xa2, 0x21, 0x0c, 0x1b, 0x44, 0x6c, 0x40, 0x04, 0xbc, 0x5e, 0xff,
+    0xcb, 0xb6, 0x65, 0x99, 0xc6, 0xdb, 0xf7, 0x6f, 0xbc, 0x75, 0xd6, 0xcb,
+    0x79, 0x6d, 0xd6, 0x94, 0xbd, 0xb7, 0x47, 0x89, 0xc6, 0xf6, 0xf0, 0xab,
+    0x67, 0x60, 0x37, 0x32, 0x7d, 0x0f, 0x31, 0x08, 0xe2, 0x4e, 0x11, 0x0d,
+    0x64, 0x1e, 0x66, 0xc6, 0xc6, 0xc5, 0x34, 0x56, 0xf8, 0xbf, 0x12, 0x83,
+    0x7a, 0x75, 0xe0, 0x67, 0xae, 0x7b, 0x7e, 0xfb, 0xb6, 0x33, 0x38, 0xaa,
+    0xea, 0x98, 0x9b, 0xfd, 0x36, 0x0d, 0x7e, 0x0f, 0xd4, 0xf9, 0x56, 0x6a,
+    0xd5, 0x40, 0xb4, 0x38, 0xae, 0x6a, 0x7a, 0xc5, 0x40, 0x2c, 0x87, 0x72,
+    0x80, 0x3e, 0x20, 0xf3, 0x48, 0xed, 0xbd, 0xb8, 0x13, 0xdf, 0xb7, 0xae,
+    0x6a, 0xe6, 0x62, 0x6e, 0x73, 0x4c, 0xf0, 0x06, 0xba, 0x6c, 0xb2, 0xed,
+    0xb6, 0x83, 0x32, 0x77, 0x63, 0xff, 0x84, 0x7e, 0xca, 0x91, 0xd7, 0x14,
+    0xc7, 0xae, 0x12, 0x91, 0x49, 0xb6, 0x32, 0x92, 0x97, 0x5e, 0x39, 0x5a,
+    0x71, 0x86, 0xdc, 0x92, 0xbb, 0x47, 0x8c, 0x3e, 0x24, 0xfc, 0x05, 0xf2,
+    0x38, 0x7b, 0xdd, 0x4c, 0xec, 0x52, 0x8f, 0x80, 0x57, 0xd1, 0x52, 0x6b,
+    0x0a, 0xb9, 0x81, 0xfd, 0x6b, 0xd2, 0x43, 0x58, 0x2c, 0x2a, 0xb8, 0x3d,
+    0x66, 0xb0, 0x61, 0x9b, 0x3e, 0x7a, 0xc9, 0x38, 0x62, 0xc8, 0x6b, 0x4f,
+    0xa0, 0xe3, 0xed, 0x13, 0x7b, 0xd6, 0x7c, 0xbb, 0x35, 0xaf, 0x81, 0xed,
+    0x88, 0x91, 0x35, 0x2a, 0x5c, 0x5f, 0x47, 0xa7, 0x2f, 0x6f, 0xf5, 0x23,
+    0x38, 0x20, 0x87, 0x5f, 0x65, 0x81, 0xfa, 0x44, 0x88, 0xd4, 0x96, 0x5e,
+    0xc2, 0x84, 0xca, 0x39, 0x20, 0x28, 0x93, 0x94, 0x06, 0x4f, 0xc5, 0x41,
+    0xff, 0x4e, 0x9d, 0xe6, 0xdb, 0x29, 0x50, 0xaf, 0x46, 0x49, 0x00, 0x24,
+    0x04, 0xf2, 0xcd, 0x13, 0x84, 0x82, 0xa3, 0xc9, 0x21, 0x36, 0x26, 0x6f,
+    0xad, 0xff, 0xb7, 0x6f, 0xf2, 0x6e, 0x15, 0x83, 0xa8, 0xb5, 0x2e, 0x89,
+    0xfb, 0xca, 0xfe, 0xfa, 0x80, 0x2d, 0xc7, 0x43, 0xfe, 0xbe, 0xd5, 0x1b,
+    0x8a, 0x4d, 0x08, 0xed, 0x55, 0x2c, 0x83, 0xc1, 0xe5, 0x7b, 0xc5, 0x1b,
+    0x5d, 0xdd, 0xb7, 0x53, 0xf1, 0x3b, 0xd7, 0x7d, 0xed, 0xe6, 0x11, 0xbe,
+    0x75, 0xb5, 0xb4, 0x22, 0x42, 0x53, 0x10, 0x81, 0x34, 0x7b, 0x81, 0x3c,
+    0x94, 0x13, 0xc7, 0x2c, 0xed, 0xa1, 0xa3, 0x0a, 0x15, 0x7a, 0xb0, 0x26,
+    0x69, 0xe0, 0x45, 0x19, 0xb1, 0x9c, 0x88, 0x9d, 0xe1, 0x61, 0x20, 0xee,
+    0x3f, 0xe6, 0xa3, 0x8c, 0x61, 0x85, 0xa7, 0x28, 0xd2, 0x09, 0x7b, 0x69,
+    0xb0, 0x95, 0x37, 0xd8, 0x96, 0x3c, 0xcc, 0x2c, 0x90, 0x83, 0x28, 0x8c,
+    0x8b, 0x3b, 0xfe, 0xb7, 0xb5, 0x19, 0x15, 0x5e, 0xcf, 0x5f, 0xaf, 0x8c,
+    0x76, 0x95, 0x02, 0x97, 0xe9, 0xac, 0x02, 0xb2, 0xee, 0x82, 0xe7, 0x16,
+    0xca, 0x5b, 0x08, 0x22, 0xc6, 0x4e, 0xd2, 0xab, 0x10, 0x0f, 0x68, 0x5c,
+    0xc2, 0x3d, 0x16, 0xf8, 0x74, 0x11, 0xd6, 0x4c, 0x65, 0xe1, 0x26, 0x9a,
+    0x2d, 0xb0, 0x20, 0x66, 0xd2, 0xed, 0x60, 0xf4, 0xd1, 0xc2, 0x7d, 0x44,
+    0xd7, 0xbd, 0x45, 0x36, 0x7b, 0xdc, 0xef, 0x87, 0xba, 0xbe, 0x16, 0x40,
+    0x13, 0xa3, 0x3a, 0x6e, 0x12, 0xc0, 0xa3, 0xe2, 0x01, 0xfa, 0xde, 0xe5,
+    0x75, 0xb9, 0x8a, 0x12, 0x19, 0x44, 0x8a, 0x12, 0xc9, 0x51, 0x84, 0xa5,
+    0xcb, 0xc0, 0xec, 0xee, 0xd3, 0xaf, 0x34, 0xa4, 0x91, 0x34, 0x52, 0x01,
+    0xeb, 0x00, 0x8e, 0x62, 0x71, 0x6f, 0x32, 0x80, 0x3e, 0xdc, 0x17, 0x3b,
+    0x7d, 0x4b, 0x50, 0x4e, 0x81, 0x90, 0x98, 0xde, 0x4c, 0xc6, 0x90, 0x09,
+    0x6e, 0xbb, 0x4e, 0x1f, 0x87, 0x0b, 0x2e, 0x1f, 0xed, 0x42, 0x0e, 0x2d,
+    0x04, 0x24, 0xb0, 0x40, 0xc3, 0xde, 0x12, 0x24, 0x15, 0x2a, 0x68, 0x09,
+    0xf8, 0xf8, 0x71, 0xf1, 0x85, 0x16, 0x12, 0xa4, 0x58, 0xc1, 0xa6, 0x19,
+    0x1a, 0x68, 0x9d, 0xa1, 0x94, 0x32, 0x08, 0x11, 0x51, 0x14, 0xb1, 0xa4,
+    0x24, 0x0c, 0xdd, 0x2c, 0x04, 0x20, 0x19, 0x72, 0x35, 0x60, 0xda, 0x79,
+    0x84, 0x11, 0x05, 0xf0, 0xe6, 0x52, 0xf8, 0x9f, 0x3a, 0xd0, 0x9e, 0xe1,
+    0xe4, 0x50, 0x99, 0x8c, 0xb4, 0xba, 0x33, 0xc7, 0xc0, 0x33, 0x00, 0x76,
+    0x0e, 0x10, 0x19, 0x31, 0x23, 0x8d, 0x34, 0x96, 0xdf, 0xd8, 0x6b, 0x24,
+    0x65, 0x3f, 0x4d, 0x1c, 0x95, 0x5a, 0x79, 0xc2, 0xe5, 0xb2, 0x36, 0xc5,
+    0xa6, 0x8b, 0x28, 0x03, 0x95, 0xda, 0x51, 0xa3, 0x96, 0x00, 0xf9, 0xe0,
+    0xbc, 0x7e, 0xc5, 0xab, 0x8a, 0x64, 0xa5, 0x7c, 0xf3, 0x65, 0x98, 0xc1,
+    0x92, 0x4b, 0x9f, 0xa6, 0x87, 0x8a, 0x35, 0xa5, 0x35, 0x14, 0x93, 0x26,
+    0x05, 0xfe, 0xec, 0x4b, 0xdc, 0xea, 0xd6, 0xb6, 0x54, 0x23, 0x2c, 0x24,
+    0x72, 0xfe, 0x71, 0x90, 0x31, 0xfd, 0x00, 0x84, 0xc2, 0xc8, 0x63, 0x8a,
+    0x88, 0xcb, 0x27, 0xf0, 0x7e, 0x05, 0x1e, 0xf3, 0xb4, 0xfa, 0x7e, 0xe1,
+    0x77, 0x67, 0xe3, 0xa6, 0x28, 0x11, 0x48, 0xe3, 0xbd, 0x00, 0x25, 0x7b,
+    0x30, 0xcb, 0xec, 0x27, 0xc1, 0x61, 0x28, 0x1c, 0x56, 0x66, 0x12, 0x10,
+    0xba, 0x08, 0x03, 0x91, 0x43, 0xd3, 0x6d, 0x2a, 0xcd, 0x2a, 0x58, 0x64,
+    0x68, 0x24, 0x4f, 0xc7, 0x47, 0xf1, 0x7c, 0x69, 0x9a, 0x14, 0x64, 0x5e,
+    0x53, 0xbd, 0x74, 0x85, 0xa9, 0x29, 0xa6, 0x7e, 0xae, 0x39, 0x35, 0x40,
+    0x8c, 0xe5, 0x59, 0x30, 0x5c, 0x7f, 0x46, 0xa1, 0x37, 0x29, 0x04, 0x07,
+    0xc5, 0xf1, 0xcf, 0x30, 0x0f, 0x89, 0x87, 0x31, 0x4f, 0x33, 0xa2, 0x04,
+    0xb2, 0x9b, 0x30, 0x55, 0x14, 0xb1, 0x82, 0xac, 0x3e, 0xb8, 0x1a, 0xb9,
+    0xca, 0xa5, 0xe9, 0x4b, 0x28, 0x77, 0x3a, 0x63, 0xe8, 0xad, 0xbe, 0x98,
+    0xd2, 0x2d, 0x32, 0xc6, 0x30, 0x82, 0x0e, 0xc1, 0x8f, 0xb9, 0x70, 0x13,
+    0xca, 0x42, 0xd8, 0x07, 0x0f, 0x23, 0xd9, 0x5a, 0xed, 0x92, 0x9b, 0x38,
+    0xc5, 0xa0, 0x65, 0xb1, 0x08, 0x90, 0xcb, 0x61, 0x2c, 0x05, 0x1f, 0xa6,
+    0x2a, 0x55, 0x24, 0x2f, 0x40, 0xc2, 0x4f, 0x5c, 0xb3, 0xcc, 0xd5, 0xfb,
+    0x57, 0xda, 0x92, 0x08, 0xed, 0x0e, 0x56, 0x4e, 0x55, 0x6d, 0xfc, 0xc3,
+    0x66, 0x95, 0x9c, 0x81, 0x27, 0xe5, 0x6c, 0x9d, 0x42, 0x94, 0x38, 0x68,
+    0x48, 0x22, 0x58, 0x48, 0x86, 0xfa, 0x83, 0x66, 0xb6, 0xbd, 0xca, 0x0d,
+    0x0c, 0x72, 0x68, 0xd6, 0x07, 0xe4, 0xcc, 0x84, 0x76, 0x85, 0x0f, 0x9c,
+    0x7a, 0x2d, 0x6a, 0xed, 0x3e, 0x34, 0xda, 0x2b, 0xf2, 0xf4, 0x67, 0xa6,
+    0x00, 0xd1, 0x64, 0x5e, 0x45, 0x12, 0x82, 0x2d, 0x95, 0x2f, 0xac, 0x58,
+    0xf9, 0xea, 0x65, 0x4b, 0x27, 0xdb, 0x3d, 0xdd, 0x8d, 0x8a, 0x5e, 0xda,
+    0xb5, 0xd6, 0x05, 0x88, 0x64, 0x1c, 0x84, 0x7f, 0x69, 0x12, 0x11, 0x2f,
+    0x80, 0x7d, 0x12, 0xbb, 0xaa, 0x50, 0x71, 0x9b, 0x4c, 0xba, 0xdf, 0xaa,
+    0x5e, 0xf6, 0x34, 0x1f, 0xef, 0xa5, 0x4f, 0xfa, 0x95, 0x34, 0xef, 0x84,
+    0xed, 0xd9, 0x2f, 0x1c, 0xcd, 0xc6, 0x5e, 0x90, 0xfb, 0x13, 0xf3, 0xf0,
+    0xfa, 0x3f, 0x7f, 0x77, 0xca, 0x76, 0x12, 0x9a, 0x3c, 0x92, 0x86, 0xed,
+    0xcb, 0xe0, 0x22, 0x84, 0x86, 0x5d, 0x02, 0xf2, 0xfa, 0x37, 0x83, 0x64,
+    0xad, 0x1f, 0x0d, 0xdb, 0x95, 0x8f, 0x3d, 0x70, 0xbe, 0xff, 0xfb, 0x5d,
+    0xfd, 0xbe, 0x1b, 0x92, 0xcc, 0xb6, 0x95, 0xef, 0x63, 0x8a, 0x72, 0xc8,
+    0x4e, 0x88, 0xf9, 0xa3, 0xb9, 0x07, 0x9c, 0xb3, 0x3f, 0xad, 0xca, 0x84,
+    0xb2, 0x06, 0x42, 0x28, 0xb7, 0xc4, 0xf1, 0x07, 0x9c, 0xcf, 0x8e, 0xe7,
+    0xd9, 0xc9, 0xa8, 0xf8, 0x9e, 0x1b, 0x96, 0x48, 0xf6, 0xa9, 0x55, 0x5d,
+    0x6d, 0xff, 0xff, 0xed, 0x49, 0xc8, 0x82, 0x8e, 0x33, 0x09, 0x78, 0x68,
+    0x44, 0x2c, 0xd9, 0xbf, 0xd4, 0x22, 0x03, 0xad, 0x38, 0x01, 0x7b, 0xeb,
+    0x1b, 0x8b, 0x6c, 0x94, 0xda, 0x81, 0x6e, 0xd8, 0x6a, 0x26, 0x02, 0x28,
+    0xa3, 0x2f, 0xa8, 0x0f, 0xef, 0x0d, 0xbc, 0xb9, 0xa2, 0x57, 0xb2, 0x72,
+    0x28, 0x81, 0x9b, 0x5d, 0x54, 0x86, 0x7b, 0xf9, 0xed, 0x13, 0xe1, 0x8c,
+    0xa4, 0x32, 0x35, 0xe4, 0x8e, 0x01, 0xe1, 0xdd, 0x71, 0xc5, 0xfe, 0x50,
+    0x53, 0xdf, 0xef, 0x6b, 0x69, 0x81, 0x35, 0x5a, 0x65, 0x16, 0x87, 0xce,
+    0x42, 0x86, 0x32, 0xd4, 0x48, 0x97, 0x3f, 0x10, 0x39, 0xa3, 0xf6, 0x03,
+    0xc1, 0xb2, 0xe7, 0xe3, 0xed, 0xae, 0x92, 0x06, 0xca, 0xd0, 0xd0, 0x96,
+    0x51, 0xd2, 0x4b, 0x9f, 0xef, 0x5a, 0xdc, 0x66, 0x2b, 0x56, 0xa3, 0x5f,
+    0xe3, 0x4b, 0x67, 0x39, 0x09, 0x6f, 0x27, 0x68, 0xd0, 0x75, 0x66, 0xf3,
+    0x5c, 0x7c, 0x99, 0x97, 0xbe, 0x95, 0xb7, 0x22, 0xde, 0x54, 0x77, 0x8e,
+    0x97, 0x05, 0x21, 0xa4, 0x00, 0x9a, 0x1d, 0xcc, 0xf5, 0x5e, 0xc6, 0xcf,
+    0x48, 0x84, 0xab, 0x80, 0xe4, 0x3d, 0x25, 0xc0, 0x88, 0xc7, 0x62, 0xce,
+    0x40, 0x32, 0x45, 0xc4, 0x89, 0x44, 0x64, 0xeb, 0x20, 0xe7, 0xba, 0x5a,
+    0x97, 0xe7, 0xb1, 0x1a, 0xa6, 0xeb, 0xe2, 0x4f, 0x30, 0x03, 0x60, 0xc2,
+    0x84, 0xcc, 0xf0, 0x0a, 0xa8, 0xb0, 0x97, 0x22, 0x48, 0x78, 0x40, 0x46,
+    0x9f, 0xc4, 0x83, 0xfe, 0x62, 0x7b, 0xfe, 0xbb, 0xfb, 0x3d, 0x36, 0x2a,
+    0xf5, 0xde, 0xb3, 0xbd, 0xf9, 0x4f, 0xcb, 0x1e, 0xbf, 0xcd, 0xe0, 0xef,
+    0x3f, 0x34, 0x9b, 0xf3, 0x96, 0xd1, 0x30, 0x84, 0x69, 0x8d, 0x00, 0xf3,
+    0x77, 0x1e, 0x06, 0x66, 0x09, 0x3d, 0xd2, 0xeb, 0x76, 0x2f, 0x96, 0xba,
+    0x56, 0x73, 0x18, 0x6b, 0x5b, 0x89, 0xef, 0x1e, 0x9f, 0x4e, 0x5c, 0x62,
+    0x73, 0xa5, 0x71, 0x7f, 0xa6, 0xb6, 0x27, 0x05, 0x89, 0xa6, 0x34, 0x6f,
+    0xb8, 0x6a, 0x5c, 0xb3, 0x72, 0xe7, 0xc1, 0x2a, 0x9e, 0xc1, 0x3f, 0xbf,
+    0x7f, 0x71, 0x7f, 0x6f, 0x3b, 0xfd, 0xf7, 0xbf, 0xb1, 0xfd, 0xaa, 0xdf,
+    0x4b, 0x7f, 0x73, 0x6d, 0x7a, 0x2e, 0x2f, 0x95, 0xb6, 0xe6, 0xe5, 0xbc,
+    0x18, 0x58, 0xcc, 0x4c, 0x3b, 0x49, 0x10, 0x88, 0x3e, 0x20, 0xe6, 0xfe,
+    0x33, 0x5c, 0xc2, 0xc7, 0x6e, 0xbe, 0x7a, 0xbb, 0xaa, 0xd6, 0xd7, 0x13,
+    0x81, 0xfb, 0xfd, 0xfe, 0x76, 0xfa, 0x26, 0xb9, 0x01, 0x87, 0x3d, 0x8f,
+    0x5d, 0xe2, 0xa1, 0xc6, 0xa9, 0x2a, 0x26, 0xf7, 0x8f, 0x04, 0x23, 0x0c,
+    0xd5, 0x49, 0x36, 0x72, 0x25, 0x74, 0x12, 0x66, 0xee, 0x7b, 0xe6, 0x2f,
+    0xbf, 0x1f, 0xdf, 0xcc, 0xd2, 0x7d, 0xfd, 0xd5, 0x0b, 0x2d, 0xf7, 0xe3,
+    0x37, 0x5b, 0xf7, 0xe3, 0xf7, 0xe5, 0x09, 0xfe, 0x7b, 0xca, 0xc7, 0x68,
+    0xa7, 0xcb, 0x9d, 0xec, 0x38, 0xe4, 0x5e, 0xec, 0x02, 0x87, 0xd4, 0xc3,
+    0xd9, 0x51, 0x5f, 0x3b, 0xef, 0xed, 0x78, 0x14, 0xe9, 0xde, 0xb7, 0xff,
+    0x4f, 0x6d, 0x5d, 0x1c, 0x36, 0xed, 0xe5, 0x57, 0xe5, 0xd8, 0x39, 0x87,
+    0x8b, 0x8e, 0xc7, 0x57, 0x97, 0xdd, 0x8a, 0x76, 0x40, 0xba, 0x23, 0xee,
+    0x4d, 0x7c, 0x65, 0x72, 0xc8, 0x9d, 0x2f, 0xee, 0x36, 0xd4, 0xfb, 0xd6,
+    0xff, 0x49, 0x7a, 0x7f, 0x93, 0xfa, 0x7b, 0x3f, 0x5a, 0x79, 0xf9, 0x85,
+    0xd6, 0xeb, 0x7b, 0xf5, 0xd1, 0x64, 0x2e, 0x72, 0xf0, 0x98, 0x36, 0x03,
+    0xed, 0xfe, 0xc0, 0x4e, 0x06, 0xec, 0x09, 0x8b, 0x83, 0x8d, 0x7f, 0x7b,
+    0xa6, 0x75, 0xd7, 0x6e, 0xf3, 0xa8, 0xdb, 0xd2, 0xb6, 0x5b, 0xf8, 0xc5,
+    0xe3, 0x86, 0xd1, 0x5a, 0xf9, 0xe7, 0x4e, 0x7a, 0x69, 0xb1, 0x65, 0xc3,
+    0xc9, 0xb0, 0xfb, 0xbd, 0xea, 0xb7, 0x05, 0xd2, 0x73, 0x9a, 0x39, 0xdc,
+    0xde, 0x2a, 0xef, 0xdf, 0x8c, 0xc3, 0xcd, 0xdf, 0x85, 0xf4, 0x89, 0xae,
+    0xbc, 0xeb, 0xbf, 0xe7, 0xad, 0xe6, 0x9c, 0x6a, 0x60, 0xef, 0x5a, 0xff,
+    0x4e, 0x95, 0xa6, 0x96, 0x2f, 0x3f, 0x97, 0x2c, 0x4d, 0x96, 0xd6, 0xe7,
+    0xf4, 0x11, 0xe9, 0x5d, 0x5e, 0x28, 0x9c, 0x75, 0x55, 0xcc, 0xef, 0x65,
+    0x6a, 0x2b, 0x29, 0xb7, 0xff, 0x43, 0x9d, 0xcb, 0x91, 0x60, 0x58, 0x50,
+    0x79, 0xef, 0xb4, 0xd8, 0x7a, 0x1d, 0x94, 0x2a, 0xe4, 0x54, 0x74, 0x4c,
+    0xe5, 0x8c, 0xeb, 0xfb, 0x13, 0xfd, 0x4a, 0xc3, 0xee, 0x3f, 0x71, 0x33,
+    0xf9, 0xba, 0xa5, 0x17, 0xde, 0xcf, 0x45, 0x28, 0x75, 0xfe, 0xb8, 0x35,
+    0xa5, 0x79, 0x9b, 0x54, 0x37, 0xc8, 0xa7, 0x8b, 0x0d, 0x56, 0x92, 0x3f,
+    0xd8, 0xc8, 0x68, 0xf4, 0xe2, 0x1c, 0xbc, 0x4a, 0x5a, 0x9d, 0xea, 0x85,
+    0x57, 0xa1, 0x45, 0x58, 0xb9, 0xc8, 0x23, 0x7a, 0xc5, 0xfe, 0x2f, 0xbd,
+    0x9d, 0xe9, 0xbf, 0x19, 0x2a, 0x14, 0x0d, 0x78, 0xa4, 0x01, 0x03, 0x0e,
+    0x97, 0x91, 0x0c, 0x5c, 0x6b, 0x9d, 0x29, 0x50, 0x5e, 0xfc, 0x18, 0x51,
+    0x91, 0x9b, 0x03, 0x41, 0x1c, 0xb9, 0xe4, 0x42, 0x59, 0xcf, 0x3b, 0xd6,
+    0xe9, 0xe3, 0x19, 0xc0, 0x82, 0x28, 0x60, 0x3f, 0x1e, 0x32, 0xe0, 0x05,
+    0xca, 0x07, 0x5c, 0x8e, 0x37, 0xb0, 0xcb, 0x0d, 0xf1, 0x21, 0x91, 0x96,
+    0x41, 0xb4, 0x67, 0x56, 0xab, 0x7d, 0x75, 0x02, 0x86, 0x83, 0xbf, 0x39,
+    0x7b, 0x9d, 0x0c, 0x7c, 0xb0, 0x7d, 0x38, 0x4f, 0x9c, 0xf2, 0xe6, 0x52,
+    0xdd, 0x2f, 0xc4, 0x3d, 0x75, 0x5e, 0xbb, 0x53, 0x7a, 0x4f, 0xa6, 0xf5,
+    0x3a, 0xdb, 0xa1, 0xc0, 0x02, 0x62, 0xf2, 0xe6, 0x90, 0xca, 0x92, 0x3e,
+    0x9c, 0x9f, 0x72, 0x0b, 0x7f, 0x63, 0xa7, 0x5f, 0x07, 0x2a, 0x62, 0xa9,
+    0xe6, 0x22, 0x25, 0xb7, 0x96, 0xad, 0x51, 0x0b, 0xc6, 0x47, 0x9d, 0x76,
+    0xbc, 0x1f, 0x83, 0x2c, 0x65, 0xd9, 0x15, 0xfb, 0x7c, 0x85, 0x6a, 0xd6,
+    0xa6, 0xc8, 0x04, 0x5c, 0x25, 0xa1, 0x96, 0x91, 0xfa, 0x31, 0xaf, 0xd2,
+    0x0d, 0xdd, 0x7f, 0x8a, 0x09, 0x4f, 0xd9, 0x38, 0x3f, 0xb6, 0x1e, 0x52,
+    0xf3, 0x8a, 0x27, 0x25, 0xe2, 0x93, 0x08, 0x7c, 0x69, 0xa4, 0x39, 0xd6,
+    0x59, 0x07, 0x0c, 0xd2, 0x91, 0x9c, 0xf3, 0x04, 0xf7, 0x7b, 0x99, 0x72,
+    0x2c, 0x73, 0x7b, 0x6d, 0xe7, 0x7b, 0x1a, 0x8b, 0x71, 0x8e, 0x8c, 0xf2,
+    0xea, 0x3a, 0x52, 0xee, 0x44, 0x91, 0xf8, 0x26, 0xfc, 0xc2, 0xde, 0x9b,
+    0xd9, 0x6c, 0x3c, 0xc4, 0xaf, 0x75, 0x64, 0x3c, 0xa4, 0x27, 0xdc, 0xf8,
+    0x5f, 0x91, 0x28, 0x87, 0xaa, 0xce, 0xea, 0x6e, 0x5c, 0xa2, 0x00, 0x04,
+    0xcb, 0x4c, 0xe5, 0x99, 0xca, 0x00, 0x27, 0x34, 0x72, 0x5e, 0x0b, 0x4e,
+    0x03, 0xbd, 0x7d, 0x10, 0x11, 0x90, 0xca, 0x8c, 0xbf, 0x04, 0xbe, 0xb2,
+    0x5b, 0x65, 0xf1, 0x22, 0x83, 0xd1, 0x84, 0x3d, 0x16, 0x26, 0x30, 0xf1,
+    0x03, 0xe6, 0x64, 0xa8, 0xc8, 0x20, 0x3c, 0x3b, 0x01, 0x72, 0xbc, 0xea,
+    0xaa, 0x94, 0xf2, 0x80, 0x1d, 0x93, 0xc3, 0x3c, 0xbf, 0x4f, 0xce, 0x48,
+    0x8f, 0xb5, 0x38, 0x83, 0x5c, 0x4d, 0x7f, 0xd6, 0x68, 0x70, 0x0c, 0x90,
+    0x8c, 0x5d, 0x2b, 0xc2, 0x60, 0x51, 0xad, 0xfb, 0xfb, 0x22, 0x97, 0x02,
+    0xe6, 0xda, 0x4c, 0x7c, 0x46, 0xfe, 0x36, 0xec, 0x8b, 0x9a, 0x09, 0x48,
+    0x7d, 0x13, 0x2e, 0xd7, 0x1b, 0x3f, 0xcb, 0xe9, 0xa5, 0x90, 0xc4, 0x30,
+    0x0c, 0x92, 0x23, 0x22, 0x89, 0x91, 0x62, 0x73, 0xb0, 0x8f, 0x55, 0xd2,
+    0x9e, 0x1c, 0x3a, 0x22, 0x57, 0x87, 0xd9, 0x6e, 0x47, 0x93, 0xdd, 0xfd,
+    0x53, 0xa0, 0x5e, 0x40, 0x92, 0x04, 0x54, 0x57, 0x3a, 0x69, 0x45, 0x7f,
+    0xe7, 0x8d, 0x03, 0x8b, 0xff, 0xe2, 0x76, 0x13, 0xc1, 0x22, 0x2d, 0xf3,
+    0xa9, 0x8b, 0xb9, 0x63, 0x33, 0x56, 0xa3, 0x9f, 0x02, 0xf5, 0x3d, 0x6c,
+    0x89, 0xe3, 0xc9, 0x88, 0xc3, 0xa3, 0xf0, 0x5e, 0x05, 0xcd, 0x22, 0xeb,
+    0xe1, 0x0c, 0x36, 0x2c, 0xb6, 0x7b, 0x40, 0x30, 0xf3, 0xab, 0x2f, 0xe0,
+    0x4f, 0x03, 0x97, 0x2b, 0xd9, 0xfe, 0xfe, 0x23, 0xa7, 0x9f, 0x05, 0xdc,
+    0x66, 0x82, 0xd2, 0x54, 0x6d, 0x87, 0xfa, 0x0c, 0x8e, 0x48, 0x25, 0xde,
+    0xb0, 0x13, 0x77, 0x71, 0x55, 0x1e, 0x89, 0x63, 0x8d, 0xdb, 0x8a, 0x1c,
+    0x31, 0x0d, 0xa2, 0xfa, 0xa0, 0x5c, 0x50, 0x34, 0x11, 0x22, 0x61, 0x1e,
+    0xe0, 0x55, 0xfe, 0xd7, 0x5a, 0x5c, 0x91, 0x2b, 0xaf, 0x65, 0x91, 0x8c,
+    0xe7, 0x1c, 0x34, 0x88, 0x22, 0x63, 0x2c, 0x56, 0x70, 0x4e, 0x15, 0x02,
+    0x9b, 0x52, 0xff, 0x22, 0x14, 0xff, 0xb3, 0x05, 0x6e, 0xb7, 0xb6, 0x41,
+    0x11, 0x21, 0x44, 0xe4, 0xf6, 0x90, 0xf0, 0x4d, 0x79, 0xf3, 0x34, 0x32,
+    0xf2, 0x33, 0xb4, 0x94, 0x69, 0x49, 0xeb, 0xd3, 0x43, 0x7b, 0x07, 0x60,
+    0xd1, 0xdc, 0x81, 0x43, 0x1a, 0x68, 0x1c, 0x9f, 0x64, 0xe3, 0x1c, 0x8d,
+    0xaf, 0x40, 0x52, 0xd5, 0x28, 0x26, 0x69, 0x9c, 0x9a, 0x26, 0x80, 0x4e,
+    0xc8, 0x12, 0x24, 0xeb, 0x56, 0x54, 0xe9, 0xb5, 0x2a, 0x0c, 0x44, 0xd2,
+    0xd2, 0xe7, 0x56, 0xab, 0x97, 0x16, 0xac, 0x18, 0x41, 0x28, 0x4e, 0x11,
+    0x46, 0x03, 0x2c, 0x79, 0x8c, 0x3f, 0xcf, 0x77, 0x96, 0x84, 0xc9, 0x03,
+    0x26, 0xee, 0x7d, 0x3e, 0x15, 0xb6, 0x6b, 0x1d, 0x90, 0xdd, 0x87, 0x29,
+    0x88, 0x06, 0x69, 0x19, 0x8c, 0x27, 0xef, 0x9d, 0x1a, 0x9f, 0xca, 0x12,
+    0xff, 0x70, 0xee, 0x16, 0x10, 0x71, 0x95, 0x2a, 0x19, 0x79, 0x54, 0x3e,
+    0x8b, 0xa7, 0x49, 0xc4, 0xe8, 0x4f, 0x2a, 0xac, 0xe0, 0x04, 0x66, 0x28,
+    0xcf, 0x2a, 0x87, 0x64, 0x3e, 0x5d, 0x04, 0x3e, 0xc4, 0x89, 0x06, 0xc9,
+    0x64, 0x98, 0xa0, 0xe7, 0x07, 0x6f, 0x05, 0xb4, 0xfb, 0x66, 0x9e, 0x33,
+    0xb3, 0xbc, 0xe3, 0x10, 0x86, 0xa4, 0x10, 0xc9, 0xfd, 0x89, 0x97, 0x13,
+    0x9e, 0x74, 0x49, 0x61, 0x29, 0xca, 0x9b, 0x98, 0x1a, 0x10, 0x84, 0x89,
+    0xac, 0x02, 0xa3, 0xbf, 0xf2, 0x5f, 0xff, 0x8a, 0xfc, 0xf9, 0xab, 0xd6,
+    0x90, 0xe5, 0xe0, 0x58, 0x2f, 0xd1, 0xde, 0x44, 0xc0, 0x5a, 0x67, 0x52,
+    0x63, 0x28, 0x0a, 0x04, 0x63, 0xcf, 0xc1, 0x21, 0x38, 0xe9, 0x8b, 0xaf,
+    0x2e, 0x4e, 0x40, 0x81, 0xa0, 0x9a, 0x1b, 0x69, 0x3f, 0x67, 0x07, 0x28,
+    0x8c, 0x24, 0x24, 0x68, 0x63, 0x12, 0xee, 0xce, 0xdf, 0x8b, 0xeb, 0x4d,
+    0x45, 0x07, 0xe7, 0xea, 0x49, 0xbb, 0xd1, 0x36, 0x6e, 0xdd, 0xd7, 0xe0,
+    0xaf, 0x12, 0xf4, 0x08, 0x48, 0x9b, 0xd4, 0x26, 0x19, 0x6a, 0x5e, 0x7b,
+    0xce, 0xd7, 0xde, 0xdd, 0x6a, 0x1f, 0xc1, 0x9b, 0xbd, 0x13, 0xb6, 0x1d,
+    0x84, 0x15, 0x93, 0x3c, 0xf4, 0xf0, 0x06, 0xfa, 0xcd, 0xce, 0x89, 0x78,
+    0x76, 0xe7, 0x23, 0x72, 0xe7, 0xf1, 0x3e, 0x27, 0x86, 0x54, 0x75, 0xec,
+    0xef, 0x9e, 0x7b, 0xf2, 0x75, 0x57, 0x46, 0xc4, 0x2b, 0xf0, 0x55, 0x6c,
+    0x95, 0x71, 0xc4, 0xf7, 0xd6, 0x32, 0xee, 0xd9, 0xa5, 0x8c, 0x6d, 0xce,
+    0x40, 0x25, 0xc9, 0x01, 0x80, 0x7d, 0x75, 0xbf, 0x8a, 0xeb, 0xbc, 0x48,
+    0xe7, 0xa7, 0x2e, 0x58, 0x06, 0x2c, 0xd5, 0xee, 0x20, 0x90, 0x22, 0xa8,
+    0x4a, 0x41, 0x1e, 0xe7, 0x62, 0x9b, 0x13, 0x28, 0x02, 0x4d, 0xd6, 0xd0,
+    0xb1, 0x80, 0x96, 0x39, 0xa3, 0x4c, 0xa4, 0x7b, 0x83, 0xf7, 0x78, 0x9f,
+    0xbe, 0x0a, 0xf9, 0x98, 0xcb, 0x17, 0x7d, 0x46, 0xe4, 0x10, 0xbd, 0xa6,
+    0x89, 0xca, 0x00, 0x98, 0xd0, 0x2f, 0xaa, 0x84, 0x09, 0xc2, 0xac, 0xc5,
+    0xd6, 0xe9, 0x91, 0x1b, 0x5e, 0x49, 0x52, 0x73, 0x15, 0xf5, 0x6b, 0xf0,
+    0xdb, 0xd4, 0x32, 0x8d, 0x34, 0xb8, 0x5c, 0x25, 0xe4, 0x21, 0x7a, 0x7c,
+    0x44, 0x2e, 0x54, 0xe3, 0x5d, 0xf2, 0x59, 0xfd, 0x63, 0x6b, 0xb6, 0x2f,
+    0x3b, 0xdb, 0xb3, 0x39, 0x94, 0xe5, 0x26, 0x26, 0x79, 0x5a, 0x0c, 0x26,
+    0x12, 0xfc, 0x41, 0x57, 0x89, 0x63, 0x11, 0x0b, 0xc6, 0x46, 0x57, 0xa3,
+    0xb2, 0xa5, 0x2a, 0x5d, 0xf6, 0xfd, 0x7c, 0x73, 0xe2, 0xaf, 0x6f, 0x5b,
+    0xa4, 0xb3, 0x05, 0x1c, 0x7d, 0xc1, 0x89, 0xfa, 0xcd, 0x03, 0x29, 0xa0,
+    0x25, 0x18, 0xcd, 0xe1, 0xf1, 0xee, 0x5a, 0x21, 0xbf, 0x4a, 0xb8, 0x4c,
+    0x9c, 0x87, 0x21, 0x09, 0x19, 0xe4, 0xa5, 0xe2, 0x03, 0x50, 0x31, 0x34,
+    0x7c, 0x49, 0xbf, 0xe6, 0x56, 0x6c, 0xb6, 0xdf, 0x4e, 0xa6, 0x34, 0xd9,
+    0xd8, 0x90, 0x50, 0x26, 0x54, 0x11, 0x14, 0x08, 0x28, 0x1f, 0x05, 0x1b,
+    0xa6, 0x5d, 0x39, 0x42, 0x77, 0xb6, 0xc7, 0xc4, 0xfa, 0xb1, 0x43, 0x0a,
+    0x93, 0x86, 0xf9, 0xe0, 0xfe, 0xa9, 0x65, 0x99, 0xfe, 0xeb, 0x93, 0xe3,
+    0x61, 0xb2, 0x2b, 0x6c, 0xde, 0xd6, 0xc6, 0x02, 0xc5, 0xc1, 0x91, 0x53,
+    0x5e, 0xf4, 0xcb, 0xf9, 0x70, 0x03, 0xb0, 0xde, 0x85, 0x18, 0xc6, 0x4b,
+    0xd0, 0xe2, 0x7a, 0x6a, 0x28, 0xc3, 0xec, 0x45, 0xc4, 0xf1, 0x91, 0x4a,
+    0x44, 0x4c, 0x78, 0xe3, 0xa4, 0x47, 0xd8, 0x6a, 0x9a, 0xc8, 0x21, 0x67,
+    0x10, 0x11, 0x35, 0x36, 0x42, 0xa2, 0xde, 0x4d, 0xb0, 0xc3, 0xb2, 0x5d,
+    0x44, 0x27, 0x18, 0xbc, 0xd5, 0xbf, 0xd4, 0x9d, 0xe4, 0xb5, 0x50, 0x88,
+    0x3a, 0xf8, 0x30, 0x8f, 0x64, 0xed, 0xbb, 0x28, 0x9e, 0x78, 0x9e, 0x41,
+    0x6d, 0x98, 0x2f, 0x6c, 0x1c, 0xe9, 0xe0, 0x51, 0x93, 0x2a, 0xd2, 0xa7,
+    0xdc, 0xcc, 0x91, 0x70, 0x40, 0xc9, 0x99, 0x82, 0x10, 0xec, 0xa9, 0xf9,
+    0xde, 0x9d, 0x5b, 0xd6, 0x9d, 0xb7, 0xb5, 0xb3, 0xe8, 0x33, 0x31, 0x0e,
+    0x49, 0x79, 0x25, 0x65, 0x51, 0x99, 0x28, 0x01, 0x3f, 0xad, 0x50, 0x9e,
+    0x5f, 0x5c, 0x0c, 0x73, 0x42, 0xac, 0x53, 0xb7, 0x71, 0x87, 0x5d, 0x3b,
+    0x53, 0x03, 0x30, 0x06, 0x7c, 0x66, 0xfa, 0x34, 0xfe, 0xa9, 0x41, 0xbf,
+    0xba, 0x85, 0xf6, 0xa8, 0xe4, 0xbb, 0x95, 0xf2, 0xce, 0x59, 0x01, 0x32,
+    0x50, 0x92, 0x13, 0xf8, 0xa9, 0x42, 0xad, 0x36, 0x27, 0x84, 0xd8, 0x5c,
+    0xe8, 0x84, 0xa4, 0x0a, 0x43, 0xc4, 0x7d, 0xdb, 0x8a, 0x8e, 0xdb, 0x4f,
+    0x34, 0xb8, 0x29, 0x1f, 0x4e, 0xa0, 0xc8, 0xa8, 0x88, 0xbf, 0xda, 0x86,
+    0xcf, 0xc5, 0xac, 0xed, 0x0e, 0x37, 0x26, 0xa4, 0xba, 0x6e, 0x40, 0xc3,
+    0x3a, 0x1f, 0x12, 0x44, 0xa4, 0xb0, 0x27, 0x28, 0x34, 0xe7, 0x7b, 0x2f,
+    0x87, 0xe7, 0x86, 0xfe, 0xce, 0x04, 0x38, 0xd3, 0x18, 0x99, 0x30, 0x29,
+    0xd6, 0x42, 0xce, 0xba, 0x73, 0xd8, 0x35, 0x6f, 0x43, 0x6a, 0x82, 0x5b,
+    0x51, 0x12, 0x0e, 0xd4, 0x61, 0x48, 0xb9, 0x4a, 0xfb, 0x34, 0x95, 0x71,
+    0x4c, 0xb8, 0x9a, 0xa7, 0x6e, 0xc6, 0x81, 0x38, 0xa4, 0x57, 0x83, 0xca,
+    0x64, 0x19, 0xb4, 0x90, 0x91, 0x32, 0xac, 0x9b, 0x79, 0xce, 0x42, 0x01,
+    0xf0, 0x66, 0x7f, 0x38, 0xa5, 0xad, 0x44, 0x43, 0x1f, 0xca, 0x0f, 0x59,
+    0xbe, 0x8f, 0x9d, 0xff, 0x16, 0xc9, 0xb6, 0xb7, 0x37, 0xa4, 0x46, 0x54,
+    0x62, 0xac, 0x03, 0x2a, 0xac, 0x07, 0x39, 0xf1, 0xc9, 0xcd, 0x9b, 0xd7,
+    0x6b, 0x47, 0x13, 0x25, 0xb0, 0x68, 0x24, 0x1e, 0xb0, 0xb8, 0xec, 0x19,
+    0xa7, 0x2e, 0xaf, 0x0e, 0xb2, 0x1b, 0xd1, 0x63, 0x56, 0x83, 0xce, 0x19,
+    0xe9, 0xcb, 0x14, 0x0b, 0x19, 0x4f, 0xc3, 0x61, 0x55, 0x8d, 0xfe, 0x94,
+    0x86, 0x4a, 0x0d, 0x78, 0xbb, 0x1b, 0x8a, 0x8d, 0x3d, 0xe4, 0xbe, 0x0e,
+    0xf4, 0xa0, 0x97, 0x91, 0x02, 0xfe, 0x7d, 0xf4, 0xda, 0x44, 0x07, 0x79,
+    0xc8, 0xa2, 0x4d, 0x24, 0x50, 0x39, 0x3f, 0x9c, 0x0f, 0x33, 0xba, 0x96,
+    0x0b, 0xf9, 0x2b, 0xb7, 0x87, 0xc5, 0x74, 0x69, 0xba, 0xb6, 0xe2, 0x67,
+    0x2d, 0xe0, 0xcc, 0x00, 0x0d, 0x5b, 0x64, 0x77, 0xb8, 0x4d, 0x1a, 0x23,
+    0x2f, 0xd3, 0xf6, 0x47, 0x76, 0xff, 0x6d, 0x74, 0xde, 0x84, 0x36, 0xc3,
+    0x7b, 0x62, 0x8c, 0x2f, 0xc4, 0x54, 0x15, 0x16, 0xc7, 0xd8, 0x10, 0xd7,
+    0xa6, 0x0e, 0xd9, 0xa3, 0x1a, 0x41, 0x19, 0x76, 0x44, 0xa5, 0xda, 0x9e,
+    0x6b, 0x0a, 0xaf, 0xea, 0x27, 0x29, 0x3f, 0xaf, 0x01, 0xb7, 0xb0, 0x31,
+    0xff, 0x9e, 0x15, 0x21, 0x3d, 0xec, 0x3e, 0x24, 0x8a, 0x38, 0x63, 0x94,
+    0x3c, 0x08, 0x39, 0xd9, 0x44, 0x99, 0x28, 0x64, 0x6b, 0x09, 0xcd, 0xe8,
+    0xf8, 0x99, 0xb1, 0x33, 0x6d, 0xd6, 0xa4, 0xa5, 0xd2, 0x3c, 0x09, 0x39,
+    0x38, 0x8b, 0x23, 0x14, 0x64, 0xb6, 0x01, 0xa2, 0x7e, 0x2c, 0xbe, 0xd5,
+    0x24, 0xe5, 0xd8, 0x19, 0xce, 0xc8, 0x77, 0x8c, 0xec, 0x6c, 0x8a, 0x38,
+    0x2d, 0x8b, 0xa8, 0x42, 0x2d, 0xb1, 0x34, 0x28, 0x9c, 0x85, 0x19, 0x78,
+    0x40, 0x0a, 0xee, 0xff, 0xfa, 0xa3, 0xd9, 0xa2, 0x26, 0x55, 0xdb, 0x8f,
+    0xa0, 0xc5, 0xd7, 0xa1, 0x07, 0x67, 0x87, 0x0f, 0x4e, 0x31, 0x09, 0x74,
+    0x2a, 0xd2, 0xf3, 0xfb, 0xf3, 0x8c, 0x51, 0x65, 0x27, 0x74, 0x67, 0x2c,
+    0x64, 0x7e, 0x6e, 0x32, 0xce, 0x12, 0x0b, 0x1b, 0xb6, 0xa2, 0xda, 0xb4,
+    0xc2, 0xf4, 0xaa, 0xfe, 0x3a, 0x47, 0x52, 0x9c, 0x91, 0x43, 0x1f, 0xe7,
+    0xee, 0x71, 0x8e, 0xa2, 0x3e, 0xbd, 0xf3, 0x2e, 0xbd, 0xbc, 0xae, 0x76,
+    0x7f, 0x15, 0x3d, 0x41, 0xc1, 0xf3, 0xed, 0xc2, 0xdb, 0x3a, 0xcd, 0x2d,
+    0xf4, 0xd4, 0x5e, 0x10, 0x02, 0x84, 0xd1, 0x23, 0x5d, 0xac, 0x86, 0x4c,
+    0x7d, 0x17, 0xd3, 0xbc, 0x7f, 0xec, 0x42, 0xa9, 0x74, 0x01, 0x01, 0xa3,
+    0x8e, 0x20, 0x8c, 0x26, 0x66, 0x4e, 0x03, 0xf5, 0x07, 0xac, 0x2b, 0xaf,
+    0x5a, 0xd2, 0xbf, 0xef, 0x74, 0xf1, 0x5c, 0xb1, 0xa7, 0x48, 0x1a, 0x48,
+    0x0c, 0x69, 0xc6, 0x32, 0xc0, 0x70, 0x80, 0x77, 0x9a, 0x4c, 0x6f, 0xd7,
+    0x22, 0xd8, 0xcd, 0x42, 0x3f, 0xae, 0xf9, 0x01, 0x08, 0x06, 0x9c, 0xca,
+    0xc8, 0x3d, 0x63, 0x2b, 0x54, 0x7e, 0x76, 0xc1, 0x2c, 0xe0, 0xf5, 0x50,
+    0x54, 0x51, 0x1b, 0xcb, 0x77, 0x36, 0xed, 0x30, 0x2e, 0x63, 0xad, 0x34,
+    0x38, 0x9a, 0xd6, 0x9b, 0x0c, 0xcd, 0x2c, 0x91, 0x7f, 0x19, 0xfc, 0x4d,
+    0x58, 0xac, 0x47, 0xdd, 0x17, 0xf3, 0xb8, 0xa0, 0x10, 0x3f, 0x16, 0xad,
+    0x9b, 0x06, 0xc9, 0x97, 0x7b, 0x3f, 0x40, 0xb0, 0x0d, 0x1d, 0x85, 0xcb,
+    0x12, 0x79, 0x61, 0x8e, 0x31, 0x20, 0x51, 0x9e, 0x59, 0x97, 0x87, 0x6d,
+    0xfa, 0x4a, 0x43, 0x70, 0x8f, 0x75, 0x9f, 0x31, 0x75, 0xd9, 0xa6, 0x84,
+    0x9b, 0x40, 0xaf, 0x62, 0xa1, 0x7b, 0x4a, 0x6e, 0x72, 0xdc, 0xd0, 0xa0,
+    0x04, 0x35, 0x94, 0xd5, 0xa7, 0x3e, 0xc6, 0xd3, 0x73, 0x7b, 0xfd, 0x5b,
+    0x64, 0x1d, 0x94, 0x48, 0x69, 0x8a, 0x89, 0xd8, 0x50, 0x22, 0x30, 0x94,
+    0xfb, 0x5f, 0xaa, 0x53, 0x0b, 0xb9, 0x53, 0xe4, 0xbe, 0x0a, 0x27, 0x97,
+    0x77, 0x53, 0x0d, 0xc5, 0xde, 0x64, 0x7f, 0x73, 0x77, 0x23, 0x5a, 0x47,
+    0xb0, 0xda, 0x7c, 0x3e, 0x00, 0xd4, 0x4f, 0x80, 0x3c, 0xd8, 0x7f, 0x4d,
+    0x76, 0x56, 0x8f, 0x55, 0xdd, 0x6d, 0x63, 0xde, 0xeb, 0xa3, 0x8e, 0x44,
+    0xcf, 0xcc, 0x9e, 0xe7, 0x42, 0x94, 0x7b, 0xb9, 0x1d, 0x7d, 0x15, 0xb3,
+    0x0a, 0x9e, 0xe8, 0xd5, 0x8f, 0x2e, 0xe4, 0xa6, 0x79, 0x55, 0x82, 0xff,
+    0xfe, 0x79, 0x3a, 0x3d, 0xa7, 0x02, 0x04, 0x8d, 0x65, 0x6e, 0xab, 0x9c,
+    0x62, 0xd8, 0x6f, 0x7e, 0xab, 0x21, 0x70, 0x12, 0x88, 0x76, 0x68, 0x5b,
+    0xe2, 0x4b, 0xc6, 0x69, 0x0d, 0x5f, 0xf8, 0x21, 0x92, 0xe5, 0x49, 0xef,
+    0xe6, 0x79, 0x9d, 0xcf, 0x6d, 0x5a, 0x7d, 0xbf, 0x08, 0x61, 0x62, 0xbd,
+    0x87, 0x75, 0x8e, 0x36, 0x1c, 0x0a, 0x13, 0x94, 0x9c, 0x03, 0x01, 0x2e,
+    0x47, 0xd8, 0x93, 0x13, 0xab, 0xab, 0x8d, 0xfe, 0x4d, 0xb3, 0x4e, 0x0a,
+    0x18, 0x67, 0x84, 0x38, 0x21, 0x11, 0xb0, 0x58, 0x7c, 0x78, 0x23, 0xaf,
+    0xbc, 0x58, 0xf7, 0x3b, 0xeb, 0x69, 0x59, 0xc9, 0x1a, 0x03, 0xe6, 0x00,
+    0x43, 0xc0, 0x15, 0x56, 0x9b, 0x19, 0xb3, 0xbc, 0xdb, 0xeb, 0xec, 0xca,
+    0xb8, 0x6a, 0x18, 0x7c, 0x59, 0xba, 0xa4, 0xc6, 0x84, 0x91, 0x12, 0x4b,
+    0x41, 0xf2, 0xbc, 0x5a, 0x52, 0x29, 0x99, 0x0c, 0x5e, 0xb0, 0x9f, 0x0c,
+    0xd4, 0xc5, 0x6e, 0xed, 0xf9, 0xb0, 0xc1, 0xc1, 0x7d, 0xae, 0x67, 0x4c,
+    0xc0, 0x55, 0xf4, 0xed, 0x03, 0xad, 0xc5, 0xb4, 0x83, 0xfe, 0xec, 0x16,
+    0x70, 0x08, 0xdd, 0x5c, 0x45, 0xb4, 0xb7, 0x99, 0x9b, 0xec, 0xa0, 0x06,
+    0x42, 0x44, 0xd0, 0x9f, 0xda, 0x05, 0xb7, 0xef, 0x7c, 0xd5, 0xa3, 0x0f,
+    0x4c, 0x36, 0xf7, 0x92, 0x98, 0xc4, 0x64, 0x89, 0xa7, 0x2a, 0x39, 0x41,
+    0xa1, 0x28, 0xcb, 0xc4, 0xc1, 0x77, 0xda, 0x49, 0xf7, 0xfa, 0xb3, 0x72,
+    0x93, 0xa0, 0xad, 0x09, 0x9b, 0xd9, 0x82, 0x44, 0xf6, 0x84, 0x9c, 0xbf,
+    0xad, 0x73, 0xde, 0x15, 0x76, 0xee, 0x9c, 0x4f, 0xce, 0x5f, 0x5d, 0xf4,
+    0x90, 0x51, 0xfc, 0xaf, 0xfc, 0x59, 0x2a, 0x70, 0x92, 0x66, 0xeb, 0xd3,
+    0x04, 0x29, 0xc8, 0xc2, 0x49, 0x40, 0x9a, 0xac, 0xff, 0x94, 0x31, 0x42,
+    0x81, 0x83, 0x17, 0x6f, 0x87, 0xdc, 0x62, 0xe7, 0x74, 0x50, 0xc9, 0xc6,
+    0x83, 0xbf, 0x7a, 0xe0, 0xae, 0x11, 0xbd, 0x86, 0x0f, 0x02, 0xdc, 0x2a,
+    0x58, 0xee, 0x50, 0x04, 0xcf, 0x28, 0x7d, 0xa0, 0xdf, 0xd8, 0x2b, 0xec,
+    0xe3, 0x79, 0xff, 0xd9, 0x2b, 0xc3, 0x23, 0x3a, 0x4a, 0x19, 0x26, 0x69,
+    0x7c, 0x5a, 0xcb, 0xf5, 0x66, 0x11, 0xdd, 0x7e, 0x4f, 0x99, 0xc6, 0xf2,
+    0x6f, 0xf6, 0xe5, 0x3f, 0x60, 0x46, 0xfe, 0x52, 0x26, 0xab, 0x3a, 0xcc,
+    0x48, 0xbf, 0xdf, 0xcc, 0xaf, 0x67, 0xc5, 0x02, 0x99, 0x93, 0x43, 0x0b,
+    0x11, 0x31, 0xda, 0x9c, 0xa6, 0x64, 0xb9, 0x4b, 0xed, 0x05, 0x56, 0xf8,
+    0x75, 0xdf, 0xbc, 0x7d, 0xfd, 0xee, 0x69, 0x59, 0xfb, 0x68, 0x7e, 0xfd,
+    0x94, 0xd3, 0x46, 0x1d, 0xa2, 0x61, 0x59, 0x8c, 0x7b, 0x05, 0x58, 0x07,
+    0x8a, 0xfe, 0x37, 0x7b, 0xbc, 0x9c, 0x40, 0x04, 0x4d, 0x08, 0x31, 0xca,
+    0x3c, 0xb9, 0x74, 0x67, 0x46, 0xbc, 0xc9, 0x79, 0x78, 0x4e, 0x60, 0xbf,
+    0xf8, 0x92, 0x51, 0xa4, 0xda, 0x35, 0xfd, 0xe8, 0x89, 0x4b, 0xe0, 0xc8,
+    0x9c, 0xb2, 0xbe, 0xb9, 0x3c, 0x26, 0x4b, 0x6a, 0x8a, 0xfa, 0xa8, 0x5c,
+    0xd3, 0x0b, 0x9a, 0x86, 0xd9, 0x5a, 0xa1, 0x2b, 0x13, 0x2d, 0xf1, 0xe9,
+    0xde, 0x99, 0x78, 0x0d, 0xc9, 0xae, 0x6d, 0x4e, 0x8e, 0x3c, 0x25, 0x2d,
+    0x1f, 0xb1, 0x04, 0x69, 0x86, 0x4b, 0x23, 0xc3, 0x70, 0x8c, 0x5d, 0x08,
+    0xc0, 0x3b, 0x8f, 0x88, 0x8f, 0x82, 0x42, 0x20, 0xef, 0xf8, 0xbb, 0x92,
+    0x06, 0x8b, 0x19, 0x3e, 0xc6, 0x34, 0xa5, 0x95, 0x90, 0xf0, 0x16, 0xac,
+    0xee, 0x4b, 0xed, 0x7c, 0xb6, 0x83, 0x2a, 0x67, 0x14, 0x8d, 0xec, 0x4c,
+    0xe5, 0x6e, 0x96, 0x92, 0xa6, 0x05, 0x2a, 0xb1, 0x57, 0xb8, 0x7c, 0x31,
+    0xc7, 0x56, 0xf4, 0xf3, 0xc9, 0x06, 0x3f, 0x51, 0x8e, 0x93, 0x45, 0xe6,
+    0x22, 0xed, 0x44, 0x71, 0xff, 0x61, 0x38, 0x7f, 0xc4, 0x57, 0xff, 0x3c,
+    0x04, 0x1a, 0xa1, 0xc8, 0x80, 0xb0, 0x97, 0x30, 0x2b, 0x17, 0xe5, 0x67,
+    0xa2, 0x54, 0x38, 0xdc, 0x5e, 0x48, 0x27, 0xe8, 0x08, 0xd7, 0xfd, 0xef,
+    0x99, 0x34, 0xb1, 0x40, 0x06, 0x14, 0x49, 0x43, 0x2b, 0x18, 0xbe, 0x5a,
+    0x1d, 0xc1, 0x8e, 0xcf, 0x0a, 0xca, 0xf0, 0x13, 0x5b, 0x8b, 0x3f, 0xe8,
+    0x3c, 0xa0, 0x84, 0x46, 0x09, 0x69, 0x14, 0x70, 0x1f, 0x06, 0x61, 0x3d,
+    0xd3, 0x25, 0x24, 0x5f, 0x37, 0x0b, 0x36, 0xea, 0xbd, 0xce, 0xd9, 0xb5,
+    0x0f, 0x21, 0x84, 0x25, 0xb4, 0x8b, 0x34, 0xe5, 0x41, 0xa7, 0x58, 0x47,
+    0xcc, 0x97, 0x91, 0x1e, 0xcc, 0x63, 0x88, 0x8b, 0x84, 0xb9, 0xf7, 0x0c,
+    0x59, 0xb4, 0x28, 0x8a, 0xa8, 0xcc, 0xa9, 0xc4, 0x9a, 0xb6, 0x2e, 0xca,
+    0x0d, 0x8c, 0x52, 0x08, 0x9b, 0xd7, 0xee, 0x2a, 0x1b, 0x0e, 0xde, 0x81,
+    0x38, 0x62, 0x97, 0x43, 0xe3, 0xd2, 0x20, 0x5a, 0x30, 0x92, 0xe9, 0x1f,
+    0x14, 0x99, 0x69, 0x8c, 0xa1, 0x13, 0xc8, 0x48, 0x4e, 0xf5, 0x73, 0x3a,
+    0xf4, 0xa1, 0xfb, 0xf4, 0x7c, 0xfb, 0x3f, 0x2d, 0xe6, 0x2d, 0x78, 0x10,
+    0x03, 0x70, 0x7c, 0xc1, 0x90, 0x96, 0x4f, 0x09, 0x04, 0xfd, 0x03, 0x55,
+    0xf7, 0x1a, 0x58, 0x5f, 0x6a, 0x26, 0x25, 0x80, 0xc6, 0x9f, 0xf7, 0x1b,
+    0x45, 0x06, 0xdc, 0xcd, 0xf4, 0x65, 0x4b, 0xfb, 0xbe, 0xd7, 0x45, 0x19,
+    0x1d, 0x41, 0x90, 0x82, 0x39, 0x14, 0x83, 0x35, 0x9c, 0xf3, 0xd7, 0x9f,
+    0x9a, 0x70, 0x43, 0x03, 0x90, 0xde, 0x6d, 0x84, 0xb0, 0xe9, 0x55, 0x68,
+    0xfb, 0xcd, 0xfb, 0x3c, 0x9b, 0x44, 0xb0, 0x22, 0x8b, 0x97, 0x79, 0x83,
+    0xe9, 0xee, 0x5b, 0x59, 0xab, 0x8a, 0x69, 0x85, 0x37, 0x57, 0x11, 0x8f,
+    0x97, 0x21, 0x80, 0xa1, 0x2c, 0x89, 0xc9, 0xed, 0x6c, 0xce, 0x4d, 0xb5,
+    0xe2, 0xb7, 0xd2, 0xc4, 0xa2, 0x70, 0xe1, 0xb4, 0x45, 0x78, 0x2f, 0x0e,
+    0x63, 0x06, 0x33, 0xc7, 0x9d, 0x1a, 0x52, 0x13, 0xdf, 0xda, 0xdb, 0xe8,
+    0x57, 0x49, 0x1d, 0x81, 0xac, 0x71, 0x8c, 0x64, 0x90, 0x29, 0x19, 0xd1,
+    0x33, 0xf9, 0xc0, 0xce, 0x13, 0xf2, 0x59, 0x16, 0xf0, 0xea, 0x6a, 0x75,
+    0x78, 0x07, 0x75, 0xf0, 0xf9, 0x0a, 0x66, 0x52, 0x48, 0xd0, 0x4e, 0xd0,
+    0x6b, 0x89, 0xd6, 0x9b, 0xef, 0x7e, 0xef, 0x23, 0x29, 0x0a, 0x4c, 0x28,
+    0xe4, 0xc8, 0x1f, 0x15, 0x13, 0x3a, 0xca, 0x98, 0x20, 0x7f, 0xe2, 0x9d,
+    0x2a, 0xe6, 0x1c, 0x77, 0xa5, 0x06, 0xe3, 0x19, 0xce, 0x7f, 0x38, 0xcf,
+    0x5e, 0xd1, 0xef, 0xf8, 0x81, 0x20, 0xfa, 0x98, 0x45, 0x9f, 0x2b, 0x27,
+    0xe0, 0x73, 0x8c, 0xe1, 0x01, 0x2c, 0x05, 0x0a, 0xa7, 0x19, 0xd9, 0xe5,
+    0xf6, 0x06, 0xd4, 0x02, 0xdb, 0xee, 0x38, 0x41, 0x35, 0x02, 0x48, 0xa4,
+    0x72, 0x0a, 0xa2, 0x6c, 0x6a, 0x8a, 0x18, 0x08, 0x4b, 0x26, 0x44, 0xa4,
+    0x0a, 0x1e, 0x20, 0xcf, 0xfc, 0xa8, 0x72, 0x37, 0xe6, 0xe4, 0xea, 0xb4,
+    0x4c, 0xe9, 0xe5, 0x6e, 0x1c, 0x57, 0x83, 0x2f, 0x44, 0x50, 0xc0, 0x3c,
+    0x37, 0x07, 0x38, 0xbd, 0x6a, 0xc7, 0x88, 0x90, 0x0b, 0x7d, 0xe9, 0x20,
+    0x2a, 0xbc, 0x73, 0xad, 0x07, 0x60, 0x52, 0x9a, 0x47, 0x2f, 0xe2, 0xc6,
+    0x9a, 0xc0, 0x0d, 0x37, 0x12, 0x60, 0x99, 0x51, 0xfc, 0x5e, 0xdf, 0xc0,
+    0x23, 0x7f, 0x47, 0xa2, 0x5c, 0xa6, 0x2f, 0xa5, 0x62, 0x13, 0xc6, 0x3b,
+    0x61, 0xf1, 0x52, 0xe1, 0x90, 0x9b, 0xba, 0x4a, 0x67, 0x02, 0x3f, 0xfd,
+    0x8d, 0xfe, 0xd7, 0xe1, 0xed, 0xd6, 0x26, 0x3a, 0xd9, 0x48, 0x3c, 0x00,
+    0x11, 0x36, 0x33, 0x18, 0x6c, 0x9e, 0x57, 0x89, 0xe5, 0x44, 0xfe, 0xae,
+    0x69, 0xd9, 0x4c, 0x22, 0x1f, 0x18, 0xe9, 0x07, 0xf8, 0xbf, 0x42, 0x8c,
+    0x0b, 0xf1, 0xb5, 0x6c, 0x95, 0x2f, 0xcb, 0x0c, 0x85, 0x90, 0xc0, 0xfa,
+    0x98, 0xcb, 0x32, 0xd8, 0xfb, 0x1a, 0x57, 0x49, 0xf5, 0xea, 0x9b, 0x27,
+    0x3d, 0xf6, 0x11, 0xf5, 0xfc, 0xa9, 0x7f, 0xca, 0xe3, 0xf5, 0xb3, 0x50,
+    0xd5, 0x78, 0xcf, 0x28, 0x99, 0x82, 0x11, 0x96, 0x46, 0x51, 0x00, 0x25,
+    0x56, 0x4e, 0xf6, 0xa6, 0x59, 0xd3, 0x97, 0xdf, 0x0c, 0x1f, 0x4e, 0xa6,
+    0x69, 0x50, 0x2f, 0xad, 0xe4, 0x84, 0x8b, 0x82, 0xc6, 0x45, 0x2f, 0xb8,
+    0x07, 0x9a, 0x5c, 0x1e, 0xa8, 0xe7, 0x9a, 0xcc, 0xff, 0xf4, 0x89, 0x30,
+    0xa7, 0x52, 0x9b, 0x99, 0x65, 0x28, 0xda, 0xef, 0x4f, 0x5a, 0x8c, 0x27,
+    0x36, 0x4a, 0x06, 0x5d, 0xc0, 0x5c, 0x79, 0x96, 0xbf, 0x2d, 0xd6, 0xcb,
+    0xa4, 0xcc, 0xc7, 0x15, 0xa0, 0x93, 0xb0, 0x2f, 0xa1, 0x19, 0x5f, 0x6e,
+    0x66, 0x94, 0xe7, 0x37, 0x74, 0xf8, 0x22, 0x57, 0xed, 0xca, 0x0f, 0x0d,
+    0x31, 0x54, 0xe2, 0x5b, 0xc6, 0xb1, 0x3d, 0x97, 0xb5, 0xdb, 0xaa, 0x5d,
+    0x60, 0x0f, 0x08, 0x22, 0x1e, 0x2d, 0x80, 0x99, 0x92, 0x1a, 0x4d, 0x2d,
+    0x90, 0x41, 0x38, 0x40, 0x0d, 0x07, 0xe0, 0xbc, 0x0c, 0x76, 0x58, 0x61,
+    0xb2, 0xd1, 0x4b, 0x97, 0x68, 0x12, 0x3f, 0x6a, 0x4f, 0xc3, 0xf9, 0x1f,
+    0xc8, 0x58, 0x39, 0x7b, 0xbc, 0x7f, 0x5a, 0xf9, 0xc4, 0x1a, 0x14, 0x88,
+    0x27, 0x1d, 0xc6, 0xf6, 0x66, 0x95, 0x87, 0xcb, 0x99, 0xee, 0x50, 0x8d,
+    0x56, 0xff, 0x90, 0x0b, 0xb4, 0x94, 0x77, 0xcb, 0x06, 0x63, 0x7a, 0x65,
+    0xf1, 0xfc, 0x35, 0x59, 0x68, 0xee, 0x50, 0x25, 0xf2, 0x5c, 0xff, 0x28,
+    0x9e, 0xd1, 0xd5, 0xea, 0x84, 0x14, 0x90, 0x28, 0xfc, 0x5f, 0xa0, 0x3e,
+    0xc8, 0xee, 0x61, 0xeb, 0x05, 0x9c, 0x6e, 0x44, 0x58, 0x78, 0xfc, 0xfe,
+    0x0c, 0xb5, 0x01, 0xf9, 0xab, 0xf3, 0xbf, 0xcd, 0x6f, 0x8e, 0x31, 0xdc,
+    0x4a, 0xb4, 0x12, 0xe9, 0x8a, 0x15, 0x90, 0x62, 0x4d, 0xc1, 0xef, 0xbf,
+    0x53, 0xeb, 0x8f, 0x90, 0x1d, 0x17, 0xbf, 0xc7, 0xa3, 0x0c, 0x35, 0x26,
+    0x76, 0x9b, 0xa4, 0x56, 0xf0, 0xfc, 0x41, 0xe0, 0x96, 0x02, 0x75, 0x9b,
+    0x0f, 0xfe, 0x1a, 0x9c, 0x10, 0x79, 0xa5, 0xfa, 0x2c, 0x5b, 0x6f, 0xfa,
+    0xf3, 0x16, 0xea, 0xca, 0xed, 0xb5, 0xe9, 0xd3, 0x73, 0xf0, 0x41, 0x29,
+    0x98, 0x4a, 0x00, 0x10, 0x03, 0xe8, 0x02, 0x6f, 0x15, 0xf8, 0x42, 0x65,
+    0xb6, 0x8b, 0xf7, 0x12, 0x96, 0x55, 0xf6, 0x0e, 0x38, 0xaa, 0xc7, 0x6f,
+    0x70, 0x7b, 0x40, 0x0f, 0xce, 0x02, 0xa7, 0xe3, 0xba, 0x8f, 0xff, 0xaa,
+    0x76, 0x7e, 0x3c, 0xc9, 0x43, 0x98, 0x59, 0xa5, 0x4c, 0x68, 0x99, 0x03,
+    0x01, 0x45, 0x11, 0x0d, 0x04, 0x60, 0xfa, 0x9d, 0xa9, 0xf7, 0xfd, 0x9e,
+    0x3b, 0xac, 0xc6, 0xf9, 0xdd, 0xd2, 0x8c, 0x9b, 0x13, 0x58, 0x83, 0xcc,
+    0x69, 0x6e, 0x63, 0x58, 0x79, 0x80, 0x10, 0xc6, 0x61, 0x21, 0xe0, 0x61,
+    0x42, 0xac, 0x07, 0x95, 0xfd, 0xbd, 0xb7, 0xa8, 0x17, 0xed, 0x71, 0xc2,
+    0x58, 0xf3, 0x36, 0x5e, 0x4e, 0x09, 0xe0, 0x3f, 0x6e, 0x1d, 0x28, 0x7c,
+    0x4b, 0x9d, 0x1f, 0xd7, 0x84, 0x27, 0x29, 0xd3, 0x1f, 0xcf, 0x0a, 0xfc,
+    0xdb, 0x3a, 0xde, 0xda, 0xd1, 0x3a, 0x50, 0x4a, 0x5a, 0x82, 0x80, 0x48,
+    0xd1, 0x38, 0x49, 0x9d, 0x88, 0xb7, 0x39, 0x16, 0xa7, 0xb7, 0xbb, 0xdf,
+    0x82, 0xfa, 0xa4, 0x08, 0xca, 0x13, 0x20, 0xe4, 0xcc, 0x69, 0x10, 0x89,
+    0x85, 0xdc, 0xfe, 0xca, 0xd5, 0xbb, 0x1c, 0x75, 0x71, 0x94, 0x70, 0xce,
+    0x46, 0x58, 0x33, 0x92, 0x5d, 0x61, 0x29, 0xe4, 0xa1, 0xaf, 0xed, 0x8e,
+    0x35, 0x89, 0xa7, 0x45, 0x82, 0x33, 0x85, 0xa5, 0x36, 0x9f, 0x70, 0xbd,
+    0xf4, 0x63, 0x5d, 0xc2, 0x3c, 0xd8, 0xea, 0x53, 0x7b, 0x6a, 0xf0, 0xa9,
+    0x19, 0xbb, 0x9b, 0x1d, 0xf5, 0xaf, 0x4e, 0x71, 0xf4, 0xae, 0x44, 0x12,
+    0x18, 0x71, 0x03, 0x4d, 0x9d, 0x04, 0x89, 0x47, 0xc4, 0x02, 0x69, 0xb9,
+    0x6b, 0x79, 0x76, 0x29, 0x6f, 0xe6, 0x9b, 0x40, 0xe8, 0x4b, 0x94, 0x84,
+    0xd1, 0x90, 0x3d, 0xaf, 0xcf, 0x3e, 0xdb, 0xe5, 0xec, 0x5e, 0x2d, 0x7f,
+    0x1a, 0x92, 0x32, 0x10, 0xcc, 0xcb, 0xb5, 0xf0, 0x13, 0x15, 0xb4, 0x2e,
+    0xec, 0x11, 0x65, 0x90, 0x42, 0x1b, 0xb5, 0x20, 0xa7, 0x7c, 0x92, 0xd1,
+    0x33, 0x9d, 0xea, 0xa8, 0x46, 0xca, 0x2a, 0x60, 0x3d, 0xcf, 0x5d, 0x8f,
+    0xa5, 0x25, 0x42, 0xe5, 0xff, 0x2a, 0x0b, 0x60, 0xcf, 0xfd, 0x8c, 0xb7,
+    0xd9, 0x83, 0xa2, 0xc9, 0x6f, 0xc2, 0x5a, 0x30, 0xc2, 0xd8, 0x41, 0xd7,
+    0x9a, 0xbe, 0x1b, 0xfe, 0x3c, 0xa3, 0x0f, 0x2d, 0x02, 0xe0, 0x4a, 0x66,
+    0x92, 0x2d, 0xb4, 0x11, 0x48, 0xcb, 0xed, 0x04, 0xd9, 0xd1, 0x5b, 0xe3,
+    0x7f, 0x9f, 0x99, 0x3b, 0x92, 0x95, 0x51, 0x64, 0x3a, 0x5d, 0x94, 0xce,
+    0xfb, 0x73, 0xf1, 0xde, 0x2b, 0xf0, 0xcf, 0xb2, 0x00, 0x44, 0xe4, 0x92,
+    0xbd, 0x3f, 0x5b, 0xa5, 0x1f, 0x97, 0xeb, 0x84, 0x52, 0x18, 0xd5, 0xad,
+    0x79, 0x2d, 0x47, 0xfd, 0x24, 0xa3, 0x43, 0x2d, 0x0f, 0xa2, 0x9a, 0xd0,
+    0xe5, 0x70, 0x23, 0x04, 0x82, 0x3d, 0x84, 0xab, 0x22, 0xf8, 0x82, 0x90,
+    0x48, 0x56, 0x50, 0xb7, 0x9a, 0x41, 0x2d, 0xfc, 0x6f, 0x25, 0x0b, 0x86,
+    0x01, 0x8b, 0x35, 0x18, 0xc4, 0xa4, 0x68, 0x78, 0x3a, 0x99, 0xd4, 0xa0,
+    0xd3, 0xa3, 0x23, 0xf5, 0xde, 0x69, 0xba, 0x22, 0x60, 0x89, 0x56, 0x51,
+    0x87, 0xe9, 0xea, 0x48, 0xbc, 0xdf, 0xe2, 0x9e, 0x7b, 0xfc, 0x88, 0x6b,
+    0x6a, 0xe9, 0x65, 0xb8, 0x9c, 0xe9, 0x72, 0x28, 0xc9, 0xe9, 0x89, 0x11,
+    0xf1, 0x2a, 0xd1, 0x4f, 0x7e, 0xf9, 0x5e, 0x07, 0x4f, 0xee, 0xdc, 0x82,
+    0x4a, 0x53, 0x30, 0xf9, 0x96, 0x85, 0x1f, 0x99, 0xac, 0xd9, 0xfa, 0x44,
+    0xa4, 0xe5, 0x4f, 0x16, 0xe7, 0x9c, 0x42, 0x11, 0x2d, 0x95, 0x2c, 0xbf,
+    0x00, 0x17, 0x9e, 0x98, 0xc9, 0x9e, 0x77, 0x85, 0xe2, 0x0b, 0x29, 0xb7,
+    0xa2, 0x4f, 0x04, 0xc9, 0x2d, 0xa3, 0x04, 0x8f, 0x82, 0x5e, 0x16, 0x58,
+    0x33, 0x00, 0x21, 0x34, 0x72, 0xe4, 0x2a, 0xd9, 0x44, 0x7a, 0x63, 0xfc,
+    0xf5, 0xa5, 0x80, 0x7f, 0x9e, 0xb6, 0xb9, 0xa5, 0xe3, 0xb4, 0x99, 0x1f,
+    0x4d, 0x61, 0x1e, 0xcd, 0xa6, 0x37, 0x9f, 0x38, 0x8c, 0xfa, 0x28, 0xa5,
+    0x81, 0x18, 0xe4, 0xbb, 0x29, 0xcf, 0x1c, 0x74, 0xd7, 0x69, 0xa7, 0xd9,
+    0xed, 0x4c, 0x10, 0x93, 0xf3, 0x47, 0x81, 0xe7, 0x90, 0x32, 0x6d, 0xc4,
+    0x74, 0x2a, 0xcd, 0x2f, 0x04, 0xd2, 0x00, 0xcc, 0x20, 0x7e, 0x71, 0xab,
+    0x73, 0xf4, 0xda, 0xd9, 0xe2, 0xf7, 0x2c, 0xf4, 0x86, 0x42, 0x85, 0x13,
+    0x47, 0x25, 0x2e, 0xe0, 0x65, 0x6f, 0x5a, 0x22, 0xbc, 0x1c, 0xf1, 0x8f,
+    0x87, 0xff, 0xda, 0x99, 0x50, 0x54, 0xa4, 0x48, 0x47, 0x0f, 0xf6, 0x2d,
+    0xdf, 0x99, 0xc9, 0xb4, 0xb4, 0x67, 0x8c, 0x06, 0x3e, 0x80, 0xf9, 0x9a,
+    0x03, 0x25, 0x97, 0x84, 0x04, 0x93, 0x97, 0xa5, 0x52, 0xc4, 0x43, 0x0e,
+    0x91, 0x45, 0x0c, 0x06, 0xf5, 0x15, 0x89, 0x47, 0x15, 0xba, 0xaa, 0x03,
+    0x90, 0xf1, 0x43, 0x8a, 0x33, 0xc6, 0xc7, 0x19, 0x21, 0x47, 0x00, 0xac,
+    0x89, 0xec, 0xa9, 0xb6, 0xb8, 0x34, 0x7b, 0xf2, 0x51, 0xd3, 0xf9, 0xf4,
+    0x18, 0x19, 0x87, 0xd0, 0x07, 0x54, 0x70, 0xf9, 0x79, 0x74, 0x51, 0xee,
+    0x41, 0x0d, 0xfa, 0xed, 0x8f, 0x0e, 0x2f, 0xf7, 0xd4, 0x8b, 0xc3, 0xb5,
+    0x72, 0x26, 0x5c, 0xe5, 0xbe, 0x9c, 0x3e, 0x01, 0x04, 0xfc, 0x6d, 0x7b,
+    0xc2, 0x4f, 0xfe, 0x2c, 0x5e, 0xea, 0xf1, 0x64, 0x31, 0xc5, 0x31, 0x31,
+    0x42, 0x7d, 0x98, 0x80, 0x64, 0x42, 0x47, 0xc4, 0x45, 0xed, 0xfc, 0xf2,
+    0x9f, 0x45, 0xad, 0xda, 0xaf, 0x51, 0x61, 0x97, 0x45, 0x68, 0x31, 0xc9,
+    0xa1, 0x46, 0x5e, 0x03, 0xa9, 0xaa, 0x05, 0x14, 0x51, 0x61, 0xe9, 0xbd,
+    0x58, 0x6c, 0x6d, 0x09, 0xd2, 0x48, 0x65, 0x7d, 0x79, 0xd9, 0xc9, 0x1e,
+    0xca, 0xa5, 0xdc, 0xa7, 0x86, 0x77, 0xd6, 0x41, 0x45, 0x0f, 0x88, 0x7e,
+    0xb1, 0xa5, 0xfa, 0xdd, 0xaa, 0x2d, 0xa8, 0x89, 0xa1, 0x32, 0x3b, 0x0b,
+    0xe0, 0x0a, 0xf5, 0x72, 0x29, 0x9c, 0x03, 0xce, 0x00, 0x42, 0x46, 0x06,
+    0x79, 0xbc, 0xd2, 0xfd, 0x23, 0x08, 0x00, 0x7c, 0xad, 0x65, 0xc5, 0x69,
+    0x51, 0xa8, 0xcc, 0x68, 0x45, 0x7b, 0xc4, 0x72, 0xdc, 0xf0, 0x43, 0xd0,
+    0xa3, 0x24, 0x94, 0x4f, 0xd3, 0x03, 0x53, 0xf9, 0x47, 0xf2, 0xcd, 0x79,
+    0xa7, 0x4b, 0x7c, 0xbb, 0x69, 0x00, 0x51, 0xaf, 0x4e, 0x11, 0xf1, 0x3e,
+    0x80, 0xaa, 0x8d, 0x57, 0x2f, 0xc9, 0x6a, 0xff, 0x3d, 0xbc, 0xdb, 0xad,
+    0xea, 0x75, 0xfb, 0xdb, 0x70, 0x64, 0xd1, 0x1b, 0xed, 0x4a, 0x55, 0x01,
+    0xe0, 0x6d, 0x99, 0x6f, 0x17, 0x56, 0x2d, 0x1e, 0x17, 0x47, 0x26, 0x1d,
+    0x50, 0xcf, 0x00, 0xdc, 0xb2, 0x28, 0x2a, 0x9f, 0xd7, 0xf7, 0x2e, 0xb6,
+    0xb9, 0xe3, 0x91, 0xca, 0x9e, 0x58, 0xdb, 0x64, 0x4a, 0x42, 0x31, 0xfa,
+    0x8a, 0xba, 0x7c, 0xa5, 0x8a, 0x76, 0xce, 0xdc, 0x47, 0xe3, 0xf8, 0xeb,
+    0x3a, 0xdc, 0x90, 0xb1, 0xc4, 0x28, 0x1c, 0xaa, 0x08, 0x51, 0xfb, 0x74,
+    0x76, 0xbd, 0x83, 0x75, 0x3e, 0xef, 0x2d, 0xb3, 0x21, 0x60, 0x04, 0xa2,
+    0xf8, 0x05, 0x14, 0x72, 0xa8, 0x61, 0x20, 0xe5, 0x26, 0x77, 0x71, 0x70,
+    0x4f, 0x8a, 0xfa, 0x3b, 0x88, 0x7b, 0x59, 0x65, 0x10, 0xdd, 0xa2, 0x22,
+    0x55, 0x58, 0x28, 0xfc, 0xb5, 0xe9, 0x91, 0x7a, 0xf2, 0x35, 0x08, 0x50,
+    0x9a, 0x5f, 0xd2, 0xda, 0xb6, 0x5b, 0xda, 0xb9, 0x14, 0x83, 0xb2, 0x5f,
+    0xee, 0x73, 0x0f, 0xa8, 0x6c, 0xb3, 0xe2, 0x4a, 0x47, 0xc1, 0x3d, 0xf5,
+    0x44, 0x8d, 0x50, 0xfa, 0xa2, 0x3e, 0x85, 0xf0, 0x1f, 0x7d, 0x49, 0x47,
+    0xc5, 0x43, 0x7f, 0x40, 0xa5, 0xe2, 0x09, 0x03, 0xae, 0x98, 0x4b, 0xd3,
+    0x07, 0xb9, 0x1e, 0x05, 0x7c, 0xf1, 0xb1, 0xe7, 0x26, 0xd6, 0xc9, 0xc9,
+    0x0f, 0x06, 0xd6, 0x9d, 0xfc, 0x2a, 0xdb, 0x7f, 0x43, 0x39, 0x61, 0x69,
+    0x32, 0xe7, 0x98, 0xdb, 0xde, 0x51, 0xd7, 0x21, 0xd1, 0x2a, 0x84, 0x9d,
+    0x16, 0x32, 0xa1, 0x4e, 0x70, 0x41, 0x23, 0x97, 0x2f, 0xa2, 0x4f, 0x4e,
+    0xb4, 0x97, 0xae, 0x5e, 0x6f, 0x05, 0x03, 0x7a, 0x23, 0x40, 0x3c, 0x2d,
+    0x42, 0xa5, 0x95, 0x6c, 0x40, 0xec, 0x65, 0x30, 0x72, 0x8e, 0x11, 0x0c,
+    0x49, 0xa0, 0x9b, 0x28, 0xcf, 0x9f, 0xca, 0x67, 0x7b, 0xa0, 0x68, 0x16,
+    0xf1, 0x31, 0xe3, 0x6f, 0xc2, 0xb6, 0xee, 0xf3, 0xd6, 0xb6, 0x68, 0x19,
+    0x86, 0x97, 0xc5, 0x22, 0x57, 0xa8, 0x1b, 0xe4, 0x78, 0xd7, 0x1d, 0xf9,
+    0xe8, 0xcf, 0x15, 0x9b, 0x73, 0x48, 0xc2, 0xd5, 0x50, 0xd1, 0x6d, 0x3d,
+    0xf8, 0xfd, 0xdb, 0x57, 0x90, 0x60, 0xdf, 0x30, 0xdd, 0x85, 0x47, 0xc6,
+    0xa3, 0x5e, 0x19, 0xef, 0x8c, 0xd9, 0x29, 0xe2, 0x46, 0x59, 0xb1, 0x72,
+    0x9d, 0x59, 0xbf, 0x72, 0xae, 0x37, 0x1c, 0xc4, 0x87, 0xc5, 0x23, 0x15,
+    0xc3, 0xc2, 0xcb, 0xe1, 0x1a, 0x52, 0x48, 0x21, 0xf7, 0x20, 0xd8, 0xb9,
+    0xdf, 0xbd, 0xd5, 0x4e, 0x45, 0x50, 0x29, 0x16, 0xe4, 0xc8, 0x4d, 0xf1,
+    0x8a, 0x34, 0x61, 0x0e, 0x50, 0xca, 0x22, 0x7e, 0x22, 0x31, 0xd9, 0xc5,
+    0x67, 0xa6, 0x83, 0x1a, 0x5c, 0x91, 0x0c, 0xf2, 0xdf, 0x19, 0x9d, 0x00,
+    0x95, 0x0f, 0x72, 0xba, 0xa2, 0xd9, 0xff, 0x1f, 0xc7, 0x45, 0xbc, 0xcc,
+    0x49, 0x90, 0xc9, 0x78, 0xc1, 0x8e, 0x98, 0x51, 0x10, 0x34, 0xf6, 0xc9,
+    0x64, 0xd5, 0x55, 0x14, 0xc5, 0xc5, 0x71, 0x2e, 0x51, 0x79, 0xbe, 0xaa,
+    0xff, 0xa6, 0xb3, 0x8d, 0x62, 0x34, 0x49, 0x63, 0xa3, 0x51, 0xd0, 0x91,
+    0x23, 0x29, 0x11, 0xe2, 0x85, 0xdc, 0xd2, 0x61, 0x57, 0x25, 0x76, 0x2b,
+    0x42, 0x08, 0x69, 0xac, 0x57, 0xa4, 0x35, 0x34, 0x4b, 0xd5, 0x86, 0xf0,
+    0x35, 0x9d, 0xb9, 0x17, 0x98, 0xbe, 0x69, 0x70, 0xd9, 0xcd, 0x0f, 0xe5,
+    0xe5, 0xaf, 0x97, 0x1f, 0xa4, 0xc7, 0xd3, 0x8b, 0x22, 0x32, 0x78, 0x49,
+    0x84, 0x64, 0xaa, 0xe7, 0xe9, 0x86, 0xd8, 0xb8, 0xad, 0xe9, 0xc5, 0x11,
+    0xcb, 0xf3, 0xad, 0xb5, 0x14, 0xa5, 0xe2, 0xf1, 0x43, 0xb5, 0xdf, 0xd3,
+    0x7e, 0xb7, 0x9e, 0x50, 0x68, 0xf6, 0xcb, 0x9e, 0x43, 0x4b, 0xf5, 0x19,
+    0x0c, 0xa9, 0x1f, 0xd6, 0x14, 0x0e, 0xdc, 0xe0, 0x09, 0x64, 0xa5, 0xe6,
+    0x02, 0x95, 0x71, 0x7c, 0xed, 0xb9, 0xb4, 0x87, 0x6c, 0x96, 0x50, 0xcc,
+    0x13, 0xa1, 0x36, 0xee, 0xbf, 0x7e, 0xdc, 0x58, 0xf7, 0x7f, 0xd1, 0x04,
+    0x13, 0x01, 0xa4, 0x6d, 0xb4, 0x9a, 0x1a, 0xd0, 0x9e, 0x4f, 0xe0, 0xe7,
+    0xdc, 0x93, 0xb6, 0xfd, 0xd4, 0x54, 0xd8, 0xed, 0x0b, 0xeb, 0x38, 0x5b,
+    0xfe, 0xde, 0xf9, 0x0e, 0x0f, 0xad, 0x17, 0x04, 0x84, 0x2c, 0x25, 0x0f,
+    0x99, 0xd2, 0x10, 0xcb, 0x19, 0x1a, 0xcc, 0x59, 0x6f, 0xe8, 0x17, 0x6f,
+    0xe5, 0x04, 0xb3, 0x40, 0x00, 0x02, 0x40, 0x77, 0x01, 0x1b, 0x6a, 0xb0,
+    0x55, 0xf7, 0x29, 0x1c, 0x95, 0x64, 0x42, 0xdd, 0xbf, 0x21, 0x1d, 0xa9,
+    0x43, 0x24, 0x8b, 0xfc, 0x52, 0xc0, 0xce, 0x58, 0x00, 0xf0, 0x1d, 0x19,
+    0x7d, 0x2c, 0x52, 0xfe, 0x5f, 0x3d, 0x5e, 0x94, 0x05, 0x22, 0x72, 0x87,
+    0x80, 0xb1, 0x4b, 0xb4, 0x94, 0xb2, 0x4d, 0x2f, 0x8e, 0x25, 0xbb, 0x22,
+    0x6c, 0x35, 0x03, 0x4c, 0xcd, 0x16, 0x45, 0xf2, 0x64, 0x9f, 0x82, 0x08,
+    0x78, 0x33, 0x8d, 0x1a, 0x20, 0x78, 0xbb, 0x99, 0xbf, 0xf8, 0x4e, 0x91,
+    0x76, 0x5d, 0x26, 0x18, 0x5b, 0x0c, 0xf0, 0x42, 0x6a, 0xa0, 0x71, 0xfe,
+    0xa7, 0xd2, 0x26, 0xd1, 0x69, 0x5e, 0x73, 0x42, 0x1d, 0xb0, 0x99, 0xd6,
+    0x49, 0x03, 0xe2, 0x2e, 0x1d, 0xd1, 0x86, 0x6c, 0x95, 0xf5, 0x14, 0x13,
+    0x56, 0xb5, 0x6e, 0x0a, 0xde, 0x8a, 0x28, 0x62, 0x37, 0x9d, 0x99, 0x29,
+    0xd0, 0x86, 0x14, 0x26, 0x81, 0x6a, 0xa8, 0x07, 0xbb, 0x23, 0x58, 0x54,
+    0xd7, 0x5a, 0x36, 0xef, 0xe7, 0xd8, 0x1b, 0x86, 0xba, 0x6e, 0x29, 0xe6,
+    0x9c, 0x91, 0xb8, 0x19, 0xe7, 0xb3, 0x03, 0xba, 0x1a, 0x39, 0x64, 0x34,
+    0x8f, 0x72, 0x0f, 0x2d, 0xff, 0x0d, 0x8a, 0xaf, 0x34, 0x4e, 0x31, 0xf6,
+    0x64, 0xbb, 0x5c, 0x0c, 0x66, 0x87, 0xb4, 0xd0, 0x95, 0x37, 0x98, 0x14,
+    0x48, 0x01, 0x10, 0x8d, 0x60, 0x1b, 0xd2, 0xc6, 0xe9, 0x02, 0xff, 0x3c,
+    0x01, 0xcc, 0xa5, 0x95, 0xa3, 0x42, 0x4d, 0x59, 0x00, 0x33, 0x5d, 0x38,
+    0xe7, 0x71, 0x79, 0xeb, 0xcc, 0x2b, 0xd3, 0x34, 0xb5, 0xd7, 0x61, 0xac,
+    0x14, 0xb2, 0xec, 0x52, 0x1a, 0x0e, 0x97, 0x02, 0x49, 0xed, 0xfc, 0x06,
+    0xbb, 0x7f, 0x6f, 0xfa, 0x23, 0xad, 0x6f, 0x96, 0x2e, 0xee, 0x03, 0x36,
+    0x34, 0x08, 0x4f, 0x26, 0x4f, 0xcd, 0x3e, 0x28, 0x54, 0x97, 0xbd, 0xfb,
+    0x31, 0x46, 0x1a, 0x6b, 0x9b, 0xcf, 0x2d, 0xca, 0x37, 0xab, 0x8f, 0xd6,
+    0x30, 0xc5, 0x95, 0x6d, 0xfe, 0x6f, 0xc8, 0x1b, 0x70, 0x90, 0x25, 0xb1,
+    0x92, 0x02, 0xb0, 0x9d, 0x81, 0x0e, 0x26, 0x51, 0x97, 0x60, 0xbe, 0x25,
+    0x62, 0xae, 0x5c, 0xd6, 0xbd, 0xfc, 0xca, 0xad, 0x6a, 0x6a, 0xdb, 0x4b,
+    0x19, 0x8a, 0x04, 0xce, 0x73, 0x73, 0x39, 0x22, 0x6b, 0x2f, 0x5f, 0x22,
+    0x78, 0xd6, 0xd1, 0xcb, 0xa3, 0xf0, 0x48, 0x78, 0x80, 0xb9, 0x69, 0xe4,
+    0x57, 0xdc, 0x0e, 0x47, 0x6a, 0x28, 0x94, 0x88, 0xca, 0xac, 0x83, 0x27,
+    0xbb, 0x11, 0x74, 0x74, 0xc8, 0xce, 0x11, 0x01, 0xc0, 0x0e, 0x92, 0xaf,
+    0x58, 0xf9, 0xd3, 0xae, 0xa5, 0xed, 0x81, 0x84, 0x69, 0xd5, 0xcb, 0xe3,
+    0x65, 0xc9, 0x84, 0xbb, 0x5d, 0x89, 0xe3, 0x8f, 0x98, 0x04, 0xf7, 0x06,
+    0x93, 0x9f, 0xd8, 0xb3, 0x61, 0xfe, 0xfa, 0xd2, 0x86, 0x39, 0x53, 0xed,
+    0x58, 0x0b, 0x61, 0x88, 0x46, 0x8f, 0x8f, 0x1f, 0xdf, 0x1a, 0x7a, 0x77,
+    0x06, 0x72, 0xc5, 0x6a, 0x88, 0x60, 0x2f, 0x4a, 0x60, 0xe4, 0xbe, 0xa0,
+    0x59, 0x69, 0xb0, 0xc6, 0x49, 0x7a, 0x95, 0x03, 0x0e, 0xa9, 0x60, 0x22,
+    0xa3, 0xd4, 0xc6, 0x54, 0x63, 0xdc, 0x1c, 0x5a, 0x8a, 0x25, 0x19, 0x4f,
+    0xc4, 0x8d, 0xae, 0xba, 0x9b, 0x3e, 0xe1, 0xd2, 0x27, 0x1c, 0x68, 0x87,
+    0x18, 0x06, 0x5f, 0x64, 0x25, 0xba, 0x67, 0x0e, 0xda, 0x9a, 0xb9, 0x97,
+    0x9e, 0x52, 0x32, 0x44, 0x25, 0x9a, 0xa7, 0xa3, 0xae, 0xce, 0x19, 0x6d,
+    0x33, 0x04, 0x63, 0x93, 0x14, 0x43, 0x8c, 0xaf, 0xa8, 0x4f, 0xa8, 0xe3,
+    0x53, 0x6f, 0x77, 0x4b, 0xc6, 0xd9, 0x6c, 0x02, 0x8f, 0xd8, 0x17, 0x9d,
+    0x52, 0x10, 0x2b, 0x4f, 0x92, 0x91, 0xd1, 0xa2, 0x94, 0x8f, 0xd5, 0xb9,
+    0xd2, 0xf5, 0xd9, 0xec, 0x47, 0x4f, 0x27, 0x87, 0x21, 0x6d, 0x2c, 0x81,
+    0x87, 0x07, 0xb5, 0x29, 0x26, 0x46, 0x7c, 0x47, 0x38, 0x97, 0x98, 0x13,
+    0xa2, 0xaa, 0x47, 0x9d, 0x23, 0x3c, 0x9c, 0x2d, 0x80, 0x56, 0x10, 0xb9,
+    0xbe, 0x78, 0xe8, 0x61, 0x17, 0x92, 0x8b, 0x88, 0x70, 0xf4, 0x31, 0xf0,
+    0x0c, 0x07, 0xe7, 0xbd, 0x1c, 0x34, 0xe5, 0x8e, 0x8c, 0xe8, 0xd6, 0x4e,
+    0x38, 0xef, 0x0b, 0x59, 0xf7, 0xc1, 0x5f, 0x0f, 0xa4, 0x21, 0x93, 0x90,
+    0x27, 0x80, 0x21, 0x29, 0xe5, 0x7d, 0x12, 0xfd, 0x0e, 0x27, 0x0b, 0x42,
+    0x8e, 0xcd, 0x12, 0x50, 0x96, 0x5b, 0x94, 0xa0, 0x3e, 0x29, 0xee, 0x1a,
+    0x6f, 0xc5, 0x07, 0x9a, 0xef, 0xbc, 0x9e, 0x9e, 0x8b, 0x6f, 0x99, 0x96,
+    0x78, 0x3b, 0x2c, 0xd2, 0xc5, 0x05, 0x91, 0x96, 0x5e, 0x39, 0x06, 0xb2,
+    0x0f, 0x34, 0xa5, 0x98, 0x98, 0x67, 0xd9, 0x4e, 0x92, 0xb8, 0x46, 0xc0,
+    0x7a, 0xf4, 0xf2, 0x90, 0x97, 0xcf, 0x33, 0x9e, 0x0b, 0xb7, 0xf3, 0xef,
+    0xa5, 0xa5, 0xbf, 0x97, 0xf9, 0x04, 0x46, 0xea, 0x31, 0x21, 0x94, 0x61,
+    0x19, 0x17, 0xd1, 0x9d, 0xe7, 0xfa, 0x3a, 0xaa, 0x52, 0x55, 0x46, 0x72,
+    0x1b, 0x97, 0xd9, 0x6b, 0x5e, 0x3d, 0x15, 0x83, 0x55, 0x01, 0x95, 0x52,
+    0x27, 0xd1, 0x0c, 0x41, 0x90, 0x67, 0x44, 0x7d, 0x4f, 0xd8, 0x7a, 0x3e,
+    0x9f, 0xae, 0xc3, 0x00, 0x86, 0xc3, 0xc2, 0x06, 0xd8, 0x99, 0xb4, 0xfc,
+    0x00, 0xbf, 0x8e, 0xa3, 0x0c, 0xf9, 0x14, 0x48, 0x2a, 0xb0, 0x5e, 0xf8,
+    0xfe, 0x6b, 0x83, 0x13, 0xaa, 0x94, 0xd0, 0x62, 0x9b, 0xbb, 0xa7, 0x33,
+    0x26, 0x18, 0xca, 0x60, 0x48, 0x0c, 0x5c, 0xe3, 0x13, 0x94, 0x24, 0xfe,
+    0x00, 0xf3, 0x1f, 0xa2, 0x2f, 0xae, 0x49, 0x92, 0xe7, 0xf6, 0x49, 0x1e,
+    0xf7, 0x57, 0x4c, 0xe5, 0x4c, 0x5f, 0x8c, 0xa3, 0xdc, 0x70, 0xbe, 0x5b,
+    0x8c, 0x3c, 0xdb, 0xd3, 0x84, 0x02, 0x6e, 0xdc, 0xd5, 0x6a, 0xc9, 0xc2,
+    0x5f, 0x95, 0x3a, 0x2d, 0x44, 0x87, 0x09, 0x52, 0x90, 0x41, 0x1f, 0xa8,
+    0x93, 0x76, 0xae, 0x53, 0xd3, 0xef, 0x26, 0x15, 0x27, 0x38, 0x04, 0xc7,
+    0xda, 0xed, 0xb1, 0x11, 0xe8, 0x2a, 0x67, 0x03, 0xd0, 0xfe, 0x5f, 0x85,
+    0xfc, 0xa0, 0x6a, 0x73, 0x6e, 0xac, 0x15, 0x8d, 0xa2, 0xca, 0x5b, 0x32,
+    0x52, 0xc1, 0x2e, 0xf4, 0xe6, 0x68, 0x99, 0xbd, 0xeb, 0x05, 0x4e, 0x8f,
+    0xb7, 0x5c, 0xd1, 0x31, 0x5b, 0x17, 0x98, 0x81, 0xef, 0x69, 0x3d, 0x23,
+    0x01, 0xc3, 0x34, 0xc7, 0x69, 0x39, 0x5e, 0xb3, 0x1e, 0x99, 0xa6, 0xbf,
+    0x78, 0xee, 0x88, 0xe2, 0xdb, 0xd7, 0x4e, 0x17, 0xa0, 0x27, 0x0f, 0xe6,
+    0x9f, 0x9f, 0x74, 0x0c, 0xa4, 0xd2, 0x47, 0xe3, 0xc1, 0xb5, 0xc9, 0x13,
+    0xaa, 0x72, 0x22, 0xbb, 0x7d, 0xd6, 0xb8, 0x76, 0x6c, 0x5e, 0xd5, 0xf7,
+    0x22, 0x69, 0x7c, 0x40, 0x4f, 0x64, 0xcd, 0x02, 0x43, 0x4a, 0x09, 0x1d,
+    0x95, 0x90, 0x16, 0x3f, 0xaa, 0x4d, 0xdf, 0x5d, 0xea, 0x76, 0xb0, 0x52,
+    0x92, 0xa1, 0xde, 0xd6, 0x2f, 0x66, 0x7d, 0x53, 0x65, 0xb4, 0xa6, 0x3e,
+    0x0a, 0x85, 0x03, 0x56, 0x82, 0x6f, 0x17, 0xe6, 0xb6, 0xef, 0x0f, 0x4e,
+    0x01, 0xc5, 0xba, 0x01, 0xdb, 0x23, 0x4c, 0x9f, 0x11, 0x59, 0x28, 0x71,
+    0xc4, 0xf2, 0xeb, 0x00, 0xa9, 0x72, 0x7b, 0xd7, 0x02, 0x94, 0xd8, 0xaf,
+    0xad, 0x16, 0x92, 0x51, 0xea, 0xe4, 0xb6, 0xf6, 0xe1, 0x80, 0xaf, 0x6b,
+    0x0d, 0x2c, 0xbc, 0x6f, 0xb4, 0x0c, 0xa9, 0xd4, 0xf8, 0xb8, 0x19, 0xc5,
+    0x69, 0x5d, 0x8f, 0xce, 0x4b, 0x98, 0x11, 0xae, 0x66, 0x19, 0x66, 0x6e,
+    0xe5, 0x88, 0xc9, 0x23, 0xf5, 0xc6, 0x3d, 0x52, 0x4d, 0x5a, 0x6d, 0x5e,
+    0xdc, 0x00, 0x21, 0x41, 0x53, 0xab, 0x97, 0x3d, 0xa3, 0xfb, 0xd9, 0xdf,
+    0x90, 0x77, 0xeb, 0x4f, 0x8d, 0xec, 0xca, 0x17, 0xad, 0x65, 0xb9, 0x92,
+    0x0c, 0x24, 0xd4, 0x80, 0x19, 0x78, 0x49, 0x7d, 0x9b, 0xcf, 0xdd, 0xaf,
+    0xfd, 0xb8, 0xdd, 0x89, 0x4b, 0xe5, 0xb9, 0x99, 0x9b, 0x70, 0x24, 0xc5,
+    0x86, 0x42, 0x92, 0x2c, 0x47, 0xd5, 0x1a, 0x50, 0x5d, 0x4d, 0xcf, 0xdc,
+    0xb4, 0x19, 0x9a, 0xe2, 0x94, 0x5f, 0x1b, 0x19, 0x40, 0xd3, 0x5c, 0xe3,
+    0x09, 0xe3, 0x7c, 0x15, 0x60, 0x49, 0xf7, 0xf9, 0xdb, 0x8e, 0x38, 0x69,
+    0xfa, 0xa2, 0xe6, 0x18, 0x11, 0xc3, 0x57, 0xa0, 0xec, 0x1b, 0x43, 0x3a,
+    0xb1, 0x5a, 0x6a, 0xcd, 0x5a, 0x2e, 0x59, 0x10, 0x8b, 0xc1, 0xfc, 0xbd,
+    0x75, 0xc9, 0x5e, 0x5c, 0xe2, 0x28, 0xb8, 0x72, 0xbc, 0xb3, 0x8a, 0x5e,
+    0x82, 0x32, 0x50, 0xa3, 0xe0, 0x77, 0xf6, 0xe0, 0x46, 0xbe, 0xda, 0x52,
+    0xa5, 0x13, 0xa5, 0x99, 0xcd, 0xc3, 0x55, 0x31, 0x83, 0x10, 0x72, 0xa3,
+    0x2d, 0x14, 0x49, 0xda, 0x57, 0x81, 0xd7, 0x7f, 0xbd, 0x29, 0x6d, 0xb8,
+    0x21, 0xe4, 0x4b, 0x58, 0x99, 0x74, 0x84, 0xef, 0x77, 0xd6, 0x92, 0xe0,
+    0x81, 0xe1, 0xc0, 0x3c, 0x10, 0x81, 0xf9, 0xa9, 0xaa, 0x63, 0x74, 0x98,
+    0x91, 0xa8, 0x72, 0x16, 0xa6, 0xf3, 0xf9, 0x89, 0xe4, 0xe6, 0x48, 0xac,
+    0x50, 0x65, 0x11, 0x4c, 0xef, 0xfe, 0xcf, 0x89, 0xd3, 0x9f, 0xc1, 0xfc,
+    0xdc, 0xea, 0x75, 0x19, 0xc7, 0xd0, 0x12, 0xaf, 0x20, 0x64, 0x82, 0x08,
+    0x8e, 0xc8, 0x0f, 0x15, 0x51, 0x7b, 0xe2, 0x6b, 0xb0, 0x1c, 0xcd, 0xad,
+    0xd1, 0x77, 0x2d, 0xad, 0xa0, 0xec, 0x81, 0xa7, 0xa8, 0x28, 0xcd, 0xb1,
+    0xcc, 0xa5, 0x43, 0xc4, 0x5b, 0xb8, 0x9c, 0x84, 0xa5, 0x2c, 0xac, 0xba,
+    0xc0, 0x2a, 0x61, 0xc7, 0xf1, 0xb6, 0x57, 0x56, 0xe5, 0xca, 0x96, 0xbb,
+    0xfb, 0x8e, 0x49, 0x3e, 0x50, 0x2f, 0x36, 0x73, 0x5b, 0x44, 0x5b, 0x36,
+    0x9c, 0xa0, 0x90, 0xc6, 0x96, 0x4e, 0x73, 0x1f, 0x68, 0x47, 0x43, 0xd3,
+    0x6b, 0x1f, 0x4d, 0x43, 0x1e, 0xbf, 0x1c, 0x28, 0xe9, 0xf5, 0x3d, 0xac,
+    0x48, 0x4c, 0xd4, 0x6d, 0x32, 0x25, 0xf3, 0x71, 0x29, 0xe9, 0xf0, 0x08,
+    0x2a, 0xd2, 0x75, 0xc1, 0xa6, 0x5f, 0x1f, 0xca, 0xbb, 0x76, 0x91, 0xdc,
+    0xca, 0x13, 0x3b, 0x18, 0xd9, 0x66, 0x48, 0xb0, 0x29, 0x01, 0x39, 0xfd,
+    0x35, 0x8b, 0xd7, 0xac, 0xeb, 0xe3, 0x92, 0x96, 0xef, 0xe1, 0x7e, 0xd7,
+    0xd0, 0xe9, 0xd6, 0xcf, 0xd7, 0x28, 0x58, 0x0a, 0x20, 0xcc, 0xc1, 0x8a,
+    0x45, 0x45, 0xe0, 0x71, 0xca, 0x66, 0x75, 0xb0, 0x97, 0x89, 0x13, 0x7b,
+    0xa3, 0x27, 0x5d, 0xce, 0x36, 0x58, 0xf6, 0x0a, 0x66, 0xf5, 0x83, 0xc8,
+    0xef, 0x6e, 0x6f, 0x98, 0x79, 0x52, 0xd7, 0xd4, 0xa3, 0x3f, 0xda, 0x70,
+    0xe2, 0x41, 0x10, 0x55, 0x20, 0x71, 0xb0, 0xd8, 0xd9, 0x14, 0x19, 0xc6,
+    0x76, 0x0d, 0x45, 0x78, 0xb5, 0x70, 0x88, 0x65, 0x5a, 0x6b, 0xeb, 0x2f,
+    0x28, 0x38, 0xf9, 0xbc, 0x28, 0xbe, 0xca, 0x44, 0x86, 0x4e, 0xd4, 0x29,
+    0xc6, 0x16, 0xca, 0x3e, 0xb7, 0x33, 0x58, 0x04, 0x33, 0x7c, 0xac, 0xb5,
+    0x9f, 0xf9, 0xfd, 0x6d, 0xb9, 0xff, 0x5a, 0x35, 0xa6, 0xd8, 0xa5, 0x28,
+    0x30, 0xf5, 0x16, 0x95, 0xa9, 0x14, 0x65, 0x97, 0x56, 0x01, 0x4d, 0xf8,
+    0x71, 0xc9, 0x93, 0xad, 0xac, 0x97, 0x1d, 0xab, 0x70, 0x21, 0x2d, 0xf3,
+    0x26, 0x16, 0x66, 0xcb, 0xa2, 0x67, 0x56, 0x09, 0xd9, 0x9d, 0x9c, 0xec,
+    0x37, 0x4d, 0x71, 0xbd, 0xef, 0xaf, 0x22, 0x78, 0xd9, 0x4c, 0xdd, 0xab,
+    0x9a, 0x12, 0x28, 0x7d, 0xb4, 0xd4, 0x9c, 0x01, 0xf2, 0x85, 0x2f, 0xbc,
+    0x58, 0x77, 0x85, 0x32, 0xdf, 0x4e, 0x79, 0x41, 0x41, 0xda, 0x6e, 0x9f,
+    0x60, 0x09, 0x82, 0xf4, 0x50, 0x15, 0x68, 0x0f, 0xfd, 0x0b, 0x5b, 0x09,
+    0x33, 0x98, 0x9c, 0x92, 0x1d, 0xc1, 0x38, 0xbe, 0xdc, 0x17, 0xbe, 0x88,
+    0xa8, 0xa6, 0x88, 0xa2, 0x0f, 0x81, 0xcd, 0xb6, 0xde, 0x42, 0xc7, 0x7d,
+    0x53, 0xc6, 0xab, 0xd3, 0x94, 0x9d, 0x2e, 0x79, 0x2f, 0x0b, 0x76, 0x63,
+    0x36, 0xa5, 0x85, 0x7f, 0x94, 0x07, 0x53, 0xe7, 0xa8, 0x6a, 0x0d, 0xb1,
+    0xda, 0x1f, 0xad, 0xb6, 0x5b, 0x13, 0xe7, 0x21, 0xcc, 0xe7, 0x29, 0x09,
+    0x48, 0x1a, 0x19, 0x7e, 0x22, 0x1b, 0x1b, 0xe5, 0xf2, 0x1a, 0x08, 0x25,
+    0x30, 0xca, 0xf1, 0xd6, 0x97, 0x56, 0x3a, 0xa7, 0x3f, 0x0b, 0xce, 0xaf,
+    0xfc, 0x50, 0x24, 0x34, 0xab, 0xf0, 0x9c, 0x91, 0x12, 0xc0, 0x4f, 0xd5,
+    0xed, 0xa4, 0xf4, 0xe4, 0x36, 0x54, 0x49, 0xed, 0x36, 0x61, 0x6d, 0xa4,
+    0x1e, 0x63, 0x24, 0x3c, 0x40, 0xb0, 0xb2, 0x44, 0xe3, 0x6d, 0xf2, 0xa6,
+    0x96, 0x97, 0xe9, 0x97, 0xd4, 0x76, 0x80, 0x0c, 0x6d, 0xa8, 0xb1, 0x39,
+    0x48, 0x48, 0x7c, 0x1b, 0x46, 0x9e, 0x94, 0x7a, 0xbf, 0xfd, 0xc6, 0xff,
+    0x72, 0xf0, 0x4d, 0x4b, 0x22, 0x46, 0x32, 0x8e, 0x51, 0x23, 0xe7, 0xb2,
+    0xe7, 0xa7, 0x05, 0x38, 0xb9, 0x25, 0xcc, 0xe2, 0xbf, 0x08, 0xff, 0x77,
+    0xf9, 0xb6, 0x37, 0xcd, 0x29, 0x47, 0xc3, 0x10, 0xe4, 0xc9, 0xd5, 0xaa,
+    0x41, 0xe8, 0x6c, 0x6d, 0x17, 0xa2, 0x8a, 0x08, 0xcc, 0xde, 0xa3, 0xcb,
+    0xeb, 0x66, 0x86, 0x2c, 0x0b, 0xd3, 0xeb, 0xb3, 0x4b, 0x9e, 0x64, 0x70,
+    0xf3, 0xa2, 0x8e, 0x30, 0x14, 0x32, 0x09, 0xea, 0xbd, 0x57, 0x4b, 0x6b,
+    0x1e, 0xa3, 0x12, 0x01, 0xc2, 0x46, 0x65, 0x23, 0xe9, 0xac, 0x21, 0xb2,
+    0xba, 0x60, 0xef, 0x6e, 0xa8, 0x32, 0x16, 0x1b, 0x69, 0x41, 0x23, 0x93,
+    0xfb, 0x48, 0x7a, 0xb3, 0xe2, 0xab, 0x9b, 0x1a, 0x44, 0xce, 0x8a, 0x35,
+    0xfc, 0x87, 0x3e, 0xe4, 0xa5, 0xec, 0xcf, 0x98, 0x04, 0x32, 0xc2, 0x32,
+    0x4b, 0x48, 0x96, 0xed, 0x6a, 0xd1, 0xca, 0x3a, 0xf0, 0xb9, 0x32, 0x14,
+    0xe3, 0x11, 0x23, 0x87, 0x09, 0x49, 0x59, 0x20, 0x6b, 0x3a, 0xb7, 0xc5,
+    0xa7, 0xb3, 0x86, 0xd1, 0x87, 0x0d, 0xcf, 0x04, 0x92, 0x2a, 0x87, 0xa4,
+    0x36, 0xc9, 0x03, 0x3f, 0x05, 0x2f, 0x39, 0xad, 0xfb, 0xbb, 0x25, 0x0c,
+    0xbe, 0x23, 0xe4, 0x18, 0x1c, 0x24, 0x71, 0xd1, 0x6c, 0xba, 0x6a, 0xba,
+    0xa6, 0xa7, 0x93, 0x08, 0x43, 0x92, 0x13, 0xfa, 0x02, 0xe0, 0x0e, 0xf6,
+    0x26, 0x20, 0x11, 0x5c, 0x4f, 0x54, 0xc0, 0xb2, 0x0b, 0x5e, 0x79, 0x41,
+    0xd9, 0x03, 0xd8, 0x4f, 0xb4, 0x60, 0xf7, 0x2c, 0xbd, 0xd8, 0xcd, 0xdd,
+    0x19, 0xee, 0x46, 0x5f, 0x44, 0x2b, 0x57, 0x3f, 0xe3, 0x6b, 0x41, 0x4b,
+    0x63, 0x19, 0x2b, 0x69, 0xb3, 0xe4, 0x14, 0xe0, 0xfc, 0x70, 0x6f, 0xc5,
+    0x9e, 0xe2, 0x56, 0xfe, 0x62, 0xc7, 0x2b, 0x68, 0x43, 0x34, 0xb0, 0xf8,
+    0x71, 0xd9, 0x0e, 0xbd, 0x20, 0x29, 0x83, 0xf1, 0xfe, 0xed, 0xec, 0xd5,
+    0xeb, 0x12, 0xc9, 0x13, 0x9d, 0x1f, 0xb4, 0xce, 0x39, 0xd8, 0x15, 0xa9,
+    0x6c, 0x24, 0x8d, 0x6f, 0xc5, 0x0a, 0x0c, 0xa2, 0x7e, 0x29, 0x67, 0xf1,
+    0x3a, 0xf8, 0xd6, 0xd0, 0x3b, 0x28, 0x30, 0x94, 0x0c, 0x28, 0x77, 0x06,
+    0x79, 0x3f, 0xfc, 0x67, 0xf2, 0x76, 0x8b, 0xb5, 0xc0, 0x4a, 0x1a, 0x79,
+    0x9c, 0x04, 0xef, 0xc1, 0x61, 0x0e, 0xe9, 0xe0, 0xf3, 0x4a, 0x03, 0x00,
+    0xf1, 0x4a, 0xa6, 0x66, 0x51, 0x53, 0x76, 0x35, 0x72, 0xc7, 0x59, 0x4b,
+    0x34, 0x34, 0xc9, 0x1d, 0x91, 0x21, 0x1a, 0x5f, 0xb6, 0x81, 0x9e, 0x7a,
+    0x62, 0x4a, 0xb8, 0x54, 0xb7, 0xdf, 0xe7, 0xd7, 0xb0, 0x5f, 0xa8, 0x1c,
+    0x93, 0xae, 0x94, 0x3d, 0x82, 0x83, 0xe7, 0x9c, 0x50, 0x79, 0xa5, 0x03,
+    0xf2, 0x3f, 0x19, 0xd7, 0x3f, 0x5f, 0x33, 0xf1, 0x5b, 0x65, 0x03, 0x4d,
+    0x40, 0x88, 0x66, 0x67, 0x3f, 0x16, 0x8e, 0x7c, 0x4f, 0xd6, 0x15, 0xb3,
+    0x1d, 0xed, 0x86, 0xc7, 0x2b, 0x82, 0x4e, 0x4e, 0xc1, 0x9b, 0x25, 0xc1,
+    0xf5, 0x3f, 0x6e, 0xde, 0xbd, 0x23, 0x44, 0xa1, 0xb4, 0x84, 0xfb, 0x0a,
+    0x95, 0x59, 0x57, 0x60, 0x73, 0x54, 0xcf, 0x4d, 0x2d, 0x5d, 0x8d, 0xc3,
+    0xc8, 0x2a, 0x98, 0x7d, 0xb2, 0x59, 0x94, 0xe6, 0x90, 0x43, 0xed, 0xa2,
+    0xc2, 0x13, 0x33, 0xf5, 0xee, 0x21, 0x72, 0x82, 0xaa, 0x33, 0xfc, 0x92,
+    0x15, 0xc1, 0xf6, 0xef, 0x7d, 0xdf, 0x25, 0x8a, 0xbe, 0x36, 0xe8, 0x69,
+    0x91, 0x42, 0x93, 0x4f, 0x1d, 0xc4, 0x92, 0xa5, 0xf3, 0xc1, 0x5d, 0x3d,
+    0x1b, 0x36, 0xd7, 0xc4, 0x35, 0x7d, 0xe5, 0x02, 0x5b, 0xca, 0x8f, 0xcc,
+    0x0c, 0x86, 0x7b, 0x20, 0xbc, 0xc2, 0xc1, 0x6f, 0x5a, 0x7c, 0xfe, 0x66,
+    0x6d, 0xeb, 0x5e, 0xa5, 0xba, 0xbe, 0x26, 0xd3, 0xda, 0xe8, 0x51, 0x26,
+    0x57, 0xac, 0xcf, 0x3f, 0x86, 0x1d, 0x38, 0x71, 0xa4, 0x35, 0x70, 0xe9,
+    0x50, 0x02, 0x72, 0xc2, 0x22, 0x79, 0x78, 0xeb, 0x7d, 0xcf, 0xc7, 0x87,
+    0xbc, 0x7e, 0xc7, 0x1c, 0x8d, 0x13, 0x44, 0xf3, 0xd0, 0x8a, 0x25, 0xf6,
+    0xf7, 0x3c, 0xd9, 0x6f, 0xf2, 0x37, 0x9e, 0xad, 0x33, 0x43, 0x86, 0x40,
+    0x4e, 0x90, 0x92, 0x33, 0x8c, 0x49, 0x90, 0x26, 0xf5, 0x25, 0x7d, 0xfe,
+    0xf7, 0x16, 0x7e, 0x57, 0xef, 0xde, 0x6f, 0x2f, 0x93, 0xbe, 0x57, 0xda,
+    0xae, 0x04, 0x35, 0x40, 0xcc, 0x4d, 0x72, 0x03, 0x2b, 0xb8, 0x1a, 0xfb,
+    0xda, 0x1b, 0xb6, 0xff, 0x86, 0x6b, 0x76, 0xa6, 0xee, 0x71, 0xdd, 0xe8,
+    0x10, 0xd8, 0x00, 0x94, 0x00, 0xa4, 0x6b, 0x00, 0x46, 0xd3, 0x8d, 0x16,
+    0x64, 0x4c, 0x21, 0xd5, 0xc0, 0xca, 0x64, 0x44, 0xd2, 0xe6, 0xee, 0x4f,
+    0xc4, 0xfa, 0x35, 0x45, 0x64, 0xc5, 0x51, 0xa8, 0x7c, 0x14, 0x77, 0xeb,
+    0x97, 0x87, 0x0b, 0xae, 0x1d, 0x9c, 0x6e, 0x0d, 0xba, 0xb8, 0xa8, 0x8c,
+    0xc8, 0x97, 0xd7, 0xb5, 0x43, 0xf3, 0x6b, 0x2d, 0x86, 0xdd, 0x01, 0xf6,
+    0x07, 0xde, 0x7d, 0x7f, 0xb7, 0x3c, 0xe2, 0x30, 0x6b, 0x98, 0x99, 0xce,
+    0xa6, 0xcb, 0x18, 0xa4, 0xa7, 0x3b, 0xc9, 0x62, 0xb9, 0x61, 0x3c, 0x87,
+    0xe0, 0x7f, 0x85, 0x0f, 0xda, 0x1f, 0x83, 0x76, 0x6e, 0x9c, 0x53, 0x95,
+    0x0c, 0x75, 0xe3, 0xc2, 0x90, 0x91, 0x96, 0x54, 0x87, 0x70, 0xcf, 0xb6,
+    0x84, 0xe2, 0xbe, 0x31, 0xe5, 0x4a, 0x79, 0x00, 0x4a, 0x25, 0x06, 0x54,
+    0x19, 0x39, 0x4d, 0x14, 0x28, 0xfd, 0x71, 0x91, 0xa2, 0x69, 0xee, 0x2b,
+    0xa2, 0x88, 0x97, 0x37, 0x4f, 0x3e, 0xfa, 0xb7, 0x2a, 0x41, 0x55, 0x10,
+    0xdf, 0xc4, 0x24, 0xfc, 0xde, 0xa9, 0x45, 0x74, 0xb5, 0xb9, 0xee, 0xef,
+    0xd7, 0xb3, 0x8d, 0xc3, 0x41, 0x0c, 0xe8, 0x23, 0x5e, 0x41, 0x29, 0x83,
+    0x23, 0x90, 0xc9, 0xf1, 0x54, 0x0e, 0xb8, 0xbf, 0x95, 0x5a, 0x28, 0x2c,
+    0x5d, 0xd2, 0xd6, 0x50, 0x60, 0x5b, 0x1d, 0xbe, 0x64, 0x4d, 0x10, 0x28,
+    0x92, 0x87, 0x88, 0x7d, 0x3f, 0x8d, 0xaf, 0xfc, 0x0f, 0x0c, 0x00, 0xa3,
+    0x29, 0xd2, 0x10, 0x8b, 0xd9, 0x14, 0xb8, 0x3b, 0x81, 0x76, 0x64, 0xc2,
+    0x97, 0xbe, 0x6f, 0x92, 0x61, 0x8b, 0xb7, 0x05, 0xbd, 0x3e, 0x6d, 0x54,
+    0x50, 0x0c, 0x87, 0x95, 0x97, 0xf4, 0x49, 0x2d, 0x06, 0xac, 0xb8, 0xa9,
+    0x31, 0xd3, 0x76, 0x92, 0x4a, 0xa3, 0xd9, 0x1f, 0xf4, 0x08, 0xd9, 0x29,
+    0x49, 0xa9, 0xe3, 0x65, 0xee, 0x68, 0x60, 0x12, 0x97, 0xcc, 0xfc, 0xe1,
+    0x5d, 0x26, 0xcc, 0xbe, 0xa8, 0x4e, 0xdd, 0x9a, 0x28, 0x21, 0xc3, 0x41,
+    0x2f, 0x8a, 0x4e, 0x60, 0xb7, 0x03, 0x8c, 0x1f, 0x6f, 0x05, 0x5e, 0x99,
+    0x73, 0x33, 0x43, 0xd2, 0xe7, 0x22, 0x75, 0xbc, 0x98, 0xe0, 0x34, 0x7e,
+    0x2c, 0xb0, 0x0f, 0xa9, 0xee, 0xbc, 0x82, 0xa8, 0x1d, 0xa0, 0xd0, 0x95,
+    0x5e, 0xa1, 0x33, 0x95, 0xf4, 0xdb, 0xe0, 0xf5, 0x3c, 0x1c, 0xa4, 0x5e,
+    0x12, 0x08, 0x40, 0x7c, 0xc6, 0x12, 0x22, 0xb3, 0x6d, 0x81, 0xa2, 0x88,
+    0xac, 0x97, 0x6f, 0x2a, 0xc9, 0xd6, 0xde, 0x6b, 0xb6, 0x02, 0x58, 0x18,
+    0x40, 0xc7, 0x92, 0x06, 0x63, 0x26, 0x11, 0x98, 0xf1, 0x05, 0x50, 0x73,
+    0x37, 0x4c, 0xcf, 0x8e, 0x77, 0xe6, 0x0f, 0x6e, 0x4f, 0x36, 0x5e, 0x7a,
+    0x94, 0xd1, 0x13, 0xa5, 0xb1, 0x22, 0x0c, 0x20, 0xa1, 0x97, 0x8c, 0x7e,
+    0xcb, 0xf9, 0xfa, 0x17, 0x4a, 0x4a, 0x40, 0x5e, 0xef, 0xe6, 0x48, 0x6c,
+    0x3b, 0x18, 0xca, 0x2c, 0x67, 0x91, 0x09, 0x85, 0x6a, 0xcd, 0xdd, 0xdb,
+    0xdb, 0x82, 0x07, 0xa7, 0x57, 0xa2, 0x42, 0x84, 0xf8, 0xe7, 0xd2, 0xbe,
+    0x8b, 0x80, 0xe4, 0xda, 0x07, 0x4e, 0xcc, 0x11, 0xc9, 0xf6, 0x5f, 0x5e,
+    0x22, 0xcd, 0xf3, 0x82, 0xa9, 0x6d, 0x7a, 0xc4, 0x26, 0x70, 0xec, 0x1d,
+    0x6a, 0x79, 0x7f, 0x37, 0x28, 0x88, 0x1a, 0x53, 0x84, 0xf8, 0x00, 0xad,
+    0x47, 0x7b, 0xfe, 0x19, 0xc9, 0xac, 0xab, 0x55, 0x76, 0xde, 0x4b, 0x6d,
+    0x6f, 0x2e, 0x77, 0xca, 0xd7, 0x4e, 0x73, 0x18, 0xcd, 0xc3, 0x41, 0xac,
+    0x39, 0x9a, 0x22, 0xac, 0xbf, 0xd2, 0xc0, 0xec, 0x4c, 0x54, 0xfb, 0xb9,
+    0x76, 0x39, 0xd4, 0xcf, 0x63, 0xd6, 0xd6, 0x3c, 0xfe, 0x6f, 0xc0, 0x22,
+    0xc0, 0x14, 0x36, 0xb8, 0x02, 0x19, 0x1e, 0x6a, 0x8b, 0xa3, 0x39, 0x78,
+    0x1a, 0x82, 0x9e, 0x78, 0xf6, 0x58, 0xdb, 0x2e, 0x0a, 0x70, 0xc3, 0xa7,
+    0x45, 0x41, 0x19, 0x8d, 0xca, 0x91, 0xed, 0x28, 0x12, 0x8c, 0xbb, 0x91,
+    0xbd, 0xb3, 0xf0, 0x6a, 0xff, 0x79, 0x7f, 0xdf, 0xbc, 0x03, 0x6c, 0x4f,
+    0x05, 0xe1, 0xaf, 0x39, 0x14, 0x37, 0x08, 0xbd, 0xd8, 0xa5, 0x3a, 0x0d,
+    0xe2, 0x65, 0xdd, 0x9f, 0x80, 0x0c, 0xca, 0xd2, 0x19, 0x36, 0x1d, 0x84,
+    0xfa, 0xa0, 0xa7, 0xb3, 0x26, 0x14, 0x4e, 0x53, 0xb5, 0x98, 0x15, 0x7b,
+    0x53, 0x55, 0xc7, 0x55, 0x59, 0x65, 0xf7, 0xf9, 0xb5, 0x6b, 0x96, 0x59,
+    0x7d, 0xb6, 0xf2, 0xab, 0x6f, 0x4e, 0x48, 0xa1, 0x30, 0x18, 0x01, 0x2a,
+    0x3e, 0x20, 0x3a, 0xc6, 0x6d, 0x2a, 0x23, 0x0d, 0x17, 0x3d, 0x66, 0x30,
+    0xe5, 0xe5, 0xac, 0x86, 0x84, 0x08, 0x01, 0x7a, 0xcc, 0xed, 0xf9, 0xfa,
+    0x83, 0xcf, 0x09, 0x95, 0xdf, 0xf8, 0xed, 0x8c, 0x12, 0x7d, 0xf0, 0xcc,
+    0x3e, 0x35, 0xfe, 0x10, 0x50, 0xed, 0x35, 0xcc, 0x8a, 0x13, 0x18, 0x67,
+    0x22, 0x79, 0x04, 0xd8, 0x43, 0xd2, 0x38, 0xb3, 0xe8, 0x4c, 0x57, 0x6b,
+    0xab, 0xfa, 0x95, 0x4e, 0x2c, 0x5e, 0x14, 0x0e, 0x7e, 0x06, 0xd6, 0x7d,
+    0xcd, 0xe9, 0xb7, 0xbb, 0x8b, 0x76, 0x35, 0xe5, 0xf1, 0x87, 0x6c, 0x92,
+    0x2c, 0x44, 0x8e, 0x59, 0xa3, 0x84, 0x27, 0x55, 0xaa, 0xe7, 0x8a, 0xda,
+    0x3a, 0x08, 0xa3, 0x3c, 0x94, 0x69, 0x07, 0x98, 0xf9, 0x33, 0x0a, 0xe8,
+    0xfe, 0xfd, 0x7e, 0x55, 0x0c, 0x5b, 0x81, 0xba, 0x56, 0xb4, 0x86, 0xd9,
+    0xca, 0x80, 0xc8, 0x12, 0xe8, 0x83, 0x8d, 0x51, 0x04, 0xb9, 0xcf, 0xe8,
+    0x0f, 0x34, 0x97, 0xe7, 0x3b, 0xab, 0xaf, 0x85, 0x7f, 0x6f, 0x38, 0x1e,
+    0x7b, 0xd8, 0x54, 0x31, 0xa7, 0x82, 0x4f, 0x2c, 0xa0, 0xff, 0x18, 0x73,
+    0x8f, 0xbc, 0x57, 0xfe, 0x8f, 0x7f, 0xe5, 0x34, 0xfa, 0x16, 0x59, 0xa5,
+    0x36, 0x3c, 0x01, 0x22, 0x89, 0x33, 0x99, 0x73, 0x93, 0xf1, 0x6b, 0x99,
+    0xe3, 0xaa, 0xab, 0xf0, 0x37, 0x21, 0x09, 0xb2, 0x5d, 0x5a, 0x61, 0x89,
+    0xb9, 0x62, 0xaf, 0x90, 0x3f, 0x8a, 0x42, 0x9d, 0x6b, 0x41, 0x86, 0x00,
+    0x51, 0x78, 0x28, 0x41, 0x37, 0x35, 0x84, 0x73, 0xc6, 0x1e, 0x42, 0x52,
+    0x91, 0x4a, 0x93, 0xce, 0x78, 0x0a, 0x08, 0x51, 0xec, 0x92, 0x15, 0x48,
+    0x58, 0xe4, 0x94, 0x48, 0xbb, 0x8b, 0xd7, 0xf6, 0x5b, 0xac, 0x69, 0x5f,
+    0x9a, 0x9d, 0x6c, 0xd9, 0x8e, 0xef, 0xb0, 0x71, 0xf8, 0x1a, 0xc4, 0xa8,
+    0x90, 0x93, 0xec, 0x1a, 0x66, 0xbd, 0x29, 0x0f, 0xa9, 0xce, 0xf1, 0x65,
+    0xb2, 0xc7, 0xb4, 0x4a, 0x92, 0x3d, 0x94, 0xcb, 0xae, 0x15, 0xc8, 0x99,
+    0x44, 0x6d, 0x82, 0x00, 0x89, 0x20, 0x96, 0x97, 0x38, 0xd0, 0x5b, 0x8e,
+    0xfa, 0x6d, 0x6a, 0x40, 0xa0, 0x72, 0xb2, 0x92, 0x27, 0xb5, 0xbc, 0x34,
+    0x50, 0xfa, 0x5f, 0x1a, 0xfa, 0xe5, 0xdd, 0x75, 0x76, 0xb7, 0x7c, 0x19,
+    0xbb, 0xe2, 0x89, 0x31, 0xab, 0xc9, 0x59, 0x72, 0x19, 0x7f, 0x3e, 0x60,
+    0x9c, 0x8d, 0x4d, 0xdf, 0x90, 0xea, 0xcb, 0x65, 0xca, 0x03, 0x96, 0x59,
+    0x22, 0x32, 0x8c, 0xfc, 0x0c, 0x97, 0x1f, 0x39, 0x75, 0xff, 0xd1, 0x79,
+    0x9b, 0xce, 0x89, 0xd2, 0xe5, 0x8d, 0x04, 0xf0, 0xe2, 0x59, 0x48, 0xd0,
+    0xf9, 0xc3, 0xbe, 0xee, 0x58, 0x06, 0xb7, 0xe6, 0xd1, 0x80, 0x6b, 0x13,
+    0xb4, 0x41, 0x11, 0x06, 0x51, 0x8c, 0x66, 0xf9, 0x7e, 0x34, 0x07, 0xc1,
+    0x4f, 0xfe, 0x9b, 0x31, 0xdf, 0x1e, 0x62, 0x44, 0xe7, 0x26, 0xc6, 0xa2,
+    0x28, 0x25, 0x22, 0x28, 0xf8, 0x8d, 0xad, 0x27, 0x0b, 0xc7, 0x78, 0x01,
+    0x82, 0x8c, 0x15, 0xe7, 0x96, 0x55, 0x1c, 0x63, 0xf1, 0xcc, 0x5d, 0xba,
+    0x89, 0xbf, 0x1a, 0xd9, 0x98, 0xaf, 0xa1, 0x87, 0x6c, 0x8c, 0x86, 0xf4,
+    0x4f, 0xc7, 0xf3, 0x13, 0x7c, 0x94, 0x5d, 0x95, 0x46, 0xbf, 0xad, 0x0d,
+    0x9d, 0x3c, 0xe8, 0x12, 0x88, 0x99, 0x92, 0x5a, 0x15, 0x62, 0x50, 0xdb,
+    0x67, 0x7a, 0xf3, 0x53, 0x6d, 0x5a, 0xd2, 0x12, 0x2f, 0x2e, 0xd0, 0x50,
+    0x22, 0x8c, 0x3f, 0x3b, 0x45, 0x54, 0x5c, 0x54, 0x35, 0xe7, 0xb3, 0x78,
+    0xf5, 0x10, 0x53, 0x38, 0xd8, 0xa1, 0x5f, 0x28, 0xe4, 0xc1, 0xf0, 0x66,
+    0x54, 0x56, 0xdb, 0xed, 0xff, 0xd3, 0x60, 0x08, 0x41, 0xb5, 0xa0, 0x41,
+    0x8c, 0x51, 0x96, 0x60, 0x0e, 0x3a, 0x5a, 0xf0, 0x13, 0xbc, 0x49, 0xd5,
+    0xf9, 0xd7, 0xcf, 0xcc, 0x04, 0x20, 0x97, 0x64, 0x1a, 0xe6, 0x36, 0x03,
+    0xa1, 0x4b, 0xaf, 0x34, 0x1d, 0x06, 0x31, 0x80, 0x8c, 0x0a, 0x5c, 0xf0,
+    0x93, 0x03, 0xde, 0xb3, 0xd9, 0xca, 0xda, 0x9e, 0xd8, 0x99, 0xce, 0x9b,
+    0xef, 0x72, 0x29, 0x72, 0x79, 0xfc, 0x5f, 0x01, 0xd7, 0x36, 0x93, 0x03,
+    0xda, 0xcf, 0xd3, 0x2f, 0xa0, 0xad, 0xb4, 0x3f, 0xc7, 0x30, 0x92, 0xf0,
+    0x3b, 0x49, 0x5d, 0xa2, 0x5c, 0xd2, 0x39, 0x45, 0x2f, 0xe8, 0xad, 0xfc,
+    0xa6, 0x3f, 0xed, 0x61, 0x3d, 0x0a, 0x24, 0x1c, 0x02, 0x78, 0x41, 0xda,
+    0xff, 0x02, 0xaa, 0xcf, 0xb1, 0xf3, 0xa3, 0xae, 0x72, 0xff, 0xe2, 0x83,
+    0xfa, 0x92, 0xf6, 0xe3, 0x45, 0x8a, 0xcb, 0x10, 0x74, 0x19, 0xdc, 0x97,
+    0x8d, 0x02, 0x75, 0x17, 0x0b, 0x05, 0x2f, 0x59, 0x62, 0x48, 0x61, 0xca,
+    0x18, 0x07, 0x65, 0x11, 0x8e, 0x63, 0xde, 0xd2, 0xaf, 0xb6, 0x66, 0xaf,
+    0xd1, 0x1f, 0xaf, 0x63, 0xe4, 0xc3, 0x50, 0xf1, 0xd0, 0x04, 0xc6, 0x3b,
+    0x66, 0xc9, 0xd6, 0x25, 0xe2, 0xe7, 0xfa, 0xdf, 0xca, 0x26, 0xde, 0x2f,
+    0xdc, 0xf9, 0x33, 0x13, 0x72, 0xa8, 0x9e, 0x6c, 0x18, 0x09, 0xc1, 0x39,
+    0x1a, 0x6e, 0x81, 0x80, 0x4f, 0x2c, 0xde, 0xb3, 0xae, 0xf2, 0xf6, 0xbe,
+    0xa5, 0xed, 0x7d, 0x66, 0xac, 0xd0, 0x63, 0xba, 0x74, 0x9a, 0x4e, 0xe7,
+    0x18, 0x71, 0x4d, 0xf0, 0xfb, 0x72, 0x49, 0x13, 0x72, 0x6b, 0x00, 0xf3,
+    0x6e, 0xc8, 0x76, 0x3a, 0xf2, 0xba, 0x5b, 0xf8, 0xd8, 0x70, 0x8a, 0x1a,
+    0x16, 0x7e, 0x43, 0x41, 0xde, 0x02, 0x50, 0x23, 0x70, 0xa5, 0x90, 0x2b,
+    0x22, 0x97, 0xc1, 0xf2, 0xb9, 0xe9, 0xa9, 0x43, 0xb0, 0x43, 0xf9, 0x37,
+    0x8c, 0x6a, 0x86, 0x49, 0x13, 0xca, 0x03, 0xc1, 0x32, 0x68, 0x1d, 0xd3,
+    0x2e, 0x9b, 0x6f, 0x51, 0xb8, 0x46, 0x19, 0x51, 0x34, 0x64, 0xd0, 0x62,
+    0x23, 0xf1, 0x7c, 0x46, 0x60, 0xdf, 0xca, 0xd6, 0x6a, 0xf3, 0x9e, 0x20,
+    0x00, 0xd1, 0x94, 0xa8, 0x04, 0xb0, 0xf0, 0x41, 0xf3, 0xd6, 0xad, 0xb3,
+    0x8a, 0x30, 0xb3, 0x4a, 0x53, 0x11, 0x8d, 0x1b, 0xd0, 0x0f, 0xc5, 0x97,
+    0xd0, 0x20, 0x4f, 0x4b, 0x36, 0xe2, 0x06, 0x14, 0xd9, 0xa0, 0x18, 0x78,
+    0x05, 0x02, 0x23, 0x09, 0xcf, 0xe3, 0xfa, 0x0a, 0x66, 0x71, 0xf6, 0xe0,
+    0xf1, 0xc0, 0xc5, 0xa0, 0xa7, 0xff, 0xb5, 0xca, 0x89, 0x2d, 0x3c, 0x67,
+    0x3f, 0x37, 0x80, 0xce, 0x59, 0x5f, 0x3f, 0xa8, 0x4b, 0xa6, 0xcd, 0x0a,
+    0x65, 0x1a, 0x25, 0x13, 0x18, 0x5e, 0xb2, 0x7b, 0x9f, 0x35, 0xc6, 0xc6,
+    0x45, 0x7b, 0x3b, 0x32, 0x8c, 0x04, 0xcc, 0x85, 0xe8, 0x68, 0xd2, 0x62,
+    0xed, 0xe7, 0x57, 0x18, 0xad, 0xda, 0xe1, 0xd9, 0x89, 0x09, 0x1f, 0x06,
+    0x79, 0x5e, 0x82, 0xcd, 0x80, 0x61, 0xb1, 0x0b, 0x8a, 0x24, 0x09, 0xc1,
+    0xe9, 0x4a, 0xac, 0x8d, 0xe7, 0x55, 0xcc, 0x55, 0x07, 0x7d, 0xdb, 0xbd,
+    0x8b, 0x29, 0x4e, 0x78, 0xfb, 0x46, 0x64, 0x94, 0xaf, 0xa1, 0x19, 0x6f,
+    0xcd, 0xbe, 0x72, 0x60, 0xe3, 0x55, 0xe1, 0xa5, 0x61, 0x83, 0xbb, 0xce,
+    0x8c, 0x62, 0xe3, 0x2e, 0x84, 0x1f, 0x3c, 0xdc, 0x03, 0xf4, 0x41, 0xab,
+    0x68, 0x63, 0xe3, 0x94, 0x8e, 0x1c, 0xe4, 0x80, 0xc6, 0xfb, 0x10, 0xb9,
+    0xaf, 0xee, 0xcd, 0xfe, 0xfa, 0x9c, 0x18, 0xd8, 0xbc, 0xd6, 0xe0, 0xa8,
+    0xe1, 0xfe, 0x78, 0x82, 0x0e, 0xd7, 0x0e, 0x80, 0xc9, 0x1f, 0x11, 0x5e,
+    0x57, 0x35, 0x41, 0xdb, 0x6c, 0x39, 0xdb, 0xda, 0xfc, 0xb3, 0x12, 0x26,
+    0x05, 0x9a, 0x01, 0xd4, 0x86, 0x4e, 0x60, 0x6a, 0x69, 0x72, 0xf1, 0x15,
+    0x9f, 0x63, 0xaf, 0x9b, 0xe7, 0x1c, 0xbc, 0x33, 0xde, 0x3b, 0x6a, 0x74,
+    0x8a, 0x9e, 0x74, 0x5c, 0xa0, 0x64, 0xc3, 0x01, 0xf1, 0x04, 0xef, 0xaf,
+    0x45, 0x52, 0x5b, 0xed, 0xb2, 0xf8, 0x80, 0xb9, 0xc6, 0x04, 0x40, 0x1e,
+    0x0b, 0xd0, 0x0f, 0xcf, 0x73, 0x2a, 0x65, 0xd2, 0xee, 0xcc, 0xdb, 0xe6,
+    0xe8, 0x84, 0xff, 0xda, 0xb1, 0x25, 0x3a, 0x14, 0x94, 0x67, 0x0e, 0x03,
+    0xdc, 0x93, 0xfe, 0x50, 0x19, 0x60, 0x61, 0xa5, 0xf3, 0xd2, 0x2d, 0x8e,
+    0x6b, 0xa2, 0xc5, 0x63, 0xa9, 0x99, 0x8e, 0xe7, 0x21, 0x5e, 0x08, 0x4c,
+    0xe5, 0x22, 0x66, 0x88, 0xc0, 0x7c, 0x0e, 0x5d, 0x97, 0xb2, 0x15, 0x30,
+    0xd5, 0xee, 0xd4, 0x25, 0x22, 0x82, 0x28, 0x64, 0xc9, 0x96, 0x12, 0x46,
+    0x53, 0xcb, 0xa1, 0xb7, 0x38, 0xe2, 0x8e, 0x52, 0x5a, 0x03, 0x1e, 0xf4,
+    0x4a, 0xb2, 0x8e, 0x77, 0xfa, 0x6b, 0xe6, 0x8c, 0x12, 0xc3, 0x4d, 0x12,
+    0x87, 0xc1, 0x78, 0x29, 0xfa, 0x86, 0xd9, 0xe0, 0xbc, 0x10, 0x87, 0xc6,
+    0x42, 0x13, 0x8d, 0x19, 0x0f, 0x02, 0x4f, 0x56, 0xac, 0xb3, 0xce, 0x6a,
+    0x84, 0xb9, 0x39, 0x59, 0x26, 0x23, 0xe0, 0xcf, 0x72, 0x2e, 0xb9, 0xa2,
+    0xda, 0x32, 0x18, 0x77, 0x12, 0xc9, 0xc1, 0x95, 0x80, 0x93, 0x93, 0xac,
+    0x2d, 0xdf, 0x4c, 0xc2, 0x53, 0x0d, 0xa3, 0x2c, 0xac, 0x3e, 0xfe, 0x72,
+    0xdb, 0xf6, 0x20, 0x80, 0x21, 0xbd, 0x98, 0x71, 0x5d, 0x21, 0xf3, 0x45,
+    0x64, 0x71, 0x0b, 0xb0, 0x33, 0x40, 0xa3, 0x33, 0x57, 0xe5, 0x96, 0x87,
+    0xc4, 0xec, 0x80, 0x90, 0x1d, 0xfb, 0x31, 0x73, 0x5d, 0x7f, 0x70, 0xb3,
+    0x61, 0xa4, 0x8b, 0x3c, 0xc8, 0x44, 0x4d, 0x09, 0xb2, 0x32, 0x74, 0x3e,
+    0xa0, 0xaf, 0xd7, 0x66, 0xe8, 0xd0, 0xb1, 0xc3, 0xa8, 0x81, 0xbc, 0x70,
+    0xe8, 0x6e, 0x68, 0x89, 0x14, 0xaf, 0x8f, 0x4b, 0x60, 0xae, 0x6a, 0xcd,
+    0xa8, 0xbc, 0xd7, 0xbd, 0x35, 0x15, 0xbc, 0xcb, 0x9c, 0x84, 0x27, 0x86,
+    0x69, 0xe5, 0x09, 0x21, 0xf6, 0xa4, 0xd9, 0xaf, 0x33, 0x48, 0x84, 0x93,
+    0x91, 0x24, 0x96, 0xe5, 0x4c, 0x78, 0xee, 0xec, 0x79, 0x5b, 0x0a, 0x3c,
+    0xa8, 0x62, 0xe9, 0xa9, 0x68, 0x21, 0x2c, 0x6a, 0x48, 0x4a, 0x17, 0x19,
+    0x60, 0x65, 0xa5, 0x0c, 0x97, 0xd4, 0xc9, 0xde, 0x56, 0xe9, 0xf0, 0xf7,
+    0x56, 0x57, 0x6c, 0x8e, 0x3e, 0xf6, 0x52, 0xe1, 0x86, 0x42, 0x80, 0x01,
+    0x80, 0xa1, 0x28, 0x64, 0x32, 0x8f, 0x80, 0xf3, 0x7d, 0xa2, 0x97, 0x84,
+    0x82, 0xe7, 0x91, 0x41, 0x92, 0x08, 0xe6, 0x02, 0x69, 0x37, 0xfe, 0xcd,
+    0xa2, 0x85, 0xfa, 0xb7, 0x64, 0xab, 0x78, 0x95, 0xb4, 0x85, 0x44, 0x28,
+    0xa5, 0xe5, 0xb8, 0xc0, 0x11, 0xac, 0x21, 0x5a, 0xd3, 0x98, 0x5e, 0x8a,
+    0x08, 0x60, 0x14, 0x0d, 0x53, 0xde, 0xce, 0x06, 0xd4, 0x37, 0xb1, 0x22,
+    0xe2, 0x68, 0x34, 0xc7, 0xc5, 0xa3, 0xf5, 0x1b, 0xce, 0xed, 0x45, 0x24,
+    0xd9, 0x4a, 0x08, 0xdd, 0x65, 0x07, 0x8b, 0xbf, 0x81, 0xda, 0x3b, 0x31,
+    0xdc, 0xb1, 0x7b, 0x3d, 0x8a, 0xb4, 0x74, 0x6e, 0xc8, 0xd4, 0x46, 0xd9,
+    0xb6, 0x97, 0x45, 0x3b, 0xa0, 0x24, 0x88, 0xc3, 0xc4, 0x1d, 0x58, 0xa5,
+    0xa7, 0xf0, 0x7c, 0xae, 0xd6, 0x77, 0x47, 0x7c, 0xe2, 0xb0, 0x18, 0xef,
+    0x2c, 0x35, 0x82, 0x8c, 0x89, 0x93, 0x76, 0x40, 0x52, 0xbc, 0xf1, 0xf9,
+    0x7f, 0x77, 0x03, 0x74, 0xdc, 0x12, 0xfd, 0x74, 0x2e, 0x16, 0xe6, 0x19,
+    0xd5, 0xe0, 0x8b, 0x06, 0x4b, 0x99, 0x1f, 0x68, 0x3c, 0xd1, 0xbe, 0xe8,
+    0x9c, 0xf7, 0xb5, 0x9d, 0x17, 0x1f, 0xaf, 0x47, 0xc5, 0x38, 0x92, 0x2c,
+    0x1b, 0x54, 0x6f, 0x2b, 0x1d, 0x09, 0xeb, 0x4d, 0x89, 0x8e, 0x32, 0xe7,
+    0x59, 0x84, 0x91, 0xfd, 0x57, 0xd9, 0x79, 0x4f, 0x8a, 0xdb, 0xc3, 0x3a,
+    0x09, 0xe0, 0x07, 0x36, 0xdd, 0x93, 0x94, 0x1e, 0x69, 0x6b, 0xe1, 0x31,
+    0xae, 0x72, 0xed, 0x66, 0x80, 0x06, 0x1b, 0x4a, 0x45, 0xdc, 0xbc, 0xdc,
+    0x93, 0x44, 0xce, 0xf4, 0x01, 0xdc, 0x08, 0x73, 0x02, 0x32, 0xa3, 0xf0,
+    0x61, 0x9a, 0x50, 0x04, 0x3b, 0x28, 0xb3, 0x9a, 0xbf, 0xe7, 0x5c, 0x5a,
+    0x99, 0x4b, 0xf7, 0xff, 0x3b, 0x76, 0x7b, 0x7a, 0xcc, 0xcd, 0x49, 0xdf,
+    0x49, 0x48, 0xcc, 0x99, 0x34, 0x14, 0x07, 0xda, 0x06, 0xfb, 0x9d, 0x97,
+    0xc4, 0xd9, 0x2e, 0x25, 0x34, 0x63, 0x0c, 0x97, 0xce, 0xfa, 0x3b, 0xcf,
+    0x87, 0x18, 0xdd, 0xf7, 0x3f, 0x8b, 0xe1, 0x00, 0xcb, 0x61, 0x03, 0x2c,
+    0x38, 0xbc, 0x31, 0xdc, 0x80, 0xc4, 0x3f, 0xd5, 0x8c, 0x64, 0xe1, 0x09,
+    0x4e, 0x86, 0x59, 0xec, 0x85, 0x55, 0xf0, 0x3a, 0xa7, 0xae, 0xae, 0x02,
+    0xd1, 0x9c, 0x00, 0xc9, 0x20, 0x3e, 0x3c, 0x3f, 0x6e, 0x2e, 0xd9, 0x64,
+    0xb9, 0x0c, 0x82, 0x32, 0x81, 0xe7, 0x46, 0xf5, 0x72, 0xb5, 0x70, 0x5c,
+    0x4c, 0xaf, 0xda, 0xfc, 0x29, 0x07, 0x12, 0x3b, 0x09, 0xde, 0xd3, 0x29,
+    0x06, 0xa0, 0x66, 0x94, 0x72, 0xbe, 0xa0, 0x3f, 0xc3, 0xef, 0x4f, 0xf2,
+    0x77, 0x21, 0x37, 0x58, 0xd9, 0x62, 0x25, 0x08, 0x41, 0xf4, 0x47, 0xc4,
+    0xcb, 0xcb, 0xac, 0x63, 0x14, 0x12, 0xb6, 0xe8, 0xfa, 0xb7, 0x12, 0x6d,
+    0x41, 0xd1, 0x1c, 0x8c, 0x3b, 0x3d, 0x10, 0x20, 0xcb, 0xcb, 0x9c, 0xab,
+    0x1a, 0x27, 0xe1, 0x71, 0xce, 0x95, 0x67, 0x02, 0xe4, 0x8b, 0x90, 0xe2,
+    0x13, 0xb3, 0xb3, 0x0d, 0x33, 0xb3, 0xb3, 0x96, 0x7e, 0xb3, 0xb6, 0x89,
+    0x44, 0x94, 0x0a, 0x0c, 0xc0, 0xd6, 0xc3, 0xe9, 0x14, 0x19, 0x0a, 0xfb,
+    0xd0, 0x9d, 0x0a, 0x39, 0x61, 0xbe, 0xbb, 0x5f, 0xa4, 0xd4, 0xf8, 0xc4,
+    0x7c, 0x91, 0x18, 0xe8, 0x84, 0x46, 0x1f, 0x25, 0x29, 0x9c, 0xbb, 0xd4,
+    0x41, 0x9e, 0xdb, 0x04, 0x3b, 0xef, 0x46, 0x72, 0xc6, 0xdb, 0x40, 0x25,
+    0x92, 0x7c, 0x34, 0x68, 0x2b, 0x43, 0xbd, 0x4b, 0xfd, 0x8c, 0x51, 0xa2,
+    0xcd, 0x91, 0x3e, 0x7b, 0xfe, 0x67, 0xb7, 0x93, 0x5b, 0x62, 0x43, 0x25,
+    0x7f, 0xd2, 0x98, 0xd5, 0xfd, 0x63, 0x21, 0x2a, 0x18, 0x0d, 0x0a, 0x3d,
+    0xc6, 0x78, 0xe5, 0xd2, 0x92, 0xb1, 0x2a, 0x11, 0xd0, 0x9b, 0xa0, 0x4a,
+    0x54, 0x1a, 0x68, 0x04, 0xca, 0x18, 0x7a, 0xc0, 0x4b, 0xeb, 0x76, 0xc9,
+    0x81, 0x8e, 0x32, 0xb4, 0x5b, 0x50, 0xa0, 0x94, 0xe6, 0x80, 0xc9, 0x19,
+    0xf8, 0x26, 0x57, 0xef, 0xf7, 0x29, 0x71, 0x17, 0xfb, 0xeb, 0x85, 0xa8,
+    0xa8, 0x41, 0x5b, 0x26, 0x48, 0x51, 0x83, 0x4c, 0x89, 0x1b, 0xa1, 0x8e,
+    0x91, 0xf1, 0xe9, 0x8c, 0xff, 0xba, 0xee, 0xd7, 0x6b, 0x0f, 0xf5, 0x39,
+    0x60, 0x69, 0xda, 0xbc, 0x76, 0xd8, 0x15, 0x79, 0x9a, 0x79, 0x59, 0x54,
+    0xa5, 0x46, 0xb2, 0x65, 0x7e, 0x34, 0xd4, 0xc4, 0xf6, 0xc7, 0x98, 0x26,
+    0x39, 0x9c, 0x30, 0x18, 0xc0, 0x04, 0xac, 0xba, 0xca, 0x5f, 0xcd, 0x7b,
+    0x03, 0xd7, 0x0d, 0xa0, 0x71, 0xdd, 0x90, 0x86, 0x85, 0x5e, 0x44, 0xfc,
+    0xe3, 0x41, 0xf7, 0xc2, 0xd6, 0x6b, 0xee, 0xa5, 0x6b, 0x2f, 0x72, 0x18,
+    0xbb, 0xc8, 0x48, 0xa0, 0x26, 0x48, 0x9b, 0xca, 0xac, 0x6d, 0x73, 0x5a,
+    0x5d, 0x3d, 0xef, 0x97, 0xdc, 0x83, 0x4d, 0x47, 0x40, 0xee, 0x60, 0x85,
+    0x61, 0xf6, 0x23, 0x2c, 0x80, 0x7c, 0x45, 0x5b, 0x49, 0x91, 0x43, 0x0c,
+    0x50, 0x6c, 0xa2, 0x19, 0x0c, 0x03, 0x1f, 0xe7, 0x85, 0x15, 0x7f, 0x75,
+    0xb2, 0xf2, 0x64, 0x05, 0x1a, 0x28, 0xbc, 0xa9, 0x21, 0x97, 0x42, 0x86,
+    0x5e, 0x10, 0x01, 0xb9, 0x3c, 0x91, 0xfb, 0x95, 0x32, 0xde, 0x1a, 0xdd,
+    0x32, 0x09, 0x81, 0x94, 0x9d, 0xda, 0x12, 0xed, 0x5a, 0x53, 0x4a, 0xc8,
+    0xa2, 0xeb, 0xa8, 0x41, 0xcd, 0xaf, 0xfc, 0xe3, 0xb5, 0x89, 0x53, 0x90,
+    0x30, 0x22, 0x59, 0x0a, 0x00, 0xcb, 0x01, 0xf0, 0x49, 0xb3, 0x5b, 0x7f,
+    0x61, 0xc3, 0xc8, 0xee, 0xd9, 0x6d, 0xc8, 0xe1, 0x01, 0xa6, 0xe7, 0x26,
+    0x84, 0xe8, 0xc8, 0x9c, 0x20, 0x3e, 0x18, 0x2a, 0xb7, 0x15, 0xd6, 0x66,
+    0xb1, 0x51, 0x09, 0x20, 0xc1, 0x1a, 0x8b, 0x2d, 0x01, 0xdc, 0xac, 0xf6,
+    0x1f, 0x6a, 0x74, 0x58, 0x8f, 0x30, 0x61, 0x46, 0x0e, 0x04, 0x91, 0x73,
+    0x29, 0x08, 0x51, 0x0f, 0x92, 0x6f, 0x03, 0xaa, 0x88, 0x1d, 0x95, 0x57,
+    0x6e, 0xec, 0xc2, 0xf8, 0xae, 0x43, 0x50, 0x14, 0xa4, 0x18, 0x19, 0x50,
+    0x19, 0x08, 0x7c, 0x78, 0xde, 0xe7, 0xb3, 0x5e, 0x5c, 0x17, 0xde, 0xc0,
+    0x66, 0x90, 0xed, 0x65, 0xaa, 0x00, 0x4e, 0x85, 0x3c, 0x6c, 0x79, 0x20,
+    0x0d, 0x0f, 0xaa, 0x95, 0xa8, 0x5e, 0xb7, 0x8f, 0xbf, 0x3c, 0x07, 0x12,
+    0x11, 0x91, 0xbd, 0xa9, 0x1f, 0x31, 0xf3, 0xd7, 0x8a, 0x6c, 0xd2, 0xa9,
+    0xbd, 0x7d, 0xd1, 0x63, 0x39, 0x63, 0x64, 0x85, 0xe1, 0x94, 0xba, 0xb1,
+    0xb5, 0xc0, 0xf4, 0xe2, 0xf7, 0x7b, 0xab, 0xc3, 0x99, 0xee, 0x43, 0x23,
+    0x18, 0x80, 0x18, 0x50, 0xc3, 0xc0, 0x8e, 0x42, 0xf9, 0xef, 0xe5, 0xad,
+    0xe2, 0x6d, 0xd8, 0xb6, 0x2e, 0xde, 0x45, 0xa3, 0x21, 0x87, 0x97, 0x70,
+    0x33, 0xcb, 0xfa, 0xe6, 0x45, 0x7b, 0x46, 0x89, 0xf9, 0xa1, 0x2b, 0x09,
+    0x65, 0x28, 0x87, 0x9b, 0xb8, 0x79, 0x04, 0x69, 0x01, 0xda, 0xbd, 0x17,
+    0x7c, 0x84, 0x94, 0x23, 0x4b, 0x0a, 0x57, 0xe3, 0xf3, 0xed, 0x5d, 0x27,
+    0xcc, 0x12, 0xe4, 0x07, 0xd3, 0x01, 0x46, 0x49, 0x43, 0x26, 0xf4, 0x70,
+    0x85, 0x6b, 0x65, 0x9f, 0xaa, 0xa4, 0x88, 0x66, 0x20, 0x88, 0x44, 0x03,
+    0x4c, 0x32, 0xa0, 0xa2, 0x5c, 0x8f, 0xb4, 0x0d, 0x90, 0x1f, 0x39, 0x41,
+    0xfb, 0x48, 0x5c, 0x04, 0x70, 0xd9, 0x47, 0xec, 0x43, 0xae, 0x77, 0x33,
+    0x84, 0xda, 0x48, 0xa6, 0xbd, 0xed, 0x92, 0xca, 0x38, 0x60, 0x28, 0x80,
+    0x18, 0xd1, 0xa1, 0xd9, 0x46, 0xc7, 0xae, 0x2e, 0xcf, 0xd6, 0x4f, 0xb3,
+    0x3c, 0xb7, 0xd0, 0x01, 0x03, 0x31, 0x97, 0xda, 0xd5, 0xee, 0xd7, 0x26,
+    0x06, 0x12, 0xa5, 0xe8, 0x2f, 0xdf, 0x80, 0x18, 0xe2, 0x59, 0x64, 0xe1,
+    0x20, 0x10, 0xc8, 0x97, 0x92, 0x4b, 0xad, 0x54, 0x02, 0x12, 0xc3, 0xcd,
+    0x8a, 0x33, 0xc7, 0xf4, 0xfd, 0x4d, 0xeb, 0x6d, 0x4c, 0xa3, 0x34, 0x00,
+    0xf8, 0xa8, 0xc8, 0x21, 0x90, 0x43, 0x3f, 0xae, 0x7b, 0xaf, 0x37, 0x7a,
+    0x72, 0xc3, 0x47, 0xce, 0xbb, 0xbf, 0xd0, 0x80, 0x6e, 0x00, 0xd6, 0x71,
+    0x42, 0x92, 0x12, 0x9c, 0x62, 0x09, 0xc7, 0x3f, 0x62, 0x36, 0xd2, 0xfe,
+    0xff, 0xba, 0xb5, 0x08, 0x27, 0x88, 0x26, 0x86, 0x3b, 0xd4, 0x34, 0x8c,
+    0x08, 0xf8, 0x24, 0xb3, 0x46, 0x1b, 0x60, 0xf3, 0x86, 0x32, 0x90, 0x47,
+    0xb6, 0x92, 0x1f, 0x8b, 0xb6, 0xa1, 0x7a, 0x4e, 0x67, 0x04, 0x86, 0x51,
+    0xfa, 0x96, 0xb4, 0xba, 0xe3, 0xe3, 0x6a, 0x97, 0x0a, 0x02, 0x30, 0x0a,
+    0xd5, 0x08, 0x35, 0x42, 0x67, 0x00, 0xac, 0xa0, 0xd6, 0x6a, 0xcc, 0x52,
+    0xa3, 0xe5, 0xec, 0xb9, 0x9c, 0xcb, 0xce, 0x53, 0xca, 0x63, 0x97, 0x95,
+    0x91, 0x16, 0x6c, 0x65, 0x16, 0xcb, 0x6c, 0x3c, 0xa0, 0xa3, 0x34, 0x42,
+    0x29, 0x5e, 0x01, 0x5e, 0xf4, 0xd2, 0xe1, 0x32, 0x9e, 0x42, 0x12, 0x3f,
+    0x72, 0x3a, 0x8d, 0xe8, 0xab, 0x8b, 0x0a, 0x86, 0x29, 0x99, 0x00, 0xe3,
+    0x38, 0x9a, 0x34, 0x0c, 0xd0, 0xcb, 0x4a, 0x21, 0x11, 0xdc, 0x07, 0xad,
+    0x53, 0xe5, 0xb2, 0x30, 0x69, 0x13, 0x92, 0xc9, 0x64, 0xb3, 0x00, 0x35,
+    0x33, 0x4d, 0xc0, 0xca, 0x64, 0x3e, 0x08, 0x03, 0x3a, 0x38, 0xde, 0x0d,
+    0xd2, 0x96, 0xb7, 0xb7, 0xab, 0xc4, 0x9a, 0x26, 0x74, 0x27, 0xe9, 0xf1,
+    0x0a, 0xc3, 0x6f, 0x5a, 0x79, 0xd5, 0xf2, 0x92, 0xd5, 0x33, 0x30, 0x40,
+    0x41, 0x06, 0x81, 0x8d, 0xe1, 0xde, 0x9c, 0x8a, 0xbd, 0xb4, 0xb5, 0xc5,
+    0x82, 0x8b, 0xe3, 0xc3, 0xf3, 0x03, 0xd3, 0x84, 0xa2, 0xcc, 0x03, 0xed,
+    0x67, 0xe6, 0x20, 0x32, 0x94, 0x92, 0x18, 0x0e, 0x44, 0x61, 0x52, 0xaf,
+    0xb8, 0x51, 0x7c, 0xac, 0x20, 0x67, 0x2c, 0x3b, 0x90, 0xe1, 0x90, 0x99,
+    0x43, 0x24, 0x3d, 0x3f, 0x68, 0xad, 0xda, 0x91, 0x3e, 0x30, 0xc5, 0x2f,
+    0xf1, 0x50, 0x71, 0x45, 0xf0, 0x09, 0x4e, 0x34, 0xd2, 0x7d, 0x94, 0xb3,
+    0xe9, 0xbd, 0x44, 0x0d, 0x34, 0x18, 0x4f, 0xc4, 0x5c, 0xc3, 0x04, 0x3c,
+    0x9b, 0x08, 0xc5, 0x2d, 0x65, 0x23, 0x40, 0x64, 0xa5, 0xf4, 0x77, 0xfb,
+    0xbf, 0xca, 0x23, 0x89, 0x8d, 0x03, 0x4b, 0x40, 0xf6, 0xb4, 0x49, 0x39,
+    0x24, 0x7c, 0x4f, 0x79, 0xce, 0x13, 0x0b, 0x38, 0xc9, 0xbf, 0xc5, 0x94,
+    0x64, 0x07, 0xd0, 0x2d, 0xed, 0xe0, 0x30, 0x14, 0x68, 0xfd, 0x3f, 0x08,
+    0x42, 0x62, 0xa3, 0xd3, 0x1c, 0x88, 0x58, 0xe8, 0x8c, 0x9b, 0x22, 0x3c,
+    0x41, 0xa6, 0xa5, 0x7d, 0x1d, 0xbf, 0xc0, 0xf9, 0xf9, 0xbe, 0x78, 0x67,
+    0x0a, 0x2f, 0xbf, 0x39, 0xd4, 0xb2, 0x6f, 0x07, 0xcc, 0x09, 0xe5, 0x7d,
+    0x54, 0xfc, 0xbb, 0x30, 0xc6, 0x22, 0x66, 0x84, 0xf2, 0xb4, 0x8c, 0xa1,
+    0x74, 0xaf, 0x04, 0x8e, 0x73, 0x71, 0x1a, 0xf0, 0x67, 0xad, 0x8a, 0x18,
+    0xd0, 0xf1, 0x63, 0x95, 0xf4, 0xc7, 0xc4, 0x7e, 0x75, 0xb6, 0x12, 0xd8,
+    0xd4, 0xe7, 0x03, 0x11, 0xb2, 0x1e, 0x70, 0x8f, 0xb2, 0xbf, 0x18, 0x7b,
+    0xf8, 0x98, 0x97, 0xe1, 0xe7, 0x08, 0x0c, 0x6f, 0x55, 0x19, 0x94, 0xfa,
+    0xd5, 0x89, 0xb7, 0xdc, 0xf1, 0x2b, 0xc6, 0x4b, 0x32, 0x8c, 0x26, 0x26,
+    0x96, 0x72, 0x4d, 0x55, 0x3d, 0xba, 0x6e, 0xbc, 0xb6, 0x98, 0xe1, 0x9c,
+    0x6e, 0x18, 0x12, 0x84, 0xf1, 0x8d, 0x14, 0x0e, 0x5e, 0x01, 0xe2, 0x74,
+    0xf7, 0x4a, 0x55, 0xff, 0xb7, 0x3c, 0xe7, 0xfe, 0xd2, 0x97, 0xce, 0xed,
+    0xc6, 0xc6, 0xec, 0xfd, 0x89, 0xe9, 0x52, 0x26, 0x8b, 0x82, 0xfa, 0x44,
+    0x8c, 0x21, 0xbc, 0xa5, 0x79, 0x76, 0x5b, 0xb7, 0x93, 0x70, 0x56, 0xe0,
+    0x00, 0x48, 0x84, 0xee, 0x09, 0x17, 0x61, 0x46, 0x90, 0x44, 0x07, 0x32,
+    0x9c, 0xc7, 0x71, 0x56, 0x64, 0x67, 0x46, 0x3e, 0xbf, 0x93, 0xdf, 0x4e,
+    0xa6, 0x2c, 0x0a, 0x05, 0x0a, 0x6b, 0x15, 0x0f, 0xe9, 0x0d, 0xb6, 0xf0,
+    0xce, 0x0a, 0x32, 0xa1, 0x59, 0x11, 0xe3, 0xa6, 0xac, 0xe1, 0xb4, 0xc4,
+    0xbf, 0xcc, 0xac, 0x9d, 0xed, 0xe7, 0x34, 0x49, 0xf1, 0x26, 0xad, 0x58,
+    0xdb, 0xf1, 0xb5, 0x00, 0xa1, 0x05, 0xed, 0xb2, 0xe0, 0xc2, 0x96, 0x82,
+    0x05, 0xa4, 0x95, 0x59, 0x76, 0xbf, 0xe6, 0x96, 0xb8, 0xd0, 0x29, 0xe5,
+    0xad, 0x2b, 0x7b, 0x73, 0xb3, 0x2d, 0x01, 0x20, 0x4d, 0x12, 0x72, 0xdc,
+    0x92, 0x5d, 0x1c, 0x24, 0x2e, 0xb8, 0x33, 0x70, 0xe9, 0x41, 0x56, 0xaf,
+    0x9f, 0xeb, 0x1a, 0xa5, 0xae, 0x1a, 0x74, 0x68, 0x04, 0x24, 0xc0, 0x01,
+    0x38, 0x4e, 0xc8, 0xc9, 0x9f, 0x01, 0xc3, 0x39, 0xc3, 0xb5, 0x0c, 0xa3,
+    0xe2, 0xaa, 0x6e, 0xf0, 0x69, 0x07, 0xda, 0x17, 0xbf, 0x6a, 0xcd, 0x92,
+    0x26, 0x87, 0xd7, 0x87, 0xae, 0x0a, 0x3d, 0xf5, 0x87, 0xfc, 0x3b, 0x9c,
+    0xb1, 0xf2, 0xe8, 0x90, 0x12, 0x92, 0x27, 0xb9, 0x40, 0xea, 0xc5, 0x63,
+    0xab, 0xfe, 0xf3, 0xbe, 0x62, 0x07, 0xa2, 0x95, 0xf3, 0x47, 0x72, 0x1b,
+    0xd9, 0xaf, 0xd2, 0x2c, 0x51, 0x28, 0x8c, 0x9f, 0xcc, 0xe4, 0xfb, 0x83,
+    0x33, 0xdd, 0xba, 0xbe, 0xb4, 0xbb, 0x33, 0xf7, 0x4d, 0x8c, 0xe0, 0xb6,
+    0x41, 0xc9, 0x13, 0xc3, 0x72, 0xad, 0xd1, 0xd1, 0xed, 0x58, 0x16, 0xf9,
+    0xff, 0xde, 0xf5, 0x0b, 0xfb, 0x38, 0xbb, 0x1b, 0x8c, 0x1e, 0xdf, 0x9a,
+    0x5f, 0xd5, 0x8d, 0xb9, 0x8c, 0x60, 0x1c, 0xbc, 0xc2, 0x58, 0x44, 0x23,
+    0x94, 0x67, 0xf4, 0x1d, 0x27, 0x10, 0x46, 0xfb, 0x75, 0xa0, 0xc3, 0x22,
+    0x6d, 0x45, 0xc1, 0x94, 0xa6, 0xc5, 0x08, 0x7e, 0x30, 0x56, 0x7d, 0xb6,
+    0x59, 0xcd, 0x35, 0xfe, 0xcf, 0xfc, 0xf0, 0x1a, 0xe7, 0xb8, 0xf3, 0x04,
+    0x0c, 0xa7, 0x05, 0x09, 0xe0, 0x15, 0x86, 0x4e, 0x56, 0xce, 0xff, 0x8b,
+    0x6e, 0xed, 0x94, 0x26, 0x79, 0xa2, 0x12, 0xe4, 0x25, 0x38, 0x12, 0xce,
+    0xe7, 0x92, 0xfa, 0x6a, 0xaa, 0xb6, 0xa8, 0x84, 0x71, 0xd9, 0x9b, 0x72,
+    0xd9, 0x14, 0xb1, 0x66, 0x85, 0x09, 0x91, 0x29, 0xe5, 0xc9, 0x17, 0xa0,
+    0x09, 0xfa, 0x20, 0xa5, 0xc3, 0x66, 0x2e, 0x3b, 0x53, 0x59, 0xd1, 0x0c,
+    0x40, 0x5c, 0xd2, 0xf7, 0x95, 0x46, 0x53, 0x01, 0x10, 0x4e, 0x53, 0xfd,
+    0x46, 0xb7, 0x82, 0x6b, 0xe8, 0xea, 0x52, 0xc6, 0x9b, 0xe5, 0xa5, 0x88,
+    0x2a, 0xf0, 0x28, 0x23, 0x51, 0x99, 0x77, 0x00, 0x46, 0x77, 0x3c, 0x9a,
+    0xfa, 0x51, 0x28, 0xad, 0x8d, 0x13, 0x0d, 0xe9, 0x41, 0x1a, 0x12, 0x43,
+    0xee, 0x12, 0x28, 0xbb, 0x8e, 0xf6, 0x0e, 0x18, 0xc0, 0x57, 0x6f, 0x2d,
+    0x28, 0x32, 0x33, 0xf2, 0xa4, 0x06, 0xf2, 0x7b, 0xa3, 0xf1, 0x6b, 0x06,
+    0xcf, 0x23, 0x81, 0xe7, 0x90, 0xc5, 0xa8, 0xa9, 0x27, 0x64, 0x97, 0x44,
+    0xba, 0x07, 0x1a, 0x52, 0xc9, 0xa2, 0x97, 0x56, 0x19, 0xca, 0x2a, 0x7e,
+    0xd8, 0x92, 0x79, 0xbd, 0x7a, 0x0d, 0xf9, 0x61, 0x80, 0x9b, 0x83, 0x31,
+    0xa6, 0xa6, 0xe8, 0x32, 0x38, 0x40, 0x99, 0x81, 0x75, 0xd5, 0xa5, 0xd8,
+    0xbd, 0x0c, 0x71, 0xb8, 0x1c, 0xe5, 0x65, 0x99, 0x50, 0x09, 0x0c, 0xb3,
+    0xe2, 0x7b, 0x5a, 0xbc, 0x1c, 0x0d, 0x21, 0xa9, 0xc8, 0x33, 0x01, 0x2c,
+    0x64, 0x66, 0x6f, 0x49, 0xf4, 0xf8, 0xb7, 0x5a, 0x5f, 0xe8, 0x86, 0x10,
+    0xcc, 0x01, 0x08, 0xc6, 0x9e, 0x8b, 0xc8, 0x91, 0x47, 0x72, 0x22, 0x55,
+    0x83, 0xfb, 0xa5, 0xa7, 0x50, 0xd3, 0x4d, 0xcb, 0xd2, 0xa5, 0x96, 0x60,
+    0x35, 0x1e, 0x52, 0x00, 0xa3, 0x39, 0x23, 0xf6, 0x4c, 0x6d, 0x4b, 0x14,
+    0x96, 0xf9, 0xa9, 0x43, 0xd9, 0x80, 0x27, 0x6a, 0xf3, 0xa2, 0xcf, 0xc3,
+    0x19, 0x19, 0x4f, 0x2a, 0x69, 0x72, 0x32, 0x95, 0x65, 0x3e, 0x9b, 0xfa,
+    0x8e, 0x23, 0x36, 0x83, 0xb0, 0x71, 0xd4, 0x0d, 0x52, 0xaf, 0x99, 0x02,
+    0xf9, 0x7b, 0x20, 0x8c, 0x82, 0x33, 0x8e, 0x5d, 0xb1, 0x34, 0x18, 0x1c,
+    0x32, 0xad, 0x70, 0x4c, 0x88, 0x95, 0x1e, 0xc2, 0xf8, 0xda, 0x70, 0xe0,
+    0xc8, 0x62, 0xfc, 0xdc, 0xc8, 0x96, 0x02, 0x83, 0x41, 0x56, 0xbf, 0xc5,
+    0xfc, 0xba, 0xdc, 0x53, 0x94, 0x9c, 0x63, 0x38, 0x9c, 0x19, 0x29, 0x99,
+    0xa4, 0x60, 0x12, 0xac, 0x53, 0x6b, 0xcc, 0xb1, 0xc3, 0xca, 0x50, 0x24,
+    0x4f, 0x68, 0x12, 0x35, 0x53, 0x3b, 0xbe, 0xca, 0x08, 0x87, 0x79, 0x49,
+    0x20, 0xd5, 0x60, 0xea, 0x68, 0xc4, 0x50, 0xcb, 0x29, 0x50, 0xf7, 0x02,
+    0xfe, 0xba, 0x30, 0x35, 0x3e, 0x06, 0xf5, 0x86, 0x7c, 0x32, 0x22, 0x53,
+    0x24, 0xa2, 0x82, 0x33, 0x19, 0x3e, 0xc8, 0x35, 0xbb, 0x30, 0xd2, 0x05,
+    0x8b, 0x9f, 0xf0, 0x22, 0xdd, 0xa3, 0x22, 0x81, 0x48, 0x37, 0xda, 0x88,
+    0x20, 0xae, 0x96, 0x5c, 0xa1, 0xbd, 0x18, 0x49, 0xe6, 0xe6, 0x6b, 0xdb,
+    0xeb, 0x19, 0x06, 0x9c, 0xe8, 0x99, 0x11, 0x93, 0xc9, 0x7d, 0x42, 0xff,
+    0xe3, 0xa3, 0x00, 0x82, 0x88, 0x1e, 0x94, 0x67, 0x47, 0xe2, 0xd6, 0x5a,
+    0x64, 0xb2, 0x26, 0x40, 0xa1, 0xe9, 0xc2, 0x45, 0x33, 0x4a, 0x8a, 0x5f,
+    0x61, 0x3c, 0x11, 0x2d, 0x23, 0xa6, 0x9c, 0xe4, 0x8a, 0x17, 0xa0, 0x4f,
+    0xe2, 0xf8, 0xb8, 0xbc, 0xd1, 0x6a, 0x34, 0xa1, 0x94, 0x19, 0x32, 0x97,
+    0x80, 0xd5, 0x67, 0x26, 0x01, 0xce, 0x95, 0x41, 0xcb, 0x42, 0x8e, 0x50,
+    0x83, 0x0e, 0x70, 0x8d, 0xc0, 0x7a, 0xdc, 0x88, 0xa2, 0x48, 0x9c, 0xf2,
+    0x52, 0xfb, 0x6c, 0x49, 0x62, 0xec, 0xcd, 0xe1, 0x39, 0x06, 0xfb, 0x09,
+    0xf6, 0x8e, 0x84, 0x8e, 0xe9, 0x25, 0xb9, 0x39, 0x7e, 0x9c, 0xaf, 0x11,
+    0x1b, 0x04, 0xf9, 0x7d, 0x9a, 0x1a, 0x4a, 0xab, 0x00, 0xdb, 0xba, 0x4a,
+    0xe6, 0xd2, 0x6b, 0x9b, 0x85, 0xf2, 0xcc, 0x32, 0xab, 0xc7, 0x2d, 0x21,
+    0x59, 0x3a, 0xb0, 0x27, 0xbf, 0xc5, 0xf2, 0x7b, 0x3f, 0x43, 0x6c, 0xab,
+    0xbf, 0xd5, 0xe5, 0x2e, 0xcd, 0x4e, 0xbe, 0xe1, 0xc8, 0x3c, 0x96, 0x13,
+    0xed, 0x14, 0xe8, 0xf8, 0x81, 0x7c, 0x49, 0x06, 0x5b, 0xd1, 0xca, 0x45,
+    0x2f, 0x2a, 0x34, 0x2e, 0x03, 0xc5, 0x86, 0x64, 0x40, 0x8e, 0x1e, 0x80,
+    0x0d, 0x42, 0x14, 0x80, 0x6f, 0xb4, 0xc9, 0xe4, 0xf6, 0xed, 0xda, 0xd4,
+    0x45, 0x0d, 0x42, 0xc1, 0x76, 0xe2, 0xbb, 0xd1, 0x05, 0x66, 0x4a, 0xd4,
+    0xd1, 0xca, 0x85, 0xc8, 0xcb, 0xfb, 0x84, 0xa5, 0xca, 0x98, 0x8f, 0xbf,
+    0xcf, 0xc5, 0x71, 0x5f, 0xfe, 0xe6, 0x92, 0x56, 0x20, 0xa4, 0x34, 0x8a,
+    0x35, 0x7a, 0xaa, 0xa2, 0xb5, 0x79, 0xe1, 0x24, 0xa9, 0xee, 0xc3, 0x2c,
+    0x4d, 0x59, 0xa0, 0x41, 0xf5, 0x87, 0xa8, 0xa0, 0xeb, 0x02, 0xe9, 0xfd,
+    0xdf, 0x77, 0xbb, 0x72, 0xc4, 0x17, 0x9e, 0xdb, 0xe1, 0x18, 0x70, 0xca,
+    0x6a, 0x87, 0x24, 0x68, 0xb8, 0x80, 0x84, 0x94, 0xc1, 0xe7, 0xd5, 0x07,
+    0xde, 0xd4, 0xdc, 0xce, 0x2a, 0xde, 0x74, 0xb8, 0xd9, 0xfd, 0x5a, 0x0f,
+    0x91, 0x9a, 0x70, 0x8a, 0x34, 0x0a, 0xc9, 0x5f, 0x88, 0x28, 0xf9, 0x3a,
+    0x79, 0xd6, 0xee, 0x4c, 0x82, 0xa4, 0x97, 0x24, 0x4a, 0x43, 0x2b, 0x25,
+    0xf5, 0x55, 0xcb, 0x6f, 0x23, 0xb1, 0x2c, 0x9a, 0x43, 0xe6, 0x9e, 0xe1,
+    0x70, 0x77, 0x07, 0x09, 0x14, 0x9c, 0x00, 0x5e, 0xb9, 0x22, 0x28, 0xd7,
+    0xf9, 0x41, 0xe6, 0x13, 0xa6, 0x2b, 0x73, 0x5a, 0x4f, 0x6b, 0x98, 0x39,
+    0xba, 0xf8, 0xa7, 0xfc, 0x07, 0x1d, 0xbf, 0x69, 0xcc, 0x00, 0xd1, 0x66,
+    0xa6, 0x41, 0x00, 0x91, 0x41, 0x1e, 0xe0, 0x07, 0xcb, 0x16, 0xfe, 0xc6,
+    0xe6, 0xd5, 0x54, 0xb4, 0x51, 0x4e, 0xf7, 0x2a, 0xb4, 0x86, 0xa0, 0x77,
+    0xb8, 0x2b, 0xf2, 0x41, 0x2f, 0xb2, 0x03, 0xc0, 0x7a, 0x92, 0x7b, 0xcb,
+    0xd5, 0x9a, 0x65, 0xd2, 0x37, 0x80, 0xbe, 0xdc, 0x4e, 0x0c, 0x3e, 0xaa,
+    0x86, 0xef, 0x86, 0x01, 0xa8, 0x77, 0x36, 0xd7, 0xf2, 0xf5, 0xb9, 0xeb,
+    0xd8, 0x6e, 0x5e, 0x12, 0x5d, 0xfc, 0xf7, 0x93, 0xb6, 0x91, 0xbc, 0x00,
+    0x04, 0x67, 0x97, 0xf7, 0x37, 0xac, 0x3b, 0x81, 0xbe, 0xab, 0x3e, 0xfa,
+    0x92, 0x67, 0xb1, 0x60, 0x4e, 0xf4, 0x64, 0x27, 0x08, 0x08, 0x32, 0x40,
+    0x9a, 0x3e, 0x2c, 0x4c, 0x9a, 0x53, 0x45, 0xcc, 0xe1, 0xfa, 0x70, 0xda,
+    0x8c, 0x00, 0x49, 0x6d, 0x0e, 0x4b, 0x22, 0xf6, 0x7f, 0xd1, 0x49, 0x37,
+    0xa0, 0x28, 0x48, 0x5e, 0xa4, 0xc5, 0x76, 0xb8, 0x86, 0x1a, 0xa5, 0x34,
+    0xe6, 0x0a, 0x25, 0x80, 0x48, 0x9f, 0x01, 0x25, 0xb3, 0xde, 0xf1, 0x0b,
+    0xaf, 0x6b, 0x22, 0x1c, 0x60, 0x1c, 0xc9, 0xa3, 0x17, 0x96, 0x19, 0xb2,
+    0x1b, 0xcb, 0xc2, 0x1d, 0xf6, 0x9f, 0xc2, 0x89, 0x99, 0xcd, 0x9b, 0x7f,
+    0x67, 0x7e, 0x39, 0xdf, 0x37, 0x9b, 0xd3, 0xf3, 0x7f, 0xfe, 0xb8, 0x34,
+    0xb0, 0xf0, 0x03, 0xbf, 0x33, 0x23, 0xa5, 0x01, 0x51, 0x28, 0x09, 0x90,
+    0x89, 0x78, 0x4f, 0xd0, 0x1c, 0xf6, 0x61, 0xc6, 0xb4, 0xd4, 0x08, 0x9d,
+    0x22, 0xcf, 0x08, 0xa4, 0x70, 0xc6, 0x79, 0x77, 0xa8, 0x15, 0xe9, 0x0d,
+    0x74, 0x0a, 0xc6, 0x04, 0xb0, 0x6f, 0x39, 0x80, 0x43, 0xcc, 0xa8, 0xfc,
+    0x5a, 0x32, 0xa0, 0x2a, 0xd6, 0x01, 0xb9, 0x41, 0xd1, 0xd8, 0x96, 0x5a,
+    0x07, 0x25, 0xf4, 0x5c, 0x48, 0x1f, 0x0b, 0x38, 0x4c, 0x2e, 0x15, 0x23,
+    0x32, 0xe2, 0xee, 0x7c, 0x7d, 0xf8, 0xa5, 0x89, 0xde, 0x89, 0x2f, 0xc7,
+    0x4d, 0xba, 0x2f, 0xfe, 0x48, 0x95, 0x19, 0x4e, 0x06, 0x64, 0x4e, 0x54,
+    0xfc, 0x0c, 0xf6, 0xc3, 0x5a, 0x17, 0xb0, 0x90, 0x9e, 0x52, 0x5c, 0xf2,
+    0x51, 0xa4, 0x15, 0xc5, 0xf2, 0x98, 0xce, 0x50, 0xfc, 0xef, 0x86, 0x91,
+    0x5b, 0x95, 0x23, 0x42, 0x48, 0xa3, 0x90, 0xea, 0xcb, 0x47, 0x98, 0xdf,
+    0xf2, 0xcc, 0xfc, 0x5b, 0x0d, 0xdc, 0x8e, 0x78, 0x86, 0x58, 0xf2, 0xed,
+    0xa0, 0x6a, 0xea, 0xe1, 0x51, 0xf1, 0x0c, 0xfb, 0x3a, 0x2c, 0x4e, 0x59,
+    0xec, 0x82, 0x32, 0x65, 0x93, 0xc2, 0xd9, 0xa4, 0x32, 0x72, 0x41, 0x91,
+    0x45, 0x23, 0x43, 0xc3, 0xab, 0x8a, 0xfb, 0xaf, 0x21, 0xc6, 0x42, 0x85,
+    0x61, 0x24, 0xcb, 0x25, 0x09, 0xf4, 0xf6, 0x54, 0x1e, 0x45, 0xe1, 0x42,
+    0x19, 0x49, 0x1c, 0x96, 0x11, 0x3c, 0x89, 0x2f, 0xf3, 0xa9, 0x48, 0x39,
+    0x02, 0x14, 0x50, 0x26, 0x8f, 0x64, 0x33, 0x85, 0x4f, 0x35, 0x85, 0xe7,
+    0xdd, 0x7f, 0x7d, 0xfb, 0xd9, 0xd4, 0x62, 0x06, 0x1a, 0x57, 0x10, 0xfe,
+    0x12, 0xc6, 0x9e, 0x26, 0xb6, 0x5d, 0x41, 0xde, 0x66, 0x1e, 0xcf, 0x32,
+    0x7b, 0x20, 0x4e, 0xec, 0xf1, 0x84, 0xb2, 0x28, 0x55, 0xd2, 0x4f, 0xcd,
+    0x23, 0xff, 0xcb, 0xd4, 0x96, 0x6a, 0x16, 0xc9, 0x1a, 0xd8, 0x02, 0x59,
+    0x7f, 0x06, 0x3e, 0x7d, 0xe1, 0x0f, 0x60, 0x79, 0xec, 0x1b, 0x41, 0x5f,
+    0x99, 0xb9, 0x65, 0x5d, 0x82, 0xbe, 0x2f, 0x97, 0x8f, 0xd2, 0xef, 0x0e,
+    0x32, 0xd7, 0xab, 0x65, 0xc5, 0xa1, 0x92, 0xf1, 0x74, 0x65, 0xf3, 0x00,
+    0xb1, 0xab, 0x54, 0x7f, 0x26, 0x43, 0x2c, 0x4e, 0xba, 0x6d, 0x83, 0xb9,
+    0x1a, 0x75, 0xec, 0x98, 0x6d, 0x1f, 0xa1, 0x37, 0xdb, 0xaa, 0x3e, 0xb4,
+    0x1a, 0xef, 0xe9, 0x4a, 0x7a, 0x76, 0xe3, 0x66, 0x0c, 0x92, 0xf5, 0x06,
+    0xcc, 0x39, 0x3d, 0x78, 0x84, 0x7a, 0x7e, 0xb0, 0x7d, 0xd5, 0xff, 0x20,
+    0x07, 0x08, 0x68, 0x35, 0xbf, 0x04, 0xd8, 0xc6, 0x59, 0x67, 0xec, 0xa4,
+    0x24, 0xfc, 0xce, 0x83, 0x4f, 0x44, 0x3e, 0xde, 0x86, 0xd4, 0x79, 0x9b,
+    0xb0, 0xaf, 0x98, 0x4c, 0xf2, 0xa8, 0xe0, 0x1f, 0x47, 0x83, 0x85, 0x12,
+    0xfb, 0x32, 0x01, 0x0a, 0x5a, 0xca, 0xc6, 0x92, 0x31, 0x8a, 0x45, 0x1a,
+    0x3f, 0x57, 0x1f, 0xb8, 0x96, 0xe1, 0xfd, 0x20, 0xc8, 0x98, 0x54, 0x56,
+    0x01, 0x27, 0x2a, 0x50, 0xcd, 0x0f, 0x9e, 0x36, 0xe2, 0x97, 0xae, 0x69,
+    0x36, 0x86, 0x5e, 0x54, 0xcc, 0x68, 0x69, 0x73, 0x32, 0xdb, 0x56, 0xbf,
+    0xfb, 0xa7, 0x66, 0x20, 0xd6, 0xcb, 0x06, 0x82, 0x07, 0x98, 0x46, 0x6f,
+    0xb9, 0x61, 0xbe, 0x3d, 0x57, 0x3d, 0xed, 0x8f, 0x50, 0x2e, 0x56, 0x2f,
+    0x37, 0x75, 0xed, 0x94, 0xc2, 0x72, 0x66, 0x91, 0x07, 0x95, 0xa5, 0x6d,
+    0xf1, 0xb5, 0xaf, 0x8e, 0xd8, 0xcb, 0x20, 0x1a, 0x44, 0x09, 0xbc, 0xd0,
+    0x13, 0x2c, 0x12, 0xb2, 0xa1, 0xf1, 0x3e, 0xda, 0x6b, 0x21, 0xad, 0x9d,
+    0x53, 0x59, 0x33, 0x6e, 0x1a, 0x50, 0xb0, 0xc3, 0x19, 0x55, 0x31, 0x00,
+    0x61, 0x7c, 0xa9, 0xe5, 0xf8, 0xb7, 0x7f, 0x2e, 0x8f, 0x9b, 0x6e, 0xd1,
+    0x3a, 0x1c, 0x66, 0xd0, 0x65, 0xc3, 0x04, 0xe6, 0xe6, 0xf0, 0x98, 0x09,
+    0x21, 0x95, 0xe2, 0x18, 0xa7, 0xb2, 0xbd, 0x90, 0x14, 0x05, 0x78, 0xcf,
+    0x21, 0x65, 0xa1, 0x93, 0x47, 0x09, 0x15, 0xbe, 0x1f, 0x92, 0xf0, 0x15,
+    0x32, 0x84, 0xd8, 0xe0, 0x22, 0x8c, 0xdc, 0xa3, 0x2f, 0x83, 0xf1, 0x43,
+    0x14, 0x4c, 0x7e, 0xe1, 0xa0, 0x18, 0xef, 0x5f, 0xa2, 0x1b, 0xe6, 0x66,
+    0x97, 0x2a, 0x3e, 0x2d, 0x7f, 0x80, 0x5a, 0x1b, 0xc7, 0x2e, 0x94, 0xdf,
+    0x17, 0xe0, 0xfe, 0x8a, 0x77, 0x05, 0xc3, 0x3c, 0x33, 0x28, 0xc2, 0x90,
+    0xc9, 0x66, 0x0a, 0x2a, 0x60, 0xa6, 0xec, 0x11, 0x9e, 0x54, 0xd2, 0x82,
+    0x5f, 0xdc, 0x10, 0x88, 0x5b, 0x24, 0x6f, 0x4f, 0x69, 0x4a, 0xf5, 0xb8,
+    0x5c, 0xac, 0xc6, 0xf7, 0x77, 0x35, 0x19, 0x81, 0x0a, 0x32, 0x0d, 0x92,
+    0x11, 0xa3, 0xf1, 0xa2, 0xc8, 0x99, 0x4c, 0xb9, 0x43, 0x2d, 0x28, 0x4a,
+    0xf5, 0x3e, 0x23, 0x36, 0x1d, 0xd1, 0xc3, 0x94, 0x87, 0xdc, 0x06, 0xfb,
+    0x07, 0x78, 0x60, 0xed, 0x05, 0x2c, 0x9f, 0x65, 0x0f, 0xe5, 0x09, 0x53,
+    0x9e, 0x84, 0x91, 0x66, 0x72, 0x4f, 0xc7, 0x1f, 0x05, 0xd6, 0x68, 0x7c,
+    0x58, 0xd0, 0xcc, 0xd0, 0xec, 0xc2, 0x86, 0x98, 0x51, 0x7c, 0xa6, 0xa3,
+    0x33, 0x56, 0xa1, 0x6f, 0xf1, 0xf8, 0x20, 0xcc, 0x48, 0xed, 0x46, 0xf2,
+    0x69, 0x72, 0xf1, 0x72, 0x39, 0x69, 0x09, 0xde, 0x33, 0xf1, 0x54, 0x2b,
+    0xcc, 0x4e, 0x3e, 0x52, 0x29, 0x11, 0xd8, 0x4f, 0x8f, 0x06, 0x60, 0xfd,
+    0xdd, 0x5d, 0x34, 0xae, 0x37, 0xe6, 0x5c, 0x5e, 0x75, 0xc1, 0xd3, 0xbe,
+    0x50, 0x24, 0xb6, 0xf7, 0x23, 0x87, 0xa5, 0xc3, 0x94, 0x12, 0xfc, 0x01,
+    0xf7, 0xfb, 0xfb, 0x3b, 0xbe, 0x9e, 0xea, 0xce, 0x5e, 0x2e, 0xf5, 0xba,
+    0x4f, 0x90, 0x5e, 0xa6, 0x8e, 0x4f, 0x4e, 0x84, 0x8d, 0x0f, 0x14, 0x61,
+    0xf6, 0xe9, 0xd5, 0x5e, 0x6b, 0x35, 0x5b, 0xea, 0xba, 0xd0, 0x3b, 0xd4,
+    0xb5, 0x33, 0x37, 0x63, 0xb7, 0x94, 0x98, 0x99, 0x4f, 0x2a, 0x7e, 0x3b,
+    0x48, 0x1c, 0xeb, 0xb4, 0xa6, 0x9e, 0x76, 0x2b, 0xc2, 0x89, 0x3b, 0xf8,
+    0x36, 0x55, 0xce, 0x57, 0x8d, 0xd0, 0x0b, 0xdd, 0x53, 0x34, 0xa0, 0x93,
+    0x01, 0xb1, 0x80, 0x25, 0xa5, 0x51, 0xf1, 0x3d, 0x3e, 0xbc, 0xb3, 0x56,
+    0x99, 0xb7, 0x12, 0xa1, 0x73, 0x23, 0x5f, 0x14, 0xf1, 0xb8, 0x83, 0x2e,
+    0x73, 0x84, 0xf8, 0x82, 0xb4, 0x54, 0xcb, 0x4c, 0x6b, 0xdb, 0xf3, 0xf1,
+    0x04, 0xad, 0x66, 0xb6, 0x7b, 0x9a, 0x25, 0x2c, 0x63, 0x80, 0xfb, 0x61,
+    0x8c, 0x0d, 0x1e, 0xe0, 0x4e, 0xfe, 0x37, 0x63, 0x1e, 0x7a, 0x86, 0xfe,
+    0xb7, 0x9d, 0x2b, 0x79, 0xd7, 0x9c, 0x0a, 0x0d, 0x35, 0x12, 0x40, 0x83,
+    0x49, 0x55, 0x8c, 0x3d, 0x3a, 0xfb, 0x4a, 0x3e, 0xb6, 0xb6, 0xbb, 0xed,
+    0x13, 0x6d, 0x2f, 0x9d, 0x95, 0x6e, 0xdc, 0xa9, 0x09, 0x9e, 0x7c, 0xfe,
+    0x9c, 0xd5, 0xdd, 0x9d, 0xf3, 0x9e, 0xcf, 0xcb, 0xb9, 0x7e, 0xd7, 0x16,
+    0xa2, 0x21, 0x08, 0x27, 0xa0, 0x8c, 0xb2, 0x20, 0x84, 0x6c, 0xee, 0xed,
+    0xd3, 0x85, 0xee, 0x7c, 0x6d, 0xc1, 0x18, 0xf4, 0x55, 0x42, 0xa2, 0x29,
+    0x55, 0x60, 0x27, 0xdb, 0xbd, 0x76, 0x26, 0x7a, 0x8f, 0x98, 0xcd, 0xa2,
+    0xe9, 0xa9, 0x1e, 0xd0, 0x08, 0x4c, 0x26, 0xa8, 0x44, 0x61, 0x89, 0xab,
+    0x01, 0xe1, 0xff, 0xb9, 0xbb, 0xc9, 0xc0, 0x14, 0xff, 0xfb, 0x38, 0xb7,
+    0xcd, 0x04, 0xa1, 0xe5, 0x81, 0x38, 0xd8, 0x0a, 0x14, 0x6a, 0xd7, 0xe9,
+    0x17, 0xb9, 0x25, 0xd0, 0xac, 0xff, 0x0b, 0xff, 0xb4, 0x60, 0xba, 0xbf,
+    0x14, 0x9d, 0xee, 0x9b, 0xb3, 0x5c, 0x36, 0xe1, 0x1b, 0x07, 0x70, 0xec,
+    0x25, 0x04, 0x03, 0x5e, 0x1d, 0x64, 0x4d, 0x3a, 0xb0, 0xdb, 0xab, 0x34,
+    0xf4, 0xff, 0xbc, 0xb0, 0xda, 0x45, 0xa4, 0x96, 0x4f, 0xd8, 0x9b, 0x81,
+    0x7f, 0xcd, 0x7e, 0xb6, 0xfb, 0x82, 0x4d, 0x88, 0x35, 0x25, 0x6c, 0x64,
+    0x17, 0x97, 0x02, 0x29, 0x14, 0x92, 0x11, 0xf3, 0x2f, 0xf5, 0x69, 0x5c,
+    0x40, 0x36, 0x9c, 0xf0, 0x29, 0xc3, 0x40, 0xb6, 0x58, 0x14, 0x27, 0x31,
+    0x42, 0x0a, 0xcd, 0x12, 0x7b, 0x83, 0x82, 0x79, 0x2d, 0x7f, 0x1d, 0x07,
+    0x43, 0x8e, 0x96, 0x8c, 0x98, 0xa0, 0xf3, 0xcf, 0x90, 0x4e, 0x1f, 0x77,
+    0x4a, 0x95, 0xaf, 0x3e, 0x8d, 0x81, 0x9f, 0x79, 0x66, 0x73, 0x92, 0x43,
+    0xb8, 0x07, 0x8b, 0xba, 0xc1, 0xaf, 0xbd, 0xee, 0x7f, 0x99, 0xbf, 0x1c,
+    0xde, 0x07, 0xac, 0xb2, 0x24, 0x83, 0xb2, 0x38, 0x76, 0xca, 0xf0, 0xdc,
+    0x5a, 0xf6, 0xf7, 0xfd, 0xdc, 0xb8, 0xc4, 0xf6, 0xc4, 0x50, 0xe3, 0x48,
+    0x11, 0x4e, 0x64, 0xbd, 0xa7, 0x2e, 0x73, 0x94, 0xaa, 0xc3, 0xe2, 0x3d,
+    0xec, 0x8f, 0xb7, 0xff, 0xe3, 0x30, 0xbe, 0x4e, 0x5d, 0x0d, 0xb1, 0xa1,
+    0xe9, 0xfb, 0x29, 0x07, 0xd8, 0x37, 0xd1, 0xd7, 0xea, 0x2e, 0x3f, 0x5c,
+    0x3a, 0xf0, 0xa9, 0x75, 0xd9, 0x5d, 0x54, 0xbf, 0x2f, 0x9e, 0x9d, 0x2b,
+    0x73, 0x97, 0xe1, 0x88, 0x5c, 0xe2, 0xe2, 0xa2, 0xd8, 0xe4, 0xbc, 0xe4,
+    0xa3, 0x0c, 0x30, 0x25, 0x77, 0x00, 0x88, 0xea, 0x97, 0x2b, 0xfe, 0xae,
+    0xdd, 0xdd, 0x6a, 0x16, 0x26, 0x40, 0xa9, 0xc4, 0x03, 0x2d, 0x89, 0x82,
+    0x06, 0x9a, 0x33, 0xbd, 0x3e, 0x20, 0x8e, 0xc5, 0x8b, 0x63, 0xda, 0xf5,
+    0xed, 0xaf, 0x83, 0xfd, 0xd8, 0x65, 0x62, 0x0e, 0xd2, 0x72, 0xa3, 0x0a,
+    0x1d, 0x90, 0xeb, 0x8e, 0xdd, 0xf7, 0x58, 0xdf, 0x8f, 0x65, 0xec, 0x3b,
+    0x5c, 0x18, 0x8c, 0xb6, 0x22, 0x4a, 0x7d, 0x63, 0x90, 0xc0, 0x9c, 0x3c,
+    0x9c, 0x65, 0x04, 0x7e, 0xc3, 0xe7, 0xa5, 0x12, 0x57, 0x96, 0x63, 0x31,
+    0xeb, 0xe6, 0x29, 0x9e, 0xdc, 0xab, 0x30, 0x3b, 0x18, 0x58, 0x38, 0x28,
+    0x20, 0x40, 0x3e, 0x01, 0x56, 0x41, 0xe2, 0xf2, 0x3f, 0x7b, 0xf3, 0x37,
+    0x60, 0x53, 0x14, 0xd6, 0x75, 0xe8, 0xb1, 0xfe, 0xb7, 0x06, 0x1b, 0x7c,
+    0x36, 0x36, 0xcc, 0x88, 0x94, 0xf5, 0x03, 0x89, 0x09, 0x42, 0x3e, 0x8b,
+    0x8d, 0x58, 0xfd, 0x5c, 0xcd, 0x2f, 0xd9, 0x96, 0xcd, 0xd7, 0x3d, 0x9d,
+    0x88, 0x13, 0x91, 0x16, 0x31, 0x38, 0xaf, 0x47, 0xb5, 0xbd, 0x88, 0x48,
+    0xfd, 0x2f, 0x39, 0xa5, 0xe0, 0x59, 0x31, 0x52, 0x99, 0xbf, 0x23, 0x72,
+    0x3b, 0xf5, 0xbb, 0xd7, 0xdd, 0xda, 0xa6, 0x26, 0x0d, 0x4c, 0x8d, 0x13,
+    0x93, 0xda, 0x52, 0x43, 0x22, 0x02, 0xa1, 0x66, 0xb8, 0x71, 0x7c, 0xad,
+    0x57, 0x9b, 0x65, 0x53, 0x2b, 0x32, 0xa7, 0x04, 0xd1, 0x0c, 0x8e, 0x34,
+    0xf2, 0xcf, 0x88, 0x3c, 0xd2, 0xd1, 0x9f, 0x17, 0xfd, 0x4e, 0x2d, 0xb7,
+    0x62, 0xac, 0x9d, 0xef, 0xb4, 0x96, 0x1b, 0x52, 0x94, 0x16, 0x69, 0xa6,
+    0x65, 0xa4, 0xac, 0x04, 0x94, 0x4f, 0x89, 0xd3, 0x7d, 0xde, 0xe1, 0xba,
+    0xd3, 0x2d, 0x8f, 0x05, 0x19, 0xa2, 0x89, 0x92, 0x3f, 0x10, 0xce, 0xb0,
+    0xf9, 0x5e, 0xfb, 0x3c, 0xb6, 0x59, 0xe5, 0xab, 0xb0, 0x21, 0x7d, 0xb3,
+    0x57, 0xf2, 0x82, 0xbf, 0x63, 0xce, 0x0c, 0x00, 0x16, 0x7e, 0xdb, 0x22,
+    0x0c, 0xb1, 0xa4, 0x72, 0x49, 0x1f, 0xb4, 0x4f, 0x51, 0xb0, 0xe9, 0xba,
+    0x69, 0xb7, 0x6a, 0xc8, 0xc4, 0x57, 0xfc, 0x94, 0xa1, 0xf4, 0x93, 0xd9,
+    0x02, 0xe3, 0xde, 0xde, 0x7f, 0x6a, 0x19, 0x52, 0xa2, 0xd0, 0xc1, 0x87,
+    0x40, 0xe3, 0x00, 0x52, 0xf6, 0x04, 0x85, 0x64, 0xc5, 0xd5, 0xa7, 0x98,
+    0x36, 0xea, 0x7c, 0xce, 0x84, 0x32, 0x93, 0x1c, 0x95, 0x06, 0x38, 0x4b,
+    0xe1, 0xa3, 0xf0, 0x22, 0x4f, 0x3e, 0xa4, 0x0c, 0x19, 0x2f, 0x70, 0x0b,
+    0x50, 0x8a, 0x9a, 0x2d, 0x87, 0x5f, 0xc6, 0xa8, 0x6c, 0xa8, 0xd7, 0xa1,
+    0x46, 0x02, 0xe8, 0x22, 0x4d, 0x01, 0x29, 0x19, 0x7c, 0xf2, 0xdf, 0xcd,
+    0xdc, 0xbb, 0xce, 0x11, 0x93, 0x4a, 0xca, 0x95, 0x58, 0x24, 0x6d, 0x7f,
+    0xf3, 0xd2, 0xdd, 0x16, 0xcb, 0x1f, 0x3c, 0xeb, 0xce, 0x8a, 0x24, 0x44,
+    0xb4, 0xfb, 0x12, 0x46, 0x61, 0x12, 0x32, 0x91, 0xab, 0x27, 0x49, 0x3f,
+    0x31, 0x13, 0xae, 0xba, 0x4f, 0x6f, 0x0a, 0x39, 0x7a, 0xc6, 0x9e, 0x43,
+    0x1f, 0x34, 0x56, 0x00, 0xf1, 0xad, 0x68, 0x63, 0xa5, 0x51, 0x03, 0x09,
+    0x38, 0xd9, 0x1e, 0xdf, 0xd8, 0x39, 0xd7, 0x07, 0x6c, 0x77, 0x51, 0xb8,
+    0x6a, 0xf6, 0x82, 0x3b, 0x46, 0x58, 0xd5, 0x69, 0xd1, 0xf7, 0xf3, 0xef,
+    0xb8, 0xf7, 0xb8, 0x7f, 0xc7, 0x7f, 0x8f, 0xeb, 0xb1, 0xe6, 0x3d, 0x1a,
+    0xcb, 0x0a, 0xc7, 0x0d, 0x3a, 0xbe, 0xb3, 0x2d, 0x00, 0x52, 0x89, 0x85,
+    0xf2, 0x08, 0x50, 0xad, 0xfc, 0x50, 0xa0, 0x25, 0x0f, 0x02, 0x78, 0x82,
+    0x9f, 0xf2, 0x56, 0x86, 0x81, 0x9b, 0xb9, 0x9e, 0x49, 0x23, 0xe2, 0xd3,
+    0x3b, 0x28, 0x9c, 0x32, 0x18, 0x07, 0xcf, 0x32, 0xbc, 0x2f, 0xe4, 0xa0,
+    0xbc, 0x68, 0x08, 0x94, 0x01, 0xe1, 0x0f, 0x33, 0x43, 0x27, 0xf1, 0x68,
+    0x8f, 0xb0, 0xcf, 0x3e, 0x27, 0x2d, 0xd4, 0xd3, 0x2f, 0x3e, 0x17, 0xa9,
+    0x49, 0xa6, 0x08, 0x9a, 0x04, 0xd0, 0xc8, 0xa4, 0xb9, 0xd6, 0x98, 0xdd,
+    0x37, 0xe2, 0x9c, 0xe7, 0x3c, 0x49, 0xc0, 0x58, 0xd4, 0x4e, 0x8e, 0x5f,
+    0xc7, 0xf5, 0x7e, 0x6f, 0xcb, 0x3c, 0x28, 0x4b, 0x58, 0x78, 0x00, 0xa0,
+    0x27, 0x94, 0x12, 0x87, 0x81, 0x67, 0x14, 0x10, 0x82, 0x89, 0xc9, 0xcc,
+    0x4e, 0x85, 0xdd, 0x5a, 0xeb, 0x11, 0xc9, 0x08, 0x28, 0xa9, 0x86, 0x39,
+    0x8c, 0x1b, 0x08, 0x16, 0xc7, 0xfb, 0xb4, 0xd3, 0x98, 0x9f, 0xd5, 0xe8,
+    0x3e, 0x41, 0x30, 0x4b, 0x2c, 0x29, 0x02, 0x4f, 0x81, 0xbf, 0xd1, 0xeb,
+    0x55, 0x7e, 0xc2, 0xcb, 0x84, 0xc1, 0x4f, 0x5c, 0xac, 0x59, 0x94, 0x94,
+    0xb7, 0x86, 0x7f, 0x31, 0xf6, 0xb8, 0xd7, 0x0b, 0x22, 0x7c, 0x47, 0x6c,
+    0xd0, 0xa8, 0xff, 0x6f, 0x82, 0x63, 0x17, 0x6c, 0xa8, 0x09, 0x48, 0x4b,
+    0xc1, 0xab, 0x50, 0xda, 0xa3, 0xaf, 0xfa, 0xe4, 0x2f, 0x7c, 0x83, 0xa4,
+    0x8e, 0xc0, 0xd5, 0xec, 0x70, 0xef, 0x24, 0x8e, 0xe1, 0x2f, 0x29, 0x64,
+    0xef, 0x58, 0xc2, 0xea, 0xf1, 0xe1, 0xb3, 0xce, 0xa9, 0xd4, 0x62, 0x89,
+    0x96, 0x42, 0x9c, 0xa6, 0x72, 0x21, 0x2c, 0xe0, 0xef, 0x9d, 0xbd, 0x6d,
+    0x7f, 0xf8, 0xa7, 0x5e, 0x0f, 0xb2, 0xcb, 0x61, 0x24, 0x51, 0x80, 0x91,
+    0x02, 0x54, 0x12, 0x33, 0xfa, 0x3b, 0x2a, 0x38, 0xb7, 0x97, 0xc0, 0x5b,
+    0x42, 0x8d, 0xed, 0xf8, 0xc8, 0x93, 0x96, 0x0c, 0x14, 0x72, 0xa7, 0x3b,
+    0xd6, 0xa3, 0xf7, 0xf9, 0xff, 0x79, 0xd9, 0x9b, 0x63, 0x83, 0xa4, 0x08,
+    0x67, 0x13, 0x48, 0xa5, 0xe3, 0x9a, 0x13, 0xee, 0x21, 0xab, 0x97, 0x69,
+    0xc3, 0xd0, 0xe8, 0x6b, 0x23, 0x44, 0x23, 0x7b, 0x47, 0x0e, 0x0a, 0x52,
+    0x47, 0xed, 0x2e, 0xe2, 0x5c, 0x6e, 0x75, 0x68, 0xea, 0xf6, 0x02, 0x70,
+    0xf4, 0x86, 0x32, 0xe7, 0x34, 0x32, 0x11, 0xc9, 0xca, 0x85, 0x64, 0x3d,
+    0x2b, 0x5a, 0x80, 0x71, 0x0c, 0x09, 0x78, 0xa6, 0x11, 0xf1, 0x10, 0x4a,
+    0xac, 0x11, 0x03, 0x32, 0x7c, 0xca, 0x80, 0xba, 0x99, 0x92, 0xb2, 0xdd,
+    0x92, 0xfd, 0x33, 0xfb, 0x69, 0x6d, 0x45, 0x0b, 0x76, 0xb7, 0x03, 0x0c,
+    0x84, 0xa6, 0x52, 0x89, 0x22, 0x85, 0xe9, 0xc2, 0x14, 0xe4, 0x4d, 0xa5,
+    0x39, 0xe5, 0x05, 0x09, 0x81, 0x97, 0x0e, 0x52, 0x57, 0xc7, 0x3e, 0x8b,
+    0xec, 0x3d, 0x3d, 0x41, 0xb9, 0x41, 0x23, 0xb2, 0x61, 0x91, 0x9c, 0x25,
+    0x02, 0xe5, 0x1c, 0xa1, 0x3f, 0xb1, 0xab, 0x31, 0x45, 0xe8, 0x97, 0xdb,
+    0x97, 0x9d, 0x19, 0x40, 0x86, 0x5a, 0x43, 0x09, 0x2b, 0xd1, 0x14, 0x3e,
+    0x2e, 0x5f, 0xa6, 0xaa, 0x2c, 0x85, 0x10, 0x68, 0x20, 0x91, 0xf9, 0xc4,
+    0xa7, 0x3f, 0x98, 0x37, 0xa7, 0xe7, 0x82, 0xff, 0x18, 0xb4, 0x38, 0x71,
+    0x43, 0x00, 0x09, 0x59, 0x82, 0x4d, 0xad, 0xbf, 0x59, 0xe7, 0x71, 0x0b,
+    0x09, 0x98, 0x34, 0xd8, 0xee, 0xe4, 0x19, 0x48, 0x37, 0x6a, 0x51, 0x95,
+    0x60, 0x0a, 0xb4, 0x39, 0x05, 0xc3, 0x21, 0x94, 0x8a, 0x18, 0x0a, 0x11,
+    0xa0, 0x04, 0x4c, 0xde, 0xad, 0xe3, 0x5c, 0xe3, 0x5e, 0x5b, 0xa3, 0xba,
+    0x46, 0xbf, 0x63, 0xa1, 0x50, 0xf2, 0x0d, 0xe5, 0xd5, 0x4f, 0xc8, 0xf1,
+    0x5c, 0xde, 0xa2, 0x83, 0xec, 0xcf, 0x3d, 0x5e, 0xfe, 0x56, 0xf3, 0xad,
+    0xe5, 0x57, 0x92, 0xc9, 0xa5, 0x25, 0x4d, 0x97, 0x22, 0x11, 0x67, 0x62,
+    0x4b, 0x46, 0x58, 0x97, 0xd0, 0x13, 0x6f, 0x7f, 0xa7, 0xe5, 0x62, 0xf3,
+    0xc3, 0x00, 0x95, 0x48, 0x69, 0x25, 0x81, 0x7f, 0xc1, 0xee, 0xb0, 0x58,
+    0x6d, 0x79, 0x9f, 0x53, 0x9e, 0xa8, 0xbb, 0x93, 0x90, 0xc2, 0x08, 0x0a,
+    0x22, 0x53, 0xab, 0x53, 0x26, 0x7c, 0xbc, 0x26, 0x9f, 0xe2, 0xc8, 0x78,
+    0x75, 0x3b, 0x08, 0x54, 0xf2, 0x86, 0x44, 0x63, 0x6c, 0x48, 0x9c, 0x67,
+    0xee, 0x3e, 0x01, 0xf0, 0xb6, 0x6c, 0x8d, 0xf9, 0x22, 0xb8, 0xbe, 0xfe,
+    0xb5, 0x7d, 0xda, 0x99, 0x7b, 0xa5, 0x3c, 0x60, 0x8d, 0x24, 0xb1, 0x40,
+    0xf7, 0x26, 0x7e, 0x2b, 0x40, 0x4f, 0x67, 0x4d, 0x90, 0xe6, 0x43, 0x7c,
+    0x53, 0x58, 0x2e, 0x09, 0x3d, 0x89, 0xff, 0xb7, 0x76, 0x5f, 0x8d, 0xf9,
+    0x85, 0x92, 0xe1, 0xbb, 0x50, 0x3b, 0x5e, 0x50, 0x46, 0x7d, 0xa3, 0x1a,
+    0x00, 0x7d, 0x85, 0xd1, 0xce, 0x62, 0x79, 0xf3, 0xaa, 0x93, 0x23, 0x39,
+    0xb8, 0x2a, 0x09, 0x13, 0x94, 0x32, 0x7e, 0x2e, 0xbb, 0x7d, 0x05, 0x4d,
+    0x25, 0x05, 0x53, 0xfd, 0x4d, 0xb8, 0x69, 0xe3, 0xb1, 0x6a, 0x8f, 0x44,
+    0x20, 0x46, 0x4e, 0x7e, 0x07, 0x57, 0x7e, 0xe5, 0xad, 0xfb, 0xcf, 0x79,
+    0xed, 0xd7, 0x09, 0x27, 0xaa, 0x0f, 0x5f, 0xd3, 0xd1, 0x0c, 0xc0, 0xc9,
+    0x95, 0xa9, 0x63, 0x0e, 0xe0, 0x43, 0xa4, 0x77, 0x40, 0xfc, 0xda, 0xa7,
+    0x7d, 0xb6, 0xd4, 0x35, 0xd9, 0x9e, 0x4f, 0x62, 0x45, 0x2b, 0x62, 0x84,
+    0x86, 0xe7, 0x07, 0x70, 0xbb, 0xef, 0x7e, 0x0b, 0x7e, 0xe3, 0xa3, 0xc0,
+    0x74, 0xc0, 0x1d, 0xf0, 0xe5, 0x18, 0x00, 0x08, 0x83, 0x40, 0xe5, 0xca,
+    0x58, 0x4b, 0x7c, 0x36, 0x76, 0x29, 0x65, 0x05, 0x49, 0xf7, 0xdf, 0xe5,
+    0x44, 0xe7, 0x71, 0x74, 0xe7, 0x83, 0x7b, 0x53, 0x0d, 0x3a, 0x78, 0xf2,
+    0x40, 0x22, 0x11, 0x4b, 0x97, 0x88, 0xae, 0xec, 0xa7, 0x3f, 0x21, 0x5a,
+    0x81, 0x9e, 0x9f, 0x4b, 0x7d, 0xb1, 0xa2, 0xa7, 0x08, 0x96, 0x70, 0x96,
+    0xc6, 0xb1, 0x6a, 0x36, 0xe2, 0x15, 0x75, 0xb0, 0xca, 0x95, 0x7e, 0x45,
+    0xc0, 0x45, 0xb2, 0xb4, 0x6b, 0xc3, 0x0c, 0x28, 0x25, 0x64, 0xfe, 0xa2,
+    0x15, 0x03, 0x3f, 0xaa, 0xde, 0xf2, 0xb5, 0xed, 0xe4, 0x03, 0x38, 0x37,
+    0xb2, 0x48, 0xa0, 0x8b, 0x60, 0x28, 0xcb, 0x2d, 0xa7, 0x84, 0x2e, 0x2d,
+    0xe3, 0x0a, 0x37, 0x36, 0xca, 0x1a, 0xaa, 0x03, 0xb4, 0x2f, 0xe5, 0xad,
+    0xf7, 0xc9, 0x0f, 0x8b, 0xab, 0x47, 0x66, 0xcb, 0x99, 0x83, 0x52, 0xc7,
+    0xa0, 0x96, 0x2a, 0xc3, 0x17, 0xbf, 0xe0, 0x62, 0xde, 0xe2, 0x1d, 0x21,
+    0x0b, 0x4f, 0x1d, 0x0c, 0x97, 0xda, 0x8b, 0xc2, 0x9e, 0xea, 0x1e, 0xd5,
+    0x88, 0x1b, 0x4e, 0xec, 0xca, 0xd0, 0x08, 0x0d, 0x20, 0x65, 0x29, 0x48,
+    0x7c, 0xc0, 0x9f, 0xce, 0x3a, 0xaf, 0xe2, 0x5b, 0xfd, 0xfc, 0xb7, 0x63,
+    0xbd, 0x6c, 0x40, 0x10, 0xab, 0xda, 0x72, 0xce, 0x88, 0xca, 0x1f, 0x6d,
+    0x49, 0x02, 0x76, 0x22, 0x5a, 0x27, 0xe2, 0x82, 0xa3, 0x9f, 0xdb, 0xdd,
+    0xa6, 0xfc, 0x09, 0xd6, 0xce, 0xec, 0xde, 0xe9, 0x34, 0xe0, 0x76, 0xa3,
+    0x33, 0x29, 0x83, 0x4d, 0xd0, 0x39, 0x04, 0x19, 0xdf, 0xb5, 0x4f, 0xd8,
+    0x29, 0xe5, 0x21, 0xba, 0x63, 0x67, 0x73, 0x40, 0x13, 0xbc, 0x3d, 0x39,
+    0x94, 0x21, 0x28, 0x43, 0x59, 0x13, 0xe2, 0x7b, 0xdc, 0xb8, 0x0e, 0x75,
+    0xdd, 0x96, 0x7d, 0x63, 0x52, 0xd9, 0x9b, 0x8d, 0xb1, 0xa0, 0x8f, 0x81,
+    0x7e, 0x5f, 0x67, 0xfe, 0xae, 0x20, 0x58, 0xb3, 0x54, 0xe1, 0x9c, 0x98,
+    0x3b, 0xed, 0x13, 0x2c, 0x47, 0x91, 0x38, 0x05, 0x0c, 0x24, 0x20, 0x03,
+    0xc7, 0x83, 0x2f, 0xde, 0x76, 0xd3, 0xa1, 0xfc, 0x83, 0x65, 0xc2, 0xae,
+    0xc6, 0x7f, 0xda, 0x0d, 0x68, 0xa1, 0x03, 0xce, 0x54, 0x75, 0x97, 0xe1,
+    0x46, 0x7c, 0xd7, 0x9b, 0x9e, 0x0f, 0xed, 0x17, 0xb1, 0xf9, 0x7a, 0x86,
+    0xc5, 0x54, 0x8b, 0xd3, 0x92, 0xac, 0x91, 0x83, 0x1e, 0xa2, 0x81, 0xcc,
+    0xe8, 0x94, 0x3e, 0xaf, 0x17, 0x33, 0x37, 0x2f, 0x2b, 0x1f, 0x88, 0x75,
+    0x27, 0x84, 0xda, 0x89, 0x72, 0x10, 0x9a, 0x13, 0x03, 0x19, 0x9e, 0x69,
+    0x1f, 0x03, 0x3a, 0xb4, 0x2b, 0xaf, 0x1c, 0xf4, 0x4e, 0xf4, 0x26, 0xc6,
+    0x14, 0x02, 0xf4, 0x4c, 0x2d, 0x90, 0xe5, 0x8c, 0x95, 0x8f, 0xf5, 0xf9,
+    0x1e, 0x38, 0x1f, 0xc7, 0x57, 0x45, 0xdd, 0xab, 0x14, 0x24, 0x1e, 0x16,
+    0xf3, 0x1c, 0x7b, 0xeb, 0x60, 0x3e, 0xa9, 0x75, 0xe4, 0xbd, 0xe7, 0xa7,
+    0x66, 0x72, 0x2e, 0xec, 0xa1, 0x6a, 0x9d, 0xc9, 0x3c, 0x79, 0xb4, 0x07,
+    0x95, 0x48, 0x88, 0x21, 0xa1, 0xf5, 0x33, 0x26, 0x34, 0x54, 0xf3, 0xc5,
+    0x44, 0x1a, 0x61, 0xea, 0x27, 0x82, 0x84, 0xe4, 0x7e, 0xa9, 0x06, 0x1e,
+    0x49, 0xc7, 0x1a, 0x62, 0x8c, 0x84, 0x33, 0x79, 0xcd, 0xa5, 0xb3, 0xb9,
+    0x4f, 0x1d, 0x1f, 0xab, 0x89, 0x3b, 0xbc, 0x08, 0x64, 0x78, 0x31, 0xd1,
+    0x9d, 0x5e, 0x60, 0x8a, 0x08, 0xf7, 0x31, 0xe7, 0xb3, 0x88, 0x65, 0x73,
+    0x01, 0x46, 0x02, 0x8c, 0xcc, 0xa4, 0x8a, 0x07, 0x2e, 0x59, 0x5f, 0x3c,
+    0x16, 0xcc, 0xda, 0x51, 0x69, 0x04, 0x20, 0xd5, 0x14, 0x8c, 0x26, 0x34,
+    0xbe, 0x39, 0x00, 0x8c, 0x60, 0xc6, 0x83, 0xd0, 0x93, 0x99, 0xf7, 0x29,
+    0x81, 0x0c, 0x31, 0x21, 0x0f, 0x32, 0xc7, 0x00, 0x48, 0x25, 0x9f, 0xb3,
+    0x84, 0x89, 0xe1, 0x3e, 0x90, 0xf8, 0x0d, 0x66, 0x4e, 0xed, 0xc5, 0x3e,
+    0xd3, 0x14, 0xce, 0x55, 0x3e, 0xf6, 0x0d, 0xc5, 0x6d, 0xe3, 0xad, 0x68,
+    0x8a, 0x07, 0x19, 0xf1, 0x8a, 0xca, 0x28, 0xf3, 0x6b, 0x54, 0x31, 0x97,
+    0x8c, 0xf2, 0x90, 0xc2, 0x17, 0xef, 0x13, 0x63, 0x8d, 0xbd, 0x29, 0x8a,
+    0x46, 0x48, 0x63, 0xe5, 0xa5, 0x65, 0xf8, 0x19, 0x92, 0xc5, 0x6d, 0x3a,
+    0x95, 0xd9, 0xce, 0xdc, 0x03, 0x01, 0x9c, 0x28, 0x55, 0x32, 0x49, 0x24,
+    0x0f, 0x39, 0x5d, 0x66, 0x55, 0xac, 0x5b, 0x4d, 0xc3, 0xa7, 0xe7, 0x70,
+    0x9c, 0x57, 0x42, 0xbc, 0x95, 0xa6, 0xa2, 0xc0, 0xa2, 0x4f, 0x64, 0xef,
+    0x38, 0x20, 0xce, 0x2a, 0x0b, 0xf1, 0x74, 0x7f, 0x6f, 0x94, 0xf7, 0xac,
+    0xa0, 0xaf, 0xd3, 0x97, 0xbc, 0xb5, 0x8a, 0x81, 0x18, 0xd8, 0x74, 0x28,
+    0x50, 0xf9, 0xfe, 0xdb, 0x69, 0x9a, 0xfc, 0xb5, 0x3a, 0xbc, 0xa2, 0x89,
+    0x74, 0xb3, 0x92, 0xf0, 0x05, 0x5f, 0xde, 0xd1, 0x0b, 0xea, 0xc1, 0x23,
+    0x31, 0x87, 0xed, 0x24, 0x67, 0x38, 0x00, 0x3f, 0x38, 0xde, 0xba, 0x70,
+    0xbc, 0x57, 0x90, 0x30, 0xa0, 0x66, 0x32, 0x53, 0x43, 0xb2, 0x78, 0x50,
+    0xf3, 0x28, 0x06, 0xf9, 0x94, 0xba, 0x7b, 0xbd, 0xf6, 0x7b, 0x6f, 0xfd,
+    0xce, 0x5f, 0xae, 0xc3, 0x1c, 0x3f, 0x4b, 0x66, 0x25, 0xa2, 0x27, 0x49,
+    0xe6, 0xed, 0x0a, 0x22, 0x84, 0xeb, 0x22, 0xf8, 0xf6, 0xb3, 0xf1, 0xdf,
+    0x9b, 0xa7, 0x17, 0x07, 0x28, 0xd3, 0xc4, 0x93, 0x46, 0x41, 0x06, 0x19,
+    0x39, 0x04, 0x7c, 0x41, 0x16, 0x66, 0xf0, 0x7b, 0x0a, 0x6e, 0x3b, 0xc7,
+    0x3a, 0xc9, 0x3e, 0x3d, 0x5d, 0x2f, 0x4d, 0xdd, 0xea, 0x14, 0x0e, 0x50,
+    0x22, 0x8e, 0x2e, 0x1f, 0x64, 0x4f, 0x0d, 0x58, 0x07, 0x37, 0x5d, 0x84,
+    0x45, 0x69, 0xdc, 0x43, 0xa8, 0x18, 0xd3, 0x92, 0x32, 0x42, 0x68, 0x1a,
+    0xb1, 0x4b, 0x16, 0x70, 0xab, 0x94, 0xa2, 0x89, 0xd6, 0xdc, 0xf7, 0x5f,
+    0xe0, 0x0f, 0xf6, 0xd7, 0x3a, 0xe6, 0x1e, 0x46, 0xca, 0x30, 0xa9, 0xa1,
+    0x90, 0x32, 0xa0, 0x5f, 0x88, 0x27, 0x41, 0x1f, 0xa8, 0x34, 0xd9, 0xe7,
+    0x49, 0x27, 0x68, 0xba, 0x5b, 0x1d, 0x75, 0x13, 0xc9, 0x9c, 0x96, 0x4f,
+    0xc1, 0x37, 0x39, 0xdf, 0xae, 0x4d, 0x6b, 0xe4, 0x84, 0x63, 0x11, 0xf1,
+    0x50, 0x08, 0xf8, 0xc8, 0x50, 0xb1, 0xbe, 0xdf, 0x52, 0x69, 0x89, 0x8a,
+    0x9d, 0xb9, 0x96, 0x30, 0x23, 0x22, 0x18, 0x43, 0x8a, 0xf4, 0xbb, 0x46,
+    0xed, 0x72, 0x67, 0x08, 0x5c, 0x7a, 0x9f, 0xa8, 0x18, 0xf8, 0xc1, 0x21,
+    0x34, 0x67, 0xe9, 0xfa, 0xad, 0xc8, 0x53, 0x18, 0x50, 0x12, 0xa1, 0x21,
+    0x33, 0x92, 0xf0, 0x89, 0xf5, 0x65, 0xfc, 0xba, 0x8a, 0x18, 0xba, 0xba,
+    0x66, 0x06, 0x3e, 0x64, 0x68, 0xb6, 0x83, 0xcf, 0x79, 0x75, 0xf9, 0x90,
+    0x86, 0x4b, 0xc5, 0x5f, 0xff, 0x6c, 0xa3, 0xab, 0x8a, 0x43, 0x28, 0xf4,
+    0x7d, 0x4e, 0x69, 0x13, 0x30, 0x32, 0xea, 0xf4, 0xea, 0xd8, 0xc7, 0xf4,
+    0xcb, 0xff, 0x4b, 0xd3, 0x8a, 0x36, 0x0c, 0xf0, 0x1f, 0x01, 0x4c, 0xd7,
+    0x41, 0x20, 0xc4, 0xde, 0xc7, 0xa5, 0x76, 0xf0, 0x65, 0xf3, 0x03, 0x10,
+    0x8e, 0xda, 0x7f, 0xd9, 0x89, 0x47, 0xce, 0x11, 0x88, 0x45, 0x36, 0x9d,
+    0x4c, 0x65, 0x5b, 0xea, 0xc5, 0xe5, 0x87, 0x75, 0x29, 0xd4, 0xff, 0x15,
+    0x4f, 0x7a, 0x3c, 0x4d, 0x07, 0x62, 0x8e, 0xab, 0x73, 0x26, 0x50, 0x02,
+    0xc6, 0x11, 0xf3, 0x34, 0x3b, 0x82, 0x52, 0xb1, 0xe1, 0x64, 0x9e, 0x9b,
+    0xff, 0x10, 0x40, 0x08, 0x0e, 0x34, 0x01, 0x33, 0x82, 0x6f, 0x4b, 0x46,
+    0x80, 0x42, 0xb2, 0xb1, 0x45, 0xdd, 0xed, 0x99, 0x39, 0x18, 0x28, 0xbc,
+    0xa8, 0xe1, 0xf1, 0x90, 0x4b, 0xfa, 0xf2, 0x6a, 0x9c, 0xa2, 0x06, 0xdc,
+    0xfe, 0x97, 0x20, 0x51, 0x24, 0xb8, 0x07, 0x1a, 0x1c, 0x7d, 0xa4, 0x7b,
+    0x68, 0x93, 0x9e, 0x2e, 0x4c, 0x3b, 0xd9, 0xae, 0x77, 0x97, 0x40, 0xd2,
+    0xd4, 0x92, 0x51, 0x39, 0x2a, 0x19, 0x10, 0x05, 0x91, 0xfc, 0x7f, 0x96,
+    0x34, 0x80, 0x4b, 0x8c, 0x0c, 0x61, 0x46, 0x8f, 0xd1, 0xf7, 0x62, 0xad,
+    0x6a, 0xfd, 0x78, 0xb9, 0x9d, 0x45, 0x8c, 0x95, 0x44, 0x21, 0xdc, 0x35,
+    0xa9, 0x92, 0x31, 0xb5, 0x06, 0x1a, 0x79, 0x46, 0x16, 0x28, 0x51, 0x4b,
+    0x48, 0x56, 0x68, 0x31, 0x45, 0x46, 0xcd, 0x05, 0x0a, 0x18, 0x7c, 0x9f,
+    0x64, 0xec, 0xb6, 0x6a, 0xf4, 0xed, 0x0f, 0x86, 0xd0, 0x28, 0x24, 0x5e,
+    0x86, 0x1c, 0xa5, 0x61, 0x03, 0x95, 0x39, 0x40, 0x17, 0xf9, 0x82, 0xd3,
+    0xf8, 0xc5, 0x2a, 0x8c, 0xde, 0x73, 0xc3, 0x7a, 0x7b, 0x91, 0x61, 0x86,
+    0x83, 0x09, 0xcf, 0xb0, 0x74, 0x3e, 0x7a, 0xc7, 0xe6, 0x76, 0x47, 0x2a,
+    0xf4, 0x7c, 0xe7, 0x0c, 0xc2, 0x63, 0x64, 0xc6, 0x57, 0x80, 0x17, 0x08,
+    0x14, 0x17, 0xe7, 0x21, 0xdb, 0x66, 0x54, 0x18, 0x88, 0x0b, 0x65, 0x42,
+    0x97, 0x46, 0x7d, 0x91, 0x26, 0x5e, 0x59, 0x3c, 0x48, 0x06, 0xbc, 0x20,
+    0x66, 0x89, 0x39, 0x64, 0xd6, 0x5a, 0x7a, 0x05, 0x10, 0x89, 0x44, 0x4a,
+    0x73, 0x98, 0x3e, 0x9f, 0xb0, 0xc3, 0x3c, 0xea, 0x77, 0x95, 0xc6, 0xc5,
+    0x5b, 0x08, 0x07, 0x2b, 0xaa, 0x63, 0x25, 0x4c, 0xf6, 0xa7, 0x08, 0xf9,
+    0x42, 0x4c, 0xc7, 0xa9, 0xe9, 0x58, 0x0a, 0x9e, 0x4a, 0x0e, 0xf6, 0x2b,
+    0xf5, 0x35, 0x20, 0x55, 0x65, 0x46, 0xda, 0x32, 0xdc, 0xb5, 0x29, 0x4a,
+    0x79, 0x2a, 0x1e, 0x20, 0xa3, 0x3f, 0xfb, 0x5c, 0xf7, 0xce, 0x5f, 0x3b,
+    0x96, 0xb9, 0x16, 0xf4, 0x6f, 0xe9, 0x5b, 0x63, 0x86, 0x85, 0xbe, 0x7f,
+    0xe8, 0x3b, 0x30, 0xdb, 0xc0, 0xd4, 0xeb, 0xf8, 0xcd, 0x40, 0x4e, 0x72,
+    0x1f, 0x37, 0x74, 0xb7, 0x28, 0x93, 0xe2, 0x0d, 0xdf, 0x5b, 0x9f, 0xa0,
+    0x1b, 0x82, 0x13, 0x2d, 0x52, 0x3b, 0xdd, 0x17, 0x32, 0x93, 0x36, 0x82,
+    0x5f, 0x68, 0x3c, 0x1d, 0xf3, 0x54, 0xcd, 0x2e, 0x24, 0x5f, 0xcb, 0x73,
+    0x5e, 0xf1, 0x31, 0xf7, 0xb5, 0x3d, 0x6c, 0x43, 0x65, 0x2a, 0x8d, 0xf9,
+    0x05, 0xb2, 0xa4, 0x67, 0x46, 0x50, 0x65, 0x8a, 0xb0, 0xcc, 0xbf, 0xea,
+    0xa5, 0x46, 0xfd, 0x39, 0xb7, 0x75, 0xa8, 0x8f, 0xd3, 0x91, 0x5a, 0x79,
+    0x98, 0x2b, 0x7b, 0xa3, 0x97, 0x49, 0xa1, 0x08, 0xb4, 0x62, 0x97, 0x58,
+    0x13, 0x9b, 0xef, 0x5e, 0x7e, 0xfd, 0x23, 0xf7, 0x6f, 0xf2, 0xfc, 0x79,
+    0x9f, 0x5a, 0x56, 0x33, 0x0d, 0x73, 0x67, 0x9a, 0x9b, 0xed, 0xc0, 0x30,
+    0xe2, 0xa3, 0x5e, 0x12, 0x91, 0x3f, 0x68, 0x95, 0xbf, 0x77, 0xfd, 0xd4,
+    0x4d, 0x8b, 0xd5, 0xf6, 0xb1, 0x4c, 0x95, 0xb7, 0x50, 0xba, 0xb5, 0xf1,
+    0x06, 0x33, 0xd2, 0x9b, 0x32, 0x8b, 0xb9, 0x34, 0x4b, 0xe3, 0x4c, 0x91,
+    0xdc, 0x27, 0xd7, 0xa9, 0x61, 0xe2, 0xfb, 0x41, 0xf7, 0xf6, 0xb9, 0x67,
+    0x3d, 0x38, 0x5a, 0xc7, 0xf5, 0x62, 0xae, 0x9b, 0x86, 0x65, 0x29, 0xa8,
+    0x90, 0x03, 0x3a, 0x27, 0x48, 0xe2, 0x63, 0x0c, 0xaf, 0xa8, 0x26, 0xfd,
+    0x8f, 0xee, 0xb7, 0x22, 0xa9, 0x97, 0x6d, 0x8b, 0xe7, 0x56, 0x56, 0xec,
+    0x50, 0x9d, 0x18, 0x20, 0x59, 0xc8, 0x4c, 0x9d, 0xe8, 0xfd, 0x86, 0x6e,
+    0xb9, 0xfd, 0xa6, 0x95, 0x30, 0x02, 0xa9, 0x4b, 0xb0, 0x83, 0x51, 0x8f,
+    0x6d, 0x00, 0x75, 0xd1, 0x37, 0x85, 0x47, 0xec, 0x75, 0xb3, 0xab, 0xb3,
+    0xf4, 0xd3, 0x62, 0x2d, 0x95, 0x0f, 0xe6, 0xd6, 0xbb, 0x49, 0xc2, 0x08,
+    0x77, 0x4b, 0x91, 0x18, 0xc2, 0xb3, 0x90, 0x99, 0x90, 0x81, 0x2b, 0xc9,
+    0xba, 0x79, 0xe3, 0xca, 0x1b, 0x71, 0x5a, 0x6d, 0xbc, 0xd9, 0x98, 0x92,
+    0xba, 0x7b, 0xe5, 0xeb, 0x9b, 0x29, 0xde, 0x6e, 0x85, 0x20, 0x10, 0x82,
+    0xb0, 0x0a, 0x73, 0x3a, 0xd1, 0xf6, 0x58, 0x5a, 0xd7, 0xc6, 0xb6, 0x29,
+    0x42, 0xca, 0x32, 0x3b, 0x04, 0xa2, 0xd4, 0x09, 0x93, 0xf6, 0xb9, 0x2a,
+    0x12, 0xfb, 0x52, 0x22, 0xfc, 0xbe, 0x66, 0xb3, 0x71, 0xd1, 0xdc, 0xe6,
+    0xf5, 0xd4, 0x09, 0xea, 0xd5, 0x57, 0x35, 0x1d, 0x00, 0x09, 0x44, 0xcc,
+    0x94, 0x65, 0x4a, 0x52, 0xee, 0x44, 0xb5, 0x26, 0xe3, 0x8c, 0xef, 0x61,
+    0x65, 0x73, 0x37, 0xed, 0x4b, 0x8c, 0xa4, 0x08, 0x32, 0x87, 0x21, 0xd1,
+    0x26, 0xad, 0xbf, 0xb4, 0xf6, 0x4e, 0x57, 0x4e, 0x53, 0xa2, 0xed, 0x3c,
+    0xdd, 0xda, 0x70, 0x93, 0xd3, 0x12, 0x9d, 0x69, 0x85, 0x02, 0x06, 0x3c,
+    0x27, 0x27, 0x0b, 0xc9, 0x21, 0xe0, 0x7f, 0xf6, 0xb1, 0x38, 0xe9, 0xbd,
+    0x22, 0x14, 0xd8, 0x83, 0x79, 0x36, 0x90, 0x08, 0x76, 0x50, 0xb0, 0xab,
+    0xc6, 0xd6, 0x75, 0xe5, 0x32, 0x3f, 0xcf, 0xc7, 0x05, 0x7e, 0x98, 0x9b,
+    0xe4, 0x1b, 0xda, 0x72, 0x06, 0xc2, 0x45, 0x5e, 0x9b, 0xf6, 0x6d, 0xcb,
+    0xe7, 0x82, 0x8c, 0xc7, 0xff, 0x56, 0xdc, 0xb2, 0x2f, 0xee, 0x6d, 0xe0,
+    0xd3, 0x5d, 0x87, 0xcc, 0x8a, 0xbc, 0xe3, 0xb5, 0xa3, 0xe9, 0xb2, 0x89,
+    0x82, 0x60, 0xb7, 0x73, 0x74, 0xb0, 0xf0, 0x3b, 0x28, 0x20, 0xb0, 0x1e,
+    0xe3, 0x3f, 0x8b, 0x7f, 0xf7, 0xf6, 0x43, 0x4d, 0x33, 0xb2, 0x02, 0x27,
+    0x4d, 0x8d, 0x80, 0xfc, 0xd1, 0xe0, 0x24, 0xe7, 0x82, 0xdf, 0xe9, 0x1c,
+    0x62, 0x34, 0xd2, 0x9b, 0xd1, 0x9a, 0x5f, 0x61, 0x6a, 0xd4, 0xd9, 0x8f,
+    0x5c, 0x8e, 0xa3, 0x19, 0x6b, 0xd2, 0xda, 0x16, 0x54, 0xc4, 0xf8, 0xb1,
+    0x95, 0x48, 0x3e, 0x26, 0x5c, 0x27, 0x1c, 0xf2, 0xd2, 0x0d, 0x36, 0x3f,
+    0x69, 0x9e, 0x6d, 0x81, 0x86, 0x1f, 0x50, 0xcd, 0xa9, 0x76, 0x08, 0xe1,
+    0xd3, 0xb0, 0xda, 0xfb, 0xd8, 0x5d, 0x93, 0xb1, 0x8e, 0x6d, 0x14, 0xed,
+    0xdf, 0xf7, 0x57, 0xff, 0xff, 0x8c, 0x4d, 0x15, 0x36, 0x21, 0x87, 0x64,
+    0xb0, 0x67, 0xe5, 0x89, 0x90, 0x9a, 0x26, 0x86, 0xa5, 0x2c, 0x20, 0xc3,
+    0xcd, 0x4b, 0x7c, 0x6c, 0xc0, 0xfa, 0x40, 0xca, 0x08, 0x65, 0xa3, 0x40,
+    0x31, 0x9a, 0x59, 0xfb, 0x46, 0xd7, 0xe7, 0xda, 0xa1, 0x46, 0x9b, 0x3c,
+    0x05, 0x40, 0x11, 0x5e, 0x7e, 0xd5, 0x8e, 0x58, 0xaf, 0x43, 0x0c, 0x86,
+    0x5f, 0x88, 0x37, 0x81, 0x4e, 0x7c, 0xea, 0xdf, 0x32, 0xde, 0x9d, 0x7f,
+    0x43, 0x1c, 0x15, 0x96, 0x10, 0xe4, 0xe8, 0x50, 0xab, 0x6f, 0x37, 0x6a,
+    0xf7, 0x6c, 0x68, 0x21, 0xda, 0x19, 0x5d, 0x2d, 0xc7, 0x9d, 0xcc, 0x88,
+    0x18, 0x8c, 0xe3, 0x00, 0x68, 0x05, 0x1c, 0xa2, 0x6a, 0xc3, 0xaf, 0xbd,
+    0xd1, 0xb3, 0xc5, 0xba, 0xa5, 0xb7, 0xc6, 0x91, 0xf3, 0x4f, 0x1c, 0xba,
+    0x10, 0x23, 0x21, 0x2a, 0x4e, 0xd8, 0xf9, 0x72, 0xf1, 0x3a, 0x7b, 0xab,
+    0x9c, 0x2d, 0xec, 0x6f, 0x2b, 0x15, 0xcb, 0x38, 0xa6, 0x60, 0x83, 0x5a,
+    0x08, 0x9d, 0xed, 0x67, 0xb5, 0x27, 0x2b, 0xb9, 0x0b, 0xa0, 0x8f, 0xf6,
+    0xfd, 0x68, 0x27, 0xe6, 0xbb, 0x6b, 0x53, 0x86, 0x30, 0x14, 0x1b, 0x89,
+    0x51, 0x39, 0x5b, 0x38, 0x60, 0xce, 0x8d, 0x65, 0xc7, 0x81, 0xbd, 0x5e,
+    0xd1, 0x08, 0xdd, 0x65, 0x15, 0x1d, 0xff, 0xfa, 0x86, 0x2d, 0x9c, 0x1d,
+    0xf3, 0x01, 0xc3, 0xc3, 0x38, 0x6a, 0x9a, 0x65, 0x38, 0xc2, 0x82, 0x38,
+    0xef, 0xe3, 0x70, 0xc2, 0xc9, 0xf3, 0xc3, 0x99, 0x75, 0x14, 0xa9, 0x85,
+    0x21, 0x5a, 0xd2, 0xd0, 0xd0, 0x4a, 0x26, 0x31, 0xc7, 0x90, 0xee, 0x41,
+    0x9a, 0x8f, 0xbf, 0x9d, 0xaf, 0x4b, 0x7b, 0x56, 0x23, 0x6e, 0xbf, 0x6b,
+    0x87, 0x1a, 0x56, 0x91, 0xe5, 0xec, 0xf9, 0xbe, 0xe1, 0x51, 0xaf, 0x50,
+    0xcb, 0xee, 0x4e, 0x33, 0xdf, 0xb3, 0xbe, 0x8e, 0xed, 0x7a, 0x47, 0x12,
+    0x0e, 0x28, 0xa8, 0xe3, 0x41, 0xb0, 0xdb, 0x12, 0xaf, 0x10, 0x0e, 0x32,
+    0x13, 0x99, 0xf9, 0xf0, 0xf5, 0x48, 0x61, 0xa2, 0xec, 0x3a, 0x8c, 0x5c,
+    0xa8, 0xab, 0xef, 0x77, 0xea, 0xe2, 0x8a, 0xc8, 0xb3, 0x8d, 0xcf, 0x70,
+    0xf0, 0x4d, 0x7e, 0x1c, 0xa2, 0x40, 0x6a, 0x28, 0x50, 0x3e, 0x29, 0x5f,
+    0x76, 0x05, 0x99, 0x90, 0x18, 0xf8, 0x48, 0xa8, 0xb5, 0x77, 0xd9, 0xb8,
+    0xd5, 0xba, 0x6a, 0x58, 0xdb, 0x83, 0x72, 0x62, 0xee, 0xfa, 0x70, 0x4b,
+    0x97, 0x4b, 0x45, 0x00, 0x68, 0xc1, 0x23, 0xdc, 0x09, 0xd8, 0x3c, 0xca,
+    0xb8, 0x73, 0xab, 0x6d, 0x6e, 0x27, 0x95, 0xcd, 0x42, 0x2f, 0x51, 0x2e,
+    0x70, 0x65, 0x1a, 0x06, 0x67, 0x1b, 0x09, 0xf6, 0xf0, 0x02, 0x40, 0x59,
+    0x3a, 0x77, 0x1b, 0x9d, 0x52, 0x3e, 0x46, 0xc7, 0x5a, 0x4e, 0xdc, 0xa6,
+    0x6e, 0x3f, 0x6c, 0xdc, 0x82, 0x1b, 0x16, 0x66, 0x43, 0x23, 0x32, 0xab,
+    0x27, 0x78, 0xb1, 0x5d, 0xad, 0x54, 0x48, 0x9a, 0x3e, 0x7b, 0x49, 0x60,
+    0x6d, 0x2d, 0xd9, 0xbf, 0x29, 0xa1, 0xa7, 0xb7, 0x34, 0x09, 0x94, 0xa0,
+    0x64, 0xbf, 0x04, 0xf7, 0x8f, 0x5b, 0x71, 0xfa, 0xa5, 0x9c, 0xdb, 0x43,
+    0x1c, 0x0c, 0x66, 0x7b, 0x21, 0xd3, 0xe3, 0x69, 0x6e, 0xf8, 0x67, 0x04,
+    0x3c, 0xb1, 0xa6, 0x7c, 0x57, 0xea, 0x83, 0x08, 0x45, 0x2e, 0x5d, 0x1a,
+    0x8d, 0x02, 0xe4, 0xe5, 0xfc, 0x61, 0x50, 0x61, 0x13, 0x9b, 0x6e, 0x54,
+    0x28, 0x0a, 0x09, 0xd7, 0x97, 0x2c, 0x72, 0x27, 0xb6, 0xa8, 0xe5, 0x43,
+    0x27, 0x29, 0xcf, 0xc4, 0x05, 0x2b, 0x78, 0xed, 0x69, 0xe0, 0x20, 0x48,
+    0x8c, 0x02, 0x5f, 0x40, 0x71, 0xfd, 0x39, 0xbe, 0x2f, 0xbb, 0xeb, 0xde,
+    0xbd, 0xb4, 0x2f, 0x97, 0xa0, 0xcc, 0xdb, 0xed, 0x1c, 0x73, 0x5e, 0x70,
+    0x32, 0xdf, 0x45, 0xcc, 0xf2, 0xbe, 0x80, 0xed, 0xf6, 0xce, 0x60, 0xeb,
+    0x66, 0x4a, 0x4b, 0x17, 0x87, 0xf1, 0x8c, 0x46, 0x0b, 0x5a, 0x74, 0x13,
+    0xcf, 0x51, 0x4c, 0xfa, 0x37, 0xb8, 0xe7, 0xf7, 0xf8, 0xbf, 0xb7, 0x0e,
+    0xee, 0x74, 0xff, 0x3e, 0x35, 0x0c, 0x3e, 0x5b, 0x64, 0x82, 0x27, 0x63,
+    0x27, 0x24, 0xa1, 0xf6, 0x0d, 0x99, 0xae, 0x3a, 0xe7, 0xe2, 0xf7, 0xdc,
+    0x47, 0x45, 0x00, 0x93, 0x0d, 0x9b, 0x37, 0xba, 0xce, 0x1c, 0x80, 0x44,
+    0x81, 0x4a, 0x28, 0x9a, 0xc1, 0xce, 0x2d, 0x49, 0xea, 0xe2, 0x73, 0xe7,
+    0xb0, 0x4c, 0xe3, 0x0d, 0x4e, 0xf7, 0x9a, 0x5c, 0x1d, 0xa0, 0xa2, 0xf4,
+    0x06, 0x12, 0x0f, 0x3d, 0x2d, 0x3f, 0xb7, 0xe5, 0xbf, 0xff, 0x60, 0x84,
+    0x94, 0x7a, 0xef, 0xce, 0xd2, 0x15, 0x1a, 0x80, 0x75, 0x18, 0x28, 0xb0,
+    0x9a, 0x08, 0x48, 0x43, 0x84, 0x6f, 0x83, 0xdb, 0xb0, 0xd0, 0x51, 0xf5,
+    0x15, 0x19, 0xc2, 0xc2, 0x53, 0xf9, 0xbf, 0x93, 0x37, 0xfc, 0xcb, 0x3a,
+    0x2f, 0x16, 0x6a, 0x54, 0x67, 0xa7, 0xa6, 0xe4, 0xd1, 0x25, 0xe0, 0x30,
+    0x06, 0x13, 0x00, 0x0a, 0x2e, 0x11, 0xf1, 0x33, 0x9e, 0xb4, 0xe7, 0x1c,
+    0xe3, 0x0c, 0x91, 0xfb, 0x52, 0x62, 0x46, 0xcd, 0xed, 0x77, 0x12, 0xff,
+    0x15, 0x7b, 0xd7, 0x3b, 0x22, 0xcd, 0xd7, 0xf4, 0x0c, 0xe1, 0x85, 0x68,
+    0x0a, 0x24, 0xd0, 0x07, 0x0e, 0xf5, 0x68, 0x5d, 0x55, 0xb5, 0xe3, 0x28,
+    0x68, 0x23, 0x40, 0xec, 0x0d, 0x94, 0x8c, 0xa8, 0x09, 0x77, 0x16, 0xe5,
+    0xab, 0xc5, 0xe8, 0x53, 0xe2, 0xc1, 0xce, 0x5c, 0xa9, 0x55, 0x10, 0xea,
+    0x9b, 0x3e, 0x8a, 0x1d, 0xae, 0x60, 0x1d, 0x09, 0xc7, 0xf7, 0xf5, 0xca,
+    0x92, 0x02, 0x5f, 0x35, 0x96, 0x74, 0x72, 0x85, 0x29, 0xf8, 0x04, 0x20,
+    0x70, 0xf7, 0xb9, 0x34, 0x46, 0x3a, 0xb2, 0x92, 0x05, 0x1f, 0xa3, 0x05,
+    0x5d, 0xb0, 0x10, 0x15, 0xbe, 0x01, 0x21, 0x03, 0x57, 0x46, 0xef, 0x43,
+    0x80, 0x10, 0xc9, 0x78, 0xf2, 0x33, 0x39, 0xd3, 0xc0, 0x6a, 0x92, 0xd9,
+    0x69, 0x22, 0xbf, 0xd9, 0xd1, 0xf4, 0xda, 0xb5, 0xe9, 0xe8, 0x65, 0x1a,
+    0x60, 0x3b, 0x19, 0xbd, 0x44, 0xe8, 0x89, 0x77, 0x28, 0xb9, 0xbb, 0xcd,
+    0x2d, 0xfb, 0x7b, 0xf0, 0x74, 0x32, 0xbf, 0x6f, 0x4c, 0x74, 0xf8, 0x0a,
+    0x0f, 0x31, 0x24, 0x51, 0xfa, 0x01, 0x51, 0xe3, 0x8d, 0x4f, 0xfe, 0x08,
+    0x8d, 0x02, 0xd8, 0x71, 0xa3, 0xfd, 0xc8, 0x19, 0x7b, 0xd1, 0x87, 0x6c,
+    0x72, 0x73, 0x7f, 0x9e, 0x31, 0xb7, 0xbf, 0xc3, 0x6f, 0xcf, 0xd3, 0xd9,
+    0x7a, 0x3a, 0x76, 0xc5, 0xe5, 0xb9, 0x7b, 0x20, 0x13, 0xa3, 0x2d, 0xa1,
+    0x7a, 0xa2, 0x60, 0x49, 0xfd, 0xba, 0x2f, 0x2c, 0xb9, 0x48, 0x49, 0xfe,
+    0x80, 0x8e, 0xc4, 0xd0, 0x96, 0x92, 0xf7, 0x0e, 0x4e, 0x6d, 0x8c, 0x32,
+    0x1a, 0x3f, 0x14, 0xf8, 0x2d, 0x63, 0x44, 0x1d, 0x1d, 0xba, 0xc2, 0xcc,
+    0xa6, 0x36, 0x8b, 0x48, 0xd5, 0xea, 0x8e, 0x87, 0xce, 0x0c, 0xfb, 0x46,
+    0x0e, 0xb9, 0xa4, 0x68, 0x0c, 0x9f, 0xa6, 0xb3, 0xfd, 0x39, 0xad, 0x69,
+    0x2e, 0x53, 0x48, 0x9c, 0x02, 0xac, 0x51, 0xd8, 0x19, 0x24, 0x82, 0x1e,
+    0x24, 0x91, 0x52, 0x0f, 0xba, 0x53, 0x25, 0x07, 0x0e, 0x83, 0xe0, 0x09,
+    0x72, 0xa2, 0x32, 0x2c, 0xee, 0x0e, 0x88, 0x5b, 0x42, 0x25, 0x3c, 0x69,
+    0xb7, 0xc5, 0x9a, 0x07, 0xc0, 0x6b, 0x94, 0x28, 0x01, 0x39, 0x34, 0xd1,
+    0xab, 0xf4, 0x32, 0x55, 0x82, 0x3c, 0x07, 0x2a, 0x11, 0x7a, 0x10, 0xc9,
+    0x55, 0xaa, 0x84, 0x39, 0xd8, 0x3c, 0x4e, 0x09, 0x65, 0xe9, 0x03, 0x39,
+    0xd0, 0xf1, 0x79, 0x70, 0x83, 0x07, 0x68, 0x72, 0x4f, 0x3f, 0x8e, 0x05,
+    0xe1, 0x41, 0xe4, 0xf8, 0x1b, 0xc6, 0x13, 0xd4, 0x95, 0xed, 0xe5, 0x2f,
+    0xab, 0x97, 0xaf, 0xa9, 0x6b, 0x59, 0x3c, 0x09, 0xe3, 0x3d, 0x26, 0xdb,
+    0x04, 0x72, 0x19, 0x05, 0x28, 0x1f, 0x00, 0x67, 0x29, 0x2a, 0xe1, 0x7b,
+    0xdb, 0x8b, 0xfb, 0x71, 0xde, 0x13, 0x5f, 0xe1, 0xb6, 0x91, 0x99, 0x90,
+    0x99, 0x4a, 0xf8, 0xf0, 0x79, 0xe2, 0x2d, 0x76, 0x9b, 0x1e, 0x29, 0xed,
+    0xf7, 0x8b, 0xa2, 0x1c, 0xf9, 0xec, 0xde, 0xf4, 0x35, 0x40, 0xca, 0x4c,
+    0xf0, 0x30, 0x4a, 0xcb, 0x9f, 0x72, 0x0f, 0xfe, 0x06, 0xcd, 0x54, 0xb0,
+    0x5d, 0x30, 0x59, 0xd6, 0x0d, 0x7e, 0x7e, 0x71, 0x45, 0xb6, 0xc3, 0xac,
+    0x5b, 0x76, 0xa7, 0xc6, 0x67, 0x08, 0x2d, 0xd1, 0xa7, 0x32, 0x1a, 0x90,
+    0x83, 0xc1, 0x55, 0x6a, 0xca, 0x9c, 0x8e, 0xb3, 0x7b, 0x8f, 0xc5, 0x05,
+    0x4f, 0x91, 0xef, 0xee, 0xa5, 0x7d, 0xcd, 0xd6, 0xb0, 0xad, 0xc1, 0x94,
+    0x98, 0x20, 0x04, 0x26, 0x54, 0xd6, 0x72, 0xb4, 0x28, 0xe4, 0xe4, 0xdf,
+    0x43, 0x7e, 0xfd, 0x15, 0x17, 0x8d, 0xd9, 0xd4, 0x62, 0xa9, 0x62, 0x47,
+    0x6d, 0x32, 0x26, 0x11, 0x41, 0x04, 0x6f, 0x50, 0x3c, 0xd2, 0x9a, 0xeb,
+    0x76, 0x2e, 0x7e, 0xcf, 0xfe, 0xbc, 0xbd, 0xae, 0x5f, 0x23, 0x77, 0x86,
+    0x9c, 0xf1, 0x99, 0xa7, 0x8c, 0xd9, 0x21, 0x58, 0x07, 0x9b, 0x3b, 0xfa,
+    0xe4, 0xc1, 0x72, 0xd9, 0x01, 0xc5, 0xe5, 0xb8, 0xc0, 0xe8, 0xb9, 0x11,
+    0x96, 0xcf, 0x39, 0x8c, 0x8a, 0x77, 0x3e, 0xd7, 0x8d, 0x27, 0xf1, 0x0b,
+    0xfc, 0xa0, 0xa7, 0x7a, 0x61, 0x44, 0xcc, 0xfc, 0x15, 0xea, 0x0b, 0xf7,
+    0x74, 0x9b, 0xa7, 0xda, 0x73, 0x9b, 0xec, 0x62, 0x43, 0x19, 0xbb, 0x16,
+    0xba, 0x0d, 0x1e, 0xd6, 0xa1, 0x4c, 0xbd, 0x58, 0xac, 0xcf, 0x79, 0x9d,
+    0xf2, 0xbd, 0xfa, 0x9c, 0xfd, 0x79, 0x81, 0x0c, 0x7d, 0xb8, 0xe9, 0xf9,
+    0x99, 0x64, 0xee, 0xa9, 0xa4, 0xe9, 0xcc, 0x94, 0x09, 0x6c, 0x3d, 0x7e,
+    0x59, 0x55, 0x80, 0x5e, 0xf1, 0xf5, 0xff, 0x5d, 0x74, 0xf2, 0xea, 0xe6,
+    0xfa, 0xb1, 0x7a, 0x48, 0xeb, 0x72, 0x53, 0x18, 0x60, 0x14, 0xfb, 0x54,
+    0x72, 0xab, 0x04, 0x13, 0xa7, 0x47, 0xfb, 0xbb, 0x21, 0x14, 0x3d, 0xd3,
+    0x56, 0x53, 0x89, 0xa4, 0x6b, 0x02, 0x79, 0x83, 0x74, 0x85, 0x2e, 0x9c,
+    0xbe, 0x03, 0xf4, 0x0b, 0xa2, 0xdc, 0xf2, 0xdb, 0x57, 0x2a, 0x25, 0x5b,
+    0x63, 0x01, 0x67, 0x18, 0xc4, 0x1c, 0xa7, 0xfa, 0x99, 0xc2, 0x3d, 0x26,
+    0xaf, 0x9b, 0x9f, 0x9f, 0x4c, 0x03, 0x73, 0xb9, 0xd7, 0x98, 0x22, 0x67,
+    0x0e, 0x5c, 0x60, 0xc8, 0xf8, 0xc0, 0x54, 0x9b, 0xfb, 0x4c, 0xd9, 0x38,
+    0xf8, 0xfc, 0x90, 0x78, 0x5b, 0xeb, 0xf0, 0xe9, 0x3f, 0xa5, 0x32, 0xc8,
+    0x28, 0xc3, 0xf8, 0x6f, 0x63, 0x62, 0x59, 0x54, 0xf1, 0x81, 0xc9, 0xa1,
+    0xf3, 0x97, 0xdf, 0x1f, 0xff, 0xfb, 0x75, 0xe3, 0xf2, 0xc3, 0x2d, 0x7c,
+    0x6f, 0x41, 0xa1, 0xa0, 0x1d, 0xc8, 0x34, 0x44, 0xca, 0x15, 0x93, 0xde,
+    0xda, 0xb9, 0x17, 0x93, 0x7f, 0x17, 0x5a, 0xfe, 0xe1, 0x3b, 0x94, 0x4c,
+    0xd9, 0x54, 0x27, 0x08, 0x13, 0x9c, 0x04, 0x89, 0x65, 0x51, 0xee, 0x41,
+    0xd7, 0x93, 0x1b, 0xef, 0x40, 0x6f, 0xac, 0xc5, 0x55, 0xe5, 0xad, 0x42,
+    0xa2, 0x65, 0xf7, 0x7a, 0xc3, 0xae, 0x99, 0xc8, 0xd3, 0x44, 0x7d, 0x36,
+    0x47, 0xaa, 0xe2, 0xd9, 0xe2, 0xa0, 0xcf, 0x34, 0xb7, 0xca, 0x0f, 0x2e,
+    0x9f, 0xa5, 0x21, 0x07, 0xf6, 0x70, 0x32, 0x34, 0xf2, 0xcf, 0x19, 0x19,
+    0xa2, 0x28, 0x4b, 0xea, 0x0f, 0x34, 0xbb, 0x4a, 0x27, 0x17, 0x35, 0xc7,
+    0x27, 0x12, 0xda, 0xd7, 0x9d, 0xde, 0x30, 0x71, 0xda, 0x0c, 0x6a, 0xbe,
+    0x72, 0x0c, 0x6b, 0x00, 0xa6, 0xb7, 0xc5, 0x3a, 0x43, 0xfb, 0x3b, 0xe4,
+    0x20, 0x5a, 0x79, 0x10, 0xa9, 0x9e, 0xfc, 0x84, 0x48, 0xc6, 0x2b, 0xa0,
+    0xa4, 0x5a, 0x90, 0x13, 0x9e, 0xf1, 0x5f, 0x0f, 0x97, 0x0e, 0x5e, 0x10,
+    0xe2, 0x42, 0x1f, 0x22, 0x73, 0xe4, 0xe0, 0xa5, 0x2a, 0x0c, 0x7c, 0xae,
+    0x95, 0x57, 0x95, 0xb1, 0x40, 0x76, 0xc7, 0x0d, 0xa2, 0xe0, 0x30, 0x62,
+    0x77, 0x07, 0x07, 0x65, 0xd6, 0xef, 0x23, 0x8d, 0xac, 0x3c, 0xc9, 0x45,
+    0xe5, 0x21, 0xe2, 0x1f, 0xee, 0x96, 0x60, 0xae, 0x6f, 0x51, 0x3f, 0x11,
+    0x0c, 0xcd, 0x1a, 0x7b, 0x32, 0xa1, 0xda, 0xe3, 0x90, 0x05, 0x0a, 0xa9,
+    0x27, 0xaf, 0xc8, 0x39, 0xbe, 0xe1, 0x7a, 0xf7, 0x94, 0x22, 0x1a, 0xd2,
+    0xad, 0xc6, 0xa7, 0xb8, 0x77, 0x5b, 0x93, 0xe5, 0x4e, 0x50, 0x30, 0x8c,
+    0x0e, 0x12, 0x0f, 0x34, 0xb6, 0x7b, 0xe0, 0xef, 0x3b, 0xbb, 0xb6, 0x92,
+    0xe8, 0xfc, 0xd4, 0x1d, 0x67, 0x18, 0x8a, 0x50, 0x9a, 0x48, 0x81, 0x4f,
+    0x2f, 0x54, 0x12, 0xbe, 0xdb, 0xd2, 0x67, 0xae, 0x1d, 0x2a, 0x5f, 0x8d,
+    0x0f, 0x55, 0xbf, 0x40, 0x00, 0x00, 0x01, 0x0a
+};
+
+void vc1_get_video_info(VideoDecodeInfo *info)
+{
+    info->profile   = GST_VAAPI_PROFILE_VC1_ADVANCED;
+    info->width     = VC1_CLIP_WIDTH;
+    info->height    = VC1_CLIP_HEIGHT;
+    info->data      = vc1_clip;
+    info->data_size = VC1_CLIP_DATA_SIZE;
+}
diff --git a/tests/test-vc1.h b/tests/test-vc1.h
new file mode 100644 (file)
index 0000000..1d78504
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  test-vc1.h - VC-1 test data
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+*/
+
+#ifndef TEST_VC1_H
+#define TEST_VC1_H
+
+#include <glib.h>
+#include "test-decode.h"
+
+void vc1_get_video_info(VideoDecodeInfo *info);
+
+#endif /* TEST_VC1_H */
diff --git a/tests/test-windows.c b/tests/test-windows.c
new file mode 100644 (file)
index 0000000..6c24f8a
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ *  test-windows.c - Test GstVaapiWindow
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+*/
+
+#include "config.h"
+#include <gst/vaapi/gstvaapisurface.h>
+#include <gst/vaapi/gstvaapiimage.h>
+#if USE_DRM
+# include <gst/vaapi/gstvaapidisplay_drm.h>
+# include <gst/vaapi/gstvaapiwindow_drm.h>
+#endif
+#if USE_X11
+# include <gst/vaapi/gstvaapidisplay_x11.h>
+# include <gst/vaapi/gstvaapiwindow_x11.h>
+#endif
+#if USE_WAYLAND
+# include <gst/vaapi/gstvaapidisplay_wayland.h>
+# include <gst/vaapi/gstvaapiwindow_wayland.h>
+#endif
+#include "image.h"
+
+static inline void
+pause(void)
+{
+    g_print("Press any key to continue...\n");
+    getchar();
+}
+
+static GstVaapiSurface *
+create_test_surface(GstVaapiDisplay *display, guint width, guint height)
+{
+    GstVaapiImage *image = NULL;
+    GstVaapiSurface *surface;
+    guint i;
+
+    static const GstVaapiChromaType  chroma_type = GST_VAAPI_CHROMA_TYPE_YUV420;
+    static const GstVaapiImageFormat image_formats[] = {
+        GST_VAAPI_IMAGE_NV12,
+        GST_VAAPI_IMAGE_YV12,
+        GST_VAAPI_IMAGE_I420,
+        GST_VAAPI_IMAGE_AYUV,
+        GST_VAAPI_IMAGE_ARGB,
+        GST_VAAPI_IMAGE_BGRA,
+        GST_VAAPI_IMAGE_RGBA,
+        GST_VAAPI_IMAGE_ABGR,
+        0
+    };
+
+    surface = gst_vaapi_surface_new(display, chroma_type, width, height);
+    if (!surface)
+        g_error("could not create Gst/VA surface");
+
+    for (i = 0; image_formats[i]; i++) {
+        const GstVaapiImageFormat format = image_formats[i];
+
+        image = image_generate(display, format, width, height);
+        if (!image)
+            break;
+        if (image_upload(image, surface))
+            break;
+    }
+    if (!image)
+        g_error("could not create Gst/VA image");
+
+    if (!gst_vaapi_surface_sync(surface))
+        g_error("could not complete image upload");
+
+    g_object_unref(image);
+    return surface;
+}
+
+int
+main(int argc, char *argv[])
+{
+    GstVaapiDisplay *display;
+    GstVaapiWindow *window;
+    GstVaapiSurface *surface;
+    guint flags = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
+
+    static const guint width       = 320;
+    static const guint height      = 240;
+    static const guint win_width   = 640;
+    static const guint win_height  = 480;
+
+    gst_init(&argc, &argv);
+
+#if USE_DRM
+    display = gst_vaapi_display_drm_new(NULL);
+    if (!display)
+        g_error("could not create Gst/VA (DRM) display");
+
+    surface = create_test_surface(display, width, height);
+    if (!surface)
+        g_error("could not create Gst/VA surface");
+
+    g_print("#\n");
+    g_print("# Create window with gst_vaapi_window_drm_new()\n");
+    g_print("#\n");
+    {
+        window = gst_vaapi_window_drm_new(display, win_width, win_height);
+        if (!window)
+            g_error("could not create dummy window");
+
+        gst_vaapi_window_show(window);
+
+        if (!gst_vaapi_window_put_surface(window, surface, NULL, NULL, flags))
+            g_error("could not render surface");
+
+        pause();
+        g_object_unref(window);
+    }
+
+    g_object_unref(surface);
+    g_object_unref(display);
+#endif
+
+#if USE_X11
+    display = gst_vaapi_display_x11_new(NULL);
+    if (!display)
+        g_error("could not create Gst/VA display");
+
+    surface = create_test_surface(display, width, height);
+    if (!surface)
+        g_error("could not create Gst/VA surface");
+
+    g_print("#\n");
+    g_print("# Create window with gst_vaapi_window_x11_new()\n");
+    g_print("#\n");
+    {
+        window = gst_vaapi_window_x11_new(display, win_width, win_height);
+        if (!window)
+            g_error("could not create window");
+
+        gst_vaapi_window_show(window);
+
+        if (!gst_vaapi_window_put_surface(window, surface, NULL, NULL, flags))
+            g_error("could not render surface");
+
+        pause();
+        g_object_unref(window);
+    }
+
+    g_print("#\n");
+    g_print("# Create window with gst_vaapi_window_x11_new_with_xid()\n");
+    g_print("#\n");
+    {
+        Display * const dpy = gst_vaapi_display_x11_get_display(GST_VAAPI_DISPLAY_X11(display));
+        Window rootwin, win;
+        int screen;
+        unsigned long white_pixel, black_pixel;
+
+        screen      = DefaultScreen(dpy);
+        rootwin     = RootWindow(dpy, screen);
+        white_pixel = WhitePixel(dpy, screen);
+        black_pixel = BlackPixel(dpy, screen);
+
+        win = XCreateSimpleWindow(
+            dpy,
+            rootwin,
+            0, 0, win_width, win_height,
+            0, black_pixel,
+            white_pixel
+        );
+        if (!win)
+            g_error("could not create X window");
+
+        window = gst_vaapi_window_x11_new_with_xid(display, win, 0);
+        if (!window)
+            g_error("could not create window");
+
+        gst_vaapi_window_show(window);
+
+        if (!gst_vaapi_window_put_surface(window, surface, NULL, NULL, flags))
+            g_error("could not render surface");
+
+        pause();
+        g_object_unref(window);
+        XUnmapWindow(dpy, win);
+        XDestroyWindow(dpy, win);
+    }
+
+    g_object_unref(surface);
+    g_object_unref(display);
+#endif
+
+#if USE_WAYLAND
+    display = gst_vaapi_display_wayland_new(NULL);
+    if (!display)
+        g_error("could not create Gst/VA (Wayland) display");
+
+    surface = create_test_surface(display, width, height);
+    if (!surface)
+        g_error("could not create Gst/VA surface");
+
+    g_print("#\n");
+    g_print("# Create window with gst_vaapi_window_wayland_new()\n");
+    g_print("#\n");
+    {
+        window = gst_vaapi_window_wayland_new(display, win_width, win_height);
+        if (!window)
+            g_error("could not create window");
+
+        gst_vaapi_window_show(window);
+
+        if (!gst_vaapi_window_put_surface(window, surface, NULL, NULL, flags))
+            g_error("could not render surface");
+
+        pause();
+        g_object_unref(window);
+    }
+
+    g_object_unref(surface);
+    g_object_unref(display);
+#endif
+
+    gst_deinit();
+    return 0;
+}