From c73a9a38e6eff31b7681fdc84feb52d223e719ed Mon Sep 17 00:00:00 2001 From: Sreerenj Balachandran Date: Wed, 9 Jul 2014 19:10:57 +0300 Subject: [PATCH] New Tool: Add a CodecAnalyzer https://bugzilla.gnome.org/show_bug.cgi?id=731853 --- codecanalyzer/.gitignore | 28 + codecanalyzer/AUTHORS | 2 + codecanalyzer/COPYING | 481 ++++++++ codecanalyzer/Makefile.am | 11 + codecanalyzer/NEWS | 0 codecanalyzer/README.md | 17 + codecanalyzer/autogen.sh | 30 + codecanalyzer/configure.ac | 79 ++ codecanalyzer/data/Makefile.am | 4 + codecanalyzer/data/pixmaps/Makefile.am | 8 + .../data/pixmaps/codecanalyzer-logo.png | Bin 0 -> 2009 bytes .../data/pixmaps/frame-thumbnail.png | Bin 0 -> 679 bytes codecanalyzer/data/ui/LICENSE.txt | 481 ++++++++ codecanalyzer/data/ui/Makefile.am | 6 + codecanalyzer/data/ui/mainwindow.xml | 358 ++++++ codecanalyzer/data/ui/menu.xml | 12 + codecanalyzer/src/Makefile.am | 41 + codecanalyzer/src/codecanalyzer.c | 1052 +++++++++++++++++ codecanalyzer/src/gst_analyzer.c | 326 +++++ codecanalyzer/src/gst_analyzer.h | 108 ++ codecanalyzer/src/plugins/Makefile.am | 4 + codecanalyzer/src/plugins/gst/Makefile.am | 4 + .../src/plugins/gst/analyzersink/Makefile.am | 44 + .../plugins/gst/analyzersink/analyzer_utils.c | 46 + .../plugins/gst/analyzersink/analyzer_utils.h | 28 + .../gst/analyzersink/gstanalyzersink.c | 446 +++++++ .../gst/analyzersink/gstanalyzersink.h | 89 ++ .../src/plugins/gst/analyzersink/mpeg_xml.c | 566 +++++++++ .../src/plugins/gst/analyzersink/mpeg_xml.h | 45 + .../src/plugins/gst/analyzersink/plugin.c | 41 + .../src/plugins/gst/analyzersink/xml_utils.c | 21 + .../src/plugins/gst/analyzersink/xml_utils.h | 106 ++ codecanalyzer/src/xml_parse.c | 182 +++ codecanalyzer/src/xml_parse.h | 59 + 34 files changed, 4725 insertions(+) create mode 100644 codecanalyzer/.gitignore create mode 100644 codecanalyzer/AUTHORS create mode 100644 codecanalyzer/COPYING create mode 100644 codecanalyzer/Makefile.am create mode 100644 codecanalyzer/NEWS create mode 100644 codecanalyzer/README.md create mode 100755 codecanalyzer/autogen.sh create mode 100644 codecanalyzer/configure.ac create mode 100644 codecanalyzer/data/Makefile.am create mode 100644 codecanalyzer/data/pixmaps/Makefile.am create mode 100644 codecanalyzer/data/pixmaps/codecanalyzer-logo.png create mode 100644 codecanalyzer/data/pixmaps/frame-thumbnail.png create mode 100644 codecanalyzer/data/ui/LICENSE.txt create mode 100644 codecanalyzer/data/ui/Makefile.am create mode 100644 codecanalyzer/data/ui/mainwindow.xml create mode 100644 codecanalyzer/data/ui/menu.xml create mode 100644 codecanalyzer/src/Makefile.am create mode 100644 codecanalyzer/src/codecanalyzer.c create mode 100644 codecanalyzer/src/gst_analyzer.c create mode 100644 codecanalyzer/src/gst_analyzer.h create mode 100644 codecanalyzer/src/plugins/Makefile.am create mode 100644 codecanalyzer/src/plugins/gst/Makefile.am create mode 100644 codecanalyzer/src/plugins/gst/analyzersink/Makefile.am create mode 100644 codecanalyzer/src/plugins/gst/analyzersink/analyzer_utils.c create mode 100644 codecanalyzer/src/plugins/gst/analyzersink/analyzer_utils.h create mode 100644 codecanalyzer/src/plugins/gst/analyzersink/gstanalyzersink.c create mode 100644 codecanalyzer/src/plugins/gst/analyzersink/gstanalyzersink.h create mode 100644 codecanalyzer/src/plugins/gst/analyzersink/mpeg_xml.c create mode 100644 codecanalyzer/src/plugins/gst/analyzersink/mpeg_xml.h create mode 100644 codecanalyzer/src/plugins/gst/analyzersink/plugin.c create mode 100644 codecanalyzer/src/plugins/gst/analyzersink/xml_utils.c create mode 100644 codecanalyzer/src/plugins/gst/analyzersink/xml_utils.h create mode 100644 codecanalyzer/src/xml_parse.c create mode 100644 codecanalyzer/src/xml_parse.h diff --git a/codecanalyzer/.gitignore b/codecanalyzer/.gitignore new file mode 100644 index 0000000000..de0209b29e --- /dev/null +++ b/codecanalyzer/.gitignore @@ -0,0 +1,28 @@ +aclocal.m4 +autom4te.cache +config.guess +config.h* +config.log +config.status +config.sub +configure +install-sh +libtool +ltmain.sh +missing +mkinstalldirs +stamp-h +stamp-h.in +stamp-h1 + +/m4 + +*.la +*.lo +*.o +*.swp +*~ +.deps +.libs +Makefile +Makefile.in diff --git a/codecanalyzer/AUTHORS b/codecanalyzer/AUTHORS new file mode 100644 index 0000000000..b6766dcc19 --- /dev/null +++ b/codecanalyzer/AUTHORS @@ -0,0 +1,2 @@ +Sreerenj Balachandran + diff --git a/codecanalyzer/COPYING b/codecanalyzer/COPYING new file mode 100644 index 0000000000..99b316fb63 --- /dev/null +++ b/codecanalyzer/COPYING @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 51 Franklin St, 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 library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + 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 Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the 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 a program 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. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + 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, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile 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) 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. + + c) 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. + + d) 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 source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/codecanalyzer/Makefile.am b/codecanalyzer/Makefile.am new file mode 100644 index 0000000000..e3c5c3ebe2 --- /dev/null +++ b/codecanalyzer/Makefile.am @@ -0,0 +1,11 @@ +ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} + +AUTOMAKE_OPTIONS = foreign + +SUBDIRS = src data + +# 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 diff --git a/codecanalyzer/NEWS b/codecanalyzer/NEWS new file mode 100644 index 0000000000..e69de29bb2 diff --git a/codecanalyzer/README.md b/codecanalyzer/README.md new file mode 100644 index 0000000000..dfb7bd90e6 --- /dev/null +++ b/codecanalyzer/README.md @@ -0,0 +1,17 @@ +codecanalyzer +============= + +An analyzer for doing in-depth analysis on compressed media. +It is built on top of gstreamer, gtk+ and libxml2. +The goal of the codecanalyzer is to support the follwoing +features: + +-- unpack the elementary stream from a container +-- do packetization for the non-packetized stream +-- Parse all the syntax elements from the elementary video stream +-- A simple UI to navigate through all the headers of each frame separately +-- Users would be able to analyze the media files residing in the local machine +and the remote streams via http or rtp. + +Supported codecs: +-- mpeg2 diff --git a/codecanalyzer/autogen.sh b/codecanalyzer/autogen.sh new file mode 100755 index 0000000000..dc32600f74 --- /dev/null +++ b/codecanalyzer/autogen.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +PROJECT="codecanalyzer" + +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 + +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 diff --git a/codecanalyzer/configure.ac b/codecanalyzer/configure.ac new file mode 100644 index 0000000000..102e477b87 --- /dev/null +++ b/codecanalyzer/configure.ac @@ -0,0 +1,79 @@ +AC_PREREQ([2.66]) +AC_INIT([codecanalyzer], [0.1.0], + [sreerenj.balachandran@intel.com]) + +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([1.11 no-dist-gzip dist-xz tar-ustar]) + +m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) + +dnl Check for tools +AC_PROG_CC +AM_PROG_CC_C_O + +dnl Initialize libtool +LT_PREREQ([2.2]) +LT_INIT + +# codecanalyzer packag versions +m4_define([codecanalyzer_major_version], [0]) +m4_define([codecanalyzer_minor_version], [1]) +m4_define([codecanalyzer_build_version], [0]) + +dnl Check for glib +PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.32.0]) +PKG_CHECK_MODULES([GMODULE_EXPORT], [gmodule-2.0 >= 2.32.0]) +PKG_CHECK_MODULES([GTK], [gtk+-3.0 >= 3.4.2]) +PKG_CHECK_MODULES([GST], [gstreamer-1.0 >= 1.3.1]) +PKG_CHECK_MODULES([GST_BASE], [gstreamer-base-1.0 >= 1.3.1]) +PKG_CHECK_MODULES([GST_PLUGINS_BASE], [gstreamer-plugins-base-1.0 >= 1.3.1]) +PKG_CHECK_MODULES([GST_VIDEO], [gstreamer-video-1.0 >= 1.3.1]) +PKG_CHECK_MODULES([GST_PBUTILS], [gstreamer-pbutils-1.0 >= 1.3.1]) +PKG_CHECK_MODULES([GST_CODEC_PARSERS], [gstreamer-plugins-bad-1.0 >= 1.3.1]) +PKG_CHECK_MODULES([LIBXML2], [libxml-2.0 >= 2.7.8]) + +GST_ALL_LDFLAGS="-no-undefined" +AC_SUBST(GST_ALL_LDFLAGS) + +AC_SUBST(GLIB_CFLAGS) +AC_SUBST(GLIB_LIBS) +AC_SUBST(GMODULE_EXPORT_CFLAGS) +AC_SUBST(GMODULE_EXPORT_LIBS) +AC_SUBST(GTK_CFLAGS) +AC_SUBST(GTK_LIBS) +AC_SUBST(GST_CFLAGS) +AC_SUBST(GST_LIBS) +AC_SUBST(GST_BASE_CFLAGS) +AC_SUBST(GST_BASE_LIBS) +AC_SUBST(GST_PLUGINS_CFLAGS) +AC_SUBST(GST_PLUGINS_LIBS) +AC_SUBST(GST_VIDEO_CFLAGS) +AC_SUBST(GST_VIDEO_LIBS) +AC_SUBST(GST_PBUTILS_CFLAGS) +AC_SUBST(GST_PBUTILS_LIBS) +AC_SUBST(GST_CODEC_PARSERS_LIBS) +AC_SUBST(GST_CODEC_PARSERS_CFLAGS) +AC_SUBST(LIBXML2_CFLAGS) +AC_SUBST(LIBXML2_LIBS) + +AC_CONFIG_FILES([Makefile + src/Makefile + src/plugins/Makefile + src/plugins/gst/Makefile + src/plugins/gst/analyzersink/Makefile + data/Makefile + data/ui/Makefile + data/pixmaps/Makefile + ]) +AC_OUTPUT + +echo +echo $PACKAGE $VERSION +echo " configure complete, now type make and make install " +echo " ===================================================== " diff --git a/codecanalyzer/data/Makefile.am b/codecanalyzer/data/Makefile.am new file mode 100644 index 0000000000..95f5031631 --- /dev/null +++ b/codecanalyzer/data/Makefile.am @@ -0,0 +1,4 @@ +SUBDIRS = pixmaps ui + +# Extra clean files so that maintainer-clean removes *everything* +MAINTAINERCLEANFILES = Makefile.in diff --git a/codecanalyzer/data/pixmaps/Makefile.am b/codecanalyzer/data/pixmaps/Makefile.am new file mode 100644 index 0000000000..1eee60239f --- /dev/null +++ b/codecanalyzer/data/pixmaps/Makefile.am @@ -0,0 +1,8 @@ +pixmapdir = $(datadir)/codecanalyzer/pixmaps + +pixmap_DATA = \ + frame-thumbnail.png \ + codecanalyzer-logo.png + +EXTRA_DIST = \ + $(pixmap_DATA) diff --git a/codecanalyzer/data/pixmaps/codecanalyzer-logo.png b/codecanalyzer/data/pixmaps/codecanalyzer-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..81099a6853f97eebed4db12828c433bccc2e65f9 GIT binary patch literal 2009 zcmV;~2PXK5P){WG;xT3c0=QmLa_6^NKpniNR4BqKbM5O5d}CyNumV#km8KFmF)z8s0fl6#8u`bij#F>JkmakWsp-VdonMmr`jNcmxOI!* ztFKm~we=}PBF`d~szW?p3Q@d(x8B-BRi z^C_%bx0f6`^zM9w2LNtX)o0E;i;j*1NG7XiHI7mONisr`+(@V07#`jLgCPlnA&yY! zIw+lls%F8m#Ym;Rh{c@W>%p>9@cI4-r}N|a3J=U;2hdZeDzJb5Uy#juL5K>TPXb5* zPyrM`QH)5Z#k_XJY!QS>_9>#tAEXY2fTKv7W$l)j1ba)9S$tXdU<+Z}_^ zDC6qYLIeULdV8x-TDlI==o%yvc4V`rIj@jqGw}Q0fYw3df`i9@e*6?L+sEKM&=P17KkE7D@r<0Qi)CZ=@oanz0NZr6CczZ* z*gPHabo{TLBG1KL)w_aaY+2On_9}VIBLow{^5gx-*I0CxpT7Og+gm88z!5I1LjBY2 zx<%aq2ip$*ux+GmZzLVrl9tlqY{uI3w(AUGZaB@(a}Az`4!_NR(eLpGrwMKvP7H5) zzvunkM&4KxNk?i`sO|D8BueAB2KJR%OG@_{~}XwfPJZSfPKdW9=`uJGW2l!Ja$U z7e#>GY#%hnj7L`3SA?7vXUJu7h1@oG2mo%zZ!QTYf+g)Y+aK3)I=`eyrSWXsIoCPw z1Z23J)8ah-YR#*^-CDPGqzO&;+FT3)`Op$*A>nk`-7(a$B$x=+iF)y=i=m4<2_Y<{ zl$~x%KL|pIBI?DUx6pf-Qu^ojcDy$_ZQY{|K7*8!E8#2a+i$dQOy-h)S(U4kxnz-| z-v2~t)meu)hU={=syg|?@)wRhQ~6BjfubID$b1;QG01l&I*VIxv@VTj;^igglDeFd zbER^r5`h&`I!+e?#Yo?HU+*&evfxX;m;P14l*GJlFP*7(-U3EPb6hkkSyYv>03ZlV z&SK$`4u`NHC$`1nz5-63j52L)@q*G)VOf8FdRs6!wJaW&y@Y@P09B>((xv(fB_+a$ z$D{9xMx`E6A0(pOze=N(DAA&V_S8#;d~?_|057cM=B}|vfHg!u3SlT zHXCQ96kE=nn|KaDZ6>3-6ouY>bEBfj9o@RM@YnnHmCwujzXu99c`|DL$atNNo+sd6C}WV3On8XK3s zylq=yaPHk^W>)8b%aG?C{}bV~Y`f)&lM$#d6|AbWK-RvOb$tpN>SNnoLHu<}+3hm{f5we^n63 z-!^Wv9ewRJSI=SvpEm(_iQt=?qxRO;n60+f)DVkFkA=fh+309)Im3Vj07^k+ndT}h zjTh~9{<6WqoH3i(ffrx2kNJG2hx+U6zed1xOe7|l(SI|dBoRFTuq=^9k&ikYg7hfD rYG`O^XlQ6?XlQ6?XlQ6?0Kk6$UVtc6IYa*G00000NkvXXu0mjfhE43+ literal 0 HcmV?d00001 diff --git a/codecanalyzer/data/pixmaps/frame-thumbnail.png b/codecanalyzer/data/pixmaps/frame-thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..cd046436267664e418aab7684ba3971766d2bd48 GIT binary patch literal 679 zcmeAS@N?(olHy`uVBq!ia0vp^l0YoS!3HF6zS(-4fq_xj)5S5wqx0=V#dFOL0)GFjwQk(cTUBPJzkBk` z+W4}t1DY+9U%c6I&h?>+ma4AIAw?+q6wNVLrqpCnb~;;We^l7$bHo>+e_W0|sPLougr2c;KP28|~&;9%)oi3%A>#gs9@3@<{BX0d0g?Y~( ze*T#dDQ2|m`RC4cuN6)kS$jydNgNlvz3pMq&I$Wp{FZYR*w7pj+PW>*kcauyrk2MR z0ijbX{xD8fw*QoDo~I2AB?eDdKbLh*2~C|ugryQREH5dZZg!AhFPNwpakpIHaLnbD zEj!mQklx1nwkc8UFGJtb*4l0PTCvy_+!NZ1D-Fn{`?nBcn=#K*rX%V@2=6+v}%^*V%DxOVe z)13J&=bw+z5v$mL9~jOTN@cg@CU1?p=v=m2_S7bs`D=2cSsWYIy%sobX#1pS=Y!8b f6?}tFZ0dRb*|IL(bJ7R)HxGR--&vLM6**`D{XQtn literal 0 HcmV?d00001 diff --git a/codecanalyzer/data/ui/LICENSE.txt b/codecanalyzer/data/ui/LICENSE.txt new file mode 100644 index 0000000000..61ba5a91b3 --- /dev/null +++ b/codecanalyzer/data/ui/LICENSE.txt @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 51 Franklin St, 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 library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + 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 Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the 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 a program 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. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + 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, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile 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) 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. + + c) 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. + + d) 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 source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/codecanalyzer/data/ui/Makefile.am b/codecanalyzer/data/ui/Makefile.am new file mode 100644 index 0000000000..bcc06a5cb6 --- /dev/null +++ b/codecanalyzer/data/ui/Makefile.am @@ -0,0 +1,6 @@ +uidir = $(datadir)/codecanalyzer/ui + +ui_DATA = \ + mainwindow.xml menu.xml LICENSE.txt + +EXTRA_DIST = $(ui_DATA) diff --git a/codecanalyzer/data/ui/mainwindow.xml b/codecanalyzer/data/ui/mainwindow.xml new file mode 100644 index 0000000000..d1b1ce78de --- /dev/null +++ b/codecanalyzer/data/ui/mainwindow.xml @@ -0,0 +1,358 @@ + + + + + CodecAnalyzer + False + 800 + 600 + GTK_WIN_POS_CENTER + + + + False + False + vertical + 5 + False + + + False + False + vertical + + + False + False + + + + + True + False + vertical + 5 + + + + True + False + vertical + + + + True + 5 + + + True + False + + + True + False + + + + + True + False + 0 + <b>Open the Stream file:</b> + True + + + False + False + + + + + Select a Stream + True + False + + + + False + False + + + + + True + False + + + True + False + + + + + True + False + 0 + <b>Number of frames to Analyze:</b> + True + + + False + False + + + + + True + True + True + + + False + False + + + + + True + False + + + True + False + + + + + + + False + False + + + + + True + False + vertical + + + + True + 5 + + + True + False + + + True + False + + + + + Analyze + True + True + True + True + False + + + + False + False + + + + + Cancel + True + True + True + True + False + + + + False + False + + + + + True + False + + + True + False + + + + + + + + + False + False + + + + + + False + + + + + + True + False + vertical + + + True + True + automatic + never + GTK_SHADOW_IN + 20 + + + True + True + + + True + False + + + + + + + + + + False + + + + + + True + True + vertical + 5 + False + + + + True + True + 15 + + + + True + False + + + + True + False + vertical + 5 + + + + True + False + General Stream Info + + + False + False + + + + + + True + False + + + True + True + + + + + + + + + False + False + + + + + + True + False + 0.5 + 1.0 + + + + True + True + + + + True + True + vertical + + + False + False + + + + + + True + True + vertical + + + + + + + + True + True + + + + + + + + + True + True + + + + + + + + diff --git a/codecanalyzer/data/ui/menu.xml b/codecanalyzer/data/ui/menu.xml new file mode 100644 index 0000000000..dd0b90a9db --- /dev/null +++ b/codecanalyzer/data/ui/menu.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/codecanalyzer/src/Makefile.am b/codecanalyzer/src/Makefile.am new file mode 100644 index 0000000000..93f3a9293e --- /dev/null +++ b/codecanalyzer/src/Makefile.am @@ -0,0 +1,41 @@ +SUBDIRS = plugins + +bin_PROGRAMS = codecanalyzer + +codecanalyzer_SOURCES = \ + gst_analyzer.c \ + xml_parse.c \ + codecanalyzer.c \ + $(NULL) + +noinst_HEADERS = gst_analyzer.h xml_parse.h + +codecanalyzer_CFLAGS = \ + $(GLIB_CFLAGS) \ + $(GMODULE_EXPORT_CFLAGS) \ + $(GTK_CFLAGS) \ + $(GST_CFLAGS) \ + $(GST_PBUTILS_CFLAGS) \ + $(LIBXML2_CFLAGS) \ + -I$(top_builddir)/src/plugins/gst/analyzersink \ + -I$(top_srcdir)/src/plugins/gst/analyzersink \ + -DDATADIR=\"$(datadir)\" \ + $(NULL) + +codecanalyzer_LDADD = \ + $(GLIB_LIBS) \ + $(GMODULE_EXPORT_LIBS) \ + $(GTK_LIBS) \ + $(GST_LIBS) \ + $(GST_PBUTILS_LIBS) \ + $(top_builddir)/src/plugins/gst/analyzersink/libcodecanalyzer-gst-analyzersink.la \ + $(LIBXML2_LIBS) \ + $(NULL) + +codecanalyzer_LDFLAGS = \ + $(GST_ALL_LDFLAGS) \ + $(NULL) + + +# Extra clean files so that maintainer-clean removes *everything* +MAINTAINERCLEANFILES = Makefile.in diff --git a/codecanalyzer/src/codecanalyzer.c b/codecanalyzer/src/codecanalyzer.c new file mode 100644 index 0000000000..0a53a49e0e --- /dev/null +++ b/codecanalyzer/src/codecanalyzer.c @@ -0,0 +1,1052 @@ +/* + * Copyright (c) 2013, Intel Corporation. + * Author: Sreerenj Balachandran + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the 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 St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +/** + * CodecAnalyzer is an analyzer for doing in-depth analysis + * on compressed media which is built on top of gstreamer, gtk+ and + * libxml2. It is capable of parsing all the syntax elements + * from an elementary video stream. + */ +#include +#include +#include +#include +#include + +#include "gst_analyzer.h" +#include "xml_parse.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +typedef struct +{ + + GtkBuilder *builder; + + GtkWidget *main_window; + GtkWidget *main_vbox; + GtkWidget *child_vbox1; + GtkWidget *child_vbox2; + GtkWidget *child_vbox3; + GtkWidget *menubar_vbox; + GtkWidget *stream_chooser; + GtkWidget *numframes_chooser; + GtkWidget *analyze_button; + GtkWidget *cancel_button; + GtkWidget *thumbnails_scroll_window; + GtkWidget *thumbnails_view_port; + GtkWidget *child_hbox_in_vbox1_2; + GtkWidget *hbox1_in_vbox2; + GtkWidget *general_info_frame; + GtkWidget *general_info_vbox; + GtkWidget *general_info_treeview; + GtkWidget *parsed_info_frame; + GtkWidget *parsed_info_hbox; + GtkWidget *parsed_info_vbox; + GtkWidget *parsed_info_button_box; + GtkWidget *tree_view; + GtkWidget *header_button; + GtkWidget *slice_button; + GtkWidget *hexval_button; + + GtkUIManager *menu_manager; + GtkWidget *menubar; + + GHashTable *notebook_hash; + GtkWidget *prev_page; + + guint analyze_idle_id; + + gchar *file_name; + gchar *uri; + gchar *analyzer_home; + gchar *codec_name; + gchar *current_xml; + gchar *current_hex; + + gint num_frames; + gint num_frames_analyzed; + +} AnalyzerUI; + +static AnalyzerUI *ui; +GstAnalyzer *gst_analyzer; + +static char *treeview_headers[] = { "Field", "Value", "NumofBits" }; + +enum +{ + COLUMN_NAME, + COLUMN_VALUE, + COLUMN_NBITS, + NUM_COLS +}; + +enum +{ + GENERAL_INFO_LIST_NAME, + GENERAL_INFO_LIST_VALUE, + NUM_GENERAL_INFO_LIST +}; + +typedef enum +{ + COMPONENTS_UNKNOWN, + COMPONENTS_HEADERS_GENERAL, + COMPONENTS_HEADERS_SLICE, + COMPONENTS_HEXVAL +} CodecComponents; + + +GtkBuilder * +make_builder (char *file_name) +{ + GtkBuilder *builder; + + builder = gtk_builder_new (); + g_assert (gtk_builder_add_from_file (builder, file_name, NULL) > 0); + + return builder; +} + +GtkWidget * +get_widget_from_builder (GtkBuilder * builder, char *widget_name) +{ + GtkWidget *widget; + + widget = GTK_WIDGET (gtk_builder_get_object (builder, widget_name)); + + return widget; +} + +static void +display_error_dialog (const char *msg) +{ + GtkWidget *dialog; + dialog = gtk_message_dialog_new (GTK_WINDOW (ui->main_window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, GTK_BUTTONS_CANCEL, "%s", msg); + gtk_window_set_title (GTK_WINDOW (dialog), "Error"); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); +} + +static void +fill_tree_store (gpointer data, gpointer user_data) +{ + AnalyzerNode *node; + GtkTreeStore *treestore; + GtkTreeIter toplevel, child; + gchar *buf; + + node = (AnalyzerNode *) data; + treestore = (GtkTreeStore *) user_data; + + gtk_tree_store_append (treestore, &toplevel, NULL); + gtk_tree_store_set (treestore, &toplevel, COLUMN_NAME, node->field_name, -1); + if (!node->is_matrix) + gtk_tree_store_set (treestore, &toplevel, COLUMN_VALUE, node->value, -1); + else { + buf = g_strdup_printf ("[%s][%s] :click description", node->rows, node->columns); + gtk_tree_store_set (treestore, &toplevel, COLUMN_VALUE, buf, -1); + g_free (buf); + } + gtk_tree_store_set (treestore, &toplevel, COLUMN_NBITS, node->nbits, -1); + + gtk_tree_store_append (treestore, &child, &toplevel); + if (node->is_matrix) + gtk_tree_store_set (treestore, &child, COLUMN_NAME, node->value, -1); + else + gtk_tree_store_set (treestore, &child, + COLUMN_NAME, "Description.. (TODO)", -1); +} + +static GtkWidget * +create_tree_view () +{ + GtkTreeViewColumn *col; + GtkCellRenderer *renderer; + GtkWidget *view; + guint i; + + view = gtk_tree_view_new (); + + for (i = 0; i < G_N_ELEMENTS (treeview_headers); i++) { + + col = gtk_tree_view_column_new (); + + gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (col), TRUE); + gtk_tree_view_column_set_resizable (GTK_TREE_VIEW_COLUMN (col), TRUE); + gtk_tree_view_column_set_title (col, treeview_headers[i]); + gtk_tree_view_append_column (GTK_TREE_VIEW (view), col); + + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_column_pack_start (col, renderer, FALSE); + gtk_tree_view_column_add_attribute (col, renderer, "text", i); + } + + return view; +} + +static void +populate_notebook (gpointer data, gpointer user_data) +{ + gchar *header_name; + GtkWidget *header = NULL; + GtkWidget *h_data; + GtkWidget *scrolled_window; + GtkWidget *notebook; + + notebook = (GtkWidget *) user_data; + header_name = (gchar *) data; + + if (strcmp (header_name, "comment")) { + + header = gtk_label_new (header_name); + gtk_label_set_text (GTK_LABEL (header), header_name); + + h_data = create_tree_view (); + + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); + gtk_container_add (GTK_CONTAINER (scrolled_window), h_data); + + gtk_notebook_append_page_menu (GTK_NOTEBOOK (notebook), + scrolled_window, header, NULL); + + gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (notebook), + scrolled_window, TRUE); + + g_hash_table_insert (ui->notebook_hash, header_name, scrolled_window); + } +} + +static void +analyzer_display_parsed_info_button_box (GtkWidget * vbox) +{ + ui->header_button = gtk_button_new_with_label ("Headers"); + ui->slice_button = gtk_button_new_with_label ("Slices"); + ui->hexval_button = gtk_button_new_with_label ("Hex-values"); + + gtk_box_pack_start (GTK_BOX (vbox), ui->header_button, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (vbox), ui->slice_button, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (vbox), ui->hexval_button, TRUE, TRUE, 2); + + gtk_widget_show_all (ui->main_window); +} + +static gboolean +callback_button_box_click (GtkWidget * widget, GdkEvent * event, + gpointer user_data) +{ + GList *list, *header_list; + GList *hlist = NULL, *slist = NULL; + GtkWidget *notebook = NULL; + GtkWidget *textview = NULL; + GFile *hexfile; + GtkWidget *sc_window, *tree_view; + gboolean is_header, is_slice, is_hexval; + + CodecComponents component = (CodecComponents) user_data; + + char *xml_name = ui->current_xml; + char *hex_name = ui->current_hex; + + switch (component) { + case COMPONENTS_HEADERS_GENERAL: + is_header = TRUE; + is_slice = FALSE; + is_hexval = FALSE; + break; + case COMPONENTS_HEADERS_SLICE: + is_slice = TRUE; + is_header = FALSE; + is_hexval = FALSE; + break; + case COMPONENTS_HEXVAL: + is_hexval = TRUE; + is_header = FALSE; + is_slice = FALSE; + break; + default: + break; + } + + if (ui->prev_page) + gtk_widget_destroy (GTK_WIDGET (ui->prev_page)); + if (ui->notebook_hash) + g_hash_table_destroy (ui->notebook_hash); + ui->notebook_hash = g_hash_table_new (g_str_hash, g_str_equal); + + if (!is_hexval) { + header_list = analyzer_get_list_header_strings (xml_name); + + while (header_list) { + if (strcmp (header_list->data, "comment")) { + if (is_header && !g_str_has_prefix (header_list->data, "slice")) + hlist = g_list_append (hlist, header_list->data); + else if (is_slice && g_str_has_prefix (header_list->data, "slice")) + hlist = g_list_append (hlist, header_list->data); + } + header_list = header_list->next; + } + + notebook = gtk_notebook_new (); + g_object_set (G_OBJECT (notebook), "expand", TRUE, NULL); + gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE); + gtk_notebook_popup_enable (GTK_NOTEBOOK (notebook)); + gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), TRUE); + + g_list_foreach (hlist, (GFunc) populate_notebook, (gpointer) notebook); + + while (hlist) { + sc_window = g_hash_table_lookup (ui->notebook_hash, hlist->data); + if (sc_window && GTK_IS_BIN (sc_window)) + tree_view = gtk_bin_get_child (GTK_BIN (sc_window)); + + if (tree_view) { + list = analyzer_get_list_analyzer_node_from_xml (xml_name, hlist->data); + if (list) { + GtkTreeStore *treestore; + GtkTreeModel *model; + + treestore = gtk_tree_store_new (NUM_COLS, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + + g_list_foreach (list, (GFunc) fill_tree_store, treestore); + analyzer_node_list_free (list); + list = NULL; + + model = GTK_TREE_MODEL (treestore); + gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), model); + g_object_unref (model); + } + } + hlist = hlist->next; + } + ui->prev_page = notebook; + gtk_container_add (GTK_CONTAINER (ui->parsed_info_vbox), notebook); + } else { + /*Display the hex dump of the frame */ + GtkWidget *scrolled_window; + GtkTextBuffer *buffer; + gchar *contents; + gsize length; + + textview = gtk_text_view_new (); + gtk_text_view_set_left_margin (GTK_TEXT_VIEW (textview), 20); + g_object_set (G_OBJECT (textview), "expand", TRUE, "editable", FALSE, NULL); + + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); + gtk_container_add (GTK_CONTAINER (scrolled_window), textview); + + hexfile = g_file_new_for_path (hex_name); + if (hexfile) { + if (g_file_load_contents (hexfile, NULL, &contents, &length, NULL, NULL)) { + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview)); + gtk_text_buffer_set_text (buffer, contents, length); + g_free (contents); + g_object_unref (G_OBJECT (hexfile)); + } + } + ui->prev_page = scrolled_window; + gtk_container_add (GTK_CONTAINER (ui->parsed_info_vbox), scrolled_window); + } + + gtk_widget_show_all (ui->main_window); + + return TRUE; +} + +static void +callback_frame_thumbnail_press (GtkWidget * event_box, + GdkEventButton * event, gpointer user_data) +{ + GtkWidget *label; + gchar *file_name; + gchar *name; + gchar *frame_name_markup; + gint frame_num; + + frame_num = (gint) user_data; + + name = g_strdup_printf ("%s-%d.xml",ui->codec_name, frame_num); + file_name = g_build_filename (ui->analyzer_home, "xml", name, NULL); + if (ui->current_xml) + g_free (ui->current_xml); + g_free (name); + ui->current_xml = file_name; + + name = g_strdup_printf ("%s-%d.hex",ui->codec_name, frame_num); + file_name = g_build_filename (ui->analyzer_home, "hex", name, NULL); + if (ui->current_hex) + g_free (ui->current_hex); + g_free(name); + ui->current_hex = file_name; + + g_signal_connect (G_OBJECT (ui->header_button), "button-press-event", + G_CALLBACK (callback_button_box_click), + (gpointer) COMPONENTS_HEADERS_GENERAL); + g_signal_connect (G_OBJECT (ui->slice_button), "button-press-event", + G_CALLBACK (callback_button_box_click), + (gpointer) COMPONENTS_HEADERS_SLICE); + g_signal_connect (G_OBJECT (ui->hexval_button), "button-press-event", + G_CALLBACK (callback_button_box_click), (gpointer) COMPONENTS_HEXVAL); + + /* load general headers by default */ + callback_button_box_click (NULL, NULL, (gpointer) COMPONENTS_HEADERS_GENERAL); + + /*update the label of parsed_info_frame with frame_number */ + gtk_frame_set_label (GTK_FRAME (ui->parsed_info_frame), ""); + label = gtk_frame_get_label_widget (GTK_FRAME (ui->parsed_info_frame)); + frame_name_markup = + g_markup_printf_escaped + ("Frame %d", + frame_num + 1); + gtk_label_set_markup (GTK_LABEL (label), frame_name_markup); + g_free (frame_name_markup); + + gtk_widget_show_all (ui->main_window); +} + +static GtkWidget * +create_image (int frame_num) +{ + GtkWidget *image; + GtkWidget *event_box; + char *path; + + path = + g_build_filename (DATADIR, "codecanalyzer", "pixmaps", + "frame-thumbnail.png", NULL); + image = gtk_image_new_from_file (path); + g_free (path); + + event_box = gtk_event_box_new (); + + gtk_event_box_set_above_child (GTK_EVENT_BOX (event_box), TRUE); + gtk_event_box_set_visible_window (GTK_EVENT_BOX (event_box), FALSE); + + gtk_container_add (GTK_CONTAINER (event_box), image); + + g_signal_connect (G_OBJECT (event_box), "button_press_event", + G_CALLBACK (callback_frame_thumbnail_press), (gpointer)frame_num); + return event_box; +} + +static void +analyzer_create_thumbnails () +{ + GtkWidget *image; + guint i; + + for (i = 0; i < ui->num_frames_analyzed; i++) { + image = create_image (i); + g_object_set (G_OBJECT (image), "visible", TRUE, "can-focus", TRUE, NULL); + gtk_box_pack_start (GTK_BOX (ui->hbox1_in_vbox2), image, TRUE, TRUE, 2); + gtk_widget_show_all (image); + + /* Update the details of frame_0 by default */ + if (i == 0) { + analyzer_display_parsed_info_button_box (ui->parsed_info_button_box); + callback_frame_thumbnail_press (GTK_WIDGET (image), NULL, (gpointer) i); + callback_button_box_click (NULL, NULL, + (gpointer) COMPONENTS_HEADERS_GENERAL); + } + } +} + +static void +analyzer_ui_destroy () +{ + gtk_widget_destroy (ui->main_window); + + if (ui->file_name) + g_free (ui->file_name); + + if (ui->uri) + g_free (ui->uri); + + if (ui->codec_name) + g_free (ui->codec_name); + + if (ui->analyzer_home) + g_free (ui->analyzer_home); + + if (ui->current_xml) + g_free (ui->current_xml); + + if (ui->current_hex) + g_free (ui->current_hex); + + if (ui->notebook_hash) + g_hash_table_destroy (ui->notebook_hash); + + g_slice_free (AnalyzerUI, ui); +} + +void +callback_main_window_destroy (GtkWidget * widget, gpointer user_data) +{ + if (gst_analyzer) + gst_analyzer_destroy (gst_analyzer); + + analyzer_ui_destroy (); + + gtk_main_quit (); +} + + +static void +fill_general_info_list_row (gchar * name, char *content) +{ + GtkListStore *store; + GtkTreeIter iter; + GtkTreeView *list = GTK_TREE_VIEW (ui->general_info_treeview); + + store = GTK_LIST_STORE (gtk_tree_view_get_model (list)); + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, GENERAL_INFO_LIST_NAME, name, + GENERAL_INFO_LIST_VALUE, content, -1); +} + +static void +list_store_init (GtkWidget * treeview) +{ + GtkCellRenderer *renderer; + GtkTreeViewColumn *col; + GtkListStore *store; + guint i; + + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE); + + for (i = 0; i < NUM_GENERAL_INFO_LIST; i++) { + + col = gtk_tree_view_column_new (); + gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (col), TRUE); + gtk_tree_view_column_set_resizable (GTK_TREE_VIEW_COLUMN (col), TRUE); + gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), col); + + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_column_pack_start (col, renderer, FALSE); + gtk_tree_view_column_add_attribute (col, renderer, "text", i); + } + + store = + gtk_list_store_new (NUM_GENERAL_INFO_LIST, G_TYPE_STRING, G_TYPE_STRING); + + gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (store)); + + g_object_unref (store); +} + +static void +analyzer_display_general_stream_info (GstAnalyzerVideoInfo * analyzer_vinfo) +{ + char *str; + + if (!analyzer_vinfo || !ui->general_info_treeview) + return; + + list_store_init (ui->general_info_treeview); + + if (analyzer_vinfo->codec_name) + fill_general_info_list_row ("codec", analyzer_vinfo->codec_name); + + if (analyzer_vinfo->width) { + str = g_strdup_printf ("%d", analyzer_vinfo->width); + fill_general_info_list_row ("width", str); + g_free (str); + } + if (analyzer_vinfo->height) { + str = g_strdup_printf ("%d", analyzer_vinfo->height); + fill_general_info_list_row ("height", str); + g_free (str); + } + if (analyzer_vinfo->depth) { + str = g_strdup_printf ("%d", analyzer_vinfo->depth); + fill_general_info_list_row ("depth", str); + g_free (str); + } + if (analyzer_vinfo->avg_bitrate) { + str = g_strdup_printf ("%d", analyzer_vinfo->avg_bitrate); + fill_general_info_list_row ("avg_bitrate", str); + g_free (str); + } + if (analyzer_vinfo->max_bitrate) { + str = g_strdup_printf ("%d", analyzer_vinfo->max_bitrate); + fill_general_info_list_row ("max_bitrate", str); + g_free (str); + } + if (analyzer_vinfo->fps_n) { + str = g_strdup_printf ("%d", analyzer_vinfo->fps_n); + fill_general_info_list_row ("fps_n", str); + g_free (str); + } + if (analyzer_vinfo->fps_d) { + str = g_strdup_printf ("%d", analyzer_vinfo->fps_d); + fill_general_info_list_row ("fps_d", str); + g_free (str); + } + if (analyzer_vinfo->par_n) { + str = g_strdup_printf ("%d", analyzer_vinfo->par_n); + fill_general_info_list_row ("par_n", str); + g_free (str); + } + if (analyzer_vinfo->par_d) { + str = g_strdup_printf ("%d", analyzer_vinfo->par_d); + fill_general_info_list_row ("par_d", str); + g_free (str); + } + + gtk_widget_show_all (ui->general_info_treeview); +} + +static void +reset_analyzer_ui () +{ + + if (ui->hbox1_in_vbox2) { + gtk_widget_destroy (GTK_WIDGET (ui->hbox1_in_vbox2)); + ui->hbox1_in_vbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + g_object_set (G_OBJECT (ui->hbox1_in_vbox2), "visible", TRUE, + "can-focus", FALSE, NULL); + gtk_container_add (GTK_CONTAINER (ui->thumbnails_view_port), + ui->hbox1_in_vbox2); + } + + if (ui->general_info_treeview) { + gtk_widget_destroy (GTK_WIDGET (ui->general_info_treeview)); + ui->general_info_treeview = gtk_tree_view_new (); + gtk_box_pack_end (GTK_BOX (ui->general_info_vbox), + ui->general_info_treeview, TRUE, TRUE, 0); + } + + if (ui->parsed_info_button_box) { + gtk_widget_destroy (GTK_WIDGET (ui->parsed_info_button_box)); + ui->parsed_info_button_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); + g_object_set (G_OBJECT (ui->parsed_info_button_box), "visible", TRUE, + "can-focus", TRUE, NULL); + gtk_box_pack_start (GTK_BOX (ui->parsed_info_hbox), + ui->parsed_info_button_box, FALSE, FALSE, 0); + } + if (ui->parsed_info_vbox) { + gtk_widget_destroy (GTK_WIDGET (ui->parsed_info_vbox)); + ui->parsed_info_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); + g_object_set (G_OBJECT (ui->parsed_info_vbox), "visible", TRUE, + "can-focus", TRUE, NULL); + gtk_box_pack_start (GTK_BOX (ui->parsed_info_hbox), ui->parsed_info_vbox, + TRUE, TRUE, 0); + } + + if (ui->parsed_info_frame) + gtk_frame_set_label (GTK_FRAME (ui->parsed_info_frame), ""); + + if (ui->notebook_hash) + g_hash_table_destroy (ui->notebook_hash); + ui->notebook_hash = g_hash_table_new (g_str_hash, g_str_equal); + + ui->prev_page = NULL; + + gtk_widget_show_all (ui->main_window); +} + +guint +analyze_idle_callback (gpointer data) +{ + guint i; + + if (!gst_analyzer) + return TRUE; + + ui->num_frames_analyzed = gst_analyzer->NumOfAnalyzedFrames; + + if (!gst_analyzer->complete_analyze) + return TRUE; + + /* Once the analysis is complete, we doesn't need to hold the gst_analyzer */ + if (gst_analyzer) { + gst_analyzer_destroy (gst_analyzer); + gst_analyzer = NULL; + } + + analyzer_create_thumbnails (); + + gtk_widget_set_sensitive (ui->cancel_button, FALSE); + gtk_widget_set_sensitive (ui->analyze_button, TRUE); + + ui->analyze_idle_id = 0; + + return FALSE; +} + +void +callback_analyzer_button_analyze (GtkWidget * widget, gpointer user_data) +{ + const char *str; + GstAnalyzerVideoInfo *analyzer_vinfo; + guint i, j, k; + + gtk_widget_set_sensitive (ui->analyze_button, FALSE); + gtk_widget_set_sensitive (ui->cancel_button, TRUE); + gtk_widget_set_sensitive (ui->child_vbox3, TRUE); + + g_signal_emit_by_name (ui->numframes_chooser, "activate", NULL, NULL); + str = gtk_entry_get_text ((GtkEntry *) ui->numframes_chooser); + + /* initialize the back-end */ + if (!gst_analyzer) { + GstAnalyzerStatus status; + gst_analyzer = g_slice_new0 (GstAnalyzer); + status = gst_analyzer_init (gst_analyzer, ui->uri); + if (status != GST_ANALYZER_STATUS_SUCCESS) { + const gchar *msg; + + reset_analyzer_ui (); + + msg = gst_analyzer_status_get_name (status); + display_error_dialog (msg); + + gtk_widget_set_sensitive (ui->analyze_button, TRUE); + gtk_widget_set_sensitive (ui->cancel_button, FALSE); + gtk_widget_set_sensitive (ui->child_vbox3, FALSE); + if (gst_analyzer) + gst_analyzer_destroy (gst_analyzer); + gst_analyzer = NULL; + goto done; + } + } + + /* reset the necessary UI components for each Analysis */ + reset_analyzer_ui (); + + ui->num_frames = atoi (str); + + if (gst_analyzer->codec_name) + ui->codec_name = g_strdup (gst_analyzer->codec_name); + + if (ui->file_name) + gst_analyzer_set_file_name (gst_analyzer, ui->file_name); + if (ui->num_frames) + gst_analyzer_set_num_frames (gst_analyzer, ui->num_frames); + if (ui->analyzer_home) + gst_analyzer_set_destination_dir_path (gst_analyzer, ui->analyzer_home); + + gst_analyzer_start (gst_analyzer); + + analyzer_display_general_stream_info (gst_analyzer->video_info); + ui->analyze_idle_id = g_idle_add ((GSourceFunc) analyze_idle_callback, NULL); +done:{ + } +} + +void +callback_cancel_button_cancel (GtkWidget * widget, gpointer user_data) +{ + g_debug ("Cancel the analysis.. \n"); + + gtk_widget_set_sensitive (ui->cancel_button, FALSE); + + if (ui->analyze_idle_id) + g_source_remove (ui->analyze_idle_id); + + if (gst_analyzer) { + gst_analyzer_destroy (gst_analyzer); + gst_analyzer = NULL; + } + + /* display the frame contents which are already analyzed */ + analyzer_create_thumbnails (); + gtk_widget_set_sensitive (ui->analyze_button, TRUE); +} + +void +callback_stream_chooser_new_stream (GtkFileChooserButton * widget, + gpointer user_data) +{ + if (ui->file_name) + g_free (ui->file_name); + ui->file_name = gtk_file_chooser_get_filename ((GtkFileChooser *) widget); + + if (ui->uri) + g_free (ui->uri); + ui->uri = gtk_file_chooser_get_uri ((GtkFileChooser *) widget); + gtk_widget_set_sensitive (ui->analyze_button, TRUE); +} + +static void +menu_quit_callback () +{ + gtk_widget_destroy (ui->main_window); +} + +static void +menu_about_callback () +{ + GFile *license_file; + GdkPixbuf *logo; + gchar *contents = NULL; + gsize length = 0; + char *file_name; + char *authors[] = + { "Sreerenj Balachandran", "< sreerenj.balachandran@intel.com >", + NULL + }; + + file_name = g_build_filename (DATADIR, "codecanalyzer", "pixmaps", + "codecanalyzer-logo.png", NULL); + if (file_name) { + logo = gdk_pixbuf_new_from_file (file_name, NULL); + g_free (file_name); + } + + file_name = + g_build_filename (DATADIR, "codecanalyzer", "ui", "LICENSE.txt", NULL); + if (file_name) { + license_file = g_file_new_for_path (file_name); + if (license_file) { + g_file_load_contents (license_file, NULL, &contents, &length, NULL, NULL); + g_object_unref (G_OBJECT (license_file)); + } + g_free (file_name); + } + + gtk_show_about_dialog (GTK_WINDOW (ui->main_window), + "program-name", "Codecanalyzer", + "version", PACKAGE_VERSION, + "copyright", "Copyright © Intel Corporation", + "authors", authors, + "comments", "An analyzer for doing in-depth analysis on compressed media", + "license", contents, "logo", logo, NULL); + if (logo) + g_object_unref (G_OBJECT (logo)); + if (contents) + g_free (contents); +} + +static void +menu_help_callback () +{ + GtkWidget *dialog; + dialog = gtk_message_dialog_new (GTK_WINDOW (ui->main_window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, GTK_BUTTONS_OK, + "See https://github.com/Codecanalyzer/codecanalyzer/blob/master/README"); + gtk_window_set_title (GTK_WINDOW (dialog), "Help"); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); +} + +static GtkActionEntry entries_actiongroup[] = { + {"MediaMenuAction", NULL, "Media"}, + {"HelpMenuAction", NULL, "Help"}, + + {"QuitAction", GTK_STOCK_QUIT, + "Quit", "Q", + "Quit", + G_CALLBACK (menu_quit_callback)}, + + {"HelpAction", GTK_STOCK_HELP, + "Help", NULL, + "Help", + G_CALLBACK (menu_help_callback)}, + + {"AboutAction", GTK_STOCK_ABOUT, + "About", NULL, + "About", + G_CALLBACK (menu_about_callback)} +}; + +static gboolean +analyzer_ui_init () +{ + GtkActionGroup *action_group; + char *path; + + ui = g_slice_new0 (AnalyzerUI); + + path = + g_build_filename (DATADIR, "codecanalyzer", "ui", "mainwindow.xml", NULL); + ui->builder = make_builder (path); + g_free (path); + + ui->main_window = + get_widget_from_builder (ui->builder, "Codecanalyzer-main-window"); + ui->main_vbox = get_widget_from_builder (ui->builder, "MainVBox"); + ui->child_vbox1 = get_widget_from_builder (ui->builder, "child_vbox1"); + ui->child_vbox2 = get_widget_from_builder (ui->builder, "child_vbox2"); + ui->child_vbox3 = get_widget_from_builder (ui->builder, "child_vbox3"); + ui->menubar_vbox = get_widget_from_builder (ui->builder, "menubar_vbox"); + ui->stream_chooser = get_widget_from_builder (ui->builder, "StreamChooser"); + ui->numframes_chooser = + get_widget_from_builder (ui->builder, "NumFrameEntryButton"); + ui->analyze_button = get_widget_from_builder (ui->builder, "AnalyzeButton"); + ui->cancel_button = get_widget_from_builder (ui->builder, "CancelButton"); + ui->hbox1_in_vbox2 = get_widget_from_builder (ui->builder, "hbox1_in_vbox2"); + ui->child_hbox_in_vbox1_2 = get_widget_from_builder (ui->builder, + "child_hbox_in_vbox1_2"); + ui->thumbnails_scroll_window = + get_widget_from_builder (ui->builder, "thumbnails_scrolled_window"); + ui->thumbnails_view_port = + get_widget_from_builder (ui->builder, "thumbnails_view_port"); + ui->general_info_frame = + get_widget_from_builder (ui->builder, "general_info_frame"); + ui->general_info_vbox = + get_widget_from_builder (ui->builder, "general_info_vbox"); + ui->general_info_treeview = + get_widget_from_builder (ui->builder, "general_info_treeview"); + ui->parsed_info_hbox = + get_widget_from_builder (ui->builder, "parsed_info_hbox"); + ui->parsed_info_vbox = + get_widget_from_builder (ui->builder, "parsed_info_vbox"); + ui->parsed_info_frame = + get_widget_from_builder (ui->builder, "parsed_info_frame"); + ui->parsed_info_button_box = + get_widget_from_builder (ui->builder, "parsed_info_button_box"); + + /* Create menu */ + action_group = gtk_action_group_new ("ActionGroup"); + gtk_action_group_add_actions (action_group, entries_actiongroup, + G_N_ELEMENTS (entries_actiongroup), NULL); + ui->menu_manager = gtk_ui_manager_new (); + gtk_ui_manager_insert_action_group (ui->menu_manager, action_group, 0); + path = g_build_filename (DATADIR, "codecanalyzer", "ui", "menu.xml", NULL); + gtk_ui_manager_add_ui_from_file (ui->menu_manager, path, NULL); + g_free (path); + ui->menubar = gtk_ui_manager_get_widget (ui->menu_manager, "/MainMenu"); + gtk_box_pack_start (GTK_BOX (ui->menubar_vbox), ui->menubar, FALSE, FALSE, 0); + gtk_window_add_accel_group (GTK_WINDOW (ui->main_window), + gtk_ui_manager_get_accel_group (ui->menu_manager)); + + ui->notebook_hash = g_hash_table_new (g_str_hash, g_str_equal); + ui->prev_page = NULL; + ui->num_frames = 0; + + gtk_window_maximize (GTK_WINDOW (ui->main_window)); + + path = + g_build_filename (DATADIR, "codecanalyzer", "pixmaps", + "codecanalyzer-logo.png", NULL); + if (!gtk_window_set_icon_from_file (GTK_WINDOW (ui->main_window), path, NULL)) + g_warning ("Failed to load the icon image.. "); + g_free (path); + + return TRUE; +} + +static gboolean +analyzer_create_dirs () +{ + const gchar *user_cache_dir; + gchar *xml_files_path; + gchar *hex_files_path; + gboolean ret = TRUE; + + user_cache_dir = g_get_user_cache_dir(); + if (!user_cache_dir) { + ret = FALSE; + goto done; + } + + ui->analyzer_home = g_build_filename (user_cache_dir, "codecanalyzer", NULL); + + xml_files_path = g_build_filename (ui->analyzer_home, "xml", NULL); + if (g_mkdir_with_parents (xml_files_path, 0777) < 0){ + ret = FALSE; + goto done; + } + + hex_files_path = g_build_filename (ui->analyzer_home, "hex", NULL); + if (g_mkdir_with_parents (hex_files_path, 0777) < 0) { + ret = FALSE; + goto done; + } + + g_debug ("Analyzer_Home %s", ui->analyzer_home); + +done: + if (xml_files_path) + g_free (xml_files_path); + if (hex_files_path) + g_free (hex_files_path); + + return ret; +} + +int +main (int argc, char *argv[]) +{ + + gboolean ret; + gboolean debug_mode = FALSE; + GOptionContext *ctx; + GError *err = NULL; + GOptionEntry options[] = { + {"debug-mode", 'd', 0, G_OPTION_ARG_NONE, &debug_mode, "debug mode", NULL}, + {NULL} + }; + + gtk_init (&argc, &argv); + + ctx = g_option_context_new (" -codecanalyzer options"); + g_option_context_add_main_entries (ctx, options, NULL); + if (!g_option_context_parse (ctx, &argc, &argv, &err)) { + if (err) + g_printerr ("Failed to initialize: %s\n", err->message); + else + g_printerr ("Failed to initialize, Unknown error\n"); + exit (1); + } + g_option_context_free (ctx); + + if (debug_mode) { + g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL, + g_log_default_handler, NULL); + g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); + g_debug ("Codecanalyzer is in DEBUG_MODE.."); + } + + xmlKeepBlanksDefault (0); + + ret = analyzer_ui_init (); + if (!ret) { + g_error ("Failed to activate the gtk+-3.x backend \n"); + goto done; + } + + ret = analyzer_create_dirs (); + if (!ret) { + g_error ("Failed to create the necessary dir names \n"); + goto done; + } + + gtk_builder_connect_signals (ui->builder, NULL); + + gtk_widget_show_all (ui->main_window); + + gtk_main (); + +done: + g_printf ("Closing Codecanalyzer....\n"); + return 0; +} diff --git a/codecanalyzer/src/gst_analyzer.c b/codecanalyzer/src/gst_analyzer.c new file mode 100644 index 0000000000..74bd1bb361 --- /dev/null +++ b/codecanalyzer/src/gst_analyzer.c @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2013, Intel Corporation. + * Author: Sreerenj Balachandran + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the 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 St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +/* SECTION: gst-analyzer + * gst-analyzer is the back-end code of codecanalyzer + * which is for activating the whole gstreamer pipeline. + * The usual pipeline contains three gstreamer elements, + * a src(filesrc), parser(any video parser element supporing + * by the codecanalyzer and upstream gstreamer) and an + * analyzersink which is residing in plugins/gst/analzyersink. + */ +#include +#include +#include + +#include "gst_analyzer.h" +#include + +typedef struct +{ + const gint ret; + const gchar *name; +} GstAnalyzerStatusInfo; + +static GstAnalyzerStatusInfo analyzer_status_info[] = { + {GST_ANALYZER_STATUS_SUCCESS, "Success"}, + {GST_ANALYZER_STATUS_CODEC_PARSER_MISSING, "Codec Parser is missing"}, + {GST_ANALYZER_STATUS_CODEC_NOT_SUPPORTED, "Codec not supported"}, + {GST_ANALYZER_STATUS_STREAM_FORMAT_UNKNOWN, "Unknown stream format"}, + {GST_ANALYZER_STATUS_ERROR_UNKNOWN, "Failed to start the gstreamer engine"} +}; + +const gchar * +gst_analyzer_status_get_name (GstAnalyzerStatus status) +{ + gint i; + + for (i = 0; i < G_N_ELEMENTS (analyzer_status_info); i++) { + if (status == analyzer_status_info[i].ret) + return analyzer_status_info[i].name; + } + return "unknown"; +} + +typedef struct +{ + const gchar *discoverer_codec_name; + const gchar *codec_short_name; + GstAnalyzerCodecType codec_type; + gchar *parser_name; +} CodecInfo; + +static const CodecInfo codecs_info[] = { + + {"MPEG-2 Video", "mpeg2", GST_ANALYZER_CODEC_MPEG2_VIDEO, "mpegvideoparse"}, + {"H.264", "h264", GST_ANALYZER_CODEC_H264, "h264parse"}, + {"H.265", "h265", GST_ANALYZER_CODEC_H265, "h265parse"}, + {"UNKNOWN", "unknown", GST_ANALYZER_CODEC_UNKNOWN, NULL} +}; + +static const CodecInfo * +find_codec_info (gchar * name) +{ + guint i; + for (i = 0; i < G_N_ELEMENTS (codecs_info); ++i) { + if (!strcmp (name, codecs_info[i].discoverer_codec_name)) + return &codecs_info[i]; + } + return NULL; +} + +void +gst_analyzer_video_info_destroy (GstAnalyzerVideoInfo * analyzer_vinfo) +{ + g_return_if_fail (analyzer_vinfo != NULL); + + if (analyzer_vinfo->codec_name) + g_free (analyzer_vinfo->codec_name); + + g_slice_free (GstAnalyzerVideoInfo, analyzer_vinfo); +} + +gboolean +gst_analyzer_video_info_from_uri (GstAnalyzerVideoInfo * analyzer_vinfo, + gchar * uri) +{ + g_return_val_if_fail (analyzer_vinfo != NULL, FALSE); + g_return_val_if_fail (uri != NULL, FALSE); + + GstDiscoverer *discoverer = NULL; + GstDiscovererInfo *d_info = NULL; + GstDiscovererVideoInfo *dv_info = NULL; + GList *list = NULL; + GstCaps *caps = NULL; + + discoverer = gst_discoverer_new (3 * GST_SECOND, NULL); + g_return_val_if_fail (discoverer != NULL, FALSE); + + d_info = gst_discoverer_discover_uri (discoverer, uri, NULL); + g_return_val_if_fail (d_info != NULL, FALSE); + + list = gst_discoverer_info_get_video_streams (d_info); + g_return_val_if_fail (list != NULL && list->data != NULL, FALSE); + + caps = gst_discoverer_stream_info_get_caps ((GstDiscovererStreamInfo *) + list->data); + dv_info = (GstDiscovererVideoInfo *) list->data; + + if (caps) + analyzer_vinfo->codec_name = gst_pb_utils_get_codec_description (caps); + + analyzer_vinfo->width = gst_discoverer_video_info_get_width (dv_info); + analyzer_vinfo->height = gst_discoverer_video_info_get_height (dv_info); + analyzer_vinfo->depth = gst_discoverer_video_info_get_depth (dv_info); + analyzer_vinfo->avg_bitrate = gst_discoverer_video_info_get_bitrate (dv_info); + analyzer_vinfo->max_bitrate = + gst_discoverer_video_info_get_max_bitrate (dv_info); + analyzer_vinfo->fps_n = gst_discoverer_video_info_get_framerate_num (dv_info); + analyzer_vinfo->fps_d = + gst_discoverer_video_info_get_framerate_denom (dv_info); + analyzer_vinfo->par_n = gst_discoverer_video_info_get_par_num (dv_info); + analyzer_vinfo->par_d = gst_discoverer_video_info_get_par_denom (dv_info); + + gst_caps_unref (caps); + gst_discoverer_stream_info_list_free (list); + g_object_unref (discoverer); + + g_debug + ("codec=%s w=%d h=%d d=%d avg_bitrate=%d max_bitrate=%d fps_n=%d fps_d=%d par_n=%d par_d=%d \n", + analyzer_vinfo->codec_name, analyzer_vinfo->width, analyzer_vinfo->height, + analyzer_vinfo->depth, analyzer_vinfo->avg_bitrate, + analyzer_vinfo->max_bitrate, analyzer_vinfo->fps_n, analyzer_vinfo->fps_d, + analyzer_vinfo->par_n, analyzer_vinfo->par_d); + + return TRUE; +} + +GstAnalyzerVideoInfo * +gst_analyzer_video_info_new () +{ + GstAnalyzerVideoInfo *vinfo; + + vinfo = g_slice_new0 (GstAnalyzerVideoInfo); + + return vinfo; +} + +static void +new_frame_callback (GstElement * element, GstBuffer * buffer, gint frame_num, + gpointer data) +{ + GstAnalyzer *analyzer = (GstAnalyzer *) data; + + analyzer->NumOfAnalyzedFrames = frame_num + 1; + + if (analyzer->NumOfAnalyzedFrames == analyzer->NumOfFramesToAnalyze) + analyzer->complete_analyze = TRUE; +} + +static gboolean +bus_callback (GstBus * bus, GstMessage * message, gpointer data) +{ + GstAnalyzer *analyzer = (GstAnalyzer *) data; + + if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_EOS) { + g_printf ("<===Received EOS: All frames are analyzed====> \n"); + analyzer->complete_analyze = TRUE; + return FALSE; + } else if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR) { + GError *error = NULL; + gst_message_parse_error (message, &error, NULL); + g_error ("gstreamer error : %s", error->message); + g_error_free (error); + return FALSE; + } + return TRUE; +} + +void +gst_analyzer_destroy (GstAnalyzer * analyzer) +{ + if (analyzer) { + if (analyzer->video_info) + gst_analyzer_video_info_destroy (analyzer->video_info); + + if (analyzer->codec_name) + g_free (analyzer->codec_name); + + gst_analyzer_stop (analyzer); + g_slice_free (GstAnalyzer, analyzer); + } +} + +void +gst_analyzer_set_file_name (GstAnalyzer * analyzer, char *uri) +{ + g_object_set (G_OBJECT (analyzer->src), "location", uri, NULL); +} + +void +gst_analyzer_set_destination_dir_path (GstAnalyzer * analyzer, char *path) +{ + g_object_set (G_OBJECT (analyzer->sink), "location", path, NULL); + g_debug ("Destination for xml_files and hex_files %s ", path); +} + +void +gst_analyzer_set_num_frames (GstAnalyzer * analyzer, gint frame_count) +{ + g_object_set (G_OBJECT (analyzer->sink), "num-frames", frame_count, NULL); + analyzer->NumOfFramesToAnalyze = frame_count; +} + +gboolean +gst_analyzer_stop (GstAnalyzer * analyzer) +{ + if (analyzer->pipeline) + gst_element_set_state (analyzer->pipeline, GST_STATE_NULL); + + if (analyzer->bus_watch_id) + g_source_remove (analyzer->bus_watch_id); + + return TRUE; +} + +gboolean +gst_analyzer_start (GstAnalyzer * analyzer) +{ + gst_element_set_state (analyzer->pipeline, GST_STATE_PLAYING); + return TRUE; +} + +GstAnalyzerStatus +gst_analyzer_init (GstAnalyzer * analyzer, char *uri) +{ + GstAnalyzerStatus status = GST_ANALYZER_STATUS_ERROR_UNKNOWN; + const CodecInfo *codec_info; + GstBus *bus; + gboolean ret; + + analyzer->NumOfAnalyzedFrames = 0; + analyzer->complete_analyze = FALSE; + analyzer->NumOfFramesToAnalyze = -1; + + if (!gst_is_initialized ()) + gst_init (NULL, NULL); + + if (!analyzer_sink_register_static ()) { + g_error ("Failed to register static plugins.... \n"); + status = GST_ANALYZER_STATUS_CODEC_PARSER_MISSING; + goto error; + } + + /* GstDiscoverer to extract general stream info */ + analyzer->video_info = gst_analyzer_video_info_new (); + ret = gst_analyzer_video_info_from_uri (analyzer->video_info, uri); + + if (ret && analyzer->video_info->codec_name) + codec_info = find_codec_info (analyzer->video_info->codec_name); + + if (!ret || codec_info == NULL + || codec_info->codec_type == GST_ANALYZER_CODEC_UNKNOWN) { + status = GST_ANALYZER_STATUS_STREAM_FORMAT_UNKNOWN; + goto error; + } + + if (ret && codec_info) { + switch (codec_info->codec_type) { + case GST_ANALYZER_CODEC_MPEG2_VIDEO: + status = GST_ANALYZER_STATUS_SUCCESS; + break; + default: + status = GST_ANALYZER_STATUS_CODEC_NOT_SUPPORTED; + goto error; + break; + } + } + analyzer->codec_name = g_strdup (codec_info->codec_short_name); + + analyzer->src = gst_element_factory_make ("filesrc", "file-src"); + analyzer->parser = + gst_element_factory_make (codec_info->parser_name, + "codec-analyzer-video-parse"); + analyzer->sink = gst_element_factory_make ("analyzersink", "sink"); + analyzer->pipeline = gst_pipeline_new ("pipeline"); + + if (!analyzer->src || !analyzer->parser || !analyzer->sink) { + g_error ("Failed to create the necessary gstreamer elements.."); + status = GST_ANALYZER_STATUS_ERROR_UNKNOWN; + goto error; + } + + g_signal_connect (analyzer->sink, "new-frame", (GCallback) new_frame_callback, + analyzer); + if (!strcmp (analyzer->codec_name, "mpeg2")) + g_object_set (G_OBJECT (analyzer->parser), "drop", FALSE, NULL); + + gst_bin_add_many (GST_BIN (analyzer->pipeline), analyzer->src, + analyzer->parser, analyzer->sink, NULL); + gst_element_link_many (analyzer->src, analyzer->parser, analyzer->sink, NULL); + + bus = gst_pipeline_get_bus (GST_PIPELINE (analyzer->pipeline)); + analyzer->bus_watch_id = gst_bus_add_watch (bus, bus_callback, analyzer); + gst_object_unref (GST_OBJECT (bus)); + + return status; + +error: + return status; +} diff --git a/codecanalyzer/src/gst_analyzer.h b/codecanalyzer/src/gst_analyzer.h new file mode 100644 index 0000000000..81d4a91f02 --- /dev/null +++ b/codecanalyzer/src/gst_analyzer.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013, Intel Corporation. + * Author: Sreerenj Balachandran + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the 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 St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#ifndef __GST_ANALYZER__ +#define __GST_ANALYZER__ + +#include +#include +#include +#include +#include + +typedef struct _GstAnalyzer GstAnalyzer; +typedef struct _GstAnalyzerVideoInfo GstAnalyzerVideoInfo; + +typedef enum { + GST_ANALYZER_STATUS_SUCCESS = 0, + GST_ANALYZER_STATUS_CODEC_PARSER_MISSING = 1, + GST_ANALYZER_STATUS_CODEC_NOT_SUPPORTED = 2, + GST_ANALYZER_STATUS_STREAM_FORMAT_UNKNOWN = 3, + GST_ANALYZER_STATUS_ERROR_UNKNOWN = 4 +} GstAnalyzerStatus; + +const gchar* gst_analyzer_status_get_name (GstAnalyzerStatus status); + +typedef enum { + GST_ANALYZER_CODEC_UNKNOWN = 0, + GST_ANALYZER_CODEC_MPEG2_VIDEO = 1, + GST_ANALYZER_CODEC_H264 = 2, + GST_ANALYZER_CODEC_VC1 = 3, + GST_ANALYZER_CODEC_MPEG4_PART_TWO = 4, + GST_ANALYZER_CODEC_H265 = 5, + GST_ANALYZER_CODEC_VP8 = 6, + GST_ANALYZER_CODEC_VP9 = 7 +} GstAnalyzerCodecType; + +struct _GstAnalyzerVideoInfo +{ + gchar *codec_name; + guint width; + guint height; + guint depth; + guint avg_bitrate; + guint max_bitrate; + guint fps_n; + guint fps_d; + guint par_n; + guint par_d; +}; + +struct _GstAnalyzer +{ + GstAnalyzerVideoInfo *video_info; + + gchar *codec_name; + + GstElement *pipeline; + GstElement *src; + GstElement *parser; + GstElement *sink; + + guint bus_watch_id; + + gboolean complete_analyze; + gint NumOfFramesToAnalyze; + gint NumOfAnalyzedFrames; +}; + +GstAnalyzerStatus gst_analyzer_init (GstAnalyzer *analyzer, char *uri); + +void gst_analyzer_set_file_name (GstAnalyzer *analyzer, + char *file_name); + +void gst_analyzer_set_destination_dir_path (GstAnalyzer * analyzer, + char *uri); + +void gst_analyzer_set_num_frames (GstAnalyzer *analyzer, + gint num_frames); + +gboolean gst_analyzer_start (GstAnalyzer *analyzer); + +gboolean gst_analyzer_stop (GstAnalyzer *analyzer); + +void gst_analyzer_destory (GstAnalyzer *analyzer); + +GstAnalyzerVideoInfo *gst_analyzer_video_info_new (); + +gboolean gst_analyzer_video_info_from_uri (GstAnalyzerVideoInfo *vinfo, gchar *uri); + +void gst_analyzer_video_info_destroy (GstAnalyzerVideoInfo *video_info); + +#endif /* __GST_ANALYZER__ */ diff --git a/codecanalyzer/src/plugins/Makefile.am b/codecanalyzer/src/plugins/Makefile.am new file mode 100644 index 0000000000..d5356a6f97 --- /dev/null +++ b/codecanalyzer/src/plugins/Makefile.am @@ -0,0 +1,4 @@ +SUBDIRS = gst + +# Extra clean files so that maintainer-clean removes *everything* +MAINTAINERCLEANFILES = Makefile.in diff --git a/codecanalyzer/src/plugins/gst/Makefile.am b/codecanalyzer/src/plugins/gst/Makefile.am new file mode 100644 index 0000000000..9355164200 --- /dev/null +++ b/codecanalyzer/src/plugins/gst/Makefile.am @@ -0,0 +1,4 @@ +SUBDIRS = analyzersink + +# Extra clean files so that maintainer-clean removes *everything* +MAINTAINERCLEANFILES = Makefile.in diff --git a/codecanalyzer/src/plugins/gst/analyzersink/Makefile.am b/codecanalyzer/src/plugins/gst/analyzersink/Makefile.am new file mode 100644 index 0000000000..a6b00715b2 --- /dev/null +++ b/codecanalyzer/src/plugins/gst/analyzersink/Makefile.am @@ -0,0 +1,44 @@ +noinst_LTLIBRARIES = \ + libcodecanalyzer-gst-analyzersink.la \ + $(NULL) + +noinst_HEADERS = gstanalyzersink.h mpeg_xml.h xml_utils.h analyzer_utils.h + +libcodecanalyzer_gst_analyzersink_cflags = \ + -DGST_USE_UNSTABLE_API \ + $(GST_BASE_CFLAGS) \ + $(GST_VIDEO_CFLAGS) \ + $(GST_CFLAGS) \ + $(GST_CODEC_PARSERS_CFLAGS) \ + $(LIBXML2_CFLAGS) \ + $(NULL) + +libcodecanalyzer_gst_analyzersink_libs = \ + $(GST_BASE_LIBS) \ + $(GST_LIBS) \ + $(GST_VIDEO_LIBS) \ + $(GST_CODEC_PARSERS_LIBS) \ + $(LIBXML2_LIBS) \ + $(NULL) + +libcodecanalyzer_gst_analyzersink_la_SOURCES = \ + gstanalyzersink.c \ + mpeg_xml.c \ + plugin.c \ + analyzer_utils.c \ + $(NULL) + +libcodecanalyzer_gst_analyzersink_la_CFLAGS = \ + $(libcodecanalyzer_gst_analyzersink_cflags) \ + $(NULL) + +libcodecanalyzer_gst_analyzersink_la_LIBADD = \ + $(libcodecanalyzer_gst_analyzersink_libs) -lgstcodecparsers-1.0 \ + $(NULL) + +libcodecanalyzer_gst_analyzersink_la_LDFLAGS = \ + $(GST_ALL_LDFLAGS) \ + $(NULL) + +# Extra clean files so that maintainer-clean removes *everything* +MAINTAINERCLEANFILES = Makefile.in diff --git a/codecanalyzer/src/plugins/gst/analyzersink/analyzer_utils.c b/codecanalyzer/src/plugins/gst/analyzersink/analyzer_utils.c new file mode 100644 index 0000000000..4a91cc39a0 --- /dev/null +++ b/codecanalyzer/src/plugins/gst/analyzersink/analyzer_utils.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013, Intel Corporation. + * Author: Sreerenj Balachandran + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the 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 St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#include "analyzer_utils.h" +#include "gstanalyzersink.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gboolean ret = FALSE; + + ret |= gst_element_register (plugin, "analyzersink", + GST_RANK_PRIMARY + 1, GST_TYPE_ANALYZER_SINK); + + return ret; +} + +gboolean +analyzer_sink_register_static () +{ + return gst_plugin_register_static (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "analzsersink", + "sink element to dump parsed information to the xml", + plugin_init, VERSION, "LGPL", "codecanalyzer", PACKAGE_NAME, PACKAGE_URL); +} diff --git a/codecanalyzer/src/plugins/gst/analyzersink/analyzer_utils.h b/codecanalyzer/src/plugins/gst/analyzersink/analyzer_utils.h new file mode 100644 index 0000000000..cc62a5e31c --- /dev/null +++ b/codecanalyzer/src/plugins/gst/analyzersink/analyzer_utils.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2013, Intel Corporation. + * Author: Sreerenj Balachandran + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the 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 St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#ifndef __ANALYZER_UTILS__ +#define __ANALYZER_UTILS__ + +#include + +gboolean +analyzer_sink_register_static (); + +#endif diff --git a/codecanalyzer/src/plugins/gst/analyzersink/gstanalyzersink.c b/codecanalyzer/src/plugins/gst/analyzersink/gstanalyzersink.c new file mode 100644 index 0000000000..6301104e8d --- /dev/null +++ b/codecanalyzer/src/plugins/gst/analyzersink/gstanalyzersink.c @@ -0,0 +1,446 @@ +/* + * Copyright (c) <2013-2014>, Intel Corporation. + * Author: Sreerenj Balachandran + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the 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 St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +/*SECTION: analyzersink + * A sink element to generate xml and hex files for each + * video frame providing by the upstream parser element + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gstanalyzersink.h" + +#include + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/mpeg, mpegversion=2" ";" + "video/x-h264" ";" "video/x-h265")); + +/* AnalyzerSink signals and args */ +enum +{ + SIGNAL_NEW_FRAME, + LAST_SIGNAL +}; + +#define DEFAULT_SYNC FALSE +#define DEFAULT_DUMP TRUE +#define DEFAULT_NUM_BUFFERS -1 + +enum +{ + PROP_0, + PROP_LOCATION, + PROP_SILENT, + PROP_DUMP, + PROP_NUM_BUFFERS +}; + +#define gst_analyzer_sink_parent_class parent_class +G_DEFINE_TYPE (GstAnalyzerSink, gst_analyzer_sink, GST_TYPE_BASE_SINK); + +static gboolean gst_analyzer_sink_set_caps (GstBaseSink * sink, GstCaps * caps); +static void gst_analyzer_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_analyzer_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_analyzer_sink_finalize (GObject * obj); + +static GstStateChangeReturn gst_analyzer_sink_change_state (GstElement * + element, GstStateChange transition); + +static GstFlowReturn gst_analyzer_sink_render (GstBaseSink * bsink, + GstBuffer * buffer); +static gboolean gst_analyzer_sink_event (GstBaseSink * bsink, GstEvent * event); +static gboolean gst_analyzer_sink_query (GstBaseSink * bsink, GstQuery * query); + +static guint gst_analyzer_sink_signals[LAST_SIGNAL] = { 0 }; + +static void +gst_analyzer_sink_class_init (GstAnalyzerSinkClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseSinkClass *gstbase_sink_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + gstbase_sink_class = GST_BASE_SINK_CLASS (klass); + + gstbase_sink_class->set_caps = gst_analyzer_sink_set_caps; + gobject_class->set_property = gst_analyzer_sink_set_property; + gobject_class->get_property = gst_analyzer_sink_get_property; + gobject_class->finalize = gst_analyzer_sink_finalize; + + g_object_class_install_property (gobject_class, PROP_LOCATION, + g_param_spec_string ("location", "xml/hex files location", + "Location of the xml/hex folder/files to write", NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_DUMP, + g_param_spec_boolean ("dump", "Dump", + "Dump frame contents as hex to the specified location", DEFAULT_DUMP, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_NUM_BUFFERS, + g_param_spec_int ("num-frames", "num-frames", + "Number of frames to accept before going EOS", -1, G_MAXINT, + DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstAnalyzerSink::new-frame: + * @analyzersink: the analyzersink instance + * @buffer: the buffer that just has been received and analysed + * @frame_num: the frame count + * + * This signal gets emitted before unreffing the buffer. + */ + gst_analyzer_sink_signals[SIGNAL_NEW_FRAME] = + g_signal_new ("new-frame", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstAnalyzerSinkClass, new_frame), NULL, NULL, + g_cclosure_marshal_generic, G_TYPE_NONE, 2, + GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE, G_TYPE_INT); + + gst_element_class_set_static_metadata (gstelement_class, + "Codec Analyzer Sink", + "Sink", + "Sink to dump the parsed information", + "Sreerenj Balachandran"); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sinktemplate)); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_analyzer_sink_change_state); + + gstbase_sink_class->event = GST_DEBUG_FUNCPTR (gst_analyzer_sink_event); + gstbase_sink_class->render = GST_DEBUG_FUNCPTR (gst_analyzer_sink_render); + gstbase_sink_class->query = GST_DEBUG_FUNCPTR (gst_analyzer_sink_query); +} + +static void +gst_analyzer_sink_init (GstAnalyzerSink * analyzersink) +{ + analyzersink->dump = DEFAULT_DUMP; + analyzersink->num_buffers = DEFAULT_NUM_BUFFERS; + analyzersink->codec_type = GST_ANALYZER_CODEC_UNKNOWN; + analyzersink->frame_num = 0; + analyzersink->location = NULL; + /* XXX: Add a generic structure to handle different codecs */ + analyzersink->mpeg2_hdrs = g_slice_new0 (Mpeg2Headers); + gst_base_sink_set_sync (GST_BASE_SINK (analyzersink), DEFAULT_SYNC); +} + +static void +gst_analyzer_sink_finalize (GObject * obj) +{ + GstAnalyzerSink *sink = GST_ANALYZER_SINK (obj); + + if (sink->location) + g_free (sink->location); + + if (sink->mpeg2_hdrs) { + if (sink->mpeg2_hdrs->sequencehdr) + g_slice_free (GstMpegVideoSequenceHdr, sink->mpeg2_hdrs->sequencehdr); + if (sink->mpeg2_hdrs->sequenceext) + g_slice_free (GstMpegVideoSequenceExt, sink->mpeg2_hdrs->sequenceext); + if (sink->mpeg2_hdrs->sequencedispext) + g_slice_free (GstMpegVideoSequenceDisplayExt, + sink->mpeg2_hdrs->sequencedispext); + if (sink->mpeg2_hdrs->quantext) + g_slice_free (GstMpegVideoQuantMatrixExt, sink->mpeg2_hdrs->quantext); + g_slice_free (Mpeg2Headers, sink->mpeg2_hdrs); + } + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static gboolean +gst_analyzer_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) +{ + GstStructure *structure; + GstAnalyzerSink *sink = GST_ANALYZER_SINK (bsink); + + if (!caps) + return FALSE; + + structure = gst_caps_get_structure (caps, 0); + const gchar *name = gst_structure_get_name (structure); + + if (!strcmp (name, "video/mpeg")) + sink->codec_type = GST_ANALYZER_CODEC_MPEG2_VIDEO; + else + return FALSE; + + return TRUE; +} + +static void +gst_analyzer_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstAnalyzerSink *sink; + const gchar *location; + + sink = GST_ANALYZER_SINK (object); + + switch (prop_id) { + case PROP_LOCATION: + location = g_value_get_string (value); + if (sink->location) + g_free (sink->location); + sink->location = g_strdup (location); + break; + case PROP_DUMP: + sink->dump = g_value_get_boolean (value); + break; + case PROP_NUM_BUFFERS: + sink->num_buffers = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_analyzer_sink_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstAnalyzerSink *sink; + + sink = GST_ANALYZER_SINK (object); + + switch (prop_id) { + case PROP_LOCATION: + g_value_set_string (value, sink->location); + break; + case PROP_DUMP: + g_value_set_boolean (value, sink->dump); + break; + case PROP_NUM_BUFFERS: + g_value_set_int (value, sink->num_buffers); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_analyzer_sink_event (GstBaseSink * bsink, GstEvent * event) +{ + GstAnalyzerSink *sink = GST_ANALYZER_SINK (bsink); + + return GST_BASE_SINK_CLASS (parent_class)->event (bsink, event); +} + +static gboolean +gst_analyzer_sink_dump_mem (GstAnalyzerSink * sink, const guchar * mem, + guint size) +{ + GString *string; + FILE *fd; + gchar *name; + gchar *file_name; + guint i = 0, j = 0; + + GST_DEBUG ("dump frame content with size = %d", size); + + /* XXX: Add a generic structure to handle different codec name string + * For now analyzersink can only handle mpeg2meta:*/ + + /* create a new hex file for each frame */ + name = g_strdup_printf ("mpeg2-%d.hex", sink->frame_num); + file_name = g_build_filename (sink->location, "hex", name, NULL); + GST_LOG ("Created a New hex file %s to dump the content", file_name); + free (name); + + fd = fopen (file_name, "w"); + if (fd == NULL) + return FALSE; + + string = g_string_sized_new (50); + + while (i < size) { + g_string_append_printf (string, "%02x ", mem[i]); + + j++; + i++; + + if (j == 32 || i == size) { + fprintf (fd, "%s \n", string->str); + g_string_set_size (string, 0); + j = 0; + } + } + g_string_free (string, TRUE); + if (file_name) + g_free (file_name); + + fclose (fd); + return TRUE; +} + +static GstFlowReturn +gst_analyzer_sink_render (GstBaseSink * bsink, GstBuffer * buf) +{ + GstAnalyzerSink *sink = GST_ANALYZER_SINK_CAST (bsink); + GstMpegVideoMeta *mpeg_meta; + gboolean ret; + + if (sink->num_buffers_left == 0) + goto eos; + + if (sink->num_buffers_left != -1) + sink->num_buffers_left--; + + if (sink->dump) { + GstMapInfo info; + + gst_buffer_map (buf, &info, GST_MAP_READ); + ret = gst_analyzer_sink_dump_mem (sink, info.data, info.size); + gst_buffer_unmap (buf, &info); + } + + switch (sink->codec_type) { + case GST_ANALYZER_CODEC_MPEG2_VIDEO: + { + mpeg_meta = gst_buffer_get_mpeg_video_meta (buf); + if (!mpeg_meta) + goto no_mpeg_meta; + + GST_DEBUG_OBJECT (sink, + "creatin mpeg2video_frame_xml for mpeg2frame with num=%d \n", + sink->frame_num); + if (!analyzer_create_mpeg2video_frame_xml (mpeg_meta, sink->location, + sink->frame_num, sink->mpeg2_hdrs)) + goto error_create_xml; + } + break; + + case GST_ANALYZER_CODEC_H264: + case GST_ANALYZER_CODEC_VC1: + case GST_ANALYZER_CODEC_MPEG4_PART_TWO: + case GST_ANALYZER_CODEC_H265: + { + GST_WARNING ("No codec support in analyzer sink"); + goto unknown_codec; + } + break; + + case GST_ANALYZER_CODEC_UNKNOWN: + default: + goto unknown_codec; + } + + g_signal_emit (sink, gst_analyzer_sink_signals[SIGNAL_NEW_FRAME], 0, buf, + sink->frame_num); + sink->frame_num++; + + if (sink->num_buffers_left == 0) + goto eos; + + return GST_FLOW_OK; + + /* ERRORS */ +no_mpeg_meta: + { + GST_DEBUG_OBJECT (sink, "no mpeg meta"); + return GST_FLOW_EOS; + } +unknown_codec: + { + GST_DEBUG_OBJECT (sink, "unknown codec"); + return GST_FLOW_EOS; + } +error_create_xml: + { + GST_DEBUG_OBJECT (sink, "failed to create xml for meta"); + return GST_FLOW_EOS; + } +eos: + { + GST_DEBUG_OBJECT (sink, "we are EOS"); + return GST_FLOW_EOS; + } +} + +static gboolean +gst_analyzer_sink_query (GstBaseSink * bsink, GstQuery * query) +{ + gboolean ret; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_SEEKING:{ + GstFormat fmt; + + /* we don't supporting seeking */ + gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); + gst_query_set_seeking (query, fmt, FALSE, 0, -1); + ret = TRUE; + break; + } + default: + ret = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query); + break; + } + + return ret; +} + +static GstStateChangeReturn +gst_analyzer_sink_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstAnalyzerSink *analyzersink = GST_ANALYZER_SINK (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + analyzersink->num_buffers_left = analyzersink->num_buffers; + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + 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: + break; + default: + break; + } + + return ret; + + /* ERROR */ +error: + GST_ELEMENT_ERROR (element, CORE, STATE_CHANGE, (NULL), + ("Erroring out on state change as requested")); + return GST_STATE_CHANGE_FAILURE; +} diff --git a/codecanalyzer/src/plugins/gst/analyzersink/gstanalyzersink.h b/codecanalyzer/src/plugins/gst/analyzersink/gstanalyzersink.h new file mode 100644 index 0000000000..b97ac566c9 --- /dev/null +++ b/codecanalyzer/src/plugins/gst/analyzersink/gstanalyzersink.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013, Intel Corporation. + * Author: Sreerenj Balachandran + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the 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 St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef __GST_ANALYZER_SINK_H__ +#define __GST_ANALYZER_SINK_H__ + +#include +#include +#include +#include +#include "mpeg_xml.h" + +G_BEGIN_DECLS + +#define GST_TYPE_ANALYZER_SINK \ + (gst_analyzer_sink_get_type()) +#define GST_ANALYZER_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ANALYZER_SINK,GstAnalyzerSink)) +#define GST_ANALYZER_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ANALYZER_SINK,GstAnalyzerSinkClass)) +#define GST_IS_ANALYZER_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ANALYZER_SINK)) +#define GST_IS_ANALYZER_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ANALYZER_SINK)) +#define GST_ANALYZER_SINK_CAST(obj) ((GstAnalyzerSink *)obj) + +typedef enum { + GST_ANALYZER_CODEC_UNKNOWN = 0, + GST_ANALYZER_CODEC_MPEG2_VIDEO = 1, + GST_ANALYZER_CODEC_H264 = 2, + GST_ANALYZER_CODEC_VC1 = 3, + GST_ANALYZER_CODEC_MPEG4_PART_TWO = 4, + GST_ANALYZER_CODEC_H265 = 5, + GST_ANALYZER_CODEC_VP8 = 6, + GST_ANALYZER_CODEC_VP9 = 7 +} GstAnalyzerCodecType; + +typedef struct _GstAnalyzerSink GstAnalyzerSink; +typedef struct _GstAnalyzerSinkClass GstAnalyzerSinkClass; + +/** + * GstAnalyzerSink: + * + * The opaque #GstAnalyzerSink data structure. + */ +struct _GstAnalyzerSink { + GstBaseSink element; + + gboolean dump; + gint num_buffers; + gint num_buffers_left; + gint frame_num; + gchar* location; + + GstAnalyzerCodecType codec_type; + + /* codec specific headers */ + Mpeg2Headers *mpeg2_hdrs; +}; + +struct _GstAnalyzerSinkClass { + GstBaseSinkClass parent_class; + + /* signals */ + void (*new_frame) (GstElement *element, GstBuffer *buf, gint frame_num); +}; + +G_GNUC_INTERNAL GType gst_analyzer_sink_get_type (void); + +G_END_DECLS + +#endif /* __GST_ANALYZER_SINK_H__ */ diff --git a/codecanalyzer/src/plugins/gst/analyzersink/mpeg_xml.c b/codecanalyzer/src/plugins/gst/analyzersink/mpeg_xml.c new file mode 100644 index 0000000000..adfd7effc9 --- /dev/null +++ b/codecanalyzer/src/plugins/gst/analyzersink/mpeg_xml.c @@ -0,0 +1,566 @@ +/* + * Copyright (c) 2013, Intel Corporation. + * Author: Sreerenj Balachandran + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the 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 St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "mpeg_xml.h" +#include "xml_utils.h" + + +static gboolean +create_seq_hdr_xml (xmlTextWriterPtr writer, GstMpegVideoSequenceHdr * seq_hdr) +{ + ANALYZER_XML_ELEMENT_START (writer, "SequenceHdr"); + + ANALYZER_XML_ELEMENT_CREATE_STRING (writer, "sequence_hdr_id", "0xb3", + "nbits", 8); + + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "horizontal_size_value", + seq_hdr->width, "nbits", 12); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "vertical_size_value", + seq_hdr->height, "nbits", 12); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "aspect_ratio_information", + seq_hdr->aspect_ratio_info, "nbits", 4); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "frame_rate_code", + seq_hdr->frame_rate_code, "nbits", 4); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "bit_rate_value", + seq_hdr->bitrate_value, "nbits", 18); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "vbv_buffer_size_value", + seq_hdr->vbv_buffer_size_value, "nbits", 10); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "constrained_parameters_flag", + seq_hdr->constrained_parameters_flag, "nbits", 1); +#if 0 + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "load_intra_quantiser_matrix", + seq_hdr->load_intra_quantiser_matrix, "nbits", 1); +#endif + ANALYZER_XML_ELEMENT_CREATE_MATRIX (writer, "intra_quantiser_matrix", + seq_hdr->intra_quantizer_matrix, 8, 8); +#if 0 + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "load_non_intra_quantiser_matrix", + seq_hdr->load_non_intra_quantiser_matrix, "nbits", 1); +#endif + ANALYZER_XML_ELEMENT_CREATE_MATRIX (writer, "non_intra_quantizer_matrix", + seq_hdr->non_intra_quantizer_matrix, 8, 8); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "bit_rate_calculated", + seq_hdr->bitrate, "nbits", 0); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "par_w_calculated", + seq_hdr->par_w, "nbits", 0); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "par_h_calculated", + seq_hdr->par_h, "nbits", 0); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "fps_n_calculated", + seq_hdr->fps_n, "nbits", 0); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "fps_d_calculated", + seq_hdr->fps_d, "nbits", 0); + + + ANALYZER_XML_ELEMENT_END (writer); + + return TRUE; + +error: + { + GST_ERROR ("Failed to write the xml for Mpeg2Video SequenceHeader \n"); + return FALSE; + } +} + +static gboolean +create_seq_ext_xml (xmlTextWriterPtr writer, GstMpegVideoSequenceExt * seq_ext) +{ + ANALYZER_XML_ELEMENT_START (writer, "SequenceExt"); + + ANALYZER_XML_ELEMENT_CREATE_STRING (writer, "extension_identifier", "0xb5", + "nbits", 8); + ANALYZER_XML_ELEMENT_CREATE_STRING (writer, "sequence_extension_id", "0x01", + "nbits", 4); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "profile", seq_ext->profile, "nbits", + 3); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "level", seq_ext->level, "nbits", 4); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "progressive_sequence", + seq_ext->progressive, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "chroma_fromat", + seq_ext->chroma_format, "nbits", 2); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "horizontal_size_ext", + seq_ext->horiz_size_ext, "nbits", 2); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "vertical_size_ext", + seq_ext->vert_size_ext, "nbits", 2); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "bit_rate_ext", seq_ext->bitrate_ext, + "nbits", 12); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "vbv_buffer_size_ex", + seq_ext->vbv_buffer_size_extension, "nbits", 8); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "low_delay", seq_ext->low_delay, + "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "fps_ext_n", seq_ext->fps_n_ext, + "nbits", 2); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "fps_ext_d", seq_ext->fps_d_ext, + "nbits", 5); + + ANALYZER_XML_ELEMENT_END (writer); + + return TRUE; + +error: + { + GST_ERROR ("Failed to write the xml for Mpeg2Video SequenceExt \n"); + return FALSE; + } +} + +static gboolean +create_seq_disp_ext_xml (xmlTextWriterPtr writer, + GstMpegVideoSequenceDisplayExt * seq_disp_ext) +{ + ANALYZER_XML_ELEMENT_START (writer, "SequenceDispExt"); + + ANALYZER_XML_ELEMENT_CREATE_STRING (writer, "extension_identifier", "0xb5", + "nbits", 8); + ANALYZER_XML_ELEMENT_CREATE_STRING (writer, "sequence_display_extension_id", + "0x02", "nbits", 4); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "video_format", + seq_disp_ext->video_format, "nbits", 3); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "colour_description_flag", + seq_disp_ext->colour_description_flag, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "colour_primaries", + seq_disp_ext->colour_primaries, "nbits", 8); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "transfer_characteristics", + seq_disp_ext->transfer_characteristics, "nbits", 8); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "matrix_coefficients", + seq_disp_ext->matrix_coefficients, "nbits", 8); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "display_horizontal_size", + seq_disp_ext->display_horizontal_size, "nbits", 14); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "display_vertical_size", + seq_disp_ext->display_vertical_size, "nbits", 14); + + ANALYZER_XML_ELEMENT_END (writer); + + return TRUE; + +error: + { + GST_ERROR ("Failed to write the xml for Mpeg2Video SequenceDisplayExt \n"); + return FALSE; + } +} + +static gboolean +create_gop_hdr_xml (xmlTextWriterPtr writer, GstMpegVideoGop * gop_hdr) +{ + ANALYZER_XML_ELEMENT_START (writer, "GopHdr"); + + ANALYZER_XML_ELEMENT_CREATE_STRING (writer, "gop_hdr_id", "0xb8", "nbits", 8); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "drop_frame_flag", + gop_hdr->drop_frame_flag, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "time_code_hours", gop_hdr->hour, + "nbits", 5); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "time_code_minutes", gop_hdr->minute, + "nbits", 6); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "time_code_seconds", gop_hdr->second, + "nbits", 6); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "time_code_pictures", gop_hdr->frame, + "nbits", 6); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "closed_gop", gop_hdr->closed_gop, + "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "broken_link", gop_hdr->broken_link, + "nbits", 1); + ANALYZER_XML_ELEMENT_END (writer); + + return TRUE; +error: + { + GST_ERROR ("Failed to write the xml for Mpeg2Video GopHdr \n"); + return FALSE; + } +} + +static gboolean +create_pic_hdr_xml (xmlTextWriterPtr writer, GstMpegVideoPictureHdr * pic_hdr) +{ + ANALYZER_XML_ELEMENT_START (writer, "PicHdr"); + + ANALYZER_XML_ELEMENT_CREATE_STRING (writer, "picture_hdr_id", "0x00", + "nbits", 8); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "temporal_reference", pic_hdr->tsn, + "nbits", 10); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "picture_coding_type", + pic_hdr->pic_type, "nbits", 3); +#if 0 + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "vbv_delay", pic_hdr->vbv_delay, + "nbits", 16); +#endif + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "full_pel_forward_vector", + pic_hdr->full_pel_forward_vector, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "forward_f_code", + pic_hdr->f_code[0][0], "nbits", 3); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "full_pel_backword_vector", + pic_hdr->full_pel_backward_vector, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "backword_f_code", + pic_hdr->f_code[1][0], "nbits", 3); + + ANALYZER_XML_ELEMENT_END (writer); + + return TRUE; +error: + { + GST_ERROR ("Failed to write the xml for Mpeg2Video PicHdr \n"); + return FALSE; + } +} + +static gboolean +create_pic_ext_xml (xmlTextWriterPtr writer, GstMpegVideoPictureExt * pic_ext) +{ + ANALYZER_XML_ELEMENT_START (writer, "PicExt"); + + ANALYZER_XML_ELEMENT_CREATE_STRING (writer, "extension_identifier", "0xb5", + "nbits", 8); + ANALYZER_XML_ELEMENT_CREATE_STRING (writer, "picture_extension_id", "0x08", + "nbits", 4); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "f_code_forward_horizontal", + pic_ext->f_code[0][0], "nbits", 4); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "f_code_forward_vertical", + pic_ext->f_code[0][1], "nbits", 4); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "f_code_backward_horizontal", + pic_ext->f_code[1][0], "nbits", 4); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "f_cod_backward_vertical", + pic_ext->f_code[1][1], "nbits", 4); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "intra_dc_precision", + pic_ext->intra_dc_precision, "nbits", 2); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "picture_structure", + pic_ext->picture_structure, "nbits", 2); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "top_field_first", + pic_ext->top_field_first, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "frame_pred_frame_dct", + pic_ext->frame_pred_frame_dct, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "concealment_motion_vectors", + pic_ext->concealment_motion_vectors, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "q_scale_type", + pic_ext->q_scale_type, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "intra_vlc_format", + pic_ext->intra_vlc_format, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "alternate_scan", + pic_ext->alternate_scan, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "repeat_first_field", + pic_ext->repeat_first_field, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "chroma_420_type", + pic_ext->chroma_420_type, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "progressive_frame", + pic_ext->progressive_frame, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "composite_display_flag", + pic_ext->composite_display, "nbits", 1); + if (pic_ext->composite_display) { + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "v_axis", pic_ext->v_axis, "nbits", + 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "field_sequence", + pic_ext->field_sequence, "nbits", 3); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "sub_carrier", + pic_ext->sub_carrier, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "burst_amplitude", + pic_ext->burst_amplitude, "nbits", 7); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "sub_carrier_phase", + pic_ext->sub_carrier_phase, "nbits", 8); + } + ANALYZER_XML_ELEMENT_END (writer); + + return TRUE; +error: + { + GST_ERROR ("Failed to write the xml for Mpeg2Video PicHdr \n"); + return FALSE; + } +} + +static gboolean +create_quant_ext_xml (xmlTextWriterPtr writer, + GstMpegVideoQuantMatrixExt * quant_ext) +{ + ANALYZER_XML_ELEMENT_START (writer, "QuantMatrixExt"); + + ANALYZER_XML_ELEMENT_CREATE_STRING (writer, "extension_identifier", "0xb5", + "nbits", 8); + ANALYZER_XML_ELEMENT_CREATE_STRING (writer, "quant_matrix_extension_id", + "0x03", "nbits", 4); + + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "load_intra_quantiser_matrix", + quant_ext->load_intra_quantiser_matrix, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_MATRIX (writer, "intra_quantizer_matrix", + quant_ext->intra_quantiser_matrix, 8, 8); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "load_non_intra_quantiser_matrix", + quant_ext->load_non_intra_quantiser_matrix, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_MATRIX (writer, "non_intra_quantizer_matrix", + quant_ext->non_intra_quantiser_matrix, 8, 8); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "load_chroma_intra_quantiser_matrix", + quant_ext->load_chroma_intra_quantiser_matrix, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_MATRIX (writer, "chroma_intra_quantizer_matrix", + quant_ext->chroma_intra_quantiser_matrix, 8, 8); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, + "load_chroma_non_intra_quantiser_matrix", + quant_ext->load_chroma_non_intra_quantiser_matrix, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_MATRIX (writer, + "chroma_non_intra_quantizer_matrix", + quant_ext->chroma_non_intra_quantiser_matrix, 8, 8); + + ANALYZER_XML_ELEMENT_END (writer); + + return TRUE; +error: + { + GST_ERROR ("Failed to write the xml for Mpeg2Video QuantizationMatrices! "); + return FALSE; + } + return TRUE; +} + +#if 0 +static gboolean +create_slice_hdr_xml (xmlTextWriterPtr writer, + GstMpegVideoMetaSliceInfo * slice_info, gint slice_num) +{ + char header_name[256]; + + sprintf (header_name, "slice_%d", slice_num); + + ANALYZER_XML_ELEMENT_START (writer, header_name); + + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "slice_hdr_identifier", + slice_info->slice_hdr.slice_id, "nbits", 8); + if (slice_info->slice_hdr.vertical_position_ext) { + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "vertical_position_ext", + slice_info->slice_hdr.vertical_position_ext, "nbits", 3); + } + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "priority_breakpoint", + slice_info->slice_hdr.priority_breakpoint, "nbits", 7); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "quantiser_scale_code", + slice_info->slice_hdr.quantiser_scale_code, "nbits", 5); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "slice_ext_flag", + slice_info->slice_hdr.slice_ext_flag, "nbits", 1); + + if (!slice_info->slice_hdr.slice_ext_flag) { + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "intra_slice", + slice_info->slice_hdr.intra_slice, "nbits", 1); + } else { + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "intra_slice", + slice_info->slice_hdr.intra_slice, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "slice_picture_id_enable", + slice_info->slice_hdr.slice_picture_id_enable, "nbits", 1); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "slice_picture_id", + slice_info->slice_hdr.slice_picture_id, "nbits", 6); + } + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "header_size_calculated", + slice_info->slice_hdr.header_size, "nbits", 0); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "mb_row_calculated", + slice_info->slice_hdr.mb_row, "nbits", 0); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "mb_column_calculated", + slice_info->slice_hdr.mb_column, "nbits", 0); + + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "slice_offset_calculated", + slice_info->slice_offset, "nbits", 0); + ANALYZER_XML_ELEMENT_CREATE_INT (writer, "slice_size_calculated", + slice_info->slice_size, "nbits", 0); + + ANALYZER_XML_ELEMENT_END (writer); + + return TRUE; +error: + { + GST_ERROR ("Failed to write the xml for Mpeg2Video SliceHdr_%d \n", + slice_num); + return FALSE; + } + return TRUE; +} +#endif +gboolean +analyzer_create_mpeg2video_frame_xml (GstMpegVideoMeta * mpeg_meta, + gchar * location, gint frame_num, Mpeg2Headers * mpeg2_hdrs) +{ + xmlTextWriterPtr writer; + xmlDocPtr doc; + xmlBufferPtr buf; + xmlChar *tmp; + gchar *file_name; + gchar *name; + int fd, i; + GstMpegVideoSequenceHdr *sequencehdr = NULL; + GstMpegVideoSequenceExt *sequenceext = NULL; + GstMpegVideoSequenceDisplayExt *sequencedispext = NULL; + GstMpegVideoQuantMatrixExt *quantext = NULL; + + if (!mpeg_meta) + return FALSE; + + xmlKeepBlanksDefault (0); + + writer = xmlNewTextWriterDoc (&doc, 0); + if (!writer) { + GST_ERROR ("Error: creating xml text writer \n"); + return FALSE; + } + + if (xmlTextWriterStartDocument (writer, NULL, "UTF-8", NULL) < 0) { + GST_ERROR ("Error: xmlTextWriterStartDocument"); + return FALSE; + } + + if (xmlTextWriterStartElement (writer, (xmlChar *) "mpeg2") < 0) { + GST_ERROR ("Error: Failed to start the new element (root element) mpeg2"); + return FALSE; + } + + if (xmlTextWriterWriteComment (writer, + (xmlChar *) "Data parssed from the mpeg2 stream") < 0) { + g_error ("Error: Failed to write the comment \n"); + return FALSE; + } + + /* Each time we save the gerneral headers, which will get appended for + each frame xml files */ + + /* SequenceHdr */ + if (mpeg_meta->sequencehdr) { + sequencehdr = mpeg_meta->sequencehdr; + + if (mpeg2_hdrs->sequencehdr) + g_slice_free (GstMpegVideoSequenceHdr, mpeg2_hdrs->sequencehdr); + mpeg2_hdrs->sequencehdr = + g_slice_dup (GstMpegVideoSequenceHdr, mpeg_meta->sequencehdr); + + } else if (mpeg2_hdrs->sequencehdr) + sequencehdr = mpeg2_hdrs->sequencehdr; + + /* SequenceExtHdr */ + if (mpeg_meta->sequenceext) { + sequenceext = mpeg_meta->sequenceext; + + if (mpeg2_hdrs->sequenceext) + g_slice_free (GstMpegVideoSequenceExt, mpeg2_hdrs->sequenceext); + mpeg2_hdrs->sequenceext = + g_slice_dup (GstMpegVideoSequenceExt, mpeg_meta->sequenceext); + + } else if (mpeg2_hdrs->sequenceext) + sequenceext = mpeg2_hdrs->sequenceext; + + /* SequenceDisplayExt */ + if (mpeg_meta->sequencedispext) { + sequencedispext = mpeg_meta->sequencedispext; + + if (mpeg2_hdrs->sequencedispext) + g_slice_free (GstMpegVideoSequenceDisplayExt, + mpeg2_hdrs->sequencedispext); + mpeg2_hdrs->sequencedispext = + g_slice_dup (GstMpegVideoSequenceDisplayExt, + mpeg_meta->sequencedispext); + + } else if (mpeg2_hdrs->sequencedispext) + sequencedispext = mpeg2_hdrs->sequencedispext; + + /* QuantMatrixExt */ + if (mpeg_meta->quantext) { + quantext = mpeg_meta->quantext; + + if (mpeg2_hdrs->quantext) + g_slice_free (GstMpegVideoQuantMatrixExt, mpeg2_hdrs->quantext); + mpeg2_hdrs->quantext = + g_slice_dup (GstMpegVideoQuantMatrixExt, mpeg_meta->quantext); + + } else if (mpeg2_hdrs->quantext) + quantext = mpeg2_hdrs->quantext; + + /*Create xmls for each headers */ + + if (sequencehdr) + if (!create_seq_hdr_xml (writer, sequencehdr)) + return FALSE; + + if (sequenceext) { + if (!create_seq_ext_xml (writer, sequenceext)) + return FALSE; + } + + if (mpeg_meta->sequencedispext) { + if (!create_seq_disp_ext_xml (writer, sequencedispext)) + return FALSE; + } + + if (quantext) { + if (!create_quant_ext_xml (writer, quantext)) + return FALSE; + } +#if 0 + if (mpeg_meta->gophdr) { + if (!create_gop_hdr_xml (writer, mpeg_meta->gophdr)) + return FALSE; + } +#endif + if (mpeg_meta->pichdr) { + if (!create_pic_hdr_xml (writer, mpeg_meta->pichdr)) + return FALSE; + } + + if (mpeg_meta->picext) { + if (!create_pic_ext_xml (writer, mpeg_meta->picext)) + return FALSE; + } +#if 0 + if (mpeg_meta->slice_info_array) { + for (i = 0; i < mpeg_meta->slice_info_array->len; i++) { + GstMpegVideoMetaSliceInfo *slice_info = NULL; + slice_info = + &g_array_index (mpeg_meta->slice_info_array, + GstMpegVideoMetaSliceInfo, i); + if (!slice_info) { + g_error ("Failed to get slice details from meta.. \n"); + return FALSE; + } + if (!create_slice_hdr_xml (writer, slice_info, i)) + return FALSE; + } + } +#endif + if (xmlTextWriterEndElement (writer) < 0) { + g_error ("Error: Failed to end mpeg2 root element \n"); + return FALSE; + } + + if (xmlTextWriterEndDocument (writer) < 0) { + g_error ("Error: Ending document \n"); + return FALSE; + } + + xmlFreeTextWriter (writer); + + /* create a new xml file for each frame */ + name = g_strdup_printf ("mpeg2-%d.xml", frame_num); + file_name = g_build_filename (location, "xml", name, NULL); + GST_LOG ("Created a New xml file %s to dump the parsed info", file_name); + + xmlSaveFormatFile (file_name, doc, 1); + + if (name) + g_free (name); + if (file_name) + g_free (file_name); + + return TRUE; +} + +gboolean +analyzer_create_mpeg2video_frame_hex (GstMpegVideoMeta * mpeg_meta, + gint frame_num, guint * data) +{ + return TRUE; +} diff --git a/codecanalyzer/src/plugins/gst/analyzersink/mpeg_xml.h b/codecanalyzer/src/plugins/gst/analyzersink/mpeg_xml.h new file mode 100644 index 0000000000..c83646d21c --- /dev/null +++ b/codecanalyzer/src/plugins/gst/analyzersink/mpeg_xml.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, Intel Corporation. + * Author: Sreerenj Balachandran + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the 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 St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#ifndef __GST_OPEN_CODEC_ANALYSER_MPEG_XML__ +#define __GST_OPEN_CODEC_ANALYSER_MPEG_XML__ + +#include +#include +#include +#include +#include + +typedef struct { + GstMpegVideoSequenceHdr *sequencehdr; + GstMpegVideoSequenceExt *sequenceext; + GstMpegVideoSequenceDisplayExt *sequencedispext; + GstMpegVideoQuantMatrixExt *quantext; +}Mpeg2Headers; + +gboolean +analyzer_create_mpeg2video_frame_xml (GstMpegVideoMeta *mpeg_meta, + gchar *location, + gint frame_num, + Mpeg2Headers *mpeg2_hdrs); + +gboolean +analyzer_create_mpeg2video_frame_hex (GstMpegVideoMeta *mpeg_meta, + gint frame_num, guint *data); +#endif diff --git a/codecanalyzer/src/plugins/gst/analyzersink/plugin.c b/codecanalyzer/src/plugins/gst/analyzersink/plugin.c new file mode 100644 index 0000000000..a3e200b804 --- /dev/null +++ b/codecanalyzer/src/plugins/gst/analyzersink/plugin.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013, Intel Corporation. + * Author: Sreerenj Balachandran + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the 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 St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstanalyzersink.h" + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gboolean ret = FALSE; + + ret |= gst_element_register (plugin, "analyzersink", + GST_RANK_PRIMARY + 1, GST_TYPE_ANALYZER_SINK); + + return ret; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + analyzersink, + "sink element to dump parsed information to the xml", + plugin_init, VERSION, "LGPL", PACKAGE_NAME, PACKAGE_URL); diff --git a/codecanalyzer/src/plugins/gst/analyzersink/xml_utils.c b/codecanalyzer/src/plugins/gst/analyzersink/xml_utils.c new file mode 100644 index 0000000000..01dba13ea0 --- /dev/null +++ b/codecanalyzer/src/plugins/gst/analyzersink/xml_utils.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2013, Intel Corporation. + * Author: Sreerenj Balachandran + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the 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 St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "xml_utils.h" diff --git a/codecanalyzer/src/plugins/gst/analyzersink/xml_utils.h b/codecanalyzer/src/plugins/gst/analyzersink/xml_utils.h new file mode 100644 index 0000000000..acfdb03a81 --- /dev/null +++ b/codecanalyzer/src/plugins/gst/analyzersink/xml_utils.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2013, Intel Corporation. + * Author: Sreerenj Balachandran + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the 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 St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#ifndef __XML_UTILS_H__ +#define __XML_UTILS_H__ + +#include +#include +#include +#include + +#define ANALYZER_XML_ELEMENT_START(writer,element) { \ + if (xmlTextWriterStartElement (writer, (xmlChar *)element) < 0) { \ + GST_ERROR ("Failed to start the element %s",element); \ + goto error; \ + } \ +} + +/* to create a new #element with #content */ +#define ANALYZER_XML_ELEMENT_NEW(writer,element, content) { \ + if (xmlTextWriterWriteElement (writer, (xmlChar *)element, content) < 0) { \ + GST_ERROR ("Failed to write %s to the element %s",content, element); \ + goto error; \ + } \ +} + +#define ANALYZER_XML_ELEMENT_CONTENT_INTEGER_WRITE(writer,content) { \ + if (xmlTextWriterWriteFormatRaw (writer, "%d ", content) < 0) { \ + GST_ERROR ("Failed to write %d to the element",content); \ + goto error; \ + } \ +} + +#define ANALYZER_XML_ELEMENT_CONTENT_STRING_WRITE(writer,content) { \ + if (xmlTextWriterWriteFormatRaw (writer, "%s", content) < 0) { \ + GST_ERROR ("Failed to write %s to the element",content); \ + goto error; \ + } \ +} + +#define ANALYZER_XML_ELEMENT_ATTRIBUTE_INTEGER_WRITE(writer, attribute, value) { \ + if (xmlTextWriterWriteFormatAttribute (writer, (xmlChar *)attribute, "%d", value) < 0) { \ + GST_ERROR ("Failed to add attribute %s with value %d",attribute, value); \ + goto error; \ + } \ +} + +#define ANALYZER_XML_ELEMENT_WRITE_STRING (writer,element,content) { \ + if (xmlTextWriterWriteFormatElement (writer, (xmlChar *)element, "%s", content) < 0) { \ + GST_ERROR ("Failed to write %s to the element %s",content, element); \ + goto error; \ + } \ +} + +#define ANALYZER_XML_ELEMENT_END(writer) { \ + if (xmlTextWriterEndElement (writer) < 0) { \ + GST_ERROR ("Failed to end the element"); \ + goto error; \ + } \ +} + +#define ANALYZER_XML_ELEMENT_CREATE_INT(writer,element,content,attribute,value) { \ + ANALYZER_XML_ELEMENT_START (writer, element); \ + if (0 != value) \ + ANALYZER_XML_ELEMENT_ATTRIBUTE_INTEGER_WRITE (writer, attribute, value); \ + ANALYZER_XML_ELEMENT_CONTENT_INTEGER_WRITE (writer, content); \ + ANALYZER_XML_ELEMENT_END (writer); \ +} + +#define ANALYZER_XML_ELEMENT_CREATE_STRING(writer,element,content,attribute,value) { \ + ANALYZER_XML_ELEMENT_START (writer, element); \ + if (value != 0) \ + ANALYZER_XML_ELEMENT_ATTRIBUTE_INTEGER_WRITE (writer, attribute, value); \ + ANALYZER_XML_ELEMENT_CONTENT_STRING_WRITE (writer, content); \ + ANALYZER_XML_ELEMENT_END (writer); \ +} + +#define ANALYZER_XML_ELEMENT_CREATE_MATRIX(writer,element,content,rows,columns) { \ + int i, j; \ + int num_elements = rows * columns; \ + ANALYZER_XML_ELEMENT_START (writer, element); \ + ANALYZER_XML_ELEMENT_ATTRIBUTE_INTEGER_WRITE (writer, "is-matrix", 1); \ + ANALYZER_XML_ELEMENT_ATTRIBUTE_INTEGER_WRITE (writer, "rows", rows); \ + ANALYZER_XML_ELEMENT_ATTRIBUTE_INTEGER_WRITE (writer, "columns", columns); \ + for (i = 0; i < num_elements; i++) \ + ANALYZER_XML_ELEMENT_CONTENT_INTEGER_WRITE (writer, content[i]); \ + ANALYZER_XML_ELEMENT_END (writer); \ +} + +#endif /* __XML_UTILS_H__ */ diff --git a/codecanalyzer/src/xml_parse.c b/codecanalyzer/src/xml_parse.c new file mode 100644 index 0000000000..f6800fc7b5 --- /dev/null +++ b/codecanalyzer/src/xml_parse.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2013, Intel Corporation. + * Author: Sreerenj Balachandran + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the 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 St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#include "xml_parse.h" + +void +analyzer_node_list_free (GList * list) +{ + g_list_free_full (list, (GDestroyNotify) analyzer_node_free); +} + +void +analyzer_node_free (gpointer data) +{ + AnalyzerNode *node = (AnalyzerNode *) data; + + if (node) { + if (node->field_name) + g_free (node->field_name); + if (node->value) + g_free (node->value); + if (node->nbits) + g_free (node->nbits); + if (node->is_matrix) + g_free (node->is_matrix); + } +} + +AnalyzerNode * +analyzer_node_new () +{ + AnalyzerNode *node; + + node = g_slice_new0 (AnalyzerNode); + + return node; +} + +GList * +analyzer_get_list_header_strings (char *file_name) +{ + xmlDocPtr doc; + xmlNodePtr cur, tmp; + GList *list = NULL; + AnalyzerNode *node; + + doc = xmlParseFile (file_name); + if (!doc) { + g_error ("Failed to do xmlParseFile for the file.. %s\n", file_name); + goto error; + } + + cur = xmlDocGetRootElement (doc); + if (cur == NULL) { + g_error ("empty document\n"); + xmlFreeDoc (doc); + goto error; + } + + if (xmlStrcmp (cur->name, (const xmlChar *) "mpeg2") && + xmlStrcmp (cur->name, (const xmlChar *) "h264") && + xmlStrcmp (cur->name, (const xmlChar *) "h265")) { + g_error ("document of the wrong type !!"); + xmlFreeDoc (doc); + goto error; + } + + tmp = cur->xmlChildrenNode; + while (tmp) { + list = g_list_prepend (list, g_strdup (tmp->name)); + tmp = tmp->next; + } + if (list) + list = g_list_reverse (list); + + return list; + +error: + return NULL; +} + +GList * +analyzer_get_list_analyzer_node_from_xml (char *file_name, char *node_name) +{ + xmlDocPtr doc; + xmlNodePtr cur, tmp; + GList *list = NULL; + AnalyzerNode *node; + + doc = xmlParseFile (file_name); + if (!doc) { + g_error ("Failed to do xmlParseFile for the file.. %s\n", file_name); + } + + cur = xmlDocGetRootElement (doc); + if (cur == NULL) { + g_error ("empty document\n"); + xmlFreeDoc (doc); + return; + } + + if (xmlStrcmp (cur->name, (const xmlChar *) "mpeg2") && + xmlStrcmp (cur->name, (const xmlChar *) "h264") && + xmlStrcmp (cur->name, (const xmlChar *) "h265")) { + g_error ("document of the wrong type !!"); + xmlFreeDoc (doc); + return; + } + + tmp = cur->xmlChildrenNode; + while (tmp) { + if (!xmlStrcmp (tmp->name, (const xmlChar *) node_name)) { + g_debug ("Parsing the Child: %s \n", tmp->name); + + cur = tmp->xmlChildrenNode; + while (cur != NULL) { + xmlChar *key; + xmlChar *nbits = NULL; + xmlChar *is_matrix = NULL; + xmlChar *rows; + xmlChar *columns; + + key = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1); + nbits = xmlGetProp (cur, "nbits"); + is_matrix = xmlGetProp (cur, "is-matrix"); + if (is_matrix) { + rows = xmlGetProp (cur, "rows"); + columns = xmlGetProp (cur, "columns"); + } + node = g_slice_new0 (AnalyzerNode); + node->field_name = g_strdup (cur->name); + if (key) { + node->value = g_strdup ((gchar *) key); + xmlFree (key); + } + if (nbits) { + node->nbits = g_strdup ((gchar *) nbits); + xmlFree (nbits); + } + if (is_matrix) { + node->is_matrix = g_strdup ((gchar *) is_matrix); + xmlFree (is_matrix); + + node->rows = g_strdup ((gchar *) rows); + xmlFree (rows); + + node->columns = g_strdup ((gchar *) columns); + xmlFree (columns); + } + + list = g_list_prepend (list, node); + + cur = cur->next; + } + break; + } + tmp = tmp->next; + } + + xmlFreeDoc (doc); + + if (list) + list = g_list_reverse (list); + + return list; +} diff --git a/codecanalyzer/src/xml_parse.h b/codecanalyzer/src/xml_parse.h new file mode 100644 index 0000000000..68ba31eb1c --- /dev/null +++ b/codecanalyzer/src/xml_parse.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013, Intel Corporation. + * Author: Sreerenj Balachandran + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the 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 St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#ifndef __XML_PARSE__ +#define __XML_PARSE__ + +#include +#include +#include +#include +#include + +typedef enum { + ANALYZER_ALL, + ANALYZER_HEADERS, + ANALYZER_QUANTMATRIX, + ANALYZER_SLICE, + ANALYZER_HEXVAL +} AnalyzerHeaderGroup; + +typedef struct { + xmlChar *field_name; + xmlChar *value; + xmlChar *nbits; + + xmlChar *is_matrix; + xmlChar *rows; + xmlChar *columns; +}AnalyzerNode; + +AnalyzerNode *analyzer_node_new (); + +GList * +analyzer_get_list_analyzer_node_from_xml (char *file_name, char *node_name); + +GList * +analyzer_get_list_header_strings (char *file_name); + +void analyzer_node_free (gpointer data); + +void analyzer_node_list_free (GList *list); + +#endif